Commit 30304fc9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: xattr locking fixes

From: Chris Mason <mason@suse.com>

From: jeffm@suse.com

reiserfs xattr locking fixes
parent 647c60b9
...@@ -979,6 +979,7 @@ static void init_inode (struct inode * inode, struct path * path) ...@@ -979,6 +979,7 @@ static void init_inode (struct inode * inode, struct path * path)
REISERFS_I(inode)->i_jl = NULL; REISERFS_I(inode)->i_jl = NULL;
REISERFS_I(inode)->i_acl_access = NULL; REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL; REISERFS_I(inode)->i_acl_default = NULL;
init_rwsem (&REISERFS_I(inode)->xattr_sem);
if (stat_data_v1 (ih)) { if (stat_data_v1 (ih)) {
struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
...@@ -1642,6 +1643,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, ...@@ -1642,6 +1643,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode ); sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );
REISERFS_I(inode)->i_acl_access = NULL; REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL; REISERFS_I(inode)->i_acl_default = NULL;
init_rwsem (&REISERFS_I(inode)->xattr_sem);
if (old_format_only (sb)) if (old_format_only (sb))
make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT); make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
......
...@@ -521,6 +521,7 @@ reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer, ...@@ -521,6 +521,7 @@ reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer,
} }
xinode = fp->f_dentry->d_inode; xinode = fp->f_dentry->d_inode;
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
/* we need to copy it off.. */ /* we need to copy it off.. */
if (xinode->i_nlink > 1) { if (xinode->i_nlink > 1) {
...@@ -631,6 +632,7 @@ reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer, ...@@ -631,6 +632,7 @@ reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer,
xinode = fp->f_dentry->d_inode; xinode = fp->f_dentry->d_inode;
isize = xinode->i_size; isize = xinode->i_size;
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
/* Just return the size needed */ /* Just return the size needed */
if (buffer == NULL) { if (buffer == NULL) {
...@@ -834,6 +836,8 @@ reiserfs_delete_xattrs (struct inode *inode) ...@@ -834,6 +836,8 @@ reiserfs_delete_xattrs (struct inode *inode)
fput(fp); fput(fp);
out: out:
if (!err)
REISERFS_I(inode)->i_flags = REISERFS_I(inode)->i_flags & ~i_has_xattr_dir;
return err; return err;
} }
...@@ -945,11 +949,11 @@ reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer, ...@@ -945,11 +949,11 @@ reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer,
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP; return -EOPNOTSUPP;
down (&dentry->d_inode->i_sem); reiserfs_read_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb); reiserfs_read_lock_xattrs (dentry->d_sb);
err = xah->get (dentry->d_inode, name, buffer, size); err = xah->get (dentry->d_inode, name, buffer, size);
reiserfs_read_unlock_xattrs (dentry->d_sb); reiserfs_read_unlock_xattrs (dentry->d_sb);
up (&dentry->d_inode->i_sem); reiserfs_read_unlock_xattr_i (dentry->d_inode);
return err; return err;
} }
...@@ -965,6 +969,7 @@ reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, ...@@ -965,6 +969,7 @@ reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value,
{ {
struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
int err; int err;
int lock;
if (!xah || !reiserfs_xattrs(dentry->d_sb) || if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
...@@ -976,9 +981,18 @@ reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, ...@@ -976,9 +981,18 @@ reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value,
if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode))
return -EROFS; return -EROFS;
reiserfs_write_lock_xattrs (dentry->d_sb); reiserfs_write_lock_xattr_i (dentry->d_inode);
lock = !has_xattr_dir (dentry->d_inode);
if (lock)
reiserfs_write_lock_xattrs (dentry->d_sb);
else
reiserfs_read_lock_xattrs (dentry->d_sb);
err = xah->set (dentry->d_inode, name, value, size, flags); err = xah->set (dentry->d_inode, name, value, size, flags);
reiserfs_write_unlock_xattrs (dentry->d_sb); if (lock)
reiserfs_write_unlock_xattrs (dentry->d_sb);
else
reiserfs_read_unlock_xattrs (dentry->d_sb);
reiserfs_write_unlock_xattr_i (dentry->d_inode);
return err; return err;
} }
...@@ -1003,6 +1017,7 @@ reiserfs_removexattr (struct dentry *dentry, const char *name) ...@@ -1003,6 +1017,7 @@ reiserfs_removexattr (struct dentry *dentry, const char *name)
if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode))
return -EPERM; return -EPERM;
reiserfs_write_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb); reiserfs_read_lock_xattrs (dentry->d_sb);
/* Deletion pre-operation */ /* Deletion pre-operation */
...@@ -1019,6 +1034,7 @@ reiserfs_removexattr (struct dentry *dentry, const char *name) ...@@ -1019,6 +1034,7 @@ reiserfs_removexattr (struct dentry *dentry, const char *name)
out: out:
reiserfs_read_unlock_xattrs (dentry->d_sb); reiserfs_read_unlock_xattrs (dentry->d_sb);
reiserfs_write_unlock_xattr_i (dentry->d_inode);
return err; return err;
} }
...@@ -1081,7 +1097,7 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) ...@@ -1081,7 +1097,7 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP; return -EOPNOTSUPP;
down (&dentry->d_inode->i_sem); reiserfs_read_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb); reiserfs_read_lock_xattrs (dentry->d_sb);
dir = open_xa_dir (dentry->d_inode, FL_READONLY); dir = open_xa_dir (dentry->d_inode, FL_READONLY);
reiserfs_read_unlock_xattrs (dentry->d_sb); reiserfs_read_unlock_xattrs (dentry->d_sb);
...@@ -1104,6 +1120,8 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) ...@@ -1104,6 +1120,8 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
buf.r_pos = 0; buf.r_pos = 0;
buf.r_inode = dentry->d_inode; buf.r_inode = dentry->d_inode;
REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir;
err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf); err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf);
if (err) if (err)
goto out_dir; goto out_dir;
...@@ -1117,7 +1135,7 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) ...@@ -1117,7 +1135,7 @@ reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size)
fput(fp); fput(fp);
out: out:
up (&dentry->d_inode->i_sem); reiserfs_read_unlock_xattr_i (dentry->d_inode);
return err; return err;
} }
...@@ -1352,11 +1370,13 @@ __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd, ...@@ -1352,11 +1370,13 @@ __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd,
if (!(mode & S_IRWXG)) if (!(mode & S_IRWXG))
goto check_groups; goto check_groups;
reiserfs_read_lock_xattr_i (inode);
if (need_lock) if (need_lock)
reiserfs_read_lock_xattrs (inode->i_sb); reiserfs_read_lock_xattrs (inode->i_sb);
acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS); acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS);
if (need_lock) if (need_lock)
reiserfs_read_unlock_xattrs (inode->i_sb); reiserfs_read_unlock_xattrs (inode->i_sb);
reiserfs_read_unlock_xattr_i (inode);
if (IS_ERR (acl)) { if (IS_ERR (acl)) {
if (PTR_ERR (acl) == -ENODATA) if (PTR_ERR (acl) == -ENODATA)
goto check_groups; goto check_groups;
......
...@@ -399,9 +399,11 @@ reiserfs_cache_default_acl (struct inode *inode) ...@@ -399,9 +399,11 @@ reiserfs_cache_default_acl (struct inode *inode)
if (reiserfs_posixacl (inode->i_sb) && if (reiserfs_posixacl (inode->i_sb) &&
!is_reiserfs_priv_object (inode)) { !is_reiserfs_priv_object (inode)) {
struct posix_acl *acl; struct posix_acl *acl;
reiserfs_read_lock_xattr_i (inode);
reiserfs_read_lock_xattrs (inode->i_sb); reiserfs_read_lock_xattrs (inode->i_sb);
acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT); acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT);
reiserfs_read_unlock_xattrs (inode->i_sb); reiserfs_read_unlock_xattrs (inode->i_sb);
reiserfs_read_unlock_xattr_i (inode);
ret = acl ? 1 : 0; ret = acl ? 1 : 0;
posix_acl_release (acl); posix_acl_release (acl);
} }
...@@ -437,9 +439,18 @@ reiserfs_acl_chmod (struct inode *inode) ...@@ -437,9 +439,18 @@ reiserfs_acl_chmod (struct inode *inode)
return -ENOMEM; return -ENOMEM;
error = posix_acl_chmod_masq(clone, inode->i_mode); error = posix_acl_chmod_masq(clone, inode->i_mode);
if (!error) { if (!error) {
reiserfs_write_lock_xattrs (inode->i_sb); int lock = !has_xattr_dir (inode);
reiserfs_write_lock_xattr_i (inode);
if (lock)
reiserfs_write_lock_xattrs (inode->i_sb);
else
reiserfs_read_lock_xattrs (inode->i_sb);
error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
reiserfs_write_unlock_xattrs (inode->i_sb); if (lock)
reiserfs_write_unlock_xattrs (inode->i_sb);
else
reiserfs_read_unlock_xattrs (inode->i_sb);
reiserfs_write_unlock_xattr_i (inode);
} }
posix_acl_release(clone); posix_acl_release(clone);
return error; return error;
......
...@@ -24,6 +24,7 @@ typedef enum { ...@@ -24,6 +24,7 @@ typedef enum {
i_link_saved_unlink_mask = 0x0010, i_link_saved_unlink_mask = 0x0010,
i_link_saved_truncate_mask = 0x0020, i_link_saved_truncate_mask = 0x0020,
i_priv_object = 0x0080, i_priv_object = 0x0080,
i_has_xattr_dir = 0x0100,
} reiserfs_inode_flags; } reiserfs_inode_flags;
...@@ -55,6 +56,7 @@ struct reiserfs_inode_info { ...@@ -55,6 +56,7 @@ struct reiserfs_inode_info {
struct posix_acl *i_acl_access; struct posix_acl *i_acl_access;
struct posix_acl *i_acl_default; struct posix_acl *i_acl_default;
struct rw_semaphore xattr_sem;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
...@@ -32,6 +32,7 @@ struct reiserfs_xattr_handler { ...@@ -32,6 +32,7 @@ struct reiserfs_xattr_handler {
#ifdef CONFIG_REISERFS_FS_XATTR #ifdef CONFIG_REISERFS_FS_XATTR
#define is_reiserfs_priv_object(inode) (REISERFS_I(inode)->i_flags & i_priv_object) #define is_reiserfs_priv_object(inode) (REISERFS_I(inode)->i_flags & i_priv_object)
#define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name, ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name,
void *buffer, size_t size); void *buffer, size_t size);
int reiserfs_setxattr (struct dentry *dentry, const char *name, int reiserfs_setxattr (struct dentry *dentry, const char *name,
...@@ -80,6 +81,28 @@ reiserfs_read_unlock_xattrs(struct super_block *sb) ...@@ -80,6 +81,28 @@ reiserfs_read_unlock_xattrs(struct super_block *sb)
up_read (&REISERFS_XATTR_DIR_SEM(sb)); up_read (&REISERFS_XATTR_DIR_SEM(sb));
} }
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);
}
#else #else
#define is_reiserfs_priv_object(inode) 0 #define is_reiserfs_priv_object(inode) 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment