The per-inode locking can be made more fine-grained to surround just the interaction with the filesystem itself. This really only applies to protecting reads during a write, since concurrent writes are barred with inode->i_mutex at the vfs level. Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx> -- fs/reiserfs/inode.c | 2 - fs/reiserfs/xattr.c | 62 +++++++++++++++++------------------------ fs/reiserfs/xattr_acl.c | 7 ---- include/linux/reiserfs_fs_i.h | 3 - include/linux/reiserfs_xattr.h | 26 ----------------- 5 files changed, 28 insertions(+), 72 deletions(-) --- a/fs/reiserfs/inode.c 2007-06-11 14:49:36.000000000 -0400 +++ b/fs/reiserfs/inode.c 2007-06-11 14:50:06.000000000 -0400 @@ -1128,7 +1128,6 @@ static void init_inode(struct inode *ino mutex_init(&(REISERFS_I(inode)->i_mmap)); reiserfs_init_acl_access(inode); reiserfs_init_acl_default(inode); - reiserfs_init_xattr_rwsem(inode); if (stat_data_v1(ih)) { struct stat_data_v1 *sd = @@ -1832,7 +1831,6 @@ int reiserfs_new_inode(struct reiserfs_t mutex_init(&(REISERFS_I(inode)->i_mmap)); reiserfs_init_acl_access(inode); reiserfs_init_acl_default(inode); - reiserfs_init_xattr_rwsem(inode); if (old_format_only(sb)) make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET, --- a/fs/reiserfs/xattr.c 2007-06-11 14:49:36.000000000 -0400 +++ b/fs/reiserfs/xattr.c 2007-06-11 14:50:07.000000000 -0400 @@ -29,10 +29,8 @@ * to the inode so that unnecessary lookups are avoided. * * Locking works like so: - * The xattr root (/.reiserfs_priv/xattrs) is protected by its i_mutex. - * The xattr dir (/.reiserfs_priv/xattrs/<oid>.<gen>) is protected by - * inode->xattr_sem. - * The xattrs themselves are likewise protected by the xattr_sem. + * Every component (xattr root, xattr dir, and the xattrs themselves) are + * protected by their i_mutex. */ #include <linux/reiserfs_fs.h> @@ -318,16 +316,12 @@ int xattr_readdir(struct file *file, fil int res = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; - mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); -// down(&inode->i_zombie); res = -ENOENT; if (!IS_DEADDIR(inode)) { lock_kernel(); res = __xattr_readdir(file, buf, filler); unlock_kernel(); } -// up(&inode->i_zombie); - mutex_unlock(&inode->i_mutex); out: return res; } @@ -387,9 +381,8 @@ reiserfs_xattr_set(struct inode *inode, if (get_inode_sd_version(inode) == STAT_DATA_V1) return -EOPNOTSUPP; - /* Empty xattrs are ok, they're just empty files, no hash */ - if (buffer && buffer_size) - xahash = xattr_hash(buffer, buffer_size); + if (!buffer) + return reiserfs_xattr_del(inode, name); open_file: fp = open_xattr_file(inode, name, flags); @@ -398,6 +391,7 @@ reiserfs_xattr_set(struct inode *inode, goto out; } + xahash = xattr_hash(buffer, buffer_size); xinode = fp->f_path.dentry->d_inode; REISERFS_I(inode)->i_flags |= i_has_xattr_dir; @@ -531,6 +525,8 @@ reiserfs_xattr_get(const struct inode *i goto out_fput; } + mutex_lock(&fp->f_path.dentry->d_inode->i_mutex); + while (file_pos < isize) { size_t chunk; char *data; @@ -585,6 +581,7 @@ reiserfs_xattr_get(const struct inode *i } out_fput: + mutex_unlock(&fp->f_path.dentry->d_inode->i_mutex); fput(fp); out: @@ -597,6 +594,7 @@ __reiserfs_xattr_del(struct dentry *xadi struct dentry *dentry; struct inode *dir = xadir->d_inode; int err = 0; + struct reiserfs_xattr_handler *xah; dentry = lookup_one_len(name, xadir, namelen); if (IS_ERR(dentry)) { @@ -624,6 +622,14 @@ __reiserfs_xattr_del(struct dentry *xadi return -EIO; } + /* Deletion pre-operation */ + xah = find_xattr_handler_prefix(name); + if (xah && xah->del) { + err = xah->del(inode, name); + if (err) + goto out; + } + err = vfs_unlink(xadir->d_inode, dentry); out_file: @@ -644,7 +650,9 @@ int reiserfs_xattr_del(struct inode *ino goto out; } + mutex_lock(&dir->i_mutex); err = __reiserfs_xattr_del(dir, name, strlen(name)); + mutex_unlock(&dir->i_mutex); dput(dir); if (!err) { @@ -689,7 +697,8 @@ int reiserfs_delete_xattrs(struct inode goto out; } else if (!dir->d_inode) { dput(dir); - return 0; + err = 0; + goto out; } fp = dentry_open(dir, NULL, O_RDWR); @@ -699,12 +708,13 @@ int reiserfs_delete_xattrs(struct inode goto out; } + mutex_lock_nested(&fp->f_path.dentry->d_inode->i_mutex, I_MUTEX_XATTR); lock_kernel(); err = xattr_readdir(fp, reiserfs_delete_xattrs_filler, dir); - if (err) { - unlock_kernel(); + unlock_kernel(); + mutex_unlock(&fp->f_path.dentry->d_inode->i_mutex); + if (err) goto out_dir; - } /* Leftovers besides . and .. -- that's not good. */ if (dir->d_inode->i_nlink <= 2) { @@ -717,7 +727,6 @@ int reiserfs_delete_xattrs(struct inode reiserfs_warning(inode->i_sb, "jdm-20004", "Couldn't remove all entries in directory"); } - unlock_kernel(); out_dir: fput(fp); @@ -791,6 +800,7 @@ int reiserfs_chown_xattrs(struct inode * goto out; } + mutex_lock_nested(&fp->f_path.dentry->d_inode->i_mutex, I_MUTEX_XATTR); lock_kernel(); attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); @@ -808,6 +818,7 @@ int reiserfs_chown_xattrs(struct inode * unlock_kernel(); out_dir: + mutex_unlock(&fp->f_path.dentry->d_inode->i_mutex); fput(fp); out: @@ -831,9 +842,7 @@ reiserfs_getxattr(struct dentry * dentry get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; - reiserfs_read_lock_xattr_i(dentry->d_inode); err = xah->get(dentry->d_inode, name, buffer, size); - reiserfs_read_unlock_xattr_i(dentry->d_inode); return err; } @@ -853,9 +862,7 @@ reiserfs_setxattr(struct dentry *dentry, get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; - reiserfs_write_lock_xattr_i(dentry->d_inode); err = xah->set(dentry->d_inode, name, value, size, flags); - reiserfs_write_unlock_xattr_i(dentry->d_inode); return err; } @@ -873,21 +880,12 @@ int reiserfs_removexattr(struct dentry * get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; - reiserfs_write_lock_xattr_i(dentry->d_inode); - /* Deletion pre-operation */ - if (xah->del) { - err = xah->del(dentry->d_inode, name); - if (err) - goto out; - } - err = reiserfs_xattr_del(dentry->d_inode, name); dentry->d_inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(dentry->d_inode); out: - reiserfs_write_unlock_xattr_i(dentry->d_inode); return err; } @@ -950,7 +948,6 @@ ssize_t reiserfs_listxattr(struct dentry get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; - reiserfs_read_lock_xattr_i(dentry->d_inode); dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); @@ -986,7 +983,6 @@ ssize_t reiserfs_listxattr(struct dentry fput(fp); out: - reiserfs_read_unlock_xattr_i(dentry->d_inode); return err; } @@ -1190,12 +1186,8 @@ static int reiserfs_check_acl(struct ino struct posix_acl *acl; int error = -EAGAIN; /* do regular unix permission checks by default */ - reiserfs_read_lock_xattr_i(inode); - acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); - reiserfs_read_unlock_xattr_i(inode); - if (acl) { if (!IS_ERR(acl)) { error = posix_acl_permission(inode, acl, mask); --- a/fs/reiserfs/xattr_acl.c 2007-06-11 14:49:36.000000000 -0400 +++ b/fs/reiserfs/xattr_acl.c 2007-06-11 14:50:06.000000000 -0400 @@ -418,9 +418,7 @@ int reiserfs_cache_default_acl(struct in int ret = 0; if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) { struct posix_acl *acl; - reiserfs_read_lock_xattr_i(inode); acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); - reiserfs_read_unlock_xattr_i(inode); ret = (acl && !IS_ERR(acl)); if (ret) posix_acl_release(acl); @@ -452,11 +450,8 @@ int reiserfs_acl_chmod(struct inode *ino if (!clone) return -ENOMEM; error = posix_acl_chmod_masq(clone, inode->i_mode); - if (!error) { - reiserfs_write_lock_xattr_i(inode); + if (!error) error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); - reiserfs_write_unlock_xattr_i(inode); - } posix_acl_release(clone); return error; } --- a/include/linux/reiserfs_fs_i.h 2007-06-11 14:49:05.000000000 -0400 +++ b/include/linux/reiserfs_fs_i.h 2007-06-11 14:50:06.000000000 -0400 @@ -58,9 +58,6 @@ struct reiserfs_inode_info { struct posix_acl *i_acl_access; struct posix_acl *i_acl_default; #endif -#ifdef CONFIG_REISERFS_FS_XATTR - struct rw_semaphore xattr_sem; -#endif struct inode vfs_inode; }; --- a/include/linux/reiserfs_xattr.h 2007-06-11 14:49:36.000000000 -0400 +++ b/include/linux/reiserfs_xattr.h 2007-06-11 14:50:06.000000000 -0400 @@ -68,34 +68,12 @@ extern struct reiserfs_xattr_handler sec int reiserfs_xattr_register_handlers(void) __init; void reiserfs_xattr_unregister_handlers(void); -static inline void reiserfs_write_lock_xattr_i(struct inode *inode) -{ - down_write(&REISERFS_I(inode)->xattr_sem); -} -static inline void reiserfs_write_unlock_xattr_i(struct inode *inode) -{ - up_write(&REISERFS_I(inode)->xattr_sem); -} -static inline void reiserfs_read_lock_xattr_i(struct inode *inode) -{ - down_read(&REISERFS_I(inode)->xattr_sem); -} - -static inline void reiserfs_read_unlock_xattr_i(struct inode *inode) -{ - up_read(&REISERFS_I(inode)->xattr_sem); -} static inline void reiserfs_mark_inode_private(struct inode *inode) { inode->i_flags |= S_PRIVATE; } -static inline void reiserfs_init_xattr_rwsem(struct inode *inode) -{ - init_rwsem(&REISERFS_I(inode)->xattr_sem); -} - #else #define is_reiserfs_priv_object(inode) 0 @@ -104,10 +82,6 @@ static inline void reiserfs_init_xattr_r #define reiserfs_setxattr NULL #define reiserfs_listxattr NULL #define reiserfs_removexattr NULL -#define reiserfs_write_lock_xattrs(sb) do {;} while(0) -#define reiserfs_write_unlock_xattrs(sb) do {;} while(0) -#define reiserfs_read_lock_xattrs(sb) -#define reiserfs_read_unlock_xattrs(sb) #define reiserfs_permission NULL -- Jeff Mahoney SUSE Labs - To unsubscribe from this list: send the line "unsubscribe reiserfs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html