Lock updates to the mutal fields in the volume header, and document the locing in the hfsplus_sb_info structure. Signed-off-by: Christoph Hellwig <hch@xxxxxxxxxx> Index: linux-2.6/fs/hfsplus/hfsplus_fs.h =================================================================== --- linux-2.6.orig/fs/hfsplus/hfsplus_fs.h 2010-09-30 12:07:34.800782662 +0200 +++ linux-2.6/fs/hfsplus/hfsplus_fs.h 2010-09-30 12:07:35.632782662 +0200 @@ -116,23 +116,26 @@ struct hfsplus_sb_info { struct inode *hidden_dir; struct nls_table *nls; - /* synchronize block allocations */ - struct mutex alloc_mutex; - /* Runtime variables */ u32 blockoffset; u32 sect_count; int fs_shift; - /* Stuff in host order from Vol Header */ + /* immutable data from the volume header */ u32 alloc_blksz; int alloc_blksz_shift; u32 total_blocks; + u32 data_clump_blocks, rsrc_clump_blocks; + + /* mutable data from the volume header, protected by alloc_mutex */ u32 free_blocks; + struct mutex alloc_mutex; + + /* mutable data from the volume header, protected by vh_mutex */ u32 next_cnid; u32 file_count; u32 folder_count; - u32 data_clump_blocks, rsrc_clump_blocks; + struct mutex vh_mutex; /* Config options */ u32 creator; Index: linux-2.6/fs/hfsplus/dir.c =================================================================== --- linux-2.6.orig/fs/hfsplus/dir.c 2010-09-30 12:07:30.825782662 +0200 +++ linux-2.6/fs/hfsplus/dir.c 2010-09-30 12:07:35.634782662 +0200 @@ -251,6 +251,7 @@ static int hfsplus_link(struct dentry *s if (HFSPLUS_IS_RSRC(inode)) return -EPERM; + mutex_lock(&sbi->vh_mutex); if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { for (;;) { get_random_bytes(&id, sizeof(cnid)); @@ -263,7 +264,7 @@ static int hfsplus_link(struct dentry *s if (!res) break; if (res != -EEXIST) - return res; + goto out; } HFSPLUS_I(inode)->dev = id; cnid = sbi->next_cnid++; @@ -271,13 +272,13 @@ static int hfsplus_link(struct dentry *s res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); if (res) /* panic? */ - return res; + goto out; sbi->file_count++; } cnid = sbi->next_cnid++; res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); if (res) - return res; + goto out; inc_nlink(inode); hfsplus_instantiate(dst_dentry, inode, cnid); @@ -286,8 +287,9 @@ static int hfsplus_link(struct dentry *s mark_inode_dirty(inode); sbi->file_count++; dst_dir->i_sb->s_dirt = 1; - - return 0; +out: + mutex_unlock(&sbi->vh_mutex); + return res; } static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) @@ -302,6 +304,7 @@ static int hfsplus_unlink(struct inode * if (HFSPLUS_IS_RSRC(inode)) return -EPERM; + mutex_lock(&sbi->vh_mutex); cnid = (u32)(unsigned long)dentry->d_fsdata; if (inode->i_ino == cnid && atomic_read(&HFSPLUS_I(inode)->opencnt)) { @@ -312,11 +315,11 @@ static int hfsplus_unlink(struct inode * sbi->hidden_dir, &str); if (!res) inode->i_flags |= S_DEAD; - return res; + goto out; } res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); if (res) - return res; + goto out; if (inode->i_nlink > 0) drop_nlink(inode); @@ -339,37 +342,44 @@ static int hfsplus_unlink(struct inode * sbi->file_count--; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); - +out: + mutex_unlock(&sbi->vh_mutex); return res; } static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) { - struct inode *inode; + struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + struct inode *inode = dentry->d_inode; int res; - inode = dentry->d_inode; if (inode->i_size != 2) return -ENOTEMPTY; + + mutex_lock(&sbi->vh_mutex); res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); if (res) - return res; + goto out; clear_nlink(inode); inode->i_ctime = CURRENT_TIME_SEC; hfsplus_delete_inode(inode); mark_inode_dirty(inode); - return 0; +out: + mutex_unlock(&sbi->vh_mutex); + return res; } static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { + struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); struct inode *inode; - int res; + int res = -ENOSPC; + mutex_lock(&sbi->vh_mutex); inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); if (!inode) - return -ENOSPC; + goto out; res = page_symlink(inode, symname, strlen(symname) + 1); if (res) @@ -381,31 +391,35 @@ static int hfsplus_symlink(struct inode hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); - return 0; + goto out; out_err: inode->i_nlink = 0; hfsplus_delete_inode(inode); iput(inode); +out: + mutex_unlock(&sbi->vh_mutex); return res; } static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { + struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); struct inode *inode; - int res; + int res = -ENOSPC; + mutex_lock(&sbi->vh_mutex); inode = hfsplus_new_inode(dir->i_sb, mode); if (!inode) - return -ENOSPC; + goto out; res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); if (res) { inode->i_nlink = 0; hfsplus_delete_inode(inode); iput(inode); - return res; + goto out; } if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) @@ -413,7 +427,9 @@ static int hfsplus_mknod(struct inode *d hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); - return 0; +out: + mutex_unlock(&sbi->vh_mutex); + return res; } static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, Index: linux-2.6/fs/hfsplus/super.c =================================================================== --- linux-2.6.orig/fs/hfsplus/super.c 2010-09-30 12:07:34.803782662 +0200 +++ linux-2.6/fs/hfsplus/super.c 2010-09-30 12:07:35.639782662 +0200 @@ -160,6 +160,7 @@ int hfsplus_sync_fs(struct super_block * dprint(DBG_SUPER, "hfsplus_write_super\n"); + mutex_lock(&sbi->vh_mutex); mutex_lock(&sbi->alloc_mutex); sb->s_dirt = 0; @@ -194,6 +195,7 @@ int hfsplus_sync_fs(struct super_block * sbi->flags &= ~HFSPLUS_SB_WRITEBACKUP; } mutex_unlock(&sbi->alloc_mutex); + mutex_unlock(&sbi->vh_mutex); return 0; } @@ -319,6 +321,7 @@ static int hfsplus_fill_super(struct sup sb->s_fs_info = sbi; mutex_init(&sbi->alloc_mutex); + mutex_init(&sbi->vh_mutex); hfsplus_fill_defaults(sbi); if (!hfsplus_parse_options(data, sbi)) { printk(KERN_ERR "hfs: unable to parse mount options\n"); @@ -453,9 +456,13 @@ static int hfsplus_fill_super(struct sup if (!sbi->hidden_dir) { printk(KERN_DEBUG "hfs: create hidden dir...\n"); + + mutex_lock(&sbi->vh_mutex); sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, &str, sbi->hidden_dir); + mutex_unlock(&sbi->vh_mutex); + mark_inode_dirty(sbi->hidden_dir); } out: -- 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