#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
-/* Returns and possibly creates the xattr dir. */
-static struct dentry *lookup_or_create_dir(struct dentry *parent,
- const char *name, int flags)
+static struct dentry *open_xa_root(struct super_block *sb, int flags)
{
- struct dentry *dentry;
- BUG_ON(!parent);
+ struct dentry *privroot = REISERFS_SB(sb)->priv_root;
+ struct dentry *xaroot;
+ if (!privroot->d_inode)
+ return ERR_PTR(-ENODATA);
- mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_XATTR);
- dentry = lookup_one_len(name, parent, strlen(name));
- if (!IS_ERR(dentry) && !dentry->d_inode) {
- int err = -ENODATA;
+ mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
+ xaroot = dget(REISERFS_SB(sb)->xattr_root);
+ if (!xaroot)
+ xaroot = ERR_PTR(-ENODATA);
+ else if (!xaroot->d_inode) {
+ int err = -ENODATA;
if (xattr_may_create(flags))
- err = xattr_mkdir(parent->d_inode, dentry, 0700);
-
+ err = xattr_mkdir(privroot->d_inode, xaroot, 0700);
if (err) {
- dput(dentry);
- dentry = ERR_PTR(err);
+ dput(xaroot);
+ xaroot = ERR_PTR(err);
}
}
- mutex_unlock(&parent->d_inode->i_mutex);
- return dentry;
-}
-static struct dentry *open_xa_root(struct super_block *sb, int flags)
-{
- struct dentry *privroot = REISERFS_SB(sb)->priv_root;
- if (!privroot)
- return ERR_PTR(-ENODATA);
- return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
+ mutex_unlock(&privroot->d_inode->i_mutex);
+ return xaroot;
}
static struct dentry *open_xa_dir(const struct inode *inode, int flags)
le32_to_cpu(INODE_PKEY(inode)->k_objectid),
inode->i_generation);
- xadir = lookup_or_create_dir(xaroot, namebuf, flags);
+ mutex_lock_nested(&xaroot->d_inode->i_mutex, I_MUTEX_XATTR);
+
+ xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
+ if (!IS_ERR(xadir) && !xadir->d_inode) {
+ int err = -ENODATA;
+ if (xattr_may_create(flags))
+ err = xattr_mkdir(xaroot->d_inode, xadir, 0700);
+ if (err) {
+ dput(xadir);
+ xadir = ERR_PTR(err);
+ }
+ }
+
+ mutex_unlock(&xaroot->d_inode->i_mutex);
dput(xaroot);
return xadir;
-
}
/* The following are side effects of other operations that aren't explicitly
return err;
}
-/* Actual operations that are exported to VFS-land */
-struct xattr_handler *reiserfs_xattr_handlers[] = {
- &reiserfs_xattr_user_handler,
- &reiserfs_xattr_trusted_handler,
-#ifdef CONFIG_REISERFS_FS_SECURITY
- &reiserfs_xattr_security_handler,
-#endif
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
- &reiserfs_posix_acl_access_handler,
- &reiserfs_posix_acl_default_handler,
-#endif
- NULL
-};
-
/*
* In order to implement different sets of xattr operations for each xattr
* prefix with the generic xattr API, a filesystem should create a
if (!dentry->d_inode)
return -EINVAL;
- if (!reiserfs_xattrs(dentry->d_sb) ||
+ if (!dentry->d_sb->s_xattr ||
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
return error;
}
-int reiserfs_permission(struct inode *inode, int mask)
-{
- /*
- * We don't do permission checks on the internal objects.
- * Permissions are determined by the "owning" object.
- */
- if (IS_PRIVATE(inode))
- return 0;
- /*
- * Stat data v1 doesn't support ACLs.
- */
- if (get_inode_sd_version(inode) == STAT_DATA_V1)
- return generic_permission(inode, mask, NULL);
- else
- return generic_permission(inode, mask, reiserfs_check_acl);
-}
-
static int create_privroot(struct dentry *dentry)
{
int err;
return 0;
}
+#else
+int __init reiserfs_xattr_register_handlers(void) { return 0; }
+void reiserfs_xattr_unregister_handlers(void) {}
+static int create_privroot(struct dentry *dentry) { return 0; }
+#endif
+
+/* Actual operations that are exported to VFS-land */
+struct xattr_handler *reiserfs_xattr_handlers[] = {
+#ifdef CONFIG_REISERFS_FS_XATTR
+ &reiserfs_xattr_user_handler,
+ &reiserfs_xattr_trusted_handler,
+#endif
+#ifdef CONFIG_REISERFS_FS_SECURITY
+ &reiserfs_xattr_security_handler,
+#endif
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
+ &reiserfs_posix_acl_access_handler,
+ &reiserfs_posix_acl_default_handler,
+#endif
+ NULL
+};
+
static int xattr_mount_check(struct super_block *s)
{
/* We need generation numbers to ensure that the oid mapping is correct
return 0;
}
-#else
-int __init reiserfs_xattr_register_handlers(void) { return 0; }
-void reiserfs_xattr_unregister_handlers(void) {}
+int reiserfs_permission(struct inode *inode, int mask)
+{
+ /*
+ * We don't do permission checks on the internal objects.
+ * Permissions are determined by the "owning" object.
+ */
+ if (IS_PRIVATE(inode))
+ return 0;
+
+#ifdef CONFIG_REISERFS_FS_XATTR
+ /*
+ * Stat data v1 doesn't support ACLs.
+ */
+ if (get_inode_sd_version(inode) != STAT_DATA_V1)
+ return generic_permission(inode, mask, reiserfs_check_acl);
#endif
+ return generic_permission(inode, mask, NULL);
+}
/* This will catch lookups from the fs root to .reiserfs_priv */
static int
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
{
int err = 0;
+ struct dentry *privroot = REISERFS_SB(s)->priv_root;
-#ifdef CONFIG_REISERFS_FS_XATTR
err = xattr_mount_check(s);
if (err)
goto error;
- if (!REISERFS_SB(s)->priv_root->d_inode && !(mount_flags & MS_RDONLY)) {
+ if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) {
mutex_lock(&s->s_root->d_inode->i_mutex);
err = create_privroot(REISERFS_SB(s)->priv_root);
mutex_unlock(&s->s_root->d_inode->i_mutex);
}
- if (!err)
+
+ if (privroot->d_inode) {
s->s_xattr = reiserfs_xattr_handlers;
+ mutex_lock(&privroot->d_inode->i_mutex);
+ if (!REISERFS_SB(s)->xattr_root) {
+ struct dentry *dentry;
+ dentry = lookup_one_len(XAROOT_NAME, privroot,
+ strlen(XAROOT_NAME));
+ if (!IS_ERR(dentry))
+ REISERFS_SB(s)->xattr_root = dentry;
+ else
+ err = PTR_ERR(dentry);
+ }
+ mutex_unlock(&privroot->d_inode->i_mutex);
+ }
error:
if (err) {
clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt));
clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt));
}
-#endif
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
- s->s_flags = s->s_flags & ~MS_POSIXACL;
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
if (reiserfs_posixacl(s))
s->s_flags |= MS_POSIXACL;
-#endif
+ else
+ s->s_flags &= ~MS_POSIXACL;
return err;
}