^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2001 Clemson University and The University of Chicago
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2018 Omnibond Systems, L.L.C.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * See COPYING in top-level directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Linux VFS extended attribute operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "protocol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "orangefs-kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "orangefs-bufmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/posix_acl_xattr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/xattr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/hashtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SYSTEM_ORANGEFS_KEY_LEN 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * this function returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 0 if the key corresponding to name is not meant to be printed as part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * of a listxattr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 1 if the key corresponding to name is meant to be returned as part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * a listxattr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * The ones that start SYSTEM_ORANGEFS_KEY are the ones to avoid printing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int is_reserved_key(const char *key, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (size < SYSTEM_ORANGEFS_KEY_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return strncmp(key, SYSTEM_ORANGEFS_KEY, SYSTEM_ORANGEFS_KEY_LEN) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline int convert_to_internal_xattr_flags(int setxattr_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int internal_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (setxattr_flags & XATTR_REPLACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Attribute must exist! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) internal_flag = ORANGEFS_XATTR_REPLACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } else if (setxattr_flags & XATTR_CREATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Attribute must not exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) internal_flag = ORANGEFS_XATTR_CREATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return internal_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static unsigned int xattr_key(const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) while (key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) i += *key++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return i % 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct orangefs_cached_xattr *cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct hlist_head *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct hlist_node *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) h = &orangefs_inode->xattr_cache[xattr_key(key)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (hlist_empty(h))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hlist_for_each_entry_safe(cx, tmp, h, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* if (!time_before(jiffies, cx->timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) hlist_del(&cx->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) kfree(cx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!strcmp(cx->key, key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Tries to get a specified key's attributes of a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * file into a user-specified buffer. Note that the getxattr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * interface allows for the users to probe the size of an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * extended attribute by passing in a value of 0 to size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Thus our return value is always the size of the attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * unless the key does not exist for the file and/or if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * there were errors in fetching the attribute value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) void *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct orangefs_kernel_op_s *new_op = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct orangefs_cached_xattr *cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ssize_t ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ssize_t length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int fsuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int fsgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "%s: name %s, buffer_size %zd\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __func__, name, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (S_ISLNK(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) fsuid = from_kuid(&init_user_ns, current_fsuid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) fsgid = from_kgid(&init_user_ns, current_fsgid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "getxattr on inode %pU, name %s "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "(uid %o, gid %o)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) get_khandle_from_ino(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) fsuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fsgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) down_read(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cx = find_cached_xattr(inode, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (cx && time_before(jiffies, cx->timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (cx->length == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ret = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = cx->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (cx->length > size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) memcpy(buffer, cx->val, cx->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) memset(buffer + cx->length, 0, size - cx->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret = cx->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!new_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) new_op->upcall.req.getxattr.refn = orangefs_inode->refn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) strcpy(new_op->upcall.req.getxattr.key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * NOTE: Although keys are meant to be NULL terminated textual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * strings, I am going to explicitly pass the length just in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * we change this later on...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) new_op->upcall.req.getxattr.key_sz = strlen(name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = service_operation(new_op, "orangefs_inode_getxattr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) get_interruptible_flag(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ret == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) "orangefs_inode_getxattr: inode %pU key %s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) " does not exist!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) get_khandle_from_ino(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) (char *)new_op->upcall.req.getxattr.key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) cx = kmalloc(sizeof *cx, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) strcpy(cx->key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) cx->length = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) cx->timeout = jiffies +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) orangefs_getattr_timeout_msecs*HZ/1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) hash_add(orangefs_inode->xattr_cache, &cx->node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) xattr_key(cx->key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto out_release_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Length returned includes null terminator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) length = new_op->downcall.resp.getxattr.val_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * Just return the length of the queried attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ret = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto out_release_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * Check to see if key length is > provided buffer size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (length > size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out_release_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) memcpy(buffer, new_op->downcall.resp.getxattr.val, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) memset(buffer + length, 0, size - length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "orangefs_inode_getxattr: inode %pU "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "key %s key_sz %d, val_len %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) get_khandle_from_ino(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) (char *)new_op->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) upcall.req.getxattr.key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) (int)new_op->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) upcall.req.getxattr.key_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) (int)ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ret = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) strcpy(cx->key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) memcpy(cx->val, buffer, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cx->length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) cx->timeout = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) cx = kmalloc(sizeof *cx, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (cx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) strcpy(cx->key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) memcpy(cx->val, buffer, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) cx->length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) cx->timeout = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) hash_add(orangefs_inode->xattr_cache, &cx->node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) xattr_key(cx->key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) out_release_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) op_release(new_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) up_read(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int orangefs_inode_removexattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct orangefs_kernel_op_s *new_op = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct orangefs_cached_xattr *cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct hlist_head *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct hlist_node *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) down_write(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!new_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) new_op->upcall.req.removexattr.refn = orangefs_inode->refn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * NOTE: Although keys are meant to be NULL terminated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * textual strings, I am going to explicitly pass the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * length just in case we change this later on...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) strcpy(new_op->upcall.req.removexattr.key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) new_op->upcall.req.removexattr.key_sz = strlen(name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) "orangefs_inode_removexattr: key %s, key_sz %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) (char *)new_op->upcall.req.removexattr.key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) (int)new_op->upcall.req.removexattr.key_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ret = service_operation(new_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) "orangefs_inode_removexattr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) get_interruptible_flag(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (ret == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Request to replace a non-existent attribute is an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (flags & XATTR_REPLACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) "orangefs_inode_removexattr: returning %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) op_release(new_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) h = &orangefs_inode->xattr_cache[xattr_key(name)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) hlist_for_each_entry_safe(cx, tmp, h, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!strcmp(cx->key, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) hlist_del(&cx->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) kfree(cx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) up_write(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Tries to set an attribute for a given key on a file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * Returns a -ve number on error and 0 on success. Key is text, but value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * can be binary!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int orangefs_inode_setxattr(struct inode *inode, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const void *value, size_t size, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct orangefs_kernel_op_s *new_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int internal_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct orangefs_cached_xattr *cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct hlist_head *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct hlist_node *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "%s: name %s, buffer_size %zd\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) __func__, name, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (size > ORANGEFS_MAX_XATTR_VALUELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) internal_flag = convert_to_internal_xattr_flags(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* This is equivalent to a removexattr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (size == 0 && !value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) "removing xattr (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return orangefs_inode_removexattr(inode, name, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "setxattr on inode %pU, name %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) get_khandle_from_ino(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) down_write(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!new_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) new_op->upcall.req.setxattr.refn = orangefs_inode->refn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) new_op->upcall.req.setxattr.flags = internal_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * NOTE: Although keys are meant to be NULL terminated textual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * strings, I am going to explicitly pass the length just in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * case we change this later on...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) strcpy(new_op->upcall.req.setxattr.keyval.key, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) new_op->upcall.req.setxattr.keyval.key_sz = strlen(name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) memcpy(new_op->upcall.req.setxattr.keyval.val, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) new_op->upcall.req.setxattr.keyval.val_sz = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) "orangefs_inode_setxattr: key %s, key_sz %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) " value size %zd\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) (char *)new_op->upcall.req.setxattr.keyval.key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) (int)new_op->upcall.req.setxattr.keyval.key_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ret = service_operation(new_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) "orangefs_inode_setxattr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) get_interruptible_flag(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) gossip_debug(GOSSIP_XATTR_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) "orangefs_inode_setxattr: returning %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* when request is serviced properly, free req op struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) op_release(new_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) h = &orangefs_inode->xattr_cache[xattr_key(name)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) hlist_for_each_entry_safe(cx, tmp, h, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!strcmp(cx->key, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) hlist_del(&cx->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) kfree(cx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) up_write(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Tries to get a specified object's keys into a user-specified buffer of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * given size. Note that like the previous instances of xattr routines, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * also allows you to pass in a NULL pointer and 0 size to probe the size for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * subsequent memory allocations. Thus our return value is always the size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * all the keys unless there were errors in fetching the keys!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct inode *inode = dentry->d_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct orangefs_kernel_op_s *new_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) __u64 token = ORANGEFS_ITERATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ssize_t ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) ssize_t total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int count_keys = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int key_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int returned_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (size > 0 && !buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) gossip_err("%s: bogus NULL pointers\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) down_read(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!new_op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (buffer && size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) memset(buffer, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) try_again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) key_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) new_op->upcall.req.listxattr.refn = orangefs_inode->refn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) new_op->upcall.req.listxattr.token = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) new_op->upcall.req.listxattr.requested_count =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = service_operation(new_op, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) get_interruptible_flag(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * This is a bit of a big upper limit, but I did not want to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * spend too much time getting this correct, since users end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * up allocating memory rather than us...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) total = new_op->downcall.resp.listxattr.returned_count *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ORANGEFS_MAX_XATTR_NAMELEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) returned_count = new_op->downcall.resp.listxattr.returned_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (returned_count < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) returned_count > ORANGEFS_MAX_XATTR_LISTLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) gossip_err("%s: impossible value for returned_count:%d:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) returned_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * Check to see how much can be fit in the buffer. Fit only whole keys.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) for (i = 0; i < returned_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (new_op->downcall.resp.listxattr.lengths[i] < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) new_op->downcall.resp.listxattr.lengths[i] >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ORANGEFS_MAX_XATTR_NAMELEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) gossip_err("%s: impossible value for lengths[%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) new_op->downcall.resp.listxattr.lengths[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (total + new_op->downcall.resp.listxattr.lengths[i] > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Since many dumb programs try to setxattr() on our reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * xattrs this is a feeble attempt at defeating those by not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * listing them in the output of listxattr.. sigh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (is_reserved_key(new_op->downcall.resp.listxattr.key +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) key_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) new_op->downcall.resp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) listxattr.lengths[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) i, new_op->downcall.resp.listxattr.key +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) key_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) memcpy(buffer + total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) new_op->downcall.resp.listxattr.key + key_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) new_op->downcall.resp.listxattr.lengths[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) total += new_op->downcall.resp.listxattr.lengths[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) count_keys++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) i, new_op->downcall.resp.listxattr.key +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) key_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) key_size += new_op->downcall.resp.listxattr.lengths[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * Since the buffer was large enough, we might have to continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * fetching more keys!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) token = new_op->downcall.resp.listxattr.token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (token != ORANGEFS_ITERATE_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto try_again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) " [size of buffer %ld] (filled in %d keys)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ret ? (int)ret : (int)total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) (long)size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) count_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) op_release(new_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) up_read(&orangefs_inode->xattr_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int orangefs_xattr_set_default(const struct xattr_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct dentry *unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) const void *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return orangefs_inode_setxattr(inode, name, buffer, size, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int orangefs_xattr_get_default(const struct xattr_handler *handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct dentry *unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) void *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return orangefs_inode_getxattr(inode, name, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static const struct xattr_handler orangefs_xattr_default_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .prefix = "", /* match any name => handlers called with full name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .get = orangefs_xattr_get_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .set = orangefs_xattr_set_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) const struct xattr_handler *orangefs_xattr_handlers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) &posix_acl_access_xattr_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) &posix_acl_default_xattr_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) &orangefs_xattr_default_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) };