15db11c21SMike Marshall /* 25db11c21SMike Marshall * (C) 2001 Clemson University and The University of Chicago 35db11c21SMike Marshall * 45db11c21SMike Marshall * See COPYING in top-level directory. 55db11c21SMike Marshall */ 65db11c21SMike Marshall 75db11c21SMike Marshall #include "protocol.h" 8*575e9461SMike Marshall #include "orangefs-kernel.h" 9*575e9461SMike Marshall #include "orangefs-bufmap.h" 105db11c21SMike Marshall #include <linux/posix_acl_xattr.h> 115db11c21SMike Marshall #include <linux/fs_struct.h> 125db11c21SMike Marshall 138bb8aefdSYi Liu struct posix_acl *orangefs_get_acl(struct inode *inode, int type) 145db11c21SMike Marshall { 155db11c21SMike Marshall struct posix_acl *acl; 165db11c21SMike Marshall int ret; 175db11c21SMike Marshall char *key = NULL, *value = NULL; 185db11c21SMike Marshall 195db11c21SMike Marshall switch (type) { 205db11c21SMike Marshall case ACL_TYPE_ACCESS: 218bb8aefdSYi Liu key = ORANGEFS_XATTR_NAME_ACL_ACCESS; 225db11c21SMike Marshall break; 235db11c21SMike Marshall case ACL_TYPE_DEFAULT: 248bb8aefdSYi Liu key = ORANGEFS_XATTR_NAME_ACL_DEFAULT; 255db11c21SMike Marshall break; 265db11c21SMike Marshall default: 278bb8aefdSYi Liu gossip_err("orangefs_get_acl: bogus value of type %d\n", type); 285db11c21SMike Marshall return ERR_PTR(-EINVAL); 295db11c21SMike Marshall } 305db11c21SMike Marshall /* 315db11c21SMike Marshall * Rather than incurring a network call just to determine the exact 325db11c21SMike Marshall * length of the attribute, I just allocate a max length to save on 335db11c21SMike Marshall * the network call. Conceivably, we could pass NULL to 348bb8aefdSYi Liu * orangefs_inode_getxattr() to probe the length of the value, but 355db11c21SMike Marshall * I don't do that for now. 365db11c21SMike Marshall */ 378bb8aefdSYi Liu value = kmalloc(ORANGEFS_MAX_XATTR_VALUELEN, GFP_KERNEL); 385db11c21SMike Marshall if (value == NULL) 395db11c21SMike Marshall return ERR_PTR(-ENOMEM); 405db11c21SMike Marshall 415db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 425db11c21SMike Marshall "inode %pU, key %s, type %d\n", 435db11c21SMike Marshall get_khandle_from_ino(inode), 445db11c21SMike Marshall key, 455db11c21SMike Marshall type); 468bb8aefdSYi Liu ret = orangefs_inode_getxattr(inode, 475db11c21SMike Marshall "", 485db11c21SMike Marshall key, 495db11c21SMike Marshall value, 508bb8aefdSYi Liu ORANGEFS_MAX_XATTR_VALUELEN); 515db11c21SMike Marshall /* if the key exists, convert it to an in-memory rep */ 525db11c21SMike Marshall if (ret > 0) { 535db11c21SMike Marshall acl = posix_acl_from_xattr(&init_user_ns, value, ret); 545db11c21SMike Marshall } else if (ret == -ENODATA || ret == -ENOSYS) { 555db11c21SMike Marshall acl = NULL; 565db11c21SMike Marshall } else { 575db11c21SMike Marshall gossip_err("inode %pU retrieving acl's failed with error %d\n", 585db11c21SMike Marshall get_khandle_from_ino(inode), 595db11c21SMike Marshall ret); 605db11c21SMike Marshall acl = ERR_PTR(ret); 615db11c21SMike Marshall } 625db11c21SMike Marshall /* kfree(NULL) is safe, so don't worry if value ever got used */ 635db11c21SMike Marshall kfree(value); 645db11c21SMike Marshall return acl; 655db11c21SMike Marshall } 665db11c21SMike Marshall 678bb8aefdSYi Liu int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 685db11c21SMike Marshall { 698bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 705db11c21SMike Marshall int error = 0; 715db11c21SMike Marshall void *value = NULL; 725db11c21SMike Marshall size_t size = 0; 735db11c21SMike Marshall const char *name = NULL; 745db11c21SMike Marshall 755db11c21SMike Marshall switch (type) { 765db11c21SMike Marshall case ACL_TYPE_ACCESS: 778bb8aefdSYi Liu name = ORANGEFS_XATTR_NAME_ACL_ACCESS; 785db11c21SMike Marshall if (acl) { 795db11c21SMike Marshall umode_t mode = inode->i_mode; 805db11c21SMike Marshall /* 815db11c21SMike Marshall * can we represent this with the traditional file 825db11c21SMike Marshall * mode permission bits? 835db11c21SMike Marshall */ 845db11c21SMike Marshall error = posix_acl_equiv_mode(acl, &mode); 855db11c21SMike Marshall if (error < 0) { 865db11c21SMike Marshall gossip_err("%s: posix_acl_equiv_mode err: %d\n", 875db11c21SMike Marshall __func__, 885db11c21SMike Marshall error); 895db11c21SMike Marshall return error; 905db11c21SMike Marshall } 915db11c21SMike Marshall 925db11c21SMike Marshall if (inode->i_mode != mode) 938bb8aefdSYi Liu SetModeFlag(orangefs_inode); 945db11c21SMike Marshall inode->i_mode = mode; 955db11c21SMike Marshall mark_inode_dirty_sync(inode); 965db11c21SMike Marshall if (error == 0) 975db11c21SMike Marshall acl = NULL; 985db11c21SMike Marshall } 995db11c21SMike Marshall break; 1005db11c21SMike Marshall case ACL_TYPE_DEFAULT: 1018bb8aefdSYi Liu name = ORANGEFS_XATTR_NAME_ACL_DEFAULT; 1025db11c21SMike Marshall break; 1035db11c21SMike Marshall default: 1045db11c21SMike Marshall gossip_err("%s: invalid type %d!\n", __func__, type); 1055db11c21SMike Marshall return -EINVAL; 1065db11c21SMike Marshall } 1075db11c21SMike Marshall 1085db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 1095db11c21SMike Marshall "%s: inode %pU, key %s type %d\n", 1105db11c21SMike Marshall __func__, get_khandle_from_ino(inode), 1115db11c21SMike Marshall name, 1125db11c21SMike Marshall type); 1135db11c21SMike Marshall 1145db11c21SMike Marshall if (acl) { 1155db11c21SMike Marshall size = posix_acl_xattr_size(acl->a_count); 1165db11c21SMike Marshall value = kmalloc(size, GFP_KERNEL); 1175db11c21SMike Marshall if (!value) 1185db11c21SMike Marshall return -ENOMEM; 1195db11c21SMike Marshall 1205db11c21SMike Marshall error = posix_acl_to_xattr(&init_user_ns, acl, value, size); 1215db11c21SMike Marshall if (error < 0) 1225db11c21SMike Marshall goto out; 1235db11c21SMike Marshall } 1245db11c21SMike Marshall 1255db11c21SMike Marshall gossip_debug(GOSSIP_ACL_DEBUG, 1265db11c21SMike Marshall "%s: name %s, value %p, size %zd, acl %p\n", 1275db11c21SMike Marshall __func__, name, value, size, acl); 1285db11c21SMike Marshall /* 1295db11c21SMike Marshall * Go ahead and set the extended attribute now. NOTE: Suppose acl 1305db11c21SMike Marshall * was NULL, then value will be NULL and size will be 0 and that 1315db11c21SMike Marshall * will xlate to a removexattr. However, we don't want removexattr 1325db11c21SMike Marshall * complain if attributes does not exist. 1335db11c21SMike Marshall */ 1348bb8aefdSYi Liu error = orangefs_inode_setxattr(inode, "", name, value, size, 0); 1355db11c21SMike Marshall 1365db11c21SMike Marshall out: 1375db11c21SMike Marshall kfree(value); 1385db11c21SMike Marshall if (!error) 1395db11c21SMike Marshall set_cached_acl(inode, type, acl); 1405db11c21SMike Marshall return error; 1415db11c21SMike Marshall } 1425db11c21SMike Marshall 1438bb8aefdSYi Liu int orangefs_init_acl(struct inode *inode, struct inode *dir) 1445db11c21SMike Marshall { 1458bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 1465db11c21SMike Marshall struct posix_acl *default_acl, *acl; 1475db11c21SMike Marshall umode_t mode = inode->i_mode; 1485db11c21SMike Marshall int error = 0; 1495db11c21SMike Marshall 1508bb8aefdSYi Liu ClearModeFlag(orangefs_inode); 1515db11c21SMike Marshall 1525db11c21SMike Marshall error = posix_acl_create(dir, &mode, &default_acl, &acl); 1535db11c21SMike Marshall if (error) 1545db11c21SMike Marshall return error; 1555db11c21SMike Marshall 1565db11c21SMike Marshall if (default_acl) { 1578bb8aefdSYi Liu error = orangefs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); 1585db11c21SMike Marshall posix_acl_release(default_acl); 1595db11c21SMike Marshall } 1605db11c21SMike Marshall 1615db11c21SMike Marshall if (acl) { 1625db11c21SMike Marshall if (!error) 1638bb8aefdSYi Liu error = orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS); 1645db11c21SMike Marshall posix_acl_release(acl); 1655db11c21SMike Marshall } 1665db11c21SMike Marshall 1675db11c21SMike Marshall /* If mode of the inode was changed, then do a forcible ->setattr */ 1685db11c21SMike Marshall if (mode != inode->i_mode) { 1698bb8aefdSYi Liu SetModeFlag(orangefs_inode); 1705db11c21SMike Marshall inode->i_mode = mode; 1718bb8aefdSYi Liu orangefs_flush_inode(inode); 1725db11c21SMike Marshall } 1735db11c21SMike Marshall 1745db11c21SMike Marshall return error; 1755db11c21SMike Marshall } 176