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" 271a39ba99SAl Viro #include "rgrp.h" 28b3b94faaSDavid Teigland #include "trans.h" 295c676f6dSSteven Whitehouse #include "util.h" 30b3b94faaSDavid Teigland 31479c427dSSteven Whitehouse static const char *gfs2_acl_name(int type) 32b3b94faaSDavid Teigland { 33479c427dSSteven Whitehouse switch (type) { 34479c427dSSteven Whitehouse case ACL_TYPE_ACCESS: 3597d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_ACCESS; 36479c427dSSteven Whitehouse case ACL_TYPE_DEFAULT: 3797d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_DEFAULT; 38479c427dSSteven Whitehouse } 39479c427dSSteven Whitehouse return NULL; 40479c427dSSteven Whitehouse } 41b3b94faaSDavid Teigland 421a39ba99SAl Viro static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) 43479c427dSSteven Whitehouse { 44018a01cdSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode); 45479c427dSSteven Whitehouse struct posix_acl *acl; 46479c427dSSteven Whitehouse const char *name; 47479c427dSSteven Whitehouse char *data; 48479c427dSSteven Whitehouse int len; 4940b78a32SSteven Whitehouse 503767ac21SSteven Whitehouse if (!ip->i_eattr) 51479c427dSSteven Whitehouse return NULL; 52b3b94faaSDavid Teigland 53479c427dSSteven Whitehouse name = gfs2_acl_name(type); 54479c427dSSteven Whitehouse len = gfs2_xattr_acl_get(ip, name, &data); 551a39ba99SAl Viro if (len <= 0) 56479c427dSSteven Whitehouse return ERR_PTR(len); 575f3a4a28SEric W. Biederman acl = posix_acl_from_xattr(&init_user_ns, data, len); 5840b78a32SSteven Whitehouse kfree(data); 59479c427dSSteven Whitehouse return acl; 60b3b94faaSDavid Teigland } 61b3b94faaSDavid Teigland 621a39ba99SAl Viro struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 631a39ba99SAl Viro { 641a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 651a39ba99SAl Viro struct gfs2_holder gh; 661a39ba99SAl Viro bool need_unlock = false; 671a39ba99SAl Viro struct posix_acl *acl; 681a39ba99SAl Viro 691a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 701a39ba99SAl Viro int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 711a39ba99SAl Viro LM_FLAG_ANY, &gh); 721a39ba99SAl Viro if (ret) 731a39ba99SAl Viro return ERR_PTR(ret); 741a39ba99SAl Viro need_unlock = true; 751a39ba99SAl Viro } 761a39ba99SAl Viro acl = __gfs2_get_acl(inode, type); 771a39ba99SAl Viro if (need_unlock) 781a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 791a39ba99SAl Viro return acl; 801a39ba99SAl Viro } 811a39ba99SAl Viro 821a39ba99SAl Viro int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 83b3b94faaSDavid Teigland { 84b3b94faaSDavid Teigland int error; 85479c427dSSteven Whitehouse int len; 86479c427dSSteven Whitehouse char *data; 87479c427dSSteven Whitehouse const char *name = gfs2_acl_name(type); 88479c427dSSteven Whitehouse 89e01580bfSChristoph Hellwig if (acl) { 905f3a4a28SEric W. Biederman len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 91479c427dSSteven Whitehouse if (len == 0) 92479c427dSSteven Whitehouse return 0; 93479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 94479c427dSSteven Whitehouse if (data == NULL) 95479c427dSSteven Whitehouse return -ENOMEM; 965f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 97479c427dSSteven Whitehouse if (error < 0) 98479c427dSSteven Whitehouse goto out; 99e01580bfSChristoph Hellwig } else { 100e01580bfSChristoph Hellwig data = NULL; 101e01580bfSChristoph Hellwig len = 0; 102e01580bfSChristoph Hellwig } 103e01580bfSChristoph Hellwig 104431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 105479c427dSSteven Whitehouse if (error) 106479c427dSSteven Whitehouse goto out; 107106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 1082646a1f6SSteven Whitehouse out: 109e01580bfSChristoph Hellwig kfree(data); 1102646a1f6SSteven Whitehouse return error; 1112646a1f6SSteven Whitehouse } 1121a39ba99SAl Viro 1131a39ba99SAl Viro int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 1141a39ba99SAl Viro { 1151a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 1161a39ba99SAl Viro struct gfs2_holder gh; 1171a39ba99SAl Viro bool need_unlock = false; 1181a39ba99SAl Viro int ret; 119309e8cdaSErnesto A. Fernández umode_t mode; 1201a39ba99SAl Viro 121914cea93SJan Kara if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 122914cea93SJan Kara return -E2BIG; 123914cea93SJan Kara 1241a39ba99SAl Viro ret = gfs2_rsqa_alloc(ip); 1251a39ba99SAl Viro if (ret) 1261a39ba99SAl Viro return ret; 1271a39ba99SAl Viro 1281a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1291a39ba99SAl Viro ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 1301a39ba99SAl Viro if (ret) 1311a39ba99SAl Viro return ret; 1321a39ba99SAl Viro need_unlock = true; 1331a39ba99SAl Viro } 134914cea93SJan Kara 135309e8cdaSErnesto A. Fernández mode = inode->i_mode; 136309e8cdaSErnesto A. Fernández if (type == ACL_TYPE_ACCESS && acl) { 137309e8cdaSErnesto A. Fernández ret = posix_acl_update_mode(inode, &mode, &acl); 138914cea93SJan Kara if (ret) 139914cea93SJan Kara goto unlock; 140914cea93SJan Kara } 141914cea93SJan Kara 1421a39ba99SAl Viro ret = __gfs2_set_acl(inode, acl, type); 143309e8cdaSErnesto A. Fernández if (!ret && mode != inode->i_mode) { 144309e8cdaSErnesto A. Fernández inode->i_mode = mode; 145309e8cdaSErnesto A. Fernández mark_inode_dirty(inode); 146309e8cdaSErnesto A. Fernández } 147914cea93SJan Kara unlock: 1481a39ba99SAl Viro if (need_unlock) 1491a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 1501a39ba99SAl Viro return ret; 1511a39ba99SAl Viro } 152