1b3b94faaSDavid Teigland /* 2b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 33a8a9a10SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4b3b94faaSDavid Teigland * 5b3b94faaSDavid Teigland * This copyrighted material is made available to anyone wishing to use, 6b3b94faaSDavid Teigland * modify, copy, or redistribute it subject to the terms and conditions 7e9fc2aa0SSteven Whitehouse * of the GNU General Public License version 2. 8b3b94faaSDavid Teigland */ 9b3b94faaSDavid Teigland 10b3b94faaSDavid Teigland #include <linux/sched.h> 11b3b94faaSDavid Teigland #include <linux/slab.h> 12b3b94faaSDavid Teigland #include <linux/spinlock.h> 13b3b94faaSDavid Teigland #include <linux/completion.h> 14b3b94faaSDavid Teigland #include <linux/buffer_head.h> 152646a1f6SSteven Whitehouse #include <linux/xattr.h> 16b3b94faaSDavid Teigland #include <linux/posix_acl.h> 17b3b94faaSDavid Teigland #include <linux/posix_acl_xattr.h> 185c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h> 19b3b94faaSDavid Teigland 20b3b94faaSDavid Teigland #include "gfs2.h" 215c676f6dSSteven Whitehouse #include "incore.h" 22b3b94faaSDavid Teigland #include "acl.h" 23307cf6e6SSteven Whitehouse #include "xattr.h" 24b3b94faaSDavid Teigland #include "glock.h" 25b3b94faaSDavid Teigland #include "inode.h" 26b3b94faaSDavid Teigland #include "meta_io.h" 27b3b94faaSDavid Teigland #include "trans.h" 285c676f6dSSteven Whitehouse #include "util.h" 29b3b94faaSDavid Teigland 30479c427dSSteven Whitehouse static const char *gfs2_acl_name(int type) 31b3b94faaSDavid Teigland { 32479c427dSSteven Whitehouse switch (type) { 33479c427dSSteven Whitehouse case ACL_TYPE_ACCESS: 34479c427dSSteven Whitehouse return GFS2_POSIX_ACL_ACCESS; 35479c427dSSteven Whitehouse case ACL_TYPE_DEFAULT: 36479c427dSSteven Whitehouse return GFS2_POSIX_ACL_DEFAULT; 37479c427dSSteven Whitehouse } 38479c427dSSteven Whitehouse return NULL; 39479c427dSSteven Whitehouse } 40b3b94faaSDavid Teigland 41018a01cdSSteven Whitehouse struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 42479c427dSSteven Whitehouse { 43018a01cdSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode); 44479c427dSSteven Whitehouse struct posix_acl *acl; 45479c427dSSteven Whitehouse const char *name; 46479c427dSSteven Whitehouse char *data; 47479c427dSSteven Whitehouse int len; 4840b78a32SSteven Whitehouse 493767ac21SSteven Whitehouse if (!ip->i_eattr) 50479c427dSSteven Whitehouse return NULL; 51b3b94faaSDavid Teigland 52479c427dSSteven Whitehouse name = gfs2_acl_name(type); 53479c427dSSteven Whitehouse if (name == NULL) 54479c427dSSteven Whitehouse return ERR_PTR(-EINVAL); 55b3b94faaSDavid Teigland 56479c427dSSteven Whitehouse len = gfs2_xattr_acl_get(ip, name, &data); 57479c427dSSteven Whitehouse if (len < 0) 58479c427dSSteven Whitehouse return ERR_PTR(len); 59479c427dSSteven Whitehouse if (len == 0) 60479c427dSSteven Whitehouse return NULL; 61b3b94faaSDavid Teigland 625f3a4a28SEric W. Biederman acl = posix_acl_from_xattr(&init_user_ns, data, len); 6340b78a32SSteven Whitehouse kfree(data); 64479c427dSSteven Whitehouse return acl; 65b3b94faaSDavid Teigland } 66b3b94faaSDavid Teigland 67e01580bfSChristoph Hellwig int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 68b3b94faaSDavid Teigland { 69b3b94faaSDavid Teigland int error; 70479c427dSSteven Whitehouse int len; 71479c427dSSteven Whitehouse char *data; 72479c427dSSteven Whitehouse const char *name = gfs2_acl_name(type); 73479c427dSSteven Whitehouse 74479c427dSSteven Whitehouse BUG_ON(name == NULL); 75e01580bfSChristoph Hellwig 76b00263d1SBob Peterson if (acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 77f2113eb8SJie Liu return -E2BIG; 78e01580bfSChristoph Hellwig 79e01580bfSChristoph Hellwig if (type == ACL_TYPE_ACCESS) { 80e01580bfSChristoph Hellwig umode_t mode = inode->i_mode; 81e01580bfSChristoph Hellwig 82e01580bfSChristoph Hellwig error = posix_acl_equiv_mode(acl, &mode); 83e01580bfSChristoph Hellwig if (error < 0) 84e01580bfSChristoph Hellwig return error; 85e01580bfSChristoph Hellwig 86e01580bfSChristoph Hellwig if (error == 0) 87e01580bfSChristoph Hellwig acl = NULL; 88e01580bfSChristoph Hellwig 89733dbc1bSBob Peterson if (mode != inode->i_mode) { 90733dbc1bSBob Peterson inode->i_mode = mode; 91733dbc1bSBob Peterson mark_inode_dirty(inode); 92733dbc1bSBob Peterson } 93e01580bfSChristoph Hellwig } 94e01580bfSChristoph Hellwig 95e01580bfSChristoph Hellwig if (acl) { 965f3a4a28SEric W. Biederman len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 97479c427dSSteven Whitehouse if (len == 0) 98479c427dSSteven Whitehouse return 0; 99479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 100479c427dSSteven Whitehouse if (data == NULL) 101479c427dSSteven Whitehouse return -ENOMEM; 1025f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 103479c427dSSteven Whitehouse if (error < 0) 104479c427dSSteven Whitehouse goto out; 105e01580bfSChristoph Hellwig } else { 106e01580bfSChristoph Hellwig data = NULL; 107e01580bfSChristoph Hellwig len = 0; 108e01580bfSChristoph Hellwig } 109e01580bfSChristoph Hellwig 110431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 111479c427dSSteven Whitehouse if (error) 112479c427dSSteven Whitehouse goto out; 113479c427dSSteven Whitehouse 114106381bfSSteven Whitehouse if (acl) 115106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 116106381bfSSteven Whitehouse else 117106381bfSSteven Whitehouse forget_cached_acl(inode, type); 1182646a1f6SSteven Whitehouse out: 119e01580bfSChristoph Hellwig kfree(data); 1202646a1f6SSteven Whitehouse return error; 1212646a1f6SSteven Whitehouse } 122