reiserfs: Clean up xattrs when REISERFS_FS_XATTR is unset
[deliverable/linux.git] / fs / reiserfs / xattr.c
index c5fc207e529c8bfb5f3473c82984a47f9407e475..f9bcdd5750f7be288ae7cd21fba2224a77c30f61 100644 (file)
@@ -50,9 +50,6 @@
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
 
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
-                                                               *prefix);
-
 /* Returns the dentry referring to the root of the extended attribute
  * directory tree. If it has already been retrieved, it is used. If it
  * hasn't been created and the flags indicate creation is allowed, we
@@ -143,60 +140,6 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
        return xadir;
 }
 
-/* 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)
-{
-       struct dentry *xadir, *xafile;
-       int err = 0;
-
-       xadir = open_xa_dir(inode, flags);
-       if (IS_ERR(xadir)) {
-               return ERR_CAST(xadir);
-       } else if (!xadir->d_inode) {
-               dput(xadir);
-               return ERR_PTR(-ENODATA);
-       }
-
-       xafile = lookup_one_len(name, xadir, strlen(name));
-       if (IS_ERR(xafile)) {
-               dput(xadir);
-               return ERR_CAST(xafile);
-       }
-
-       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);
-
-               if (err) {
-                       dput(xafile);
-                       goto out;
-               }
-       }
-
-      out:
-       dput(xadir);
-       if (err)
-               xafile = ERR_PTR(err);
-       else if (!xafile->d_inode) {
-               dput(xafile);
-               xafile = ERR_PTR(-ENODATA);
-       }
-       return xafile;
-}
-
 /*
  * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but
  * we need to drop the path before calling the filldir struct.  That
@@ -369,6 +312,251 @@ int xattr_readdir(struct inode *inode, filldir_t filler, void *buf)
        return res;
 }
 
+static int
+__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
+{
+       struct dentry *dentry;
+       struct inode *dir = xadir->d_inode;
+       int err = 0;
+
+       dentry = lookup_one_len(name, xadir, namelen);
+       if (IS_ERR(dentry)) {
+               err = PTR_ERR(dentry);
+               goto out;
+       } else if (!dentry->d_inode) {
+               err = -ENODATA;
+               goto out_file;
+       }
+
+       /* Skip directories.. */
+       if (S_ISDIR(dentry->d_inode->i_mode))
+               goto out_file;
+
+       if (!IS_PRIVATE(dentry->d_inode)) {
+               reiserfs_error(dir->i_sb, "jdm-20003",
+                              "OID %08x [%.*s/%.*s] doesn't have "
+                              "priv flag set [parent is %sset].",
+                              le32_to_cpu(INODE_PKEY(dentry->d_inode)->
+                                          k_objectid), xadir->d_name.len,
+                              xadir->d_name.name, namelen, name,
+                              IS_PRIVATE(xadir->d_inode) ? "" :
+                              "not ");
+               dput(dentry);
+               return -EIO;
+       }
+
+       err = dir->i_op->unlink(dir, dentry);
+       if (!err)
+               d_delete(dentry);
+
+out_file:
+       dput(dentry);
+
+out:
+       return err;
+}
+
+/* The following are side effects of other operations that aren't explicitly
+ * modifying extended attributes. This includes operations such as permissions
+ * or ownership changes, object deletions, etc. */
+
+static int
+reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
+                             loff_t offset, u64 ino, unsigned int d_type)
+{
+       struct dentry *xadir = (struct dentry *)buf;
+
+       return __reiserfs_xattr_del(xadir, name, namelen);
+
+}
+
+/* This is called w/ inode->i_mutex downed */
+int reiserfs_delete_xattrs(struct inode *inode)
+{
+       struct dentry *dir, *root;
+       int err = 0;
+
+       /* Skip out, an xattr has no xattrs associated with it */
+       if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
+               return 0;
+
+       reiserfs_read_lock_xattrs(inode->i_sb);
+       dir = open_xa_dir(inode, FL_READONLY);
+       reiserfs_read_unlock_xattrs(inode->i_sb);
+       if (IS_ERR(dir)) {
+               err = PTR_ERR(dir);
+               goto out;
+       } else if (!dir->d_inode) {
+               dput(dir);
+               return 0;
+       }
+
+       lock_kernel();
+       err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
+       if (err) {
+               unlock_kernel();
+               goto out_dir;
+       }
+
+       /* Leftovers besides . and .. -- that's not good. */
+       if (dir->d_inode->i_nlink <= 2) {
+               root = get_xa_root(inode->i_sb, XATTR_REPLACE);
+               reiserfs_write_lock_xattrs(inode->i_sb);
+               err = vfs_rmdir(root->d_inode, dir);
+               reiserfs_write_unlock_xattrs(inode->i_sb);
+               dput(root);
+       } else {
+               reiserfs_warning(inode->i_sb, "jdm-20006",
+                                "Couldn't remove all entries in directory");
+       }
+       unlock_kernel();
+
+out_dir:
+       dput(dir);
+
+out:
+       if (!err)
+               REISERFS_I(inode)->i_flags =
+                   REISERFS_I(inode)->i_flags & ~i_has_xattr_dir;
+       return err;
+}
+
+struct reiserfs_chown_buf {
+       struct inode *inode;
+       struct dentry *xadir;
+       struct iattr *attrs;
+};
+
+/* XXX: If there is a better way to do this, I'd love to hear about it */
+static int
+reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen,
+                            loff_t offset, u64 ino, unsigned int d_type)
+{
+       struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf;
+       struct dentry *xafile, *xadir = chown_buf->xadir;
+       struct iattr *attrs = chown_buf->attrs;
+       int err = 0;
+
+       xafile = lookup_one_len(name, xadir, namelen);
+       if (IS_ERR(xafile))
+               return PTR_ERR(xafile);
+       else if (!xafile->d_inode) {
+               dput(xafile);
+               return -ENODATA;
+       }
+
+       if (!S_ISDIR(xafile->d_inode->i_mode))
+               err = notify_change(xafile, attrs);
+       dput(xafile);
+
+       return err;
+}
+
+int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
+{
+       struct dentry *dir;
+       int err = 0;
+       struct reiserfs_chown_buf buf;
+       unsigned int ia_valid = attrs->ia_valid;
+
+       /* Skip out, an xattr has no xattrs associated with it */
+       if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
+               return 0;
+
+       reiserfs_read_lock_xattrs(inode->i_sb);
+       dir = open_xa_dir(inode, FL_READONLY);
+       reiserfs_read_unlock_xattrs(inode->i_sb);
+       if (IS_ERR(dir)) {
+               if (PTR_ERR(dir) != -ENODATA)
+                       err = PTR_ERR(dir);
+               goto out;
+       } else if (!dir->d_inode) {
+               dput(dir);
+               goto out;
+       }
+
+       lock_kernel();
+
+       attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
+       buf.xadir = dir;
+       buf.attrs = attrs;
+       buf.inode = inode;
+
+       err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
+       if (err) {
+               unlock_kernel();
+               goto out_dir;
+       }
+
+       err = notify_change(dir, attrs);
+       unlock_kernel();
+
+out_dir:
+       dput(dir);
+
+out:
+       attrs->ia_valid = ia_valid;
+       return err;
+}
+
+#ifdef CONFIG_REISERFS_FS_XATTR
+static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
+                                                               *prefix);
+
+/* 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)
+{
+       struct dentry *xadir, *xafile;
+       int err = 0;
+
+       xadir = open_xa_dir(inode, flags);
+       if (IS_ERR(xadir)) {
+               return ERR_CAST(xadir);
+       } else if (xadir && !xadir->d_inode) {
+               dput(xadir);
+               return ERR_PTR(-ENODATA);
+       }
+
+       xafile = lookup_one_len(name, xadir, strlen(name));
+       if (IS_ERR(xafile)) {
+               dput(xadir);
+               return ERR_CAST(xafile);
+       }
+
+       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);
+
+               if (err) {
+                       dput(xafile);
+                       goto out;
+               }
+       }
+
+out:
+       dput(xadir);
+       if (err)
+               xafile = ERR_PTR(err);
+       else if (!xafile->d_inode) {
+               dput(xafile);
+               xafile = ERR_PTR(-ENODATA);
+       }
+       return xafile;
+}
+
 /* Internal operations on file data */
 static inline void reiserfs_put_page(struct page *page)
 {
@@ -554,274 +742,85 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
                goto out_dput;
        }
 
