LCOV - code coverage report
Current view: top level - fs/btrfs - acl.c (source / functions) Hit Total Coverage
Test: btrfstest.info Lines: 33 50 66.0 %
Date: 2014-11-28 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2007 Red Hat.  All rights reserved.
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU General Public
       6             :  * License v2 as published by the Free Software Foundation.
       7             :  *
       8             :  * This program is distributed in the hope that it will be useful,
       9             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      10             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      11             :  * General Public License for more details.
      12             :  *
      13             :  * You should have received a copy of the GNU General Public
      14             :  * License along with this program; if not, write to the
      15             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      16             :  * Boston, MA 021110-1307, USA.
      17             :  */
      18             : 
      19             : #include <linux/fs.h>
      20             : #include <linux/string.h>
      21             : #include <linux/xattr.h>
      22             : #include <linux/posix_acl_xattr.h>
      23             : #include <linux/posix_acl.h>
      24             : #include <linux/sched.h>
      25             : #include <linux/slab.h>
      26             : 
      27             : #include "ctree.h"
      28             : #include "btrfs_inode.h"
      29             : #include "xattr.h"
      30             : 
      31         125 : struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
      32             : {
      33             :         int size;
      34             :         const char *name;
      35             :         char *value = NULL;
      36             :         struct posix_acl *acl;
      37             : 
      38         125 :         switch (type) {
      39             :         case ACL_TYPE_ACCESS:
      40             :                 name = POSIX_ACL_XATTR_ACCESS;
      41             :                 break;
      42             :         case ACL_TYPE_DEFAULT:
      43             :                 name = POSIX_ACL_XATTR_DEFAULT;
      44         103 :                 break;
      45             :         default:
      46           0 :                 BUG();
      47             :         }
      48             : 
      49         125 :         size = __btrfs_getxattr(inode, name, "", 0);
      50         125 :         if (size > 0) {
      51           0 :                 value = kzalloc(size, GFP_NOFS);
      52           0 :                 if (!value)
      53             :                         return ERR_PTR(-ENOMEM);
      54           0 :                 size = __btrfs_getxattr(inode, name, value, size);
      55             :         }
      56         125 :         if (size > 0) {
      57           0 :                 acl = posix_acl_from_xattr(&init_user_ns, value, size);
      58         125 :         } else if (size == -ENOENT || size == -ENODATA || size == 0) {
      59             :                 /* FIXME, who returns -ENOENT?  I think nobody */
      60             :                 acl = NULL;
      61             :         } else {
      62             :                 acl = ERR_PTR(-EIO);
      63             :         }
      64         125 :         kfree(value);
      65             : 
      66         125 :         if (!IS_ERR(acl))
      67         125 :                 set_cached_acl(inode, type, acl);
      68             : 
      69         125 :         return acl;
      70             : }
      71             : 
      72             : /*
      73             :  * Needs to be called with fs_mutex held
      74             :  */
      75          14 : static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
      76             :                          struct inode *inode, struct posix_acl *acl, int type)
      77             : {
      78             :         int ret, size = 0;
      79             :         const char *name;
      80             :         char *value = NULL;
      81             : 
      82          14 :         switch (type) {
      83             :         case ACL_TYPE_ACCESS:
      84             :                 name = POSIX_ACL_XATTR_ACCESS;
      85          14 :                 if (acl) {
      86          14 :                         ret = posix_acl_equiv_mode(acl, &inode->i_mode);
      87          14 :                         if (ret < 0)
      88             :                                 return ret;
      89          14 :                         if (ret == 0)
      90             :                                 acl = NULL;
      91             :                 }
      92             :                 ret = 0;
      93             :                 break;
      94             :         case ACL_TYPE_DEFAULT:
      95           0 :                 if (!S_ISDIR(inode->i_mode))
      96           0 :                         return acl ? -EINVAL : 0;
      97             :                 name = POSIX_ACL_XATTR_DEFAULT;
      98             :                 break;
      99             :         default:
     100             :                 return -EINVAL;
     101             :         }
     102             : 
     103          14 :         if (acl) {
     104           0 :                 size = posix_acl_xattr_size(acl->a_count);
     105           0 :                 value = kmalloc(size, GFP_NOFS);
     106           0 :                 if (!value) {
     107             :                         ret = -ENOMEM;
     108             :                         goto out;
     109             :                 }
     110             : 
     111           0 :                 ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
     112           0 :                 if (ret < 0)
     113             :                         goto out;
     114             :         }
     115             : 
     116          14 :         ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
     117             : out:
     118          14 :         kfree(value);
     119             : 
     120          14 :         if (!ret)
     121          14 :                 set_cached_acl(inode, type, acl);
     122             : 
     123          14 :         return ret;
     124             : }
     125             : 
     126          14 : int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
     127             : {
     128          14 :         return __btrfs_set_acl(NULL, inode, acl, type);
     129             : }
     130             : 
     131             : /*
     132             :  * btrfs_init_acl is already generally called under fs_mutex, so the locking
     133             :  * stuff has been fixed to work with that.  If the locking stuff changes, we
     134             :  * need to re-evaluate the acl locking stuff.
     135             :  */
     136       20423 : int btrfs_init_acl(struct btrfs_trans_handle *trans,
     137             :                    struct inode *inode, struct inode *dir)
     138             : {
     139             :         struct posix_acl *default_acl, *acl;
     140             :         int ret = 0;
     141             : 
     142             :         /* this happens with subvols */
     143       20423 :         if (!dir)
     144             :                 return 0;
     145             : 
     146       20423 :         ret = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
     147       20423 :         if (ret)
     148             :                 return ret;
     149             : 
     150       20423 :         if (default_acl) {
     151           0 :                 ret = __btrfs_set_acl(trans, inode, default_acl,
     152             :                                       ACL_TYPE_DEFAULT);
     153           0 :                 posix_acl_release(default_acl);
     154             :         }
     155             : 
     156       20423 :         if (acl) {
     157           0 :                 if (!ret)
     158           0 :                         ret = __btrfs_set_acl(trans, inode, acl,
     159             :                                               ACL_TYPE_ACCESS);
     160           0 :                 posix_acl_release(acl);
     161             :         }
     162             : 
     163       20423 :         if (!default_acl && !acl)
     164             :                 cache_no_acl(inode);
     165       20423 :         return ret;
     166             : }

Generated by: LCOV version 1.10