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: add rhashtable-based simple_xattr infrastructure

Add rhashtable support to the simple_xattr subsystem while keeping the
existing rbtree code fully functional. This allows consumers to be
migrated one at a time without breaking any intermediate build.

struct simple_xattrs gains a dispatch flag and a union holding either
the rbtree (rb_root + rwlock) or rhashtable state:

struct simple_xattrs {
bool use_rhashtable;
union {
struct { struct rb_root rb_root; rwlock_t lock; };
struct rhashtable ht;
};
};

simple_xattrs_init() continues to set up the rbtree path for existing
embedded-struct callers.

Add simple_xattrs_alloc() which dynamically allocates a simple_xattrs
and initializes the rhashtable path. This is the entry point for
consumers switching to pointer-based lazy allocation.

The five core functions (get, set, list, add, free) dispatch based on
the use_rhashtable flag.

Existing callers continue to use the rbtree path unchanged. As each
consumer is converted it will switch to simple_xattrs_alloc() and the
rhashtable path. Once all consumers are converted a follow-up patch
will remove the rbtree code.

Link: https://patch.msgid.link/20260216-work-xattr-socket-v1-2-c2efa4f74cb7@kernel.org
Acked-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+356 -108
+332 -105
fs/xattr.c
··· 22 22 #include <linux/audit.h> 23 23 #include <linux/vmalloc.h> 24 24 #include <linux/posix_acl_xattr.h> 25 + #include <linux/rhashtable.h> 25 26 26 27 #include <linux/uaccess.h> 27 28 ··· 1229 1228 * Allocate a new xattr object and initialize respective members. The caller is 1230 1229 * responsible for handling the name of the xattr. 1231 1230 * 1232 - * Return: On success a new xattr object is returned. On failure NULL is 1233 - * returned. 1231 + * Return: New xattr object on success, NULL if @value is NULL, ERR_PTR on 1232 + * failure. 1234 1233 */ 1235 1234 struct simple_xattr *simple_xattr_alloc(const void *value, size_t size) 1236 1235 { 1237 1236 struct simple_xattr *new_xattr; 1238 1237 size_t len; 1239 1238 1239 + if (!value) 1240 + return NULL; 1241 + 1240 1242 /* wrap around? */ 1241 1243 len = sizeof(*new_xattr) + size; 1242 1244 if (len < sizeof(*new_xattr)) 1243 - return NULL; 1245 + return ERR_PTR(-ENOMEM); 1244 1246 1245 1247 new_xattr = kvmalloc(len, GFP_KERNEL_ACCOUNT); 1246 1248 if (!new_xattr) 1247 - return NULL; 1249 + return ERR_PTR(-ENOMEM); 1248 1250 1249 1251 new_xattr->size = size; 1250 1252 memcpy(new_xattr->value, value, size); ··· 1291 1287 return rbtree_simple_xattr_cmp(xattr->name, node); 1292 1288 } 1293 1289 1290 + static u32 simple_xattr_hashfn(const void *data, u32 len, u32 seed) 1291 + { 1292 + const char *name = data; 1293 + return jhash(name, strlen(name), seed); 1294 + } 1295 + 1296 + static u32 simple_xattr_obj_hashfn(const void *obj, u32 len, u32 seed) 1297 + { 1298 + const struct simple_xattr *xattr = obj; 1299 + return jhash(xattr->name, strlen(xattr->name), seed); 1300 + } 1301 + 1302 + static int simple_xattr_obj_cmpfn(struct rhashtable_compare_arg *arg, 1303 + const void *obj) 1304 + { 1305 + const struct simple_xattr *xattr = obj; 1306 + return strcmp(xattr->name, arg->key); 1307 + } 1308 + 1309 + static const struct rhashtable_params simple_xattr_params = { 1310 + .head_offset = offsetof(struct simple_xattr, hash_node), 1311 + .hashfn = simple_xattr_hashfn, 1312 + .obj_hashfn = simple_xattr_obj_hashfn, 1313 + .obj_cmpfn = simple_xattr_obj_cmpfn, 1314 + .automatic_shrinking = true, 1315 + }; 1316 + 1294 1317 /** 1295 1318 * simple_xattr_get - get an xattr object 1296 1319 * @xattrs: the header of the xattr object ··· 1337 1306 void *buffer, size_t size) 1338 1307 { 1339 1308 struct simple_xattr *xattr = NULL; 1340 - struct rb_node *rbp; 1341 1309 int ret = -ENODATA; 1342 1310 1343 - read_lock(&xattrs->lock); 1344 - rbp = rb_find(name, &xattrs->rb_root, rbtree_simple_xattr_cmp); 1345 - if (rbp) { 1346 - xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1347 - ret = xattr->size; 1348 - if (buffer) { 1349 - if (size < xattr->size) 1350 - ret = -ERANGE; 1351 - else 1352 - memcpy(buffer, xattr->value, xattr->size); 1311 + if (xattrs->use_rhashtable) { 1312 + guard(rcu)(); 1313 + xattr = rhashtable_lookup(&xattrs->ht, name, 1314 + simple_xattr_params); 1315 + if (xattr) { 1316 + ret = xattr->size; 1317 + if (buffer) { 1318 + if (size < xattr->size) 1319 + ret = -ERANGE; 1320 + else 1321 + memcpy(buffer, xattr->value, 1322 + xattr->size); 1323 + } 1353 1324 } 1325 + } else { 1326 + struct rb_node *rbp; 1327 + 1328 + read_lock(&xattrs->lock); 1329 + rbp = rb_find(name, &xattrs->rb_root, 1330 + rbtree_simple_xattr_cmp); 1331 + if (rbp) { 1332 + xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1333 + ret = xattr->size; 1334 + if (buffer) { 1335 + if (size < xattr->size) 1336 + ret = -ERANGE; 1337 + else 1338 + memcpy(buffer, xattr->value, 1339 + xattr->size); 1340 + } 1341 + } 1342 + read_unlock(&xattrs->lock); 1354 1343 } 1355 - read_unlock(&xattrs->lock); 1356 1344 return ret; 1357 1345 } 1358 1346 ··· 1405 1355 const char *name, const void *value, 1406 1356 size_t size, int flags) 1407 1357 { 1408 - struct simple_xattr *old_xattr = NULL, *new_xattr = NULL; 1409 - struct rb_node *parent = NULL, **rbp; 1410 - int err = 0, ret; 1358 + struct simple_xattr *old_xattr = NULL; 1359 + int err = 0; 1411 1360 1412 - /* value == NULL means remove */ 1413 - if (value) { 1414 - new_xattr = simple_xattr_alloc(value, size); 1415 - if (!new_xattr) 1416 - return ERR_PTR(-ENOMEM); 1361 + CLASS(simple_xattr, new_xattr)(value, size); 1362 + if (IS_ERR(new_xattr)) 1363 + return new_xattr; 1417 1364 1365 + if (new_xattr) { 1418 1366 new_xattr->name = kstrdup(name, GFP_KERNEL_ACCOUNT); 1419 - if (!new_xattr->name) { 1420 - simple_xattr_free(new_xattr); 1367 + if (!new_xattr->name) 1421 1368 return ERR_PTR(-ENOMEM); 1422 - } 1423 1369 } 1424 1370 1425 - write_lock(&xattrs->lock); 1426 - rbp = &xattrs->rb_root.rb_node; 1427 - while (*rbp) { 1428 - parent = *rbp; 1429 - ret = rbtree_simple_xattr_cmp(name, *rbp); 1430 - if (ret < 0) 1431 - rbp = &(*rbp)->rb_left; 1432 - else if (ret > 0) 1433 - rbp = &(*rbp)->rb_right; 1434 - else 1435 - old_xattr = rb_entry(*rbp, struct simple_xattr, rb_node); 1436 - if (old_xattr) 1437 - break; 1438 - } 1371 + if (xattrs->use_rhashtable) { 1372 + /* 1373 + * Lookup is safe without RCU here since writes are 1374 + * serialized by the caller. 1375 + */ 1376 + old_xattr = rhashtable_lookup_fast(&xattrs->ht, name, 1377 + simple_xattr_params); 1439 1378 1440 - if (old_xattr) { 1441 - /* Fail if XATTR_CREATE is requested and the xattr exists. */ 1442 - if (flags & XATTR_CREATE) { 1443 - err = -EEXIST; 1444 - goto out_unlock; 1379 + if (old_xattr) { 1380 + /* Fail if XATTR_CREATE is requested and the xattr exists. */ 1381 + if (flags & XATTR_CREATE) 1382 + return ERR_PTR(-EEXIST); 1383 + 1384 + if (new_xattr) { 1385 + err = rhashtable_replace_fast(&xattrs->ht, 1386 + &old_xattr->hash_node, 1387 + &new_xattr->hash_node, 1388 + simple_xattr_params); 1389 + if (err) 1390 + return ERR_PTR(err); 1391 + } else { 1392 + err = rhashtable_remove_fast(&xattrs->ht, 1393 + &old_xattr->hash_node, 1394 + simple_xattr_params); 1395 + if (err) 1396 + return ERR_PTR(err); 1397 + } 1398 + } else { 1399 + /* Fail if XATTR_REPLACE is requested but no xattr is found. */ 1400 + if (flags & XATTR_REPLACE) 1401 + return ERR_PTR(-ENODATA); 1402 + 1403 + /* 1404 + * If XATTR_CREATE or no flags are specified together 1405 + * with a new value simply insert it. 1406 + */ 1407 + if (new_xattr) { 1408 + err = rhashtable_insert_fast(&xattrs->ht, 1409 + &new_xattr->hash_node, 1410 + simple_xattr_params); 1411 + if (err) 1412 + return ERR_PTR(err); 1413 + } 1414 + 1415 + /* 1416 + * If XATTR_CREATE or no flags are specified and 1417 + * neither an old or new xattr exist then we don't 1418 + * need to do anything. 1419 + */ 1445 1420 } 1446 - 1447 - if (new_xattr) 1448 - rb_replace_node(&old_xattr->rb_node, 1449 - &new_xattr->rb_node, &xattrs->rb_root); 1450 - else 1451 - rb_erase(&old_xattr->rb_node, &xattrs->rb_root); 1452 1421 } else { 1453 - /* Fail if XATTR_REPLACE is requested but no xattr is found. */ 1454 - if (flags & XATTR_REPLACE) { 1455 - err = -ENODATA; 1456 - goto out_unlock; 1422 + struct rb_node *parent = NULL, **rbp; 1423 + int ret; 1424 + 1425 + write_lock(&xattrs->lock); 1426 + rbp = &xattrs->rb_root.rb_node; 1427 + while (*rbp) { 1428 + parent = *rbp; 1429 + ret = rbtree_simple_xattr_cmp(name, *rbp); 1430 + if (ret < 0) 1431 + rbp = &(*rbp)->rb_left; 1432 + else if (ret > 0) 1433 + rbp = &(*rbp)->rb_right; 1434 + else 1435 + old_xattr = rb_entry(*rbp, struct simple_xattr, 1436 + rb_node); 1437 + if (old_xattr) 1438 + break; 1457 1439 } 1458 1440 1459 - /* 1460 - * If XATTR_CREATE or no flags are specified together with a 1461 - * new value simply insert it. 1462 - */ 1463 - if (new_xattr) { 1464 - rb_link_node(&new_xattr->rb_node, parent, rbp); 1465 - rb_insert_color(&new_xattr->rb_node, &xattrs->rb_root); 1466 - } 1441 + if (old_xattr) { 1442 + /* Fail if XATTR_CREATE is requested and the xattr exists. */ 1443 + if (flags & XATTR_CREATE) { 1444 + err = -EEXIST; 1445 + goto out_unlock; 1446 + } 1467 1447 1468 - /* 1469 - * If XATTR_CREATE or no flags are specified and neither an 1470 - * old or new xattr exist then we don't need to do anything. 1471 - */ 1472 - } 1448 + if (new_xattr) 1449 + rb_replace_node(&old_xattr->rb_node, 1450 + &new_xattr->rb_node, 1451 + &xattrs->rb_root); 1452 + else 1453 + rb_erase(&old_xattr->rb_node, 1454 + &xattrs->rb_root); 1455 + } else { 1456 + /* Fail if XATTR_REPLACE is requested but no xattr is found. */ 1457 + if (flags & XATTR_REPLACE) { 1458 + err = -ENODATA; 1459 + goto out_unlock; 1460 + } 1461 + 1462 + /* 1463 + * If XATTR_CREATE or no flags are specified together 1464 + * with a new value simply insert it. 1465 + */ 1466 + if (new_xattr) { 1467 + rb_link_node(&new_xattr->rb_node, parent, rbp); 1468 + rb_insert_color(&new_xattr->rb_node, 1469 + &xattrs->rb_root); 1470 + } 1471 + 1472 + /* 1473 + * If XATTR_CREATE or no flags are specified and 1474 + * neither an old or new xattr exist then we don't 1475 + * need to do anything. 1476 + */ 1477 + } 1473 1478 1474 1479 out_unlock: 1475 - write_unlock(&xattrs->lock); 1476 - if (!err) 1477 - return old_xattr; 1478 - simple_xattr_free(new_xattr); 1479 - return ERR_PTR(err); 1480 + write_unlock(&xattrs->lock); 1481 + if (err) 1482 + return ERR_PTR(err); 1483 + } 1484 + retain_and_null_ptr(new_xattr); 1485 + return old_xattr; 1480 1486 } 1481 1487 1482 1488 static bool xattr_is_trusted(const char *name) ··· 1573 1467 { 1574 1468 bool trusted = ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN); 1575 1469 struct simple_xattr *xattr; 1576 - struct rb_node *rbp; 1577 1470 ssize_t remaining_size = size; 1578 1471 int err = 0; 1579 1472 ··· 1592 1487 remaining_size -= err; 1593 1488 err = 0; 1594 1489 1595 - read_lock(&xattrs->lock); 1596 - for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { 1597 - xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1490 + if (!xattrs) 1491 + return size - remaining_size; 1598 1492 1599 - /* skip "trusted." attributes for unprivileged callers */ 1600 - if (!trusted && xattr_is_trusted(xattr->name)) 1601 - continue; 1493 + if (xattrs->use_rhashtable) { 1494 + struct rhashtable_iter iter; 1602 1495 1603 - /* skip MAC labels; these are provided by LSM above */ 1604 - if (xattr_is_maclabel(xattr->name)) 1605 - continue; 1496 + rhashtable_walk_enter(&xattrs->ht, &iter); 1497 + rhashtable_walk_start(&iter); 1606 1498 1607 - err = xattr_list_one(&buffer, &remaining_size, xattr->name); 1608 - if (err) 1609 - break; 1499 + while ((xattr = rhashtable_walk_next(&iter)) != NULL) { 1500 + if (IS_ERR(xattr)) { 1501 + if (PTR_ERR(xattr) == -EAGAIN) 1502 + continue; 1503 + err = PTR_ERR(xattr); 1504 + break; 1505 + } 1506 + 1507 + /* skip "trusted." attributes for unprivileged callers */ 1508 + if (!trusted && xattr_is_trusted(xattr->name)) 1509 + continue; 1510 + 1511 + /* skip MAC labels; these are provided by LSM above */ 1512 + if (xattr_is_maclabel(xattr->name)) 1513 + continue; 1514 + 1515 + err = xattr_list_one(&buffer, &remaining_size, 1516 + xattr->name); 1517 + if (err) 1518 + break; 1519 + } 1520 + 1521 + rhashtable_walk_stop(&iter); 1522 + rhashtable_walk_exit(&iter); 1523 + } else { 1524 + struct rb_node *rbp; 1525 + 1526 + read_lock(&xattrs->lock); 1527 + for (rbp = rb_first(&xattrs->rb_root); rbp; 1528 + rbp = rb_next(rbp)) { 1529 + xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1530 + 1531 + /* skip "trusted." attributes for unprivileged callers */ 1532 + if (!trusted && xattr_is_trusted(xattr->name)) 1533 + continue; 1534 + 1535 + /* skip MAC labels; these are provided by LSM above */ 1536 + if (xattr_is_maclabel(xattr->name)) 1537 + continue; 1538 + 1539 + err = xattr_list_one(&buffer, &remaining_size, 1540 + xattr->name); 1541 + if (err) 1542 + break; 1543 + } 1544 + read_unlock(&xattrs->lock); 1610 1545 } 1611 - read_unlock(&xattrs->lock); 1612 1546 1613 1547 return err ? err : size - remaining_size; 1614 1548 } ··· 1680 1536 void simple_xattr_add(struct simple_xattrs *xattrs, 1681 1537 struct simple_xattr *new_xattr) 1682 1538 { 1683 - write_lock(&xattrs->lock); 1684 - rb_add(&new_xattr->rb_node, &xattrs->rb_root, rbtree_simple_xattr_less); 1685 - write_unlock(&xattrs->lock); 1539 + if (xattrs->use_rhashtable) { 1540 + WARN_ON(rhashtable_insert_fast(&xattrs->ht, 1541 + &new_xattr->hash_node, 1542 + simple_xattr_params)); 1543 + } else { 1544 + write_lock(&xattrs->lock); 1545 + rb_add(&new_xattr->rb_node, &xattrs->rb_root, 1546 + rbtree_simple_xattr_less); 1547 + write_unlock(&xattrs->lock); 1548 + } 1686 1549 } 1687 1550 1688 1551 /** ··· 1700 1549 */ 1701 1550 void simple_xattrs_init(struct simple_xattrs *xattrs) 1702 1551 { 1552 + xattrs->use_rhashtable = false; 1703 1553 xattrs->rb_root = RB_ROOT; 1704 1554 rwlock_init(&xattrs->lock); 1555 + } 1556 + 1557 + /** 1558 + * simple_xattrs_alloc - allocate and initialize a new xattr header 1559 + * 1560 + * Dynamically allocate a simple_xattrs header and initialize the 1561 + * underlying rhashtable. This is intended for consumers that want 1562 + * rhashtable-based xattr storage. 1563 + * 1564 + * Return: On success a new simple_xattrs is returned. On failure an 1565 + * ERR_PTR is returned. 1566 + */ 1567 + struct simple_xattrs *simple_xattrs_alloc(void) 1568 + { 1569 + struct simple_xattrs *xattrs __free(kfree) = NULL; 1570 + 1571 + xattrs = kzalloc(sizeof(*xattrs), GFP_KERNEL); 1572 + if (!xattrs) 1573 + return ERR_PTR(-ENOMEM); 1574 + 1575 + xattrs->use_rhashtable = true; 1576 + if (rhashtable_init(&xattrs->ht, &simple_xattr_params)) 1577 + return ERR_PTR(-ENOMEM); 1578 + 1579 + return no_free_ptr(xattrs); 1580 + } 1581 + 1582 + /** 1583 + * simple_xattrs_lazy_alloc - get or allocate xattrs for a set operation 1584 + * @xattrsp: pointer to the xattrs pointer (may point to NULL) 1585 + * @value: value being set (NULL means remove) 1586 + * @flags: xattr set flags 1587 + * 1588 + * For lazily-allocated xattrs on the write path. If no xattrs exist yet 1589 + * and this is a remove operation, returns the appropriate result without 1590 + * allocating. Otherwise ensures xattrs is allocated and published with 1591 + * store-release semantics. 1592 + * 1593 + * Return: On success a valid pointer to the xattrs is returned. On 1594 + * failure or early-exit an ERR_PTR or NULL is returned. Callers should 1595 + * check with IS_ERR_OR_NULL() and propagate with PTR_ERR() which 1596 + * correctly returns 0 for the NULL no-op case. 1597 + */ 1598 + struct simple_xattrs *simple_xattrs_lazy_alloc(struct simple_xattrs **xattrsp, 1599 + const void *value, int flags) 1600 + { 1601 + struct simple_xattrs *xattrs; 1602 + 1603 + xattrs = READ_ONCE(*xattrsp); 1604 + if (xattrs) 1605 + return xattrs; 1606 + 1607 + if (!value) 1608 + return (flags & XATTR_REPLACE) ? ERR_PTR(-ENODATA) : NULL; 1609 + 1610 + xattrs = simple_xattrs_alloc(); 1611 + if (!IS_ERR(xattrs)) 1612 + smp_store_release(xattrsp, xattrs); 1613 + return xattrs; 1614 + } 1615 + 1616 + static void simple_xattr_ht_free(void *ptr, void *arg) 1617 + { 1618 + struct simple_xattr *xattr = ptr; 1619 + size_t *freed_space = arg; 1620 + 1621 + if (freed_space) 1622 + *freed_space += simple_xattr_space(xattr->name, xattr->size); 1623 + simple_xattr_free(xattr); 1705 1624 } 1706 1625 1707 1626 /** ··· 1784 1563 */ 1785 1564 void simple_xattrs_free(struct simple_xattrs *xattrs, size_t *freed_space) 1786 1565 { 1787 - struct rb_node *rbp; 1788 - 1789 1566 if (freed_space) 1790 1567 *freed_space = 0; 1791 - rbp = rb_first(&xattrs->rb_root); 1792 - while (rbp) { 1793 - struct simple_xattr *xattr; 1794 - struct rb_node *rbp_next; 1795 1568 1796 - rbp_next = rb_next(rbp); 1797 - xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1798 - rb_erase(&xattr->rb_node, &xattrs->rb_root); 1799 - if (freed_space) 1800 - *freed_space += simple_xattr_space(xattr->name, 1801 - xattr->size); 1802 - simple_xattr_free(xattr); 1803 - rbp = rbp_next; 1569 + if (xattrs->use_rhashtable) { 1570 + rhashtable_free_and_destroy(&xattrs->ht, 1571 + simple_xattr_ht_free, freed_space); 1572 + } else { 1573 + struct rb_node *rbp; 1574 + 1575 + rbp = rb_first(&xattrs->rb_root); 1576 + while (rbp) { 1577 + struct simple_xattr *xattr; 1578 + struct rb_node *rbp_next; 1579 + 1580 + rbp_next = rb_next(rbp); 1581 + xattr = rb_entry(rbp, struct simple_xattr, rb_node); 1582 + rb_erase(&xattr->rb_node, &xattrs->rb_root); 1583 + if (freed_space) 1584 + *freed_space += simple_xattr_space(xattr->name, 1585 + xattr->size); 1586 + simple_xattr_free(xattr); 1587 + rbp = rbp_next; 1588 + } 1804 1589 } 1805 1590 }
+23 -2
include/linux/xattr.h
··· 107 107 } 108 108 109 109 struct simple_xattrs { 110 - struct rb_root rb_root; 111 - rwlock_t lock; 110 + bool use_rhashtable; 111 + union { 112 + struct { 113 + struct rb_root rb_root; 114 + rwlock_t lock; 115 + }; 116 + struct rhashtable ht; 117 + }; 112 118 }; 113 119 114 120 struct simple_xattr { ··· 127 121 }; 128 122 129 123 void simple_xattrs_init(struct simple_xattrs *xattrs); 124 + struct simple_xattrs *simple_xattrs_alloc(void); 125 + struct simple_xattrs *simple_xattrs_lazy_alloc(struct simple_xattrs **xattrsp, 126 + const void *value, int flags); 130 127 void simple_xattrs_free(struct simple_xattrs *xattrs, size_t *freed_space); 131 128 size_t simple_xattr_space(const char *name, size_t size); 132 129 struct simple_xattr *simple_xattr_alloc(const void *value, size_t size); ··· 145 136 void simple_xattr_add(struct simple_xattrs *xattrs, 146 137 struct simple_xattr *new_xattr); 147 138 int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name); 139 + 140 + DEFINE_CLASS(simple_xattr, 141 + struct simple_xattr *, 142 + if (!IS_ERR_OR_NULL(_T)) simple_xattr_free(_T), 143 + simple_xattr_alloc(value, size), 144 + const void *value, size_t size) 145 + 146 + DEFINE_CLASS(simple_xattrs, 147 + struct simple_xattrs *, 148 + if (!IS_ERR_OR_NULL(_T)) { simple_xattrs_free(_T, NULL); kfree(_T); }, 149 + simple_xattrs_alloc(), 150 + void) 148 151 149 152 #endif /* _LINUX_XATTR_H */
+1 -1
mm/shmem.c
··· 4278 4278 4279 4279 for (xattr = xattr_array; xattr->name != NULL; xattr++) { 4280 4280 new_xattr = simple_xattr_alloc(xattr->value, xattr->value_len); 4281 - if (!new_xattr) 4281 + if (IS_ERR(new_xattr)) 4282 4282 break; 4283 4283 4284 4284 len = strlen(xattr->name) + 1;