LCOV - code coverage report
Current view: top level - fs/btrfs - acl.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 53 58 91.4 %
Date: 2023-07-31 20:08:34 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2007 Red Hat.  All rights reserved.
       4             :  */
       5             : 
       6             : #include <linux/fs.h>
       7             : #include <linux/string.h>
       8             : #include <linux/xattr.h>
       9             : #include <linux/posix_acl_xattr.h>
      10             : #include <linux/posix_acl.h>
      11             : #include <linux/sched.h>
      12             : #include <linux/sched/mm.h>
      13             : #include <linux/slab.h>
      14             : #include "ctree.h"
      15             : #include "btrfs_inode.h"
      16             : #include "xattr.h"
      17             : #include "acl.h"
      18             : 
      19        1356 : struct posix_acl *btrfs_get_acl(struct inode *inode, int type, bool rcu)
      20             : {
      21        1356 :         int size;
      22        1356 :         const char *name;
      23        1356 :         char *value = NULL;
      24        1356 :         struct posix_acl *acl;
      25             : 
      26        1356 :         if (rcu)
      27             :                 return ERR_PTR(-ECHILD);
      28             : 
      29        1356 :         switch (type) {
      30             :         case ACL_TYPE_ACCESS:
      31             :                 name = XATTR_NAME_POSIX_ACL_ACCESS;
      32             :                 break;
      33        1174 :         case ACL_TYPE_DEFAULT:
      34        1174 :                 name = XATTR_NAME_POSIX_ACL_DEFAULT;
      35        1174 :                 break;
      36             :         default:
      37             :                 return ERR_PTR(-EINVAL);
      38             :         }
      39             : 
      40        1356 :         size = btrfs_getxattr(inode, name, NULL, 0);
      41        1356 :         if (size > 0) {
      42           3 :                 value = kzalloc(size, GFP_KERNEL);
      43           3 :                 if (!value)
      44             :                         return ERR_PTR(-ENOMEM);
      45           3 :                 size = btrfs_getxattr(inode, name, value, size);
      46             :         }
      47        1356 :         if (size > 0)
      48           3 :                 acl = posix_acl_from_xattr(&init_user_ns, value, size);
      49        1353 :         else if (size == -ENODATA || size == 0)
      50             :                 acl = NULL;
      51             :         else
      52           0 :                 acl = ERR_PTR(size);
      53        1356 :         kfree(value);
      54             : 
      55        1356 :         return acl;
      56             : }
      57             : 
      58      958014 : int __btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode,
      59             :                     struct posix_acl *acl, int type)
      60             : {
      61      958014 :         int ret, size = 0;
      62      958014 :         const char *name;
      63      958014 :         char *value = NULL;
      64             : 
      65      958014 :         switch (type) {
      66             :         case ACL_TYPE_ACCESS:
      67             :                 name = XATTR_NAME_POSIX_ACL_ACCESS;
      68             :                 break;
      69       15603 :         case ACL_TYPE_DEFAULT:
      70       15603 :                 if (!S_ISDIR(inode->i_mode))
      71           0 :                         return acl ? -EINVAL : 0;
      72             :                 name = XATTR_NAME_POSIX_ACL_DEFAULT;
      73             :                 break;
      74             :         default:
      75             :                 return -EINVAL;
      76             :         }
      77             : 
      78      958014 :         if (acl) {
      79       34701 :                 unsigned int nofs_flag;
      80             : 
      81       34701 :                 size = posix_acl_xattr_size(acl->a_count);
      82             :                 /*
      83             :                  * We're holding a transaction handle, so use a NOFS memory
      84             :                  * allocation context to avoid deadlock if reclaim happens.
      85             :                  */
      86       34701 :                 nofs_flag = memalloc_nofs_save();
      87       34701 :                 value = kmalloc(size, GFP_KERNEL);
      88       34701 :                 memalloc_nofs_restore(nofs_flag);
      89       34701 :                 if (!value) {
      90           0 :                         ret = -ENOMEM;
      91           0 :                         goto out;
      92             :                 }
      93             : 
      94       34701 :                 ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
      95       32456 :                 if (ret < 0)
      96           0 :                         goto out;
      97             :         }
      98             : 
      99      955769 :         if (trans)
     100       34671 :                 ret = btrfs_setxattr(trans, inode, name, value, size, 0);
     101             :         else
     102      921098 :                 ret = btrfs_setxattr_trans(inode, name, value, size, 0);
     103             : 
     104      965095 : out:
     105      965095 :         kfree(value);
     106             : 
     107      965083 :         if (!ret)
     108      965083 :                 set_cached_acl(inode, type, acl);
     109             : 
     110             :         return ret;
     111             : }
     112             : 
     113      925788 : int btrfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
     114             :                   struct posix_acl *acl, int type)
     115             : {
     116      925788 :         int ret;
     117      925788 :         struct inode *inode = d_inode(dentry);
     118      925788 :         umode_t old_mode = inode->i_mode;
     119             : 
     120      925788 :         if (type == ACL_TYPE_ACCESS && acl) {
     121      908613 :                 ret = posix_acl_update_mode(idmap, inode,
     122             :                                             &inode->i_mode, &acl);
     123      907839 :                 if (ret)
     124             :                         return ret;
     125             :         }
     126      925014 :         ret = __btrfs_set_acl(NULL, inode, acl, type);
     127      930416 :         if (ret)
     128           1 :                 inode->i_mode = old_mode;
     129             :         return ret;
     130             : }

Generated by: LCOV version 1.14