REISERFS_I(inode)->i_jl = NULL;
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
+ init_rwsem (&REISERFS_I(inode)->xattr_sem);
if (stat_data_v1 (ih)) {
struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
+ init_rwsem (&REISERFS_I(inode)->xattr_sem);
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);
}
xinode = fp->f_dentry->d_inode;
+ REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
/* we need to copy it off.. */
if (xinode->i_nlink > 1) {
xinode = fp->f_dentry->d_inode;
isize = xinode->i_size;
+ REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
/* Just return the size needed */
if (buffer == NULL) {
fput(fp);
out:
+ if (!err)
+ REISERFS_I(inode)->i_flags = REISERFS_I(inode)->i_flags & ~i_has_xattr_dir;
return err;
}
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- down (&dentry->d_inode->i_sem);
+ reiserfs_read_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb);
err = xah->get (dentry->d_inode, name, buffer, size);
reiserfs_read_unlock_xattrs (dentry->d_sb);
- up (&dentry->d_inode->i_sem);
+ reiserfs_read_unlock_xattr_i (dentry->d_inode);
return err;
}
{
struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name);
int err;
+ int lock;
if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode))
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);
- 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;
}
if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode))
return -EPERM;
+ reiserfs_write_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb);
/* Deletion pre-operation */
out:
reiserfs_read_unlock_xattrs (dentry->d_sb);
+ reiserfs_write_unlock_xattr_i (dentry->d_inode);
return err;
}
get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- down (&dentry->d_inode->i_sem);
+ reiserfs_read_lock_xattr_i (dentry->d_inode);
reiserfs_read_lock_xattrs (dentry->d_sb);
dir = open_xa_dir (dentry->d_inode, FL_READONLY);
reiserfs_read_unlock_xattrs (dentry->d_sb);
buf.r_pos = 0;
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);
if (err)
goto out_dir;
fput(fp);
out:
- up (&dentry->d_inode->i_sem);
+ reiserfs_read_unlock_xattr_i (dentry->d_inode);
return err;
}
if (!(mode & S_IRWXG))
goto check_groups;
+ reiserfs_read_lock_xattr_i (inode);
if (need_lock)
reiserfs_read_lock_xattrs (inode->i_sb);
acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS);
if (need_lock)
reiserfs_read_unlock_xattrs (inode->i_sb);
+ reiserfs_read_unlock_xattr_i (inode);
if (IS_ERR (acl)) {
if (PTR_ERR (acl) == -ENODATA)
goto check_groups;
if (reiserfs_posixacl (inode->i_sb) &&
!is_reiserfs_priv_object (inode)) {
struct posix_acl *acl;
+ reiserfs_read_lock_xattr_i (inode);
reiserfs_read_lock_xattrs (inode->i_sb);
acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT);
reiserfs_read_unlock_xattrs (inode->i_sb);
+ reiserfs_read_unlock_xattr_i (inode);
ret = acl ? 1 : 0;
posix_acl_release (acl);
}
return -ENOMEM;
error = posix_acl_chmod_masq(clone, inode->i_mode);
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);
- 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);
return error;
#ifdef CONFIG_REISERFS_FS_XATTR
#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,
void *buffer, size_t size);
int reiserfs_setxattr (struct dentry *dentry, const char *name,
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
#define is_reiserfs_priv_object(inode) 0