-       while (file_pos < isize) {
-               size_t chunk;
-               char *data;
-               size_t skip = 0;
-               if (isize - file_pos > PAGE_CACHE_SIZE)
-                       chunk = PAGE_CACHE_SIZE;
-               else
-                       chunk = isize - file_pos;
-
-               page = reiserfs_get_page(dentry->d_inode, file_pos);
-               if (IS_ERR(page)) {
-                       err = PTR_ERR(page);
-                       goto out_dput;
-               }
-
-               lock_page(page);
-               data = page_address(page);
-               if (file_pos == 0) {
-                       struct reiserfs_xattr_header *rxh =
-                           (struct reiserfs_xattr_header *)data;
-                       skip = file_pos = sizeof(struct reiserfs_xattr_header);
-                       chunk -= skip;
-                       /* Magic doesn't match up.. */
-                       if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) {
-                               unlock_page(page);
-                               reiserfs_put_page(page);
-                               reiserfs_warning(inode->i_sb, "jdm-20001",
-                                                "Invalid magic for xattr (%s) "
-                                                "associated with %k", name,
-                                                INODE_PKEY(inode));
-                               err = -EIO;
-                               goto out_dput;
-                       }
-                       hash = le32_to_cpu(rxh->h_hash);
-               }
-               memcpy(buffer + buffer_pos, data + skip, chunk);
-               unlock_page(page);
-               reiserfs_put_page(page);
-               file_pos += chunk;
-               buffer_pos += chunk;
-               skip = 0;
-       }
-       err = isize - sizeof(struct reiserfs_xattr_header);
-
-       if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) !=
-           hash) {
-               reiserfs_warning(inode->i_sb, "jdm-20002",
-                                "Invalid hash for xattr (%s) associated "
-                                "with %k", name, INODE_PKEY(inode));
-               err = -EIO;
-       }
-
-      out_dput:
-       dput(dentry);
-
-      out:
-       return err;
-}
-
-static int
-__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
-{
-       struct dentry *dentry;
-       struct inode *dir = xadir->d_inode;
-       int err = 0;
-
-       dentry = lookup_one_len(name, xadir, namelen);
-       if (IS_ERR(dentry)) {
-               err = PTR_ERR(dentry);
-               goto out;
-       } else if (!dentry->d_inode) {
-               err = -ENODATA;
-               goto out_file;
-       }
-
-       /* Skip directories.. */
-       if (S_ISDIR(dentry->d_inode->i_mode))
-               goto out_file;
-
-       if (!IS_PRIVATE(dentry->d_inode)) {
-               reiserfs_error(dir->i_sb, "jdm-20003",
-                              "OID %08x [%.*s/%.*s] doesn't have "
-                              "priv flag set [parent is %sset].",
-                              le32_to_cpu(INODE_PKEY(dentry->d_inode)->
-                                          k_objectid), xadir->d_name.len,
-                              xadir->d_name.name, namelen, name,
-                              IS_PRIVATE(xadir->d_inode) ? "" :
-                              "not ");
-               dput(dentry);
-               return -EIO;
-       }
-
-       err = dir->i_op->unlink(dir, dentry);
-       if (!err)
-               d_delete(dentry);
-
-      out_file:
-       dput(dentry);
-
-      out:
-       return err;
-}
-
-int reiserfs_xattr_del(struct inode *inode, const char *name)
-{
-       struct dentry *dir;
-       int err;
-
-       dir = open_xa_dir(inode, FL_READONLY);
-       if (IS_ERR(dir)) {
-               err = PTR_ERR(dir);
-               goto out;
-       }
-
-       err = __reiserfs_xattr_del(dir, name, strlen(name));
-       dput(dir);
-
-       if (!err) {
-               inode->i_ctime = CURRENT_TIME_SEC;
-               mark_inode_dirty(inode);
-       }
-
-      out:
-       return err;
-}
-
-/* The following are side effects of other operations that aren't explicitly
- * modifying extended attributes. This includes operations such as permissions
- * or ownership changes, object deletions, etc. */
-
-static int
-reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
-                             loff_t offset, u64 ino, unsigned int d_type)
-{
-       struct dentry *xadir = (struct dentry *)buf;
-
-       return __reiserfs_xattr_del(xadir, name, namelen);
-
-}
-
-/* This is called w/ inode->i_mutex downed */
-int reiserfs_delete_xattrs(struct inode *inode)
-{
-       struct dentry *dir, *root;
-       int err = 0;
-
-       /* Skip out, an xattr has no xattrs associated with it */
-       if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1 ||
-           !reiserfs_xattrs(inode->i_sb)) {
-               return 0;
-       }
-       reiserfs_read_lock_xattrs(inode->i_sb);
-       dir = open_xa_dir(inode, FL_READONLY);
-       reiserfs_read_unlock_xattrs(inode->i_sb);
-       if (IS_ERR(dir)) {
-               err = PTR_ERR(dir);
-               goto out;
-       } else if (!dir->d_inode) {
-               dput(dir);
-               return 0;
-       }
-
-       lock_kernel();
-       err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
-       if (err) {
-               unlock_kernel();
-               goto out_dir;
-       }
-
-       /* Leftovers besides . and .. -- that's not good. */
-       if (dir->d_inode->i_nlink <= 2) {
-               root = get_xa_root(inode->i_sb, XATTR_REPLACE);
-               reiserfs_write_lock_xattrs(inode->i_sb);
-               err = vfs_rmdir(root->d_inode, dir);
-               reiserfs_write_unlock_xattrs(inode->i_sb);
-               dput(root);
-       } else {
-               reiserfs_warning(inode->i_sb, "jdm-20006",
-                                "Couldn't remove all entries in directory");
-       }
-       unlock_kernel();
-
-      out_dir:
-       dput(dir);
-
-      out:
-       if (!err)
-               REISERFS_I(inode)->i_flags =
-                   REISERFS_I(inode)->i_flags & ~i_has_xattr_dir;
-       return err;
-}
+       while (file_pos < isize) {
+               size_t chunk;
+               char *data;
+               size_t skip = 0;
+               if (isize - file_pos > PAGE_CACHE_SIZE)
+                       chunk = PAGE_CACHE_SIZE;
+               else
+                       chunk = isize - file_pos;
 
-struct reiserfs_chown_buf {
-       struct inode *inode;
-       struct dentry *xadir;
-       struct iattr *attrs;
-};
+               page = reiserfs_get_page(dentry->d_inode, file_pos);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       goto out_dput;
+               }
 
