The xattr file open/lookup code is needlessly complex. We can use vfs-level
 operations to perform the same work, and also simplify the locking
 constraints. The locking advantages will be exploited in future patches.

 fs/reiserfs/xattr.c |  269 ++++++++++++++++++----------------------------------
 1 files changed, 98 insertions(+), 171 deletions(-)

Signed-off-by: Jeff Mahoney <[EMAIL PROTECTED]>

diff -ruNpX ../dontdiff linux-2.6.15-staging1/fs/reiserfs/xattr.c 
linux-2.6.15-staging2/fs/reiserfs/xattr.c
--- linux-2.6.15-staging1/fs/reiserfs/xattr.c   2006-02-13 14:21:02.000000000 
-0500
+++ linux-2.6.15-staging2/fs/reiserfs/xattr.c   2006-02-13 14:21:02.000000000 
-0500
@@ -46,217 +46,143 @@
 #include <linux/stat.h>
 #include <asm/semaphore.h>
 
-#define FL_READONLY 128
-#define FL_DIR_SEM_HELD 256
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
 
 static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
                                                                *prefix);
 
-static struct dentry *create_xa_root(struct super_block *sb)
+/* Opens the directory corresponding to the inode's extended attribute store.
+ * If flags allow, the tree to the directory may be created. If creation is
+ * prohibited, -ENODATA is returned. */
+static struct dentry *open_xa_dir(const struct inode *inode, int flags)
 {
-       struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root);
-       struct dentry *xaroot;
+       struct dentry *xaroot, *xadir;
+       char namebuf[17];               /* 8 for oid, 8 for gen, 1 for NUL */
+       struct dentry *privroot = dget(REISERFS_SB(inode->i_sb)->priv_root);
+       int create_ok = (!flags || flags & XATTR_CREATE);
+       int err = 0;
 
-       /* This needs to be created at mount-time */
+       /* We don't create the privroot */
        if (!privroot)
-               return ERR_PTR(-EOPNOTSUPP);
+               return ERR_PTR(-ENODATA);
 
-       xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
-       if (IS_ERR(xaroot)) {
-               goto out;
-       } else if (!xaroot->d_inode) {
-               int err;
-               mutex_lock(&privroot->d_inode->i_mutex);
-               err =
-                   privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot,
-                                                  0700);
-               mutex_unlock(&privroot->d_inode->i_mutex);
+       xaroot = dget(REISERFS_SB(inode->i_sb)->xattr_root);
 
-               if (err) {
-                       dput(xaroot);
-                       dput(privroot);
-                       return ERR_PTR(err);
+       if (!xaroot) {
+               mutex_lock(&privroot->d_inode->i_mutex);
+               xaroot = lookup_one_len(XAROOT_NAME, privroot,
+                                       strlen(XAROOT_NAME));
+               if (IS_ERR(xaroot)) {
+                       mutex_unlock(&privroot->d_inode->i_mutex);
+                       err = PTR_ERR(xaroot);
+                       goto out_err;
                }
-               REISERFS_SB(sb)->xattr_root = dget(xaroot);
-       }
-
-      out:
-       dput(privroot);
-       return xaroot;
-}
-
-/* This will return a dentry, or error, refering to the xa root directory.
- * If the xa root doesn't exist yet, the dentry will be returned without
- * an associated inode. This dentry can be used with ->mkdir to create
- * the xa directory. */
-static struct dentry *__get_xa_root(struct super_block *s)
-{
-       struct dentry *privroot = dget(REISERFS_SB(s)->priv_root);
-       struct dentry *xaroot = NULL;
+               if (!xaroot->d_inode) {
+                       if (!create_ok) {
+                               mutex_unlock(&privroot->d_inode->i_mutex);
+                               err = -ENODATA;
+                               goto out_err;
+                       }
 
-       if (IS_ERR(privroot) || !privroot)
-               return privroot;
+                       err = vfs_mkdir(privroot->d_inode, xaroot, 0700);
+                       if (err) {
+                               mutex_unlock(&privroot->d_inode->i_mutex);
+                               goto out_err;
+                       }
+               }
 
-       xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
-       if (IS_ERR(xaroot)) {
-               goto out;
-       } else if (!xaroot->d_inode) {
-               dput(xaroot);
-               xaroot = NULL;
-               goto out;
+               REISERFS_SB(inode->i_sb)->xattr_root = dget(xaroot);
+               mutex_unlock(&privroot->d_inode->i_mutex);
        }
 
-       REISERFS_SB(s)->xattr_root = dget(xaroot);
-
-      out:
-       dput(privroot);
-       return xaroot;
-}
-
-/* Returns the dentry (or NULL) referring to the root of the extended
- * attribute directory tree. If it has already been retrieved, it is used.
- * Otherwise, we attempt to retrieve it from disk. It may also return
- * a pointer-encoded error.
- */
-static inline struct dentry *get_xa_root(struct super_block *s)
-{
-       struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root);
+       snprintf (namebuf, sizeof (namebuf), "%X.%X",
+                 le32_to_cpu(INODE_PKEY(inode)->k_objectid),
+                 inode->i_generation);
 
