UPSTREAM: clk: rockchip: remove redundant checking of device_node
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / xattr.c
index 9cf20d63cc998777541ce3e527272a1d06a0c157..1fcd7b6e7564defa675b3abe12589473a58e937d 100644 (file)
 #include <linux/rwsem.h>
 #include <linux/xattr.h>
 #include <linux/security.h>
+#include <linux/posix_acl_xattr.h>
 #include "ctree.h"
 #include "btrfs_inode.h"
 #include "transaction.h"
 #include "xattr.h"
 #include "disk-io.h"
+#include "props.h"
 #include "locking.h"
 
 
@@ -109,6 +111,8 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
                                        name, name_len, -1);
                if (!di && (flags & XATTR_REPLACE))
                        ret = -ENODATA;
+               else if (IS_ERR(di))
+                       ret = PTR_ERR(di);
                else if (di)
                        ret = btrfs_delete_one_dir_name(trans, root, path, di);
                goto out;
@@ -122,18 +126,15 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
         * locks the inode's i_mutex before calling setxattr or removexattr.
         */
        if (flags & XATTR_REPLACE) {
-               if(!mutex_is_locked(&inode->i_mutex)) {
-                       pr_err("BTRFS: assertion failed: %s, file: %s, line: %d",
-                              "mutex_is_locked(&inode->i_mutex)", __FILE__,
-                              __LINE__);
-                       BUG();
-               }
+               ASSERT(mutex_is_locked(&inode->i_mutex));
                di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode),
                                        name, name_len, 0);
-               if (!di) {
+               if (!di)
                        ret = -ENODATA;
+               else if (IS_ERR(di))
+                       ret = PTR_ERR(di);
+               if (ret)
                        goto out;
-               }
                btrfs_release_path(path);
                di = NULL;
        }
@@ -156,11 +157,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
        } else if (ret == -EEXIST) {
                ret = 0;
                di = btrfs_match_dir_item_name(root, path, name, name_len);
-               if(!di) { /* logic error */
-                       pr_err("BTRFS: assertion failed: %s, file: %s, line: %d",
-                              "di", __FILE__, __LINE__);
-                       BUG();
-               }
+               ASSERT(di); /* logic error */
        } else if (ret) {
                goto out;
        }
@@ -210,7 +207,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
                        btrfs_extend_item(root, path, data_size);
                }
 
-               item = btrfs_item_nr(NULL, slot);
+               item = btrfs_item_nr(slot);
                ptr = btrfs_item_ptr(leaf, slot, char);
                ptr += btrfs_item_size(leaf, item) - data_size;
                di = (struct btrfs_dir_item *)ptr;
@@ -264,7 +261,7 @@ out:
 ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
        struct btrfs_key key, found_key;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
@@ -280,7 +277,7 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
         * first xattr that we find and walk forward
         */
        key.objectid = btrfs_ino(inode);
-       btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
+       key.type = BTRFS_XATTR_ITEM_KEY;
        key.offset = 0;
 
        path = btrfs_alloc_path();
@@ -316,8 +313,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                /* check to make sure this item is what we want */
                if (found_key.objectid != key.objectid)
                        break;
-               if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
+               if (found_key.type > BTRFS_XATTR_ITEM_KEY)
                        break;
+               if (found_key.type < BTRFS_XATTR_ITEM_KEY)
+                       goto next;
 
                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
                if (verify_dir_item(root, leaf, di))
@@ -358,8 +357,8 @@ err:
  */
 const struct xattr_handler *btrfs_xattr_handlers[] = {
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
-       &btrfs_xattr_acl_access_handler,
-       &btrfs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL,
 };
@@ -367,21 +366,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
 /*
  * Check if the attribute is in a supported namespace.
  *
- * This applied after the check for the synthetic attributes in the system
+ * This is applied after the check for the synthetic attributes in the system
  * namespace.
  */
-static bool btrfs_is_valid_xattr(const char *name)
+static int btrfs_is_valid_xattr(const char *name)
 {
-       return !strncmp(name, XATTR_SECURITY_PREFIX,
-                       XATTR_SECURITY_PREFIX_LEN) ||
-              !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
-              !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
-              !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+       int len = strlen(name);
+       int prefixlen = 0;
+
+       if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                       XATTR_SECURITY_PREFIX_LEN))
+               prefixlen = XATTR_SECURITY_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               prefixlen = XATTR_SYSTEM_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+               prefixlen = XATTR_TRUSTED_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+               prefixlen = XATTR_USER_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+               prefixlen = XATTR_BTRFS_PREFIX_LEN;
+       else
+               return -EOPNOTSUPP;
+
+       /*
+        * The name cannot consist of just prefix
+        */
+       if (len <= prefixlen)
+               return -EINVAL;
+
+       return 0;
 }
 
 ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
                       void *buffer, size_t size)
 {
+       int ret;
+
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -390,15 +410,17 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_getxattr(dentry, name, buffer, size);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
-       return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
+       return __btrfs_getxattr(d_inode(dentry), name, buffer, size);
 }
 
 int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                   size_t size, int flags)
 {
-       struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -415,19 +437,25 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_setxattr(dentry, name, value, size, flags);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
+
+       if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+               return btrfs_set_prop(d_inode(dentry), name,
+                                     value, size, flags);
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
 
-       return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+       return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size,
                                flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
 {
-       struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -444,10 +472,15 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_removexattr(dentry, name);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
+
+       if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+               return btrfs_set_prop(d_inode(dentry), name,
+                                     NULL, 0, XATTR_REPLACE);
 
-       return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+       return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0,
                                XATTR_REPLACE);
 }