11182fca3SMike Marshall /* 21182fca3SMike Marshall * (C) 2001 Clemson University and The University of Chicago 31182fca3SMike Marshall * 41182fca3SMike Marshall * See COPYING in top-level directory. 51182fca3SMike Marshall */ 61182fca3SMike Marshall 71182fca3SMike Marshall /* 81182fca3SMike Marshall * Linux VFS extended attribute operations. 91182fca3SMike Marshall */ 101182fca3SMike Marshall 111182fca3SMike Marshall #include "protocol.h" 12575e9461SMike Marshall #include "orangefs-kernel.h" 13575e9461SMike Marshall #include "orangefs-bufmap.h" 141182fca3SMike Marshall #include <linux/posix_acl_xattr.h> 151182fca3SMike Marshall #include <linux/xattr.h> 161182fca3SMike Marshall 171182fca3SMike Marshall 188bb8aefdSYi Liu #define SYSTEM_ORANGEFS_KEY "system.pvfs2." 198bb8aefdSYi Liu #define SYSTEM_ORANGEFS_KEY_LEN 13 201182fca3SMike Marshall 211182fca3SMike Marshall /* 221182fca3SMike Marshall * this function returns 231182fca3SMike Marshall * 0 if the key corresponding to name is not meant to be printed as part 241182fca3SMike Marshall * of a listxattr. 251182fca3SMike Marshall * 1 if the key corresponding to name is meant to be returned as part of 261182fca3SMike Marshall * a listxattr. 278bb8aefdSYi Liu * The ones that start SYSTEM_ORANGEFS_KEY are the ones to avoid printing. 281182fca3SMike Marshall */ 291182fca3SMike Marshall static int is_reserved_key(const char *key, size_t size) 301182fca3SMike Marshall { 311182fca3SMike Marshall 328bb8aefdSYi Liu if (size < SYSTEM_ORANGEFS_KEY_LEN) 331182fca3SMike Marshall return 1; 341182fca3SMike Marshall 358bb8aefdSYi Liu return strncmp(key, SYSTEM_ORANGEFS_KEY, SYSTEM_ORANGEFS_KEY_LEN) ? 1 : 0; 361182fca3SMike Marshall } 371182fca3SMike Marshall 381182fca3SMike Marshall static inline int convert_to_internal_xattr_flags(int setxattr_flags) 391182fca3SMike Marshall { 401182fca3SMike Marshall int internal_flag = 0; 411182fca3SMike Marshall 421182fca3SMike Marshall if (setxattr_flags & XATTR_REPLACE) { 431182fca3SMike Marshall /* Attribute must exist! */ 448bb8aefdSYi Liu internal_flag = ORANGEFS_XATTR_REPLACE; 451182fca3SMike Marshall } else if (setxattr_flags & XATTR_CREATE) { 461182fca3SMike Marshall /* Attribute must not exist */ 478bb8aefdSYi Liu internal_flag = ORANGEFS_XATTR_CREATE; 481182fca3SMike Marshall } 491182fca3SMike Marshall return internal_flag; 501182fca3SMike Marshall } 511182fca3SMike Marshall 521182fca3SMike Marshall 531182fca3SMike Marshall /* 541182fca3SMike Marshall * Tries to get a specified key's attributes of a given 551182fca3SMike Marshall * file into a user-specified buffer. Note that the getxattr 561182fca3SMike Marshall * interface allows for the users to probe the size of an 571182fca3SMike Marshall * extended attribute by passing in a value of 0 to size. 581182fca3SMike Marshall * Thus our return value is always the size of the attribute 591182fca3SMike Marshall * unless the key does not exist for the file and/or if 601182fca3SMike Marshall * there were errors in fetching the attribute value. 611182fca3SMike Marshall */ 628bb8aefdSYi Liu ssize_t orangefs_inode_getxattr(struct inode *inode, const char *prefix, 631182fca3SMike Marshall const char *name, void *buffer, size_t size) 641182fca3SMike Marshall { 658bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 668bb8aefdSYi Liu struct orangefs_kernel_op_s *new_op = NULL; 671182fca3SMike Marshall ssize_t ret = -ENOMEM; 681182fca3SMike Marshall ssize_t length = 0; 691182fca3SMike Marshall int fsuid; 701182fca3SMike Marshall int fsgid; 711182fca3SMike Marshall 721182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 731182fca3SMike Marshall "%s: prefix %s name %s, buffer_size %zd\n", 741182fca3SMike Marshall __func__, prefix, name, size); 751182fca3SMike Marshall 768bb8aefdSYi Liu if ((strlen(name) + strlen(prefix)) >= ORANGEFS_MAX_XATTR_NAMELEN) { 77eeaa3d44SMike Marshall gossip_err("Invalid key length (%d)\n", 781182fca3SMike Marshall (int)(strlen(name) + strlen(prefix))); 791182fca3SMike Marshall return -EINVAL; 801182fca3SMike Marshall } 811182fca3SMike Marshall 821182fca3SMike Marshall fsuid = from_kuid(current_user_ns(), current_fsuid()); 831182fca3SMike Marshall fsgid = from_kgid(current_user_ns(), current_fsgid()); 841182fca3SMike Marshall 851182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 861182fca3SMike Marshall "getxattr on inode %pU, name %s " 871182fca3SMike Marshall "(uid %o, gid %o)\n", 881182fca3SMike Marshall get_khandle_from_ino(inode), 891182fca3SMike Marshall name, 901182fca3SMike Marshall fsuid, 911182fca3SMike Marshall fsgid); 921182fca3SMike Marshall 938bb8aefdSYi Liu down_read(&orangefs_inode->xattr_sem); 941182fca3SMike Marshall 958bb8aefdSYi Liu new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR); 961182fca3SMike Marshall if (!new_op) 971182fca3SMike Marshall goto out_unlock; 981182fca3SMike Marshall 998bb8aefdSYi Liu new_op->upcall.req.getxattr.refn = orangefs_inode->refn; 1001182fca3SMike Marshall ret = snprintf((char *)new_op->upcall.req.getxattr.key, 1018bb8aefdSYi Liu ORANGEFS_MAX_XATTR_NAMELEN, "%s%s", prefix, name); 1021182fca3SMike Marshall 1031182fca3SMike Marshall /* 1041182fca3SMike Marshall * NOTE: Although keys are meant to be NULL terminated textual 1051182fca3SMike Marshall * strings, I am going to explicitly pass the length just in case 1061182fca3SMike Marshall * we change this later on... 1071182fca3SMike Marshall */ 1081182fca3SMike Marshall new_op->upcall.req.getxattr.key_sz = ret + 1; 1091182fca3SMike Marshall 1108bb8aefdSYi Liu ret = service_operation(new_op, "orangefs_inode_getxattr", 1111182fca3SMike Marshall get_interruptible_flag(inode)); 1121182fca3SMike Marshall if (ret != 0) { 1131182fca3SMike Marshall if (ret == -ENOENT) { 1141182fca3SMike Marshall ret = -ENODATA; 1151182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 1168bb8aefdSYi Liu "orangefs_inode_getxattr: inode %pU key %s" 1171182fca3SMike Marshall " does not exist!\n", 1181182fca3SMike Marshall get_khandle_from_ino(inode), 1191182fca3SMike Marshall (char *)new_op->upcall.req.getxattr.key); 1201182fca3SMike Marshall } 1211182fca3SMike Marshall goto out_release_op; 1221182fca3SMike Marshall } 1231182fca3SMike Marshall 1241182fca3SMike Marshall /* 1251182fca3SMike Marshall * Length returned includes null terminator. 1261182fca3SMike Marshall */ 1271182fca3SMike Marshall length = new_op->downcall.resp.getxattr.val_sz; 1281182fca3SMike Marshall 1291182fca3SMike Marshall /* 1301182fca3SMike Marshall * Just return the length of the queried attribute. 1311182fca3SMike Marshall */ 1321182fca3SMike Marshall if (size == 0) { 1331182fca3SMike Marshall ret = length; 1341182fca3SMike Marshall goto out_release_op; 1351182fca3SMike Marshall } 1361182fca3SMike Marshall 1371182fca3SMike Marshall /* 1381182fca3SMike Marshall * Check to see if key length is > provided buffer size. 1391182fca3SMike Marshall */ 1401182fca3SMike Marshall if (length > size) { 1411182fca3SMike Marshall ret = -ERANGE; 1421182fca3SMike Marshall goto out_release_op; 1431182fca3SMike Marshall } 1441182fca3SMike Marshall 1451182fca3SMike Marshall memcpy(buffer, new_op->downcall.resp.getxattr.val, length); 146a9bb3ba8SMike Marshall memset(buffer + length, 0, size - length); 1471182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 1488bb8aefdSYi Liu "orangefs_inode_getxattr: inode %pU " 1491182fca3SMike Marshall "key %s key_sz %d, val_len %d\n", 1501182fca3SMike Marshall get_khandle_from_ino(inode), 1511182fca3SMike Marshall (char *)new_op-> 1521182fca3SMike Marshall upcall.req.getxattr.key, 1531182fca3SMike Marshall (int)new_op-> 1541182fca3SMike Marshall upcall.req.getxattr.key_sz, 1551182fca3SMike Marshall (int)ret); 1561182fca3SMike Marshall 1571182fca3SMike Marshall ret = length; 1581182fca3SMike Marshall 1591182fca3SMike Marshall out_release_op: 1601182fca3SMike Marshall op_release(new_op); 1611182fca3SMike Marshall out_unlock: 1628bb8aefdSYi Liu up_read(&orangefs_inode->xattr_sem); 1631182fca3SMike Marshall return ret; 1641182fca3SMike Marshall } 1651182fca3SMike Marshall 1668bb8aefdSYi Liu static int orangefs_inode_removexattr(struct inode *inode, 1671182fca3SMike Marshall const char *prefix, 1681182fca3SMike Marshall const char *name, 1691182fca3SMike Marshall int flags) 1701182fca3SMike Marshall { 1718bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 1728bb8aefdSYi Liu struct orangefs_kernel_op_s *new_op = NULL; 1731182fca3SMike Marshall int ret = -ENOMEM; 1741182fca3SMike Marshall 1758bb8aefdSYi Liu down_write(&orangefs_inode->xattr_sem); 1768bb8aefdSYi Liu new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR); 1771182fca3SMike Marshall if (!new_op) 1781182fca3SMike Marshall goto out_unlock; 1791182fca3SMike Marshall 1808bb8aefdSYi Liu new_op->upcall.req.removexattr.refn = orangefs_inode->refn; 1811182fca3SMike Marshall /* 1821182fca3SMike Marshall * NOTE: Although keys are meant to be NULL terminated 1831182fca3SMike Marshall * textual strings, I am going to explicitly pass the 1841182fca3SMike Marshall * length just in case we change this later on... 1851182fca3SMike Marshall */ 1861182fca3SMike Marshall ret = snprintf((char *)new_op->upcall.req.removexattr.key, 1878bb8aefdSYi Liu ORANGEFS_MAX_XATTR_NAMELEN, 1881182fca3SMike Marshall "%s%s", 1891182fca3SMike Marshall (prefix ? prefix : ""), 1901182fca3SMike Marshall name); 1911182fca3SMike Marshall new_op->upcall.req.removexattr.key_sz = ret + 1; 1921182fca3SMike Marshall 1931182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 1948bb8aefdSYi Liu "orangefs_inode_removexattr: key %s, key_sz %d\n", 1951182fca3SMike Marshall (char *)new_op->upcall.req.removexattr.key, 1961182fca3SMike Marshall (int)new_op->upcall.req.removexattr.key_sz); 1971182fca3SMike Marshall 1981182fca3SMike Marshall ret = service_operation(new_op, 1998bb8aefdSYi Liu "orangefs_inode_removexattr", 2001182fca3SMike Marshall get_interruptible_flag(inode)); 2011182fca3SMike Marshall if (ret == -ENOENT) { 2021182fca3SMike Marshall /* 2031182fca3SMike Marshall * Request to replace a non-existent attribute is an error. 2041182fca3SMike Marshall */ 2051182fca3SMike Marshall if (flags & XATTR_REPLACE) 2061182fca3SMike Marshall ret = -ENODATA; 2071182fca3SMike Marshall else 2081182fca3SMike Marshall ret = 0; 2091182fca3SMike Marshall } 2101182fca3SMike Marshall 2111182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 2128bb8aefdSYi Liu "orangefs_inode_removexattr: returning %d\n", ret); 2131182fca3SMike Marshall 2141182fca3SMike Marshall op_release(new_op); 2151182fca3SMike Marshall out_unlock: 2168bb8aefdSYi Liu up_write(&orangefs_inode->xattr_sem); 2171182fca3SMike Marshall return ret; 2181182fca3SMike Marshall } 2191182fca3SMike Marshall 2201182fca3SMike Marshall /* 2211182fca3SMike Marshall * Tries to set an attribute for a given key on a file. 2221182fca3SMike Marshall * 2231182fca3SMike Marshall * Returns a -ve number on error and 0 on success. Key is text, but value 2241182fca3SMike Marshall * can be binary! 2251182fca3SMike Marshall */ 2268bb8aefdSYi Liu int orangefs_inode_setxattr(struct inode *inode, const char *prefix, 2271182fca3SMike Marshall const char *name, const void *value, size_t size, int flags) 2281182fca3SMike Marshall { 2298bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 2308bb8aefdSYi Liu struct orangefs_kernel_op_s *new_op; 2311182fca3SMike Marshall int internal_flag = 0; 2321182fca3SMike Marshall int ret = -ENOMEM; 2331182fca3SMike Marshall 2341182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 2351182fca3SMike Marshall "%s: prefix %s, name %s, buffer_size %zd\n", 2361182fca3SMike Marshall __func__, prefix, name, size); 2371182fca3SMike Marshall 2382d09a2caSMike Marshall if (size >= ORANGEFS_MAX_XATTR_VALUELEN || 2391182fca3SMike Marshall flags < 0) { 2408bb8aefdSYi Liu gossip_err("orangefs_inode_setxattr: bogus values of size(%d), flags(%d)\n", 2411182fca3SMike Marshall (int)size, 2421182fca3SMike Marshall flags); 2431182fca3SMike Marshall return -EINVAL; 2441182fca3SMike Marshall } 2451182fca3SMike Marshall 2461182fca3SMike Marshall internal_flag = convert_to_internal_xattr_flags(flags); 2471182fca3SMike Marshall 2481182fca3SMike Marshall if (prefix) { 2498bb8aefdSYi Liu if (strlen(name) + strlen(prefix) >= ORANGEFS_MAX_XATTR_NAMELEN) { 2501182fca3SMike Marshall gossip_err 2518bb8aefdSYi Liu ("orangefs_inode_setxattr: bogus key size (%d)\n", 2521182fca3SMike Marshall (int)(strlen(name) + strlen(prefix))); 2531182fca3SMike Marshall return -EINVAL; 2541182fca3SMike Marshall } 2551182fca3SMike Marshall } else { 2568bb8aefdSYi Liu if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { 2571182fca3SMike Marshall gossip_err 2588bb8aefdSYi Liu ("orangefs_inode_setxattr: bogus key size (%d)\n", 2591182fca3SMike Marshall (int)(strlen(name))); 2601182fca3SMike Marshall return -EINVAL; 2611182fca3SMike Marshall } 2621182fca3SMike Marshall } 2631182fca3SMike Marshall 2641182fca3SMike Marshall /* This is equivalent to a removexattr */ 2651182fca3SMike Marshall if (size == 0 && value == NULL) { 2661182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 2671182fca3SMike Marshall "removing xattr (%s%s)\n", 2681182fca3SMike Marshall prefix, 2691182fca3SMike Marshall name); 2708bb8aefdSYi Liu return orangefs_inode_removexattr(inode, prefix, name, flags); 2711182fca3SMike Marshall } 2721182fca3SMike Marshall 2731182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 2741182fca3SMike Marshall "setxattr on inode %pU, name %s\n", 2751182fca3SMike Marshall get_khandle_from_ino(inode), 2761182fca3SMike Marshall name); 2771182fca3SMike Marshall 2788bb8aefdSYi Liu down_write(&orangefs_inode->xattr_sem); 2798bb8aefdSYi Liu new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR); 2801182fca3SMike Marshall if (!new_op) 2811182fca3SMike Marshall goto out_unlock; 2821182fca3SMike Marshall 2831182fca3SMike Marshall 2848bb8aefdSYi Liu new_op->upcall.req.setxattr.refn = orangefs_inode->refn; 2851182fca3SMike Marshall new_op->upcall.req.setxattr.flags = internal_flag; 2861182fca3SMike Marshall /* 2871182fca3SMike Marshall * NOTE: Although keys are meant to be NULL terminated textual 2881182fca3SMike Marshall * strings, I am going to explicitly pass the length just in 2891182fca3SMike Marshall * case we change this later on... 2901182fca3SMike Marshall */ 2911182fca3SMike Marshall ret = snprintf((char *)new_op->upcall.req.setxattr.keyval.key, 2928bb8aefdSYi Liu ORANGEFS_MAX_XATTR_NAMELEN, 2931182fca3SMike Marshall "%s%s", 2941182fca3SMike Marshall prefix, name); 2951182fca3SMike Marshall new_op->upcall.req.setxattr.keyval.key_sz = ret + 1; 2961182fca3SMike Marshall memcpy(new_op->upcall.req.setxattr.keyval.val, value, size); 2971182fca3SMike Marshall new_op->upcall.req.setxattr.keyval.val_sz = size; 2981182fca3SMike Marshall 2991182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 3008bb8aefdSYi Liu "orangefs_inode_setxattr: key %s, key_sz %d " 3011182fca3SMike Marshall " value size %zd\n", 3021182fca3SMike Marshall (char *)new_op->upcall.req.setxattr.keyval.key, 3031182fca3SMike Marshall (int)new_op->upcall.req.setxattr.keyval.key_sz, 3041182fca3SMike Marshall size); 3051182fca3SMike Marshall 3061182fca3SMike Marshall ret = service_operation(new_op, 3078bb8aefdSYi Liu "orangefs_inode_setxattr", 3081182fca3SMike Marshall get_interruptible_flag(inode)); 3091182fca3SMike Marshall 3101182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, 3118bb8aefdSYi Liu "orangefs_inode_setxattr: returning %d\n", 3121182fca3SMike Marshall ret); 3131182fca3SMike Marshall 3141182fca3SMike Marshall /* when request is serviced properly, free req op struct */ 3151182fca3SMike Marshall op_release(new_op); 3161182fca3SMike Marshall out_unlock: 3178bb8aefdSYi Liu up_write(&orangefs_inode->xattr_sem); 3181182fca3SMike Marshall return ret; 3191182fca3SMike Marshall } 3201182fca3SMike Marshall 3211182fca3SMike Marshall /* 3221182fca3SMike Marshall * Tries to get a specified object's keys into a user-specified buffer of a 3231182fca3SMike Marshall * given size. Note that like the previous instances of xattr routines, this 3241182fca3SMike Marshall * also allows you to pass in a NULL pointer and 0 size to probe the size for 3251182fca3SMike Marshall * subsequent memory allocations. Thus our return value is always the size of 3261182fca3SMike Marshall * all the keys unless there were errors in fetching the keys! 3271182fca3SMike Marshall */ 3288bb8aefdSYi Liu ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size) 3291182fca3SMike Marshall { 3301182fca3SMike Marshall struct inode *inode = dentry->d_inode; 3318bb8aefdSYi Liu struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 3328bb8aefdSYi Liu struct orangefs_kernel_op_s *new_op; 3338bb8aefdSYi Liu __u64 token = ORANGEFS_ITERATE_START; 3341182fca3SMike Marshall ssize_t ret = -ENOMEM; 3351182fca3SMike Marshall ssize_t total = 0; 3361182fca3SMike Marshall int count_keys = 0; 3371182fca3SMike Marshall int key_size; 3381182fca3SMike Marshall int i = 0; 33962441fa5SMike Marshall int returned_count = 0; 3401182fca3SMike Marshall 3411182fca3SMike Marshall if (size > 0 && buffer == NULL) { 3421182fca3SMike Marshall gossip_err("%s: bogus NULL pointers\n", __func__); 3431182fca3SMike Marshall return -EINVAL; 3441182fca3SMike Marshall } 3451182fca3SMike Marshall 3468bb8aefdSYi Liu down_read(&orangefs_inode->xattr_sem); 3478bb8aefdSYi Liu new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR); 3481182fca3SMike Marshall if (!new_op) 3491182fca3SMike Marshall goto out_unlock; 3501182fca3SMike Marshall 3511182fca3SMike Marshall if (buffer && size > 0) 3521182fca3SMike Marshall memset(buffer, 0, size); 3531182fca3SMike Marshall 3541182fca3SMike Marshall try_again: 3551182fca3SMike Marshall key_size = 0; 3568bb8aefdSYi Liu new_op->upcall.req.listxattr.refn = orangefs_inode->refn; 3571182fca3SMike Marshall new_op->upcall.req.listxattr.token = token; 3581182fca3SMike Marshall new_op->upcall.req.listxattr.requested_count = 3598bb8aefdSYi Liu (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN; 3601182fca3SMike Marshall ret = service_operation(new_op, __func__, 3611182fca3SMike Marshall get_interruptible_flag(inode)); 3621182fca3SMike Marshall if (ret != 0) 3631182fca3SMike Marshall goto done; 3641182fca3SMike Marshall 3651182fca3SMike Marshall if (size == 0) { 3661182fca3SMike Marshall /* 3671182fca3SMike Marshall * This is a bit of a big upper limit, but I did not want to 3681182fca3SMike Marshall * spend too much time getting this correct, since users end 3691182fca3SMike Marshall * up allocating memory rather than us... 3701182fca3SMike Marshall */ 3711182fca3SMike Marshall total = new_op->downcall.resp.listxattr.returned_count * 3728bb8aefdSYi Liu ORANGEFS_MAX_XATTR_NAMELEN; 3731182fca3SMike Marshall goto done; 3741182fca3SMike Marshall } 3751182fca3SMike Marshall 37662441fa5SMike Marshall returned_count = new_op->downcall.resp.listxattr.returned_count; 37762441fa5SMike Marshall if (returned_count < 0 || 37862441fa5SMike Marshall returned_count >= ORANGEFS_MAX_XATTR_LISTLEN) { 37962441fa5SMike Marshall gossip_err("%s: impossible value for returned_count:%d:\n", 38062441fa5SMike Marshall __func__, 38162441fa5SMike Marshall returned_count); 38202a5cc53SMartin Brandenburg ret = -EIO; 38362441fa5SMike Marshall goto done; 38462441fa5SMike Marshall } 38562441fa5SMike Marshall 3861182fca3SMike Marshall /* 3871182fca3SMike Marshall * Check to see how much can be fit in the buffer. Fit only whole keys. 3881182fca3SMike Marshall */ 38962441fa5SMike Marshall for (i = 0; i < returned_count; i++) { 39002a5cc53SMartin Brandenburg if (new_op->downcall.resp.listxattr.lengths[i] < 0 || 39102a5cc53SMartin Brandenburg new_op->downcall.resp.listxattr.lengths[i] > 39202a5cc53SMartin Brandenburg ORANGEFS_MAX_XATTR_NAMELEN) { 39302a5cc53SMartin Brandenburg gossip_err("%s: impossible value for lengths[%d]\n", 39402a5cc53SMartin Brandenburg __func__, 39502a5cc53SMartin Brandenburg new_op->downcall.resp.listxattr.lengths[i]); 39602a5cc53SMartin Brandenburg ret = -EIO; 39702a5cc53SMartin Brandenburg goto done; 39802a5cc53SMartin Brandenburg } 3991182fca3SMike Marshall if (total + new_op->downcall.resp.listxattr.lengths[i] > size) 4001182fca3SMike Marshall goto done; 4011182fca3SMike Marshall 4021182fca3SMike Marshall /* 4031182fca3SMike Marshall * Since many dumb programs try to setxattr() on our reserved 4041182fca3SMike Marshall * xattrs this is a feeble attempt at defeating those by not 4051182fca3SMike Marshall * listing them in the output of listxattr.. sigh 4061182fca3SMike Marshall */ 4071182fca3SMike Marshall if (is_reserved_key(new_op->downcall.resp.listxattr.key + 4081182fca3SMike Marshall key_size, 4091182fca3SMike Marshall new_op->downcall.resp. 4101182fca3SMike Marshall listxattr.lengths[i])) { 4111182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n", 4121182fca3SMike Marshall i, new_op->downcall.resp.listxattr.key + 4131182fca3SMike Marshall key_size); 4141182fca3SMike Marshall memcpy(buffer + total, 4151182fca3SMike Marshall new_op->downcall.resp.listxattr.key + key_size, 4161182fca3SMike Marshall new_op->downcall.resp.listxattr.lengths[i]); 4171182fca3SMike Marshall total += new_op->downcall.resp.listxattr.lengths[i]; 4181182fca3SMike Marshall count_keys++; 4191182fca3SMike Marshall } else { 4201182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n", 4211182fca3SMike Marshall i, new_op->downcall.resp.listxattr.key + 4221182fca3SMike Marshall key_size); 4231182fca3SMike Marshall } 4241182fca3SMike Marshall key_size += new_op->downcall.resp.listxattr.lengths[i]; 4251182fca3SMike Marshall } 4261182fca3SMike Marshall 4271182fca3SMike Marshall /* 4281182fca3SMike Marshall * Since the buffer was large enough, we might have to continue 4291182fca3SMike Marshall * fetching more keys! 4301182fca3SMike Marshall */ 4311182fca3SMike Marshall token = new_op->downcall.resp.listxattr.token; 4328bb8aefdSYi Liu if (token != ORANGEFS_ITERATE_END) 4331182fca3SMike Marshall goto try_again; 4341182fca3SMike Marshall 4351182fca3SMike Marshall done: 4361182fca3SMike Marshall gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d" 4371182fca3SMike Marshall " [size of buffer %ld] (filled in %d keys)\n", 4381182fca3SMike Marshall __func__, 4391182fca3SMike Marshall ret ? (int)ret : (int)total, 4401182fca3SMike Marshall (long)size, 4411182fca3SMike Marshall count_keys); 4421182fca3SMike Marshall op_release(new_op); 4431182fca3SMike Marshall if (ret == 0) 4441182fca3SMike Marshall ret = total; 4451182fca3SMike Marshall out_unlock: 4468bb8aefdSYi Liu up_read(&orangefs_inode->xattr_sem); 4471182fca3SMike Marshall return ret; 4481182fca3SMike Marshall } 4491182fca3SMike Marshall 4508bb8aefdSYi Liu static int orangefs_xattr_set_default(const struct xattr_handler *handler, 451555fa0faSAl Viro struct dentry *dentry, 4521182fca3SMike Marshall const char *name, 4531182fca3SMike Marshall const void *buffer, 4541182fca3SMike Marshall size_t size, 455555fa0faSAl Viro int flags) 4561182fca3SMike Marshall { 4578bb8aefdSYi Liu return orangefs_inode_setxattr(dentry->d_inode, 4588bb8aefdSYi Liu ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, 4591182fca3SMike Marshall name, 4601182fca3SMike Marshall buffer, 4611182fca3SMike Marshall size, 4621182fca3SMike Marshall flags); 4631182fca3SMike Marshall } 4641182fca3SMike Marshall 4658bb8aefdSYi Liu static int orangefs_xattr_get_default(const struct xattr_handler *handler, 466555fa0faSAl Viro struct dentry *dentry, 4671182fca3SMike Marshall const char *name, 4681182fca3SMike Marshall void *buffer, 469555fa0faSAl Viro size_t size) 4701182fca3SMike Marshall { 4718bb8aefdSYi Liu return orangefs_inode_getxattr(dentry->d_inode, 4728bb8aefdSYi Liu ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, 4731182fca3SMike Marshall name, 4741182fca3SMike Marshall buffer, 4751182fca3SMike Marshall size); 4761182fca3SMike Marshall 4771182fca3SMike Marshall } 4781182fca3SMike Marshall 4798bb8aefdSYi Liu static int orangefs_xattr_set_trusted(const struct xattr_handler *handler, 480555fa0faSAl Viro struct dentry *dentry, 4811182fca3SMike Marshall const char *name, 4821182fca3SMike Marshall const void *buffer, 4831182fca3SMike Marshall size_t size, 484555fa0faSAl Viro int flags) 4851182fca3SMike Marshall { 4868bb8aefdSYi Liu return orangefs_inode_setxattr(dentry->d_inode, 4878bb8aefdSYi Liu ORANGEFS_XATTR_NAME_TRUSTED_PREFIX, 4881182fca3SMike Marshall name, 4891182fca3SMike Marshall buffer, 4901182fca3SMike Marshall size, 4911182fca3SMike Marshall flags); 4921182fca3SMike Marshall } 4931182fca3SMike Marshall 4948bb8aefdSYi Liu static int orangefs_xattr_get_trusted(const struct xattr_handler *handler, 495555fa0faSAl Viro struct dentry *dentry, 4961182fca3SMike Marshall const char *name, 4971182fca3SMike Marshall void *buffer, 498555fa0faSAl Viro size_t size) 4991182fca3SMike Marshall { 5008bb8aefdSYi Liu return orangefs_inode_getxattr(dentry->d_inode, 5018bb8aefdSYi Liu ORANGEFS_XATTR_NAME_TRUSTED_PREFIX, 5021182fca3SMike Marshall name, 5031182fca3SMike Marshall buffer, 5041182fca3SMike Marshall size); 5051182fca3SMike Marshall } 5061182fca3SMike Marshall 5078bb8aefdSYi Liu static struct xattr_handler orangefs_xattr_trusted_handler = { 5088bb8aefdSYi Liu .prefix = ORANGEFS_XATTR_NAME_TRUSTED_PREFIX, 5098bb8aefdSYi Liu .get = orangefs_xattr_get_trusted, 5108bb8aefdSYi Liu .set = orangefs_xattr_set_trusted, 5111182fca3SMike Marshall }; 5121182fca3SMike Marshall 5138bb8aefdSYi Liu static struct xattr_handler orangefs_xattr_default_handler = { 5141182fca3SMike Marshall /* 5151182fca3SMike Marshall * NOTE: this is set to be the empty string. 5161182fca3SMike Marshall * so that all un-prefixed xattrs keys get caught 5171182fca3SMike Marshall * here! 5181182fca3SMike Marshall */ 5198bb8aefdSYi Liu .prefix = ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, 5208bb8aefdSYi Liu .get = orangefs_xattr_get_default, 5218bb8aefdSYi Liu .set = orangefs_xattr_set_default, 5221182fca3SMike Marshall }; 5231182fca3SMike Marshall 5248bb8aefdSYi Liu const struct xattr_handler *orangefs_xattr_handlers[] = { 5251182fca3SMike Marshall &posix_acl_access_xattr_handler, 5261182fca3SMike Marshall &posix_acl_default_xattr_handler, 5278bb8aefdSYi Liu &orangefs_xattr_trusted_handler, 5288bb8aefdSYi Liu &orangefs_xattr_default_handler, 5291182fca3SMike Marshall NULL 5301182fca3SMike Marshall }; 531