Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xattr: move user limits for xattrs to generic infra

Link: https://patch.msgid.link/20260216-work-xattr-socket-v1-9-c2efa4f74cb7@kernel.org
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+87 -76
+3 -72
fs/kernfs/inode.c
··· 45 45 ret->ia_mtime = ret->ia_atime; 46 46 ret->ia_ctime = ret->ia_atime; 47 47 48 - atomic_set(&ret->nr_user_xattrs, 0); 49 - atomic_set(&ret->user_xattr_size, 0); 48 + simple_xattr_limits_init(&ret->xattr_limits); 50 49 51 50 /* If someone raced us, recognize it. */ 52 51 if (!try_cmpxchg(&kn->iattr, &attr, ret)) ··· 354 355 return kernfs_xattr_set(kn, name, value, size, flags); 355 356 } 356 357 357 - static int kernfs_vfs_user_xattr_add(struct kernfs_node *kn, 358 - const char *full_name, 359 - struct simple_xattrs *xattrs, 360 - const void *value, size_t size, int flags) 361 - { 362 - struct kernfs_iattrs *attr = kernfs_iattrs_noalloc(kn); 363 - atomic_t *sz = &attr->user_xattr_size; 364 - atomic_t *nr = &attr->nr_user_xattrs; 365 - struct simple_xattr *old_xattr; 366 - int ret; 367 - 368 - if (atomic_inc_return(nr) > KERNFS_MAX_USER_XATTRS) { 369 - ret = -ENOSPC; 370 - goto dec_count_out; 371 - } 372 - 373 - if (atomic_add_return(size, sz) > KERNFS_USER_XATTR_SIZE_LIMIT) { 374 - ret = -ENOSPC; 375 - goto dec_size_out; 376 - } 377 - 378 - old_xattr = simple_xattr_set(xattrs, full_name, value, size, flags); 379 - if (!old_xattr) 380 - return 0; 381 - 382 - if (IS_ERR(old_xattr)) { 383 - ret = PTR_ERR(old_xattr); 384 - goto dec_size_out; 385 - } 386 - 387 - ret = 0; 388 - size = old_xattr->size; 389 - simple_xattr_free_rcu(old_xattr); 390 - dec_size_out: 391 - atomic_sub(size, sz); 392 - dec_count_out: 393 - atomic_dec(nr); 394 - return ret; 395 - } 396 - 397 - static int kernfs_vfs_user_xattr_rm(struct kernfs_node *kn, 398 - const char *full_name, 399 - struct simple_xattrs *xattrs, 400 - const void *value, size_t size, int flags) 401 - { 402 - struct kernfs_iattrs *attr = kernfs_iattrs_noalloc(kn); 403 - atomic_t *sz = &attr->user_xattr_size; 404 - atomic_t *nr = &attr->nr_user_xattrs; 405 - struct simple_xattr *old_xattr; 406 - 407 - old_xattr = simple_xattr_set(xattrs, full_name, value, size, flags); 408 - if (!old_xattr) 409 - return 0; 410 - 411 - if (IS_ERR(old_xattr)) 412 - return PTR_ERR(old_xattr); 413 - 414 - atomic_sub(old_xattr->size, sz); 415 - atomic_dec(nr); 416 - simple_xattr_free_rcu(old_xattr); 417 - return 0; 418 - } 419 - 420 358 static int kernfs_vfs_user_xattr_set(const struct xattr_handler *handler, 421 359 struct mnt_idmap *idmap, 422 360 struct dentry *unused, struct inode *inode, ··· 376 440 if (IS_ERR_OR_NULL(xattrs)) 377 441 return PTR_ERR(xattrs); 378 442 379 - if (value) 380 - return kernfs_vfs_user_xattr_add(kn, full_name, xattrs, 381 - value, size, flags); 382 - else 383 - return kernfs_vfs_user_xattr_rm(kn, full_name, xattrs, 384 - value, size, flags); 385 - 443 + return simple_xattr_set_limited(xattrs, &attrs->xattr_limits, 444 + full_name, value, size, flags); 386 445 } 387 446 388 447 static const struct xattr_handler kernfs_trusted_xattr_handler = {
+1 -2
fs/kernfs/kernfs-internal.h
··· 27 27 struct timespec64 ia_ctime; 28 28 29 29 struct simple_xattrs *xattrs; 30 - atomic_t nr_user_xattrs; 31 - atomic_t user_xattr_size; 30 + struct simple_xattr_limits xattr_limits; 32 31 }; 33 32 34 33 struct kernfs_root {
+65
fs/xattr.c
··· 1427 1427 return old_xattr; 1428 1428 } 1429 1429 1430 + static inline void simple_xattr_limits_dec(struct simple_xattr_limits *limits, 1431 + size_t size) 1432 + { 1433 + atomic_sub(size, &limits->xattr_size); 1434 + atomic_dec(&limits->nr_xattrs); 1435 + } 1436 + 1437 + static inline int simple_xattr_limits_inc(struct simple_xattr_limits *limits, 1438 + size_t size) 1439 + { 1440 + if (atomic_inc_return(&limits->nr_xattrs) > SIMPLE_XATTR_MAX_NR) { 1441 + atomic_dec(&limits->nr_xattrs); 1442 + return -ENOSPC; 1443 + } 1444 + 1445 + if (atomic_add_return(size, &limits->xattr_size) <= SIMPLE_XATTR_MAX_SIZE) 1446 + return 0; 1447 + 1448 + simple_xattr_limits_dec(limits, size); 1449 + return -ENOSPC; 1450 + } 1451 + 1452 + /** 1453 + * simple_xattr_set_limited - set an xattr with per-inode user.* limits 1454 + * @xattrs: the header of the xattr object 1455 + * @limits: per-inode limit counters for user.* xattrs 1456 + * @name: the name of the xattr to set or remove 1457 + * @value: the value to store (NULL to remove) 1458 + * @size: the size of @value 1459 + * @flags: XATTR_CREATE, XATTR_REPLACE, or 0 1460 + * 1461 + * Like simple_xattr_set(), but enforces per-inode count and total value size 1462 + * limits for user.* xattrs. Uses speculative pre-increment of the atomic 1463 + * counters to avoid races without requiring external locks. 1464 + * 1465 + * Return: On success zero is returned. On failure a negative error code is 1466 + * returned. 1467 + */ 1468 + int simple_xattr_set_limited(struct simple_xattrs *xattrs, 1469 + struct simple_xattr_limits *limits, 1470 + const char *name, const void *value, 1471 + size_t size, int flags) 1472 + { 1473 + struct simple_xattr *old_xattr; 1474 + int ret; 1475 + 1476 + if (value) { 1477 + ret = simple_xattr_limits_inc(limits, size); 1478 + if (ret) 1479 + return ret; 1480 + } 1481 + 1482 + old_xattr = simple_xattr_set(xattrs, name, value, size, flags); 1483 + if (IS_ERR(old_xattr)) { 1484 + if (value) 1485 + simple_xattr_limits_dec(limits, size); 1486 + return PTR_ERR(old_xattr); 1487 + } 1488 + if (old_xattr) { 1489 + simple_xattr_limits_dec(limits, old_xattr->size); 1490 + simple_xattr_free_rcu(old_xattr); 1491 + } 1492 + return 0; 1493 + } 1494 + 1430 1495 static bool xattr_is_trusted(const char *name) 1431 1496 { 1432 1497 return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
-2
include/linux/kernfs.h
··· 99 99 100 100 #define KERNFS_TYPE_MASK 0x000f 101 101 #define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK 102 - #define KERNFS_MAX_USER_XATTRS 128 103 - #define KERNFS_USER_XATTR_SIZE_LIMIT (128 << 10) 104 102 105 103 enum kernfs_node_flag { 106 104 KERNFS_ACTIVATED = 0x0010,
+18
include/linux/xattr.h
··· 118 118 char value[] __counted_by(size); 119 119 }; 120 120 121 + #define SIMPLE_XATTR_MAX_NR 128 122 + #define SIMPLE_XATTR_MAX_SIZE (128 << 10) 123 + 124 + struct simple_xattr_limits { 125 + atomic_t nr_xattrs; /* current user.* xattr count */ 126 + atomic_t xattr_size; /* current total user.* value bytes */ 127 + }; 128 + 129 + static inline void simple_xattr_limits_init(struct simple_xattr_limits *limits) 130 + { 131 + atomic_set(&limits->nr_xattrs, 0); 132 + atomic_set(&limits->xattr_size, 0); 133 + } 134 + 121 135 int simple_xattrs_init(struct simple_xattrs *xattrs); 122 136 struct simple_xattrs *simple_xattrs_alloc(void); 123 137 struct simple_xattrs *simple_xattrs_lazy_alloc(struct simple_xattrs **xattrsp, ··· 146 132 struct simple_xattr *simple_xattr_set(struct simple_xattrs *xattrs, 147 133 const char *name, const void *value, 148 134 size_t size, int flags); 135 + int simple_xattr_set_limited(struct simple_xattrs *xattrs, 136 + struct simple_xattr_limits *limits, 137 + const char *name, const void *value, 138 + size_t size, int flags); 149 139 ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, 150 140 char *buffer, size_t size); 151 141 int simple_xattr_add(struct simple_xattrs *xattrs,