-/* XXX: If there is a better way to do this, I'd love to hear about it */
-static int
-reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen,
-                            loff_t offset, u64 ino, unsigned int d_type)
-{
-       struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf;
-       struct dentry *xafile, *xadir = chown_buf->xadir;
-       struct iattr *attrs = chown_buf->attrs;
-       int err = 0;
+               lock_page(page);
+               data = page_address(page);
+               if (file_pos == 0) {
+                       struct reiserfs_xattr_header *rxh =
+                           (struct reiserfs_xattr_header *)data;
+                       skip = file_pos = sizeof(struct reiserfs_xattr_header);
+                       chunk -= skip;
+                       /* Magic doesn't match up.. */
+                       if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) {
+                               unlock_page(page);
+                               reiserfs_put_page(page);
+                               reiserfs_warning(inode->i_sb, "jdm-20001",
+                                                "Invalid magic for xattr (%s) "
+                                                "associated with %k", name,
+                                                INODE_PKEY(inode));
+                               err = -EIO;
+                               goto out_dput;
+                       }
+                       hash = le32_to_cpu(rxh->h_hash);
+               }
+               memcpy(buffer + buffer_pos, data + skip, chunk);
+               unlock_page(page);
+               reiserfs_put_page(page);
+               file_pos += chunk;
+               buffer_pos += chunk;
+               skip = 0;
+       }
+       err = isize - sizeof(struct reiserfs_xattr_header);
 
