|
60 | 60 | #include <linux/slab.h> |
61 | 61 | #include <linux/xattr.h> |
62 | 62 |
|
63 | | -/* |
64 | | - * Limit the number of extended attributes per inode so that the total size |
65 | | - * (@xattr_size) is guaranteeded to fit in an 'unsigned int'. |
66 | | - */ |
67 | | -#define MAX_XATTRS_PER_INODE 65535 |
68 | | - |
69 | 63 | /* |
70 | 64 | * Extended attribute type constants. |
71 | 65 | * |
@@ -106,7 +100,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, |
106 | 100 | .new_ino_d = ALIGN(size, 8), .dirtied_ino = 1, |
107 | 101 | .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; |
108 | 102 |
|
109 | | - if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) { |
| 103 | + if (host_ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) { |
110 | 104 | ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more", |
111 | 105 | host->i_ino, host_ui->xattr_cnt); |
112 | 106 | return -ENOSPC; |
@@ -507,6 +501,69 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host, |
507 | 501 | return err; |
508 | 502 | } |
509 | 503 |
|
| 504 | +int ubifs_purge_xattrs(struct inode *host) |
| 505 | +{ |
| 506 | + union ubifs_key key; |
| 507 | + struct ubifs_info *c = host->i_sb->s_fs_info; |
| 508 | + struct ubifs_dent_node *xent, *pxent = NULL; |
| 509 | + struct inode *xino; |
| 510 | + struct fscrypt_name nm = {0}; |
| 511 | + int err; |
| 512 | + |
| 513 | + if (ubifs_inode(host)->xattr_cnt < ubifs_xattr_max_cnt(c)) |
| 514 | + return 0; |
| 515 | + |
| 516 | + ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion", |
| 517 | + host->i_ino); |
| 518 | + |
| 519 | + lowest_xent_key(c, &key, host->i_ino); |
| 520 | + while (1) { |
| 521 | + xent = ubifs_tnc_next_ent(c, &key, &nm); |
| 522 | + if (IS_ERR(xent)) { |
| 523 | + err = PTR_ERR(xent); |
| 524 | + break; |
| 525 | + } |
| 526 | + |
| 527 | + fname_name(&nm) = xent->name; |
| 528 | + fname_len(&nm) = le16_to_cpu(xent->nlen); |
| 529 | + |
| 530 | + xino = ubifs_iget(c->vfs_sb, xent->inum); |
| 531 | + if (IS_ERR(xino)) { |
| 532 | + err = PTR_ERR(xino); |
| 533 | + ubifs_err(c, "dead directory entry '%s', error %d", |
| 534 | + xent->name, err); |
| 535 | + ubifs_ro_mode(c, err); |
| 536 | + kfree(pxent); |
| 537 | + return err; |
| 538 | + } |
| 539 | + |
| 540 | + ubifs_assert(c, ubifs_inode(xino)->xattr); |
| 541 | + |
| 542 | + clear_nlink(xino); |
| 543 | + err = remove_xattr(c, host, xino, &nm); |
| 544 | + if (err) { |
| 545 | + kfree(pxent); |
| 546 | + iput(xino); |
| 547 | + ubifs_err(c, "cannot remove xattr, error %d", err); |
| 548 | + return err; |
| 549 | + } |
| 550 | + |
| 551 | + iput(xino); |
| 552 | + |
| 553 | + kfree(pxent); |
| 554 | + pxent = xent; |
| 555 | + key_read(c, &xent->key, &key); |
| 556 | + } |
| 557 | + |
| 558 | + kfree(pxent); |
| 559 | + if (err != -ENOENT) { |
| 560 | + ubifs_err(c, "cannot find next direntry, error %d", err); |
| 561 | + return err; |
| 562 | + } |
| 563 | + |
| 564 | + return 0; |
| 565 | +} |
| 566 | + |
510 | 567 | /** |
511 | 568 | * ubifs_evict_xattr_inode - Evict an xattr inode. |
512 | 569 | * @c: UBIFS file-system description object |
|
0 commit comments