root/fs/btrfs/acl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. btrfs_get_acl
  2. __btrfs_set_acl
  3. btrfs_set_acl
  4. btrfs_init_acl

   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 
  15 #include "ctree.h"
  16 #include "btrfs_inode.h"
  17 #include "xattr.h"
  18 
  19 struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
  20 {
  21         int size;
  22         const char *name;
  23         char *value = NULL;
  24         struct posix_acl *acl;
  25 
  26         switch (type) {
  27         case ACL_TYPE_ACCESS:
  28                 name = XATTR_NAME_POSIX_ACL_ACCESS;
  29                 break;
  30         case ACL_TYPE_DEFAULT:
  31                 name = XATTR_NAME_POSIX_ACL_DEFAULT;
  32                 break;
  33         default:
  34                 return ERR_PTR(-EINVAL);
  35         }
  36 
  37         size = btrfs_getxattr(inode, name, NULL, 0);
  38         if (size > 0) {
  39                 value = kzalloc(size, GFP_KERNEL);
  40                 if (!value)
  41                         return ERR_PTR(-ENOMEM);
  42                 size = btrfs_getxattr(inode, name, value, size);
  43         }
  44         if (size > 0)
  45                 acl = posix_acl_from_xattr(&init_user_ns, value, size);
  46         else if (size == -ENODATA || size == 0)
  47                 acl = NULL;
  48         else
  49                 acl = ERR_PTR(size);
  50         kfree(value);
  51 
  52         return acl;
  53 }
  54 
  55 static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
  56                          struct inode *inode, struct posix_acl *acl, int type)
  57 {
  58         int ret, size = 0;
  59         const char *name;
  60         char *value = NULL;
  61 
  62         switch (type) {
  63         case ACL_TYPE_ACCESS:
  64                 name = XATTR_NAME_POSIX_ACL_ACCESS;
  65                 break;
  66         case ACL_TYPE_DEFAULT:
  67                 if (!S_ISDIR(inode->i_mode))
  68                         return acl ? -EINVAL : 0;
  69                 name = XATTR_NAME_POSIX_ACL_DEFAULT;
  70                 break;
  71         default:
  72                 return -EINVAL;
  73         }
  74 
  75         if (acl) {
  76                 unsigned int nofs_flag;
  77 
  78                 size = posix_acl_xattr_size(acl->a_count);
  79                 /*
  80                  * We're holding a transaction handle, so use a NOFS memory
  81                  * allocation context to avoid deadlock if reclaim happens.
  82                  */
  83                 nofs_flag = memalloc_nofs_save();
  84                 value = kmalloc(size, GFP_KERNEL);
  85                 memalloc_nofs_restore(nofs_flag);
  86                 if (!value) {
  87                         ret = -ENOMEM;
  88                         goto out;
  89                 }
  90 
  91                 ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
  92                 if (ret < 0)
  93                         goto out;
  94         }
  95 
  96         if (trans)
  97                 ret = btrfs_setxattr(trans, inode, name, value, size, 0);
  98         else
  99                 ret = btrfs_setxattr_trans(inode, name, value, size, 0);
 100 
 101 out:
 102         kfree(value);
 103 
 104         if (!ret)
 105                 set_cached_acl(inode, type, acl);
 106 
 107         return ret;
 108 }
 109 
 110 int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 111 {
 112         int ret;
 113         umode_t old_mode = inode->i_mode;
 114 
 115         if (type == ACL_TYPE_ACCESS && acl) {
 116                 ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
 117                 if (ret)
 118                         return ret;
 119         }
 120         ret = __btrfs_set_acl(NULL, inode, acl, type);
 121         if (ret)
 122                 inode->i_mode = old_mode;
 123         return ret;
 124 }
 125 
 126 int btrfs_init_acl(struct btrfs_trans_handle *trans,
 127                    struct inode *inode, struct inode *dir)
 128 {
 129         struct posix_acl *default_acl, *acl;
 130         int ret = 0;
 131 
 132         /* this happens with subvols */
 133         if (!dir)
 134                 return 0;
 135 
 136         ret = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 137         if (ret)
 138                 return ret;
 139 
 140         if (default_acl) {
 141                 ret = __btrfs_set_acl(trans, inode, default_acl,
 142                                       ACL_TYPE_DEFAULT);
 143                 posix_acl_release(default_acl);
 144         }
 145 
 146         if (acl) {
 147                 if (!ret)
 148                         ret = __btrfs_set_acl(trans, inode, acl,
 149                                               ACL_TYPE_ACCESS);
 150                 posix_acl_release(acl);
 151         }
 152 
 153         if (!default_acl && !acl)
 154                 cache_no_acl(inode);
 155         return ret;
 156 }

/* [<][>][^][v][top][bottom][index][help] */