-       xafile = lookup_one_len(name, xadir, namelen);
-       if (IS_ERR(xafile))
-               return PTR_ERR(xafile);
-       else if (!xafile->d_inode) {
-               dput(xafile);
-               return -ENODATA;
+       if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) !=
+           hash) {
+               reiserfs_warning(inode->i_sb, "jdm-20002",
+                                "Invalid hash for xattr (%s) associated "
+                                "with %k", name, INODE_PKEY(inode));
+               err = -EIO;
        }
 
-       if (!S_ISDIR(xafile->d_inode->i_mode))
-               err = notify_change(xafile, attrs);
-       dput(xafile);
+out_dput:
+       dput(dentry);
 
+out:
        return err;
 }
 
-int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
+int reiserfs_xattr_del(struct inode *inode, const char *name)
 {
        struct dentry *dir;
-       int err = 0;
-       struct reiserfs_chown_buf buf;
-       unsigned int ia_valid = attrs->ia_valid;
+       int err;
 
-       /* Skip out, an xattr has no xattrs associated with it */
-       if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1 ||
-           !reiserfs_xattrs(inode->i_sb)) {
-               return 0;
-       }
-       reiserfs_read_lock_xattrs(inode->i_sb);
        dir = open_xa_dir(inode, FL_READONLY);
