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 30 static 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 41 struct 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 67 static int gfs2_set_mode(struct inode *inode, umode_t mode) 68 { 69 int error = 0; 70 71 if (mode != inode->i_mode) { 72 inode->i_mode = mode; 73 mark_inode_dirty(inode); 74 } 75 76 return error; 77 } 78 79 int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 80 { 81 int error; 82 int len; 83 char *data; 84 const char *name = gfs2_acl_name(type); 85 86 BUG_ON(name == NULL); 87 88 if (acl->a_count > GFS2_ACL_MAX_ENTRIES) 89 return -EINVAL; 90 91 if (type == ACL_TYPE_ACCESS) { 92 umode_t mode = inode->i_mode; 93 94 error = posix_acl_equiv_mode(acl, &mode); 95 if (error < 0) 96 return error; 97 98 if (error == 0) 99 acl = NULL; 100 101 error = gfs2_set_mode(inode, mode); 102 if (error) 103 return error; 104 } 105 106 if (acl) { 107 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 108 if (len == 0) 109 return 0; 110 data = kmalloc(len, GFP_NOFS); 111 if (data == NULL) 112 return -ENOMEM; 113 error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 114 if (error < 0) 115 goto out; 116 } else { 117 data = NULL; 118 len = 0; 119 } 120 121 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 122 if (error) 123 goto out; 124 125 if (acl) 126 set_cached_acl(inode, type, acl); 127 else 128 forget_cached_acl(inode, type); 129 out: 130 kfree(data); 131 return error; 132 } 133