update from rk29 server
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / acl.c
index 36160424427124947179e7270bfb77e03dbc1686..12d7be8df561dfd93c0a3c86f7c6c7f44887dab8 100644 (file)
@@ -94,7 +94,8 @@ static int btrfs_xattr_get_acl(struct inode *inode, int type,
 /*
  * Needs to be called with fs_mutex held
  */
-static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+static int btrfs_set_acl(struct btrfs_trans_handle *trans,
+                        struct inode *inode, struct posix_acl *acl, int type)
 {
        int ret, size = 0;
        const char *name;
@@ -111,12 +112,14 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        switch (type) {
        case ACL_TYPE_ACCESS:
                mode = inode->i_mode;
-               ret = posix_acl_equiv_mode(acl, &mode);
-               if (ret < 0)
-                       return ret;
-               ret = 0;
-               inode->i_mode = mode;
                name = POSIX_ACL_XATTR_ACCESS;
+               if (acl) {
+                       ret = posix_acl_equiv_mode(acl, &mode);
+                       if (ret < 0)
+                               return ret;
+                       inode->i_mode = mode;
+               }
+               ret = 0;
                break;
        case ACL_TYPE_DEFAULT:
                if (!S_ISDIR(inode->i_mode))
@@ -140,8 +143,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                        goto out;
        }
 
-       ret = __btrfs_setxattr(inode, name, value, size, 0);
-
+       ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
 out:
        kfree(value);
 
@@ -154,9 +156,12 @@ out:
 static int btrfs_xattr_set_acl(struct inode *inode, int type,
                               const void *value, size_t size)
 {
-       int ret = 0;
+       int ret;
        struct posix_acl *acl = NULL;
 
+       if (!is_owner_or_cap(inode))
+               return -EPERM;
+
        if (value) {
                acl = posix_acl_from_xattr(value, size);
                if (acl == NULL) {
@@ -167,7 +172,7 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type,
                }
        }
 
-       ret = btrfs_set_acl(inode, acl, type);
+       ret = btrfs_set_acl(NULL, inode, acl, type);
 
        posix_acl_release(acl);
 
@@ -221,7 +226,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
  * stuff has been fixed to work with that.  If the locking stuff changes, we
  * need to re-evaluate the acl locking stuff.
  */
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                  struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
        int ret = 0;
@@ -246,7 +252,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
                mode_t mode;
 
                if (S_ISDIR(inode->i_mode)) {
-                       ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
+                       ret = btrfs_set_acl(trans, inode, acl,
+                                           ACL_TYPE_DEFAULT);
                        if (ret)
                                goto failed;
                }
@@ -261,10 +268,11 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
                        inode->i_mode = mode;
                        if (ret > 0) {
                                /* we need an acl */
-                               ret = btrfs_set_acl(inode, clone,
+                               ret = btrfs_set_acl(trans, inode, clone,
                                                    ACL_TYPE_ACCESS);
                        }
                }
+               posix_acl_release(clone);
        }
 failed:
        posix_acl_release(acl);
@@ -294,7 +302,7 @@ int btrfs_acl_chmod(struct inode *inode)
 
        ret = posix_acl_chmod_masq(clone, inode->i_mode);
        if (!ret)
-               ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);
+               ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
 
        posix_acl_release(clone);
 
@@ -320,7 +328,8 @@ int btrfs_acl_chmod(struct inode *inode)
        return 0;
 }
 
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                  struct inode *inode, struct inode *dir)
 {
        return 0;
 }