-       reiserfs_read_unlock_xattrs(inode->i_sb);
        if (IS_ERR(dir)) {
-               if (PTR_ERR(dir) != -ENODATA)
-                       err = PTR_ERR(dir);
-               goto out;
-       } else if (!dir->d_inode) {
-               dput(dir);
+               err = PTR_ERR(dir);
                goto out;
        }
 
-       lock_kernel();
-
-       attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
-       buf.xadir = dir;
-       buf.attrs = attrs;
-       buf.inode = inode;
+       err = __reiserfs_xattr_del(dir, name, strlen(name));
+       dput(dir);
 
-       err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
-       if (err) {
-               unlock_kernel();
-               goto out_dir;
+       if (!err) {
+               inode->i_ctime = CURRENT_TIME_SEC;
+               mark_inode_dirty(inode);
        }
 
-       err = notify_change(dir, attrs);
-       unlock_kernel();
-
-      out_dir:
-       dput(dir);
-
       out:
-       attrs->ia_valid = ia_valid;
        return err;
 }
 
@@ -1101,6 +1100,94 @@ void reiserfs_xattr_unregister_handlers(void)
        write_unlock(&handler_lock);
 }
 
+static int reiserfs_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl;
+       int error = -EAGAIN; /* do regular unix permission checks by default */
+
+       reiserfs_read_lock_xattr_i(inode);
+       reiserfs_read_lock_xattrs(inode->i_sb);
+
+       acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
+
+       reiserfs_read_unlock_xattrs(inode->i_sb);
+       reiserfs_read_unlock_xattr_i(inode);
+
+       if (acl) {
+               if (!IS_ERR(acl)) {
+                       error = posix_acl_permission(inode, acl, mask);
+                       posix_acl_release(acl);
+               } else if (PTR_ERR(acl) != -ENODATA)
+                       error = PTR_ERR(acl);
+       }
+
+       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;
+       struct inode *inode = dentry->d_parent->d_inode;
+       mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
+       err = inode->i_op->mkdir(inode, dentry, 0700);
+       mutex_unlock(&inode->i_mutex);
+       if (err) {
+               dput(dentry);
+               dentry = NULL;
+       }
+
+       if (dentry && dentry->d_inode)
+               reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
+                             "storage.\n", PRIVROOT_NAME);
+
+       return err;
+}
+
+static int xattr_mount_check(struct super_block *s)
+{
+       /* We need generation numbers to ensure that the oid mapping is correct
+        * v3.5 filesystems don't have them. */
+       if (!old_format_only(s)) {
+               set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
+       } else if (reiserfs_xattrs_optional(s)) {
+               /* Old format filesystem, but optional xattrs have been enabled
+                * at mount time. Error out. */
+               reiserfs_warning(s, "jdm-20005",
+                                "xattrs/ACLs not supported on pre v3.6 "
+                                "format filesystem. Failing mount.");
+               return -EOPNOTSUPP;
+       } else {
+               /* Old format filesystem, but no optional xattrs have
+                * been enabled. This means we silently disable xattrs
+                * on the filesystem. */
+               clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
+       }
+
+       return 0;
+}
+
+#else
+int __init reiserfs_xattr_register_handlers(void) { return 0; }
+void reiserfs_xattr_unregister_handlers(void) {}
+#endif
+
 /* This will catch lookups from the fs root to .reiserfs_priv */
 static int
 xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
