1/* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4 * 5 * This copyrighted material is made available to anyone wishing to use, 6 * modify, copy, or redistribute it subject to the terms and conditions 7 * of the GNU General Public License version 2. 8 */ 9 10#include <linux/sched.h> 11#include <linux/slab.h> 12#include <linux/spinlock.h> 13#include <linux/completion.h> 14#include <linux/buffer_head.h> 15#include <linux/xattr.h> 16#include <linux/posix_acl.h> 17#include <linux/posix_acl_xattr.h> 18#include <linux/gfs2_ondisk.h> 19 20#include "gfs2.h" 21#include "incore.h" 22#include "acl.h" 23#include "xattr.h" 24#include "glock.h" 25#include "inode.h" 26#include "meta_io.h" 27#include "trans.h" 28#include "util.h" 29 30static const char *gfs2_acl_name(int type) 31{ 32 switch (type) { 33 case ACL_TYPE_ACCESS: 34 return GFS2_POSIX_ACL_ACCESS; 35 case ACL_TYPE_DEFAULT: 36 return GFS2_POSIX_ACL_DEFAULT; 37 } 38 return NULL; 39} 40 41struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 42{ 43 struct gfs2_inode *ip = GFS2_I(inode); 44 struct posix_acl *acl; 45 const char *name; 46 char *data; 47 int len; 48 49 if (!ip->i_eattr) 50 return NULL; 51 52 name = gfs2_acl_name(type); 53 if (name == NULL) 54 return ERR_PTR(-EINVAL); 55 56 len = gfs2_xattr_acl_get(ip, name, &data); 57 if (len < 0) 58 return ERR_PTR(len); 59 if (len == 0) 60 return NULL; 61 62 acl = posix_acl_from_xattr(&init_user_ns, data, len); 63 kfree(data); 64 return acl; 65} 66 67int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 68{ 69 int error; 70 int len; 71 char *data; 72 const char *name = gfs2_acl_name(type); 73 74 BUG_ON(name == NULL); 75 76 if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 77 return -E2BIG; 78 79 if (type == ACL_TYPE_ACCESS) { 80 umode_t mode = inode->i_mode; 81 82 error = posix_acl_equiv_mode(acl, &mode); 83 if (error < 0) 84 return error; 85 86 if (error == 0) 87 acl = NULL; 88 89 if (mode != inode->i_mode) { 90 inode->i_mode = mode; 91 mark_inode_dirty(inode); 92 } 93 } 94 95 if (acl) { 96 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 97 if (len == 0) 98 return 0; 99 data = kmalloc(len, GFP_NOFS); 100 if (data == NULL) 101 return -ENOMEM; 102 error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 103 if (error < 0) 104 goto out; 105 } else { 106 data = NULL; 107 len = 0; 108 } 109 110 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 111 if (error) 112 goto out; 113 set_cached_acl(inode, type, acl); 114out: 115 kfree(data); 116 return error; 117} 118