-       if (!dentry)
-               dentry = __get_xa_root(s);
+       mutex_lock(&xaroot->d_inode->i_mutex);
 
-       return dentry;
-}
-
-/* Opens the directory corresponding to the inode's extended attribute store.
- * If flags allow, the tree to the directory may be created. If creation is
- * prohibited, -ENODATA is returned. */
-static struct dentry *open_xa_dir(const struct inode *inode, int flags)
-{
-       struct dentry *xaroot, *xadir;
-       char namebuf[17];
-
-       xaroot = get_xa_root(inode->i_sb);
-       if (IS_ERR(xaroot)) {
-               return xaroot;
-       } else if (!xaroot) {
-               if (flags == 0 || flags & XATTR_CREATE) {
-                       xaroot = create_xa_root(inode->i_sb);
-                       if (IS_ERR(xaroot))
-                               return xaroot;
-               }
-               if (!xaroot)
-                       return ERR_PTR(-ENODATA);
-       }
-
-       /* ok, we have xaroot open */
-
-       snprintf(namebuf, sizeof(namebuf), "%X.%X",
-                le32_to_cpu(INODE_PKEY(inode)->k_objectid),
-                inode->i_generation);
        xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
        if (IS_ERR(xadir)) {
-               dput(xaroot);
-               return xadir;
+               mutex_unlock(&xaroot->d_inode->i_mutex);
+               err = PTR_ERR(xadir);
+               goto out_err;
        }
 
        if (!xadir->d_inode) {
-               int err;
-               if (flags == 0 || flags & XATTR_CREATE) {
-                       /* Although there is nothing else trying to create this 
directory,
-                        * another directory with the same hash may be created, 
so we need
-                        * to protect against that */
-                       err =
-                           xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir,
-                                                        0700);
-                       if (err) {
-                               dput(xaroot);
-                               dput(xadir);
-                               return ERR_PTR(err);
-                       }
+               if (!create_ok) {
+                       dput(xadir);
+                       mutex_unlock(&xaroot->d_inode->i_mutex);
+                       err = -ENODATA;
+                       goto out_err;
                }
-               if (!xadir->d_inode) {
-                       dput(xaroot);
+
+               err = vfs_mkdir(xaroot->d_inode, xadir, 0700);
+               if (err) {
                        dput(xadir);
-                       return ERR_PTR(-ENODATA);
+                       mutex_unlock(&xaroot->d_inode->i_mutex);
+                       goto out_err;
                }
        }
+       mutex_unlock(&xaroot->d_inode->i_mutex);
 
+      out:
        dput(xaroot);
+       dput(privroot);
        return xadir;
+
+      out_err:
+       xadir = ERR_PTR(err);
+       goto out;
 }
 
 /* Returns a dentry corresponding to a specific extended attribute file
  * for the inode. If flags allow, the file is created. Otherwise, a
  * valid or negative dentry, or an error is returned. */
-static struct dentry *get_xa_file_dentry(const struct inode *inode,
-                                        const char *name, int flags)
+static struct file *open_xattr_file(const struct inode *inode,
+                                    const char *name, int flags)
 {
        struct dentry *xadir, *xafile;
        int err = 0;
 
        xadir = open_xa_dir(inode, flags);
-       if (IS_ERR(xadir)) {
-               return ERR_PTR(PTR_ERR(xadir));
-       } else if (xadir && !xadir->d_inode) {
-               dput(xadir);
-               return ERR_PTR(-ENODATA);
-       }
+       if (IS_ERR(xadir))
+               return (struct file *)xadir;
 
-       xafile = lookup_one_len(name, xadir, strlen(name));
-       if (IS_ERR(xafile)) {
-               dput(xadir);
-               return ERR_PTR(PTR_ERR(xafile));
-       }
+       BUG_ON(!xadir->d_inode);
 
-       if (xafile->d_inode) {  /* file exists */
-               if (flags & XATTR_CREATE) {
-                       err = -EEXIST;
-                       dput(xafile);
-                       goto out;
-               }
-       } else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
-               goto out;
-       } else {
-               /* inode->i_mutex is down, so nothing else can try to create
-                * the same xattr */
-               err = xadir->d_inode->i_op->create(xadir->d_inode, xafile,
-                                                  0700 | S_IFREG, NULL);
+       mutex_lock(&xadir->d_inode->i_mutex);
 
-               if (err) {
-                       dput(xafile);
-                       goto out;
-               }
+       xafile = lookup_one_len (name, xadir, strlen(name));
+       if (IS_ERR(xafile)) {
+               err = PTR_ERR(xafile);
+               goto out_err;
        }
 
-      out:
-       dput(xadir);
-       if (err)
-               xafile = ERR_PTR(err);
-       return xafile;
-}
+       err = -EEXIST;
+       if (xafile->d_inode && flags & XATTR_CREATE)
+               goto out_err;
 
-/* Opens a file pointer to the attribute associated with inode */
-static struct file *open_xa_file(const struct inode *inode, const char *name,
-                                int flags)
-{
-       struct dentry *xafile;
-       struct file *fp;
+       if (!xafile->d_inode) {
+               err = -ENODATA;
+               if (flags & XATTR_REPLACE)
+                       goto out_err;
 
-       xafile = get_xa_file_dentry(inode, name, flags);
-       if (IS_ERR(xafile))
-               return ERR_PTR(PTR_ERR(xafile));
-       else if (!xafile->d_inode) {
-               dput(xafile);
-               return ERR_PTR(-ENODATA);
+               err = vfs_create(xadir->d_inode, xafile, 0700|S_IFREG, NULL);
+               if (err)
+                       goto out_err;
        }
 
-       fp = dentry_open(xafile, NULL, O_RDWR);
-       /* dentry_open dputs the dentry if it fails */
+       dput(xadir);
+       mutex_unlock(&xadir->d_inode->i_mutex);
+
+       return dentry_open(xafile, NULL, O_RDWR);
 
-       return fp;
+      out_err:
+       mutex_unlock(&xadir->d_inode->i_mutex);
+       dput(xafile);
+       dput(xadir);
+       return ERR_PTR(err);
 }
 
 /*
@@ -478,7 +404,7 @@ reiserfs_xattr_set(struct inode *inode, 
        }
 
       open_file:
-       fp = open_xa_file(inode, name, flags);
+       fp = open_xattr_file(inode, name, flags);
        if (IS_ERR(fp)) {
                err = PTR_ERR(fp);
                goto out;
@@ -583,7 +509,7 @@ reiserfs_xattr_get(const struct inode *i
        if (get_inode_sd_version(inode) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       fp = open_xa_file(inode, name, FL_READONLY);
+       fp = open_xattr_file(inode, name, XATTR_REPLACE);
        if (IS_ERR(fp)) {
                err = PTR_ERR(fp);
                goto out;
@@ -631,6 +557,7 @@ reiserfs_xattr_get(const struct inode *i
                                 "Invalid hash for xattr (%s) associated "
                                 "with %k", name, INODE_PKEY(inode));
                err = -EIO;
+               goto out_dput;
        }
 
       out_dput:
@@ -673,9 +600,7 @@ __reiserfs_xattr_del(struct dentry *xadi
                return -EIO;
        }
 
-       err = dir->i_op->unlink(dir, dentry);
-       if (!err)
-               d_delete(dentry);
+       err = vfs_unlink(xadir->d_inode, dentry);
 
       out_file:
        dput(dentry);
@@ -689,7 +614,7 @@ int reiserfs_xattr_del(struct inode *ino
        struct dentry *dir;
        int err;
 
-       dir = open_xa_dir(inode, FL_READONLY);
+       dir = open_xa_dir(inode, XATTR_REPLACE);
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);
                goto out;
@@ -735,7 +660,7 @@ int reiserfs_delete_xattrs(struct inode 
                return 0;
        }
        reiserfs_read_lock_xattrs(inode->i_sb);
-       dir = open_xa_dir(inode, FL_READONLY);
+       dir = open_xa_dir(inode, XATTR_REPLACE);
        reiserfs_read_unlock_xattrs(inode->i_sb);
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);
@@ -761,9 +686,11 @@ int reiserfs_delete_xattrs(struct inode 
 
        /* Leftovers besides . and .. -- that's not good. */
        if (dir->d_inode->i_nlink <= 2) {
-               root = get_xa_root(inode->i_sb);
+               root = dget(REISERFS_SB(inode->i_sb)->xattr_root);
                reiserfs_write_lock_xattrs(inode->i_sb);
+               mutex_lock(&root->d_inode->i_mutex);
                err = vfs_rmdir(root->d_inode, dir);
+               mutex_unlock(&root->d_inode->i_mutex);
                reiserfs_write_unlock_xattrs(inode->i_sb);
                dput(root);
        } else {
@@ -828,7 +755,7 @@ int reiserfs_chown_xattrs(struct inode *
                return 0;
        }
        reiserfs_read_lock_xattrs(inode->i_sb);
-       dir = open_xa_dir(inode, FL_READONLY);
+       dir = open_xa_dir(inode, XATTR_REPLACE);
        reiserfs_read_unlock_xattrs(inode->i_sb);
        if (IS_ERR(dir)) {
                if (PTR_ERR(dir) != -ENODATA)
@@ -1025,7 +952,7 @@ ssize_t reiserfs_listxattr(struct dentry
 
        reiserfs_read_lock_xattr_i(dentry->d_inode);
        reiserfs_read_lock_xattrs(dentry->d_sb);
-       dir = open_xa_dir(dentry->d_inode, FL_READONLY);
+       dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
        reiserfs_read_unlock_xattrs(dentry->d_sb);
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);

Reply via email to