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 8927870207SAndrew Elble if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 90f2113eb8SJie Liu return -E2BIG; 91e01580bfSChristoph Hellwig 92e01580bfSChristoph Hellwig if (type == ACL_TYPE_ACCESS) { 93e01580bfSChristoph Hellwig umode_t mode = inode->i_mode; 94e01580bfSChristoph Hellwig 95e01580bfSChristoph Hellwig error = posix_acl_equiv_mode(acl, &mode); 96e01580bfSChristoph Hellwig if (error < 0) 97e01580bfSChristoph Hellwig return error; 98e01580bfSChristoph Hellwig 99e01580bfSChristoph Hellwig if (error == 0) 100e01580bfSChristoph Hellwig acl = NULL; 101e01580bfSChristoph Hellwig 102733dbc1bSBob Peterson if (mode != inode->i_mode) { 103733dbc1bSBob Peterson inode->i_mode = mode; 104733dbc1bSBob Peterson mark_inode_dirty(inode); 105733dbc1bSBob Peterson } 106e01580bfSChristoph Hellwig } 107e01580bfSChristoph Hellwig 108e01580bfSChristoph Hellwig if (acl) { 1095f3a4a28SEric W. Biederman len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 110479c427dSSteven Whitehouse if (len == 0) 111479c427dSSteven Whitehouse return 0; 112479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 113479c427dSSteven Whitehouse if (data == NULL) 114479c427dSSteven Whitehouse return -ENOMEM; 1155f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 116479c427dSSteven Whitehouse if (error < 0) 117479c427dSSteven Whitehouse goto out; 118e01580bfSChristoph Hellwig } else { 119e01580bfSChristoph Hellwig data = NULL; 120e01580bfSChristoph Hellwig len = 0; 121e01580bfSChristoph Hellwig } 122e01580bfSChristoph Hellwig 123431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 124479c427dSSteven Whitehouse if (error) 125479c427dSSteven Whitehouse goto out; 126106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 1272646a1f6SSteven Whitehouse out: 128e01580bfSChristoph Hellwig kfree(data); 1292646a1f6SSteven Whitehouse return error; 1302646a1f6SSteven Whitehouse } 1311a39ba99SAl Viro 1321a39ba99SAl Viro int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 1331a39ba99SAl Viro { 1341a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 1351a39ba99SAl Viro struct gfs2_holder gh; 1361a39ba99SAl Viro bool need_unlock = false; 1371a39ba99SAl Viro int ret; 1381a39ba99SAl Viro 1391a39ba99SAl Viro ret = gfs2_rsqa_alloc(ip); 1401a39ba99SAl Viro if (ret) 1411a39ba99SAl Viro return ret; 1421a39ba99SAl Viro 1431a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1441a39ba99SAl Viro ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 1451a39ba99SAl Viro if (ret) 1461a39ba99SAl Viro return ret; 1471a39ba99SAl Viro need_unlock = true; 1481a39ba99SAl Viro } 1491a39ba99SAl Viro ret = __gfs2_set_acl(inode, acl, type); 1501a39ba99SAl Viro if (need_unlock) 1511a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 1521a39ba99SAl Viro return ret; 1531a39ba99SAl Viro } 154