@@ -1127,47 +1214,23 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
 {
        int err = 0;
 
-       /* We need generation numbers to ensure that the oid mapping is correct
-        * v3.5 filesystems don't have them. */
-       if (!old_format_only(s)) {
-               set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
-       } else if (reiserfs_xattrs_optional(s)) {
-               /* Old format filesystem, but optional xattrs have been enabled
-                * at mount time. Error out. */
-               reiserfs_warning(s, "jdm-20005",
-                                "xattrs/ACLs not supported on pre v3.6 "
-                                "format filesystem. Failing mount.");
-               err = -EOPNOTSUPP;
+#ifdef CONFIG_REISERFS_FS_XATTR
+       err = xattr_mount_check(s);
+       if (err)
                goto error;
-       } else {
-               /* Old format filesystem, but no optional xattrs have been enabled. This
-                * means we silently disable xattrs on the filesystem. */
-               clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
-       }
+#endif
 
        /* If we don't have the privroot located yet - go find it */
-       if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) {
+       if (!REISERFS_SB(s)->priv_root) {
                struct dentry *dentry;
                dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
                                        strlen(PRIVROOT_NAME));
                if (!IS_ERR(dentry)) {
-                       if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
-                               struct inode *inode = dentry->d_parent->d_inode;
-                               mutex_lock_nested(&inode->i_mutex,
-                                                 I_MUTEX_XATTR);
-                               err = inode->i_op->mkdir(inode, dentry, 0700);
-                               mutex_unlock(&inode->i_mutex);
-                               if (err) {
-                                       dput(dentry);
-                                       dentry = NULL;
-                               }
-
-                               if (dentry && dentry->d_inode)
-                                       reiserfs_info(s, "Created %s - "
-                                                     "reserved for xattr "
-                                                     "storage.\n",
-                                                     PRIVROOT_NAME);
-                       } else if (!dentry->d_inode) {
+#ifdef CONFIG_REISERFS_FS_XATTR
+                       if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
+                               err = create_privroot(dentry);
+#endif
+                       if (!dentry->d_inode) {
                                dput(dentry);
                                dentry = NULL;
                        }
@@ -1178,73 +1241,37 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
                        s->s_root->d_op = &xattr_lookup_poison_ops;
                        dentry->d_inode->i_flags |= S_PRIVATE;
                        REISERFS_SB(s)->priv_root = dentry;
-               } else if (!(mount_flags & MS_RDONLY)) {        /* xattrs are unavailable */
-                       /* If we're read-only it just means that the dir hasn't been
-                        * created. Not an error -- just no xattrs on the fs. We'll
-                        * check again if we go read-write */
+#ifdef CONFIG_REISERFS_FS_XATTR
+               /* xattrs are unavailable */
+               } else if (!(mount_flags & MS_RDONLY)) {
+                       /* If we're read-only it just means that the dir
+                        * hasn't been created. Not an error -- just no
+                        * xattrs on the fs. We'll check again if we
+                        * go read-write */
                        reiserfs_warning(s, "jdm-20006",
                                         "xattrs/ACLs enabled and couldn't "
                                         "find/create .reiserfs_priv. "
                                         "Failing mount.");
                        err = -EOPNOTSUPP;
+#endif
                }
        }
 
-      error:
-       /* This is only nonzero if there was an error initializing the xattr
-        * directory or if there is a condition where we don't support them. */
+#ifdef CONFIG_REISERFS_FS_XATTR
+error:
        if (err) {
                clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
                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
 
        return err;
 }
-
-static int reiserfs_check_acl(struct inode *inode, int mask)
-{
-       struct posix_acl *acl;
-       int error = -EAGAIN; /* do regular unix permission checks by default */
-
-       reiserfs_read_lock_xattr_i(inode);
-       reiserfs_read_lock_xattrs(inode->i_sb);
-
-       acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-
-       reiserfs_read_unlock_xattrs(inode->i_sb);
-       reiserfs_read_unlock_xattr_i(inode);
-
-       if (acl) {
-               if (!IS_ERR(acl)) {
-                       error = posix_acl_permission(inode, acl, mask);
-                       posix_acl_release(acl);
-               } else if (PTR_ERR(acl) != -ENODATA)
-                       error = PTR_ERR(acl);
-       }
-
-       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);
-}
This page took 0.034145 seconds and 5 git commands to generate.