Make sure the initial insertation of the catalog entry already contains the device number by calling init_special_inode early and setting writing out the dev field of the on-disk permission structure. The latter is facilitated by sharing the almost identical hfsplus_set_perms helpers between initial catalog entry creating and ->write_inode. Unless we crashed just after mknod this bug was harmless as the inode is marked dirty at the end of hfsplus_mknod, and hfsplus_write_inode will update the catalog entry to contain the correct value. Signed-off-by: Christoph Hellwig <hch@xxxxxxxxxx> Index: linux-2.6/fs/hfsplus/catalog.c =================================================================== --- linux-2.6.orig/fs/hfsplus/catalog.c 2010-10-11 20:02:16.780274444 +0200 +++ linux-2.6/fs/hfsplus/catalog.c 2010-10-11 20:02:40.577253560 +0200 @@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hf key->key_len = cpu_to_be16(6 + ustrlen); } -static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) +void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms) { if (inode->i_flags & S_IMMUTABLE) perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; @@ -77,10 +77,18 @@ static void hfsplus_set_perms(struct ino perms->rootflags |= HFSPLUS_FLG_APPEND; else perms->rootflags &= ~HFSPLUS_FLG_APPEND; - HFSPLUS_I(inode)->userflags = perms->userflags; + + perms->userflags = HFSPLUS_I(inode)->userflags; perms->mode = cpu_to_be16(inode->i_mode); perms->owner = cpu_to_be32(inode->i_uid); perms->group = cpu_to_be32(inode->i_gid); + + if (S_ISREG(inode->i_mode)) + perms->dev = cpu_to_be32(inode->i_nlink); + else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) + perms->dev = cpu_to_be32(inode->i_rdev); + else + perms->dev = 0; } static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) @@ -99,7 +107,7 @@ static int hfsplus_cat_build_record(hfsp folder->content_mod_date = folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); - hfsplus_set_perms(inode, &folder->permissions); + hfsplus_cat_set_perms(inode, &folder->permissions); if (inode == sbi->hidden_dir) /* invisible and namelocked */ folder->user_info.frFlags = cpu_to_be16(0x5000); @@ -118,7 +126,7 @@ static int hfsplus_cat_build_record(hfsp file->attribute_mod_date = file->access_date = hfsp_now2mt(); if (cnid == inode->i_ino) { - hfsplus_set_perms(inode, &file->permissions); + hfsplus_cat_set_perms(inode, &file->permissions); if (S_ISLNK(inode->i_mode)) { file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); Index: linux-2.6/fs/hfsplus/dir.c =================================================================== --- linux-2.6.orig/fs/hfsplus/dir.c 2010-10-11 20:01:06.023253839 +0200 +++ linux-2.6/fs/hfsplus/dir.c 2010-10-11 20:02:40.578254049 +0200 @@ -418,6 +418,9 @@ static int hfsplus_mknod(struct inode *d if (!inode) goto out; + if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) + init_special_inode(inode, mode, rdev); + res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); if (res) { inode->i_nlink = 0; @@ -426,9 +429,6 @@ static int hfsplus_mknod(struct inode *d goto out; } - if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) - init_special_inode(inode, mode, rdev); - hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); out: Index: linux-2.6/fs/hfsplus/hfsplus_fs.h =================================================================== --- linux-2.6.orig/fs/hfsplus/hfsplus_fs.h 2010-10-11 20:02:16.780274444 +0200 +++ linux-2.6/fs/hfsplus/hfsplus_fs.h 2010-10-11 20:02:40.584331783 +0200 @@ -326,6 +326,7 @@ int hfsplus_create_cat(u32, struct inode int hfsplus_delete_cat(u32, struct inode *, struct qstr *); int hfsplus_rename_cat(u32, struct inode *, struct qstr *, struct inode *, struct qstr *); +void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms); /* dir.c */ extern const struct inode_operations hfsplus_dir_inode_operations; Index: linux-2.6/fs/hfsplus/inode.c =================================================================== --- linux-2.6.orig/fs/hfsplus/inode.c 2010-10-11 20:02:16.786004155 +0200 +++ linux-2.6/fs/hfsplus/inode.c 2010-10-11 20:02:40.590255236 +0200 @@ -252,29 +252,6 @@ static void hfsplus_get_perms(struct ino inode->i_flags &= ~S_APPEND; } -static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) -{ - if (inode->i_flags & S_IMMUTABLE) - perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; - else - perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; - if (inode->i_flags & S_APPEND) - perms->rootflags |= HFSPLUS_FLG_APPEND; - else - perms->rootflags &= ~HFSPLUS_FLG_APPEND; - perms->userflags = HFSPLUS_I(inode)->userflags; - perms->mode = cpu_to_be16(inode->i_mode); - perms->owner = cpu_to_be32(inode->i_uid); - perms->group = cpu_to_be32(inode->i_gid); - - if (S_ISREG(inode->i_mode)) - perms->dev = cpu_to_be32(inode->i_nlink); - else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) - perms->dev = cpu_to_be32(inode->i_rdev); - else - perms->dev = 0; -} - static int hfsplus_file_open(struct inode *inode, struct file *file) { if (HFSPLUS_IS_RSRC(inode)) @@ -578,7 +555,7 @@ int hfsplus_cat_write_inode(struct inode hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, sizeof(struct hfsplus_cat_folder)); /* simple node checks? */ - hfsplus_set_perms(inode, &folder->permissions); + hfsplus_cat_set_perms(inode, &folder->permissions); folder->access_date = hfsp_ut2mt(inode->i_atime); folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); @@ -600,7 +577,7 @@ int hfsplus_cat_write_inode(struct inode hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, sizeof(struct hfsplus_cat_file)); hfsplus_inode_write_fork(inode, &file->data_fork); - hfsplus_set_perms(inode, &file->permissions); + hfsplus_cat_set_perms(inode, &file->permissions); if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); else -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html