0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "protocol.h"
0014 #include "orangefs-kernel.h"
0015 #include "orangefs-bufmap.h"
0016 #include <linux/posix_acl_xattr.h>
0017 #include <linux/xattr.h>
0018 #include <linux/hashtable.h>
0019
0020 #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
0021 #define SYSTEM_ORANGEFS_KEY_LEN 13
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 static int is_reserved_key(const char *key, size_t size)
0032 {
0033
0034 if (size < SYSTEM_ORANGEFS_KEY_LEN)
0035 return 1;
0036
0037 return strncmp(key, SYSTEM_ORANGEFS_KEY, SYSTEM_ORANGEFS_KEY_LEN) ? 1 : 0;
0038 }
0039
0040 static inline int convert_to_internal_xattr_flags(int setxattr_flags)
0041 {
0042 int internal_flag = 0;
0043
0044 if (setxattr_flags & XATTR_REPLACE) {
0045
0046 internal_flag = ORANGEFS_XATTR_REPLACE;
0047 } else if (setxattr_flags & XATTR_CREATE) {
0048
0049 internal_flag = ORANGEFS_XATTR_CREATE;
0050 }
0051 return internal_flag;
0052 }
0053
0054 static unsigned int xattr_key(const char *key)
0055 {
0056 unsigned int i = 0;
0057 while (key)
0058 i += *key++;
0059 return i % 16;
0060 }
0061
0062 static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
0063 const char *key)
0064 {
0065 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0066 struct orangefs_cached_xattr *cx;
0067 struct hlist_head *h;
0068 struct hlist_node *tmp;
0069 h = &orangefs_inode->xattr_cache[xattr_key(key)];
0070 if (hlist_empty(h))
0071 return NULL;
0072 hlist_for_each_entry_safe(cx, tmp, h, node) {
0073
0074
0075
0076
0077
0078 if (!strcmp(cx->key, key))
0079 return cx;
0080 }
0081 return NULL;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
0094 void *buffer, size_t size)
0095 {
0096 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0097 struct orangefs_kernel_op_s *new_op = NULL;
0098 struct orangefs_cached_xattr *cx;
0099 ssize_t ret = -ENOMEM;
0100 ssize_t length = 0;
0101 int fsuid;
0102 int fsgid;
0103
0104 gossip_debug(GOSSIP_XATTR_DEBUG,
0105 "%s: name %s, buffer_size %zd\n",
0106 __func__, name, size);
0107
0108 if (S_ISLNK(inode->i_mode))
0109 return -EOPNOTSUPP;
0110
0111 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
0112 return -EINVAL;
0113
0114 fsuid = from_kuid(&init_user_ns, current_fsuid());
0115 fsgid = from_kgid(&init_user_ns, current_fsgid());
0116
0117 gossip_debug(GOSSIP_XATTR_DEBUG,
0118 "getxattr on inode %pU, name %s "
0119 "(uid %o, gid %o)\n",
0120 get_khandle_from_ino(inode),
0121 name,
0122 fsuid,
0123 fsgid);
0124
0125 down_read(&orangefs_inode->xattr_sem);
0126
0127 cx = find_cached_xattr(inode, name);
0128 if (cx && time_before(jiffies, cx->timeout)) {
0129 if (cx->length == -1) {
0130 ret = -ENODATA;
0131 goto out_unlock;
0132 } else {
0133 if (size == 0) {
0134 ret = cx->length;
0135 goto out_unlock;
0136 }
0137 if (cx->length > size) {
0138 ret = -ERANGE;
0139 goto out_unlock;
0140 }
0141 memcpy(buffer, cx->val, cx->length);
0142 memset(buffer + cx->length, 0, size - cx->length);
0143 ret = cx->length;
0144 goto out_unlock;
0145 }
0146 }
0147
0148 new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
0149 if (!new_op)
0150 goto out_unlock;
0151
0152 new_op->upcall.req.getxattr.refn = orangefs_inode->refn;
0153 strcpy(new_op->upcall.req.getxattr.key, name);
0154
0155
0156
0157
0158
0159
0160 new_op->upcall.req.getxattr.key_sz = strlen(name) + 1;
0161
0162 ret = service_operation(new_op, "orangefs_inode_getxattr",
0163 get_interruptible_flag(inode));
0164 if (ret != 0) {
0165 if (ret == -ENOENT) {
0166 ret = -ENODATA;
0167 gossip_debug(GOSSIP_XATTR_DEBUG,
0168 "orangefs_inode_getxattr: inode %pU key %s"
0169 " does not exist!\n",
0170 get_khandle_from_ino(inode),
0171 (char *)new_op->upcall.req.getxattr.key);
0172 cx = kmalloc(sizeof *cx, GFP_KERNEL);
0173 if (cx) {
0174 strcpy(cx->key, name);
0175 cx->length = -1;
0176 cx->timeout = jiffies +
0177 orangefs_getattr_timeout_msecs*HZ/1000;
0178 hash_add(orangefs_inode->xattr_cache, &cx->node,
0179 xattr_key(cx->key));
0180 }
0181 }
0182 goto out_release_op;
0183 }
0184
0185
0186
0187
0188 length = new_op->downcall.resp.getxattr.val_sz;
0189
0190
0191
0192
0193 if (size == 0) {
0194 ret = length;
0195 goto out_release_op;
0196 }
0197
0198
0199
0200
0201 if (length > size) {
0202 ret = -ERANGE;
0203 goto out_release_op;
0204 }
0205
0206 memcpy(buffer, new_op->downcall.resp.getxattr.val, length);
0207 memset(buffer + length, 0, size - length);
0208 gossip_debug(GOSSIP_XATTR_DEBUG,
0209 "orangefs_inode_getxattr: inode %pU "
0210 "key %s key_sz %d, val_len %d\n",
0211 get_khandle_from_ino(inode),
0212 (char *)new_op->
0213 upcall.req.getxattr.key,
0214 (int)new_op->
0215 upcall.req.getxattr.key_sz,
0216 (int)ret);
0217
0218 ret = length;
0219
0220 if (cx) {
0221 strcpy(cx->key, name);
0222 memcpy(cx->val, buffer, length);
0223 cx->length = length;
0224 cx->timeout = jiffies + HZ;
0225 } else {
0226 cx = kmalloc(sizeof *cx, GFP_KERNEL);
0227 if (cx) {
0228 strcpy(cx->key, name);
0229 memcpy(cx->val, buffer, length);
0230 cx->length = length;
0231 cx->timeout = jiffies + HZ;
0232 hash_add(orangefs_inode->xattr_cache, &cx->node,
0233 xattr_key(cx->key));
0234 }
0235 }
0236
0237 out_release_op:
0238 op_release(new_op);
0239 out_unlock:
0240 up_read(&orangefs_inode->xattr_sem);
0241 return ret;
0242 }
0243
0244 static int orangefs_inode_removexattr(struct inode *inode, const char *name,
0245 int flags)
0246 {
0247 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0248 struct orangefs_kernel_op_s *new_op = NULL;
0249 struct orangefs_cached_xattr *cx;
0250 struct hlist_head *h;
0251 struct hlist_node *tmp;
0252 int ret = -ENOMEM;
0253
0254 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
0255 return -EINVAL;
0256
0257 down_write(&orangefs_inode->xattr_sem);
0258 new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR);
0259 if (!new_op)
0260 goto out_unlock;
0261
0262 new_op->upcall.req.removexattr.refn = orangefs_inode->refn;
0263
0264
0265
0266
0267
0268 strcpy(new_op->upcall.req.removexattr.key, name);
0269 new_op->upcall.req.removexattr.key_sz = strlen(name) + 1;
0270
0271 gossip_debug(GOSSIP_XATTR_DEBUG,
0272 "orangefs_inode_removexattr: key %s, key_sz %d\n",
0273 (char *)new_op->upcall.req.removexattr.key,
0274 (int)new_op->upcall.req.removexattr.key_sz);
0275
0276 ret = service_operation(new_op,
0277 "orangefs_inode_removexattr",
0278 get_interruptible_flag(inode));
0279 if (ret == -ENOENT) {
0280
0281
0282
0283 if (flags & XATTR_REPLACE)
0284 ret = -ENODATA;
0285 else
0286 ret = 0;
0287 }
0288
0289 gossip_debug(GOSSIP_XATTR_DEBUG,
0290 "orangefs_inode_removexattr: returning %d\n", ret);
0291
0292 op_release(new_op);
0293
0294 h = &orangefs_inode->xattr_cache[xattr_key(name)];
0295 hlist_for_each_entry_safe(cx, tmp, h, node) {
0296 if (!strcmp(cx->key, name)) {
0297 hlist_del(&cx->node);
0298 kfree(cx);
0299 break;
0300 }
0301 }
0302
0303 out_unlock:
0304 up_write(&orangefs_inode->xattr_sem);
0305 return ret;
0306 }
0307
0308
0309
0310
0311
0312
0313
0314 int orangefs_inode_setxattr(struct inode *inode, const char *name,
0315 const void *value, size_t size, int flags)
0316 {
0317 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0318 struct orangefs_kernel_op_s *new_op;
0319 int internal_flag = 0;
0320 struct orangefs_cached_xattr *cx;
0321 struct hlist_head *h;
0322 struct hlist_node *tmp;
0323 int ret = -ENOMEM;
0324
0325 gossip_debug(GOSSIP_XATTR_DEBUG,
0326 "%s: name %s, buffer_size %zd\n",
0327 __func__, name, size);
0328
0329 if (size > ORANGEFS_MAX_XATTR_VALUELEN)
0330 return -EINVAL;
0331 if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
0332 return -EINVAL;
0333
0334 internal_flag = convert_to_internal_xattr_flags(flags);
0335
0336
0337 if (size == 0 && !value) {
0338 gossip_debug(GOSSIP_XATTR_DEBUG,
0339 "removing xattr (%s)\n",
0340 name);
0341 return orangefs_inode_removexattr(inode, name, flags);
0342 }
0343
0344 gossip_debug(GOSSIP_XATTR_DEBUG,
0345 "setxattr on inode %pU, name %s\n",
0346 get_khandle_from_ino(inode),
0347 name);
0348
0349 down_write(&orangefs_inode->xattr_sem);
0350 new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR);
0351 if (!new_op)
0352 goto out_unlock;
0353
0354
0355 new_op->upcall.req.setxattr.refn = orangefs_inode->refn;
0356 new_op->upcall.req.setxattr.flags = internal_flag;
0357
0358
0359
0360
0361
0362 strcpy(new_op->upcall.req.setxattr.keyval.key, name);
0363 new_op->upcall.req.setxattr.keyval.key_sz = strlen(name) + 1;
0364 memcpy(new_op->upcall.req.setxattr.keyval.val, value, size);
0365 new_op->upcall.req.setxattr.keyval.val_sz = size;
0366
0367 gossip_debug(GOSSIP_XATTR_DEBUG,
0368 "orangefs_inode_setxattr: key %s, key_sz %d "
0369 " value size %zd\n",
0370 (char *)new_op->upcall.req.setxattr.keyval.key,
0371 (int)new_op->upcall.req.setxattr.keyval.key_sz,
0372 size);
0373
0374 ret = service_operation(new_op,
0375 "orangefs_inode_setxattr",
0376 get_interruptible_flag(inode));
0377
0378 gossip_debug(GOSSIP_XATTR_DEBUG,
0379 "orangefs_inode_setxattr: returning %d\n",
0380 ret);
0381
0382
0383 op_release(new_op);
0384
0385 h = &orangefs_inode->xattr_cache[xattr_key(name)];
0386 hlist_for_each_entry_safe(cx, tmp, h, node) {
0387 if (!strcmp(cx->key, name)) {
0388 hlist_del(&cx->node);
0389 kfree(cx);
0390 break;
0391 }
0392 }
0393
0394 out_unlock:
0395 up_write(&orangefs_inode->xattr_sem);
0396 return ret;
0397 }
0398
0399
0400
0401
0402
0403
0404
0405
0406 ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
0407 {
0408 struct inode *inode = dentry->d_inode;
0409 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
0410 struct orangefs_kernel_op_s *new_op;
0411 __u64 token = ORANGEFS_ITERATE_START;
0412 ssize_t ret = -ENOMEM;
0413 ssize_t total = 0;
0414 int count_keys = 0;
0415 int key_size;
0416 int i = 0;
0417 int returned_count = 0;
0418
0419 if (size > 0 && !buffer) {
0420 gossip_err("%s: bogus NULL pointers\n", __func__);
0421 return -EINVAL;
0422 }
0423
0424 down_read(&orangefs_inode->xattr_sem);
0425 new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR);
0426 if (!new_op)
0427 goto out_unlock;
0428
0429 if (buffer && size > 0)
0430 memset(buffer, 0, size);
0431
0432 try_again:
0433 key_size = 0;
0434 new_op->upcall.req.listxattr.refn = orangefs_inode->refn;
0435 new_op->upcall.req.listxattr.token = token;
0436 new_op->upcall.req.listxattr.requested_count =
0437 (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN;
0438 ret = service_operation(new_op, __func__,
0439 get_interruptible_flag(inode));
0440 if (ret != 0)
0441 goto done;
0442
0443 if (size == 0) {
0444
0445
0446
0447
0448
0449 total = new_op->downcall.resp.listxattr.returned_count *
0450 ORANGEFS_MAX_XATTR_NAMELEN;
0451 goto done;
0452 }
0453
0454 returned_count = new_op->downcall.resp.listxattr.returned_count;
0455 if (returned_count < 0 ||
0456 returned_count > ORANGEFS_MAX_XATTR_LISTLEN) {
0457 gossip_err("%s: impossible value for returned_count:%d:\n",
0458 __func__,
0459 returned_count);
0460 ret = -EIO;
0461 goto done;
0462 }
0463
0464
0465
0466
0467 for (i = 0; i < returned_count; i++) {
0468 if (new_op->downcall.resp.listxattr.lengths[i] < 0 ||
0469 new_op->downcall.resp.listxattr.lengths[i] >
0470 ORANGEFS_MAX_XATTR_NAMELEN) {
0471 gossip_err("%s: impossible value for lengths[%d]\n",
0472 __func__,
0473 new_op->downcall.resp.listxattr.lengths[i]);
0474 ret = -EIO;
0475 goto done;
0476 }
0477 if (total + new_op->downcall.resp.listxattr.lengths[i] > size)
0478 goto done;
0479
0480
0481
0482
0483
0484
0485 if (is_reserved_key(new_op->downcall.resp.listxattr.key +
0486 key_size,
0487 new_op->downcall.resp.
0488 listxattr.lengths[i])) {
0489 gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n",
0490 i, new_op->downcall.resp.listxattr.key +
0491 key_size);
0492 memcpy(buffer + total,
0493 new_op->downcall.resp.listxattr.key + key_size,
0494 new_op->downcall.resp.listxattr.lengths[i]);
0495 total += new_op->downcall.resp.listxattr.lengths[i];
0496 count_keys++;
0497 } else {
0498 gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n",
0499 i, new_op->downcall.resp.listxattr.key +
0500 key_size);
0501 }
0502 key_size += new_op->downcall.resp.listxattr.lengths[i];
0503 }
0504
0505
0506
0507
0508
0509 token = new_op->downcall.resp.listxattr.token;
0510 if (token != ORANGEFS_ITERATE_END)
0511 goto try_again;
0512
0513 done:
0514 gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d"
0515 " [size of buffer %ld] (filled in %d keys)\n",
0516 __func__,
0517 ret ? (int)ret : (int)total,
0518 (long)size,
0519 count_keys);
0520 op_release(new_op);
0521 if (ret == 0)
0522 ret = total;
0523 out_unlock:
0524 up_read(&orangefs_inode->xattr_sem);
0525 return ret;
0526 }
0527
0528 static int orangefs_xattr_set_default(const struct xattr_handler *handler,
0529 struct user_namespace *mnt_userns,
0530 struct dentry *unused,
0531 struct inode *inode,
0532 const char *name,
0533 const void *buffer,
0534 size_t size,
0535 int flags)
0536 {
0537 return orangefs_inode_setxattr(inode, name, buffer, size, flags);
0538 }
0539
0540 static int orangefs_xattr_get_default(const struct xattr_handler *handler,
0541 struct dentry *unused,
0542 struct inode *inode,
0543 const char *name,
0544 void *buffer,
0545 size_t size)
0546 {
0547 return orangefs_inode_getxattr(inode, name, buffer, size);
0548
0549 }
0550
0551 static const struct xattr_handler orangefs_xattr_default_handler = {
0552 .prefix = "",
0553 .get = orangefs_xattr_get_default,
0554 .set = orangefs_xattr_set_default,
0555 };
0556
0557 const struct xattr_handler *orangefs_xattr_handlers[] = {
0558 &posix_acl_access_xattr_handler,
0559 &posix_acl_default_xattr_handler,
0560 &orangefs_xattr_default_handler,
0561 NULL
0562 };