Skip to content

Commit 02eb184

Browse files
Zhihao Chengrichardweinberger
authored andcommitted
ubifs: Fix unattached xattr inode if powercut happens after deleting
When powercut happens after deleting file, the xattr inode could be alone existing in TNC but its' xattr entry cannot be found in TNC. File inode and xattr inode are added into orphan list after deleting file, file inode's nlink is 0 but xattr inode's nlink is not 0 (PS: zero nlink xattr inode is written on disk in evicting process by ubifs_jnl_write_inode). So, following process could happen: 1. touch file 2. setxattr(file) 3. unlink file // inode(nlink=0), xattr inode(nlink=1) are added into orphan list 4. commit // write inode inum and xattr inum into orphan area 5. powercut 6. mount do_kill_orphans // inode(nlink=0) is deleted from TNC by ubifs_tnc_remove_range, // xattr entry is deleted too. // xattr inode(nlink=1) is not deleted from TNC Finally we could see following error while debugging UBIFS: UBIFS error (ubi0:0 pid 1093): dbg_check_filesystem [ubifs]: inode 66 nlink is 1, but calculated nlink is 0 UBIFS (ubi0:0): dump of the inode 66 sitting in LEB 12:2128 node_type 0 (inode node) group_type 1 (in node group) len 197 key (66, inode) size 37 nlink 1 flags 0x20 xattr_cnt 0 xattr_size 0 xattr_names 0 data len 37 Fix it by removing entire inode with it's xattrs while replaying orphan, just replace function ubifs_tnc_remove_range by ubifs_tnc_remove_ino. Fixes: ee1438c ("ubifs: Check link count of inodes when killing orphans.") Link: https://bugzilla.kernel.org/show_bug.cgi?id=218661 Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: Richard Weinberger <richard@nod.at>
1 parent 02096a0 commit 02eb184

File tree

1 file changed

+4
-7
lines changed

1 file changed

+4
-7
lines changed

fs/ubifs/orphan.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -691,12 +691,12 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
691691

692692
n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
693693
for (i = 0; i < n; i++) {
694-
union ubifs_key key1, key2;
694+
union ubifs_key key;
695695

696696
inum = le64_to_cpu(orph->inos[i]);
697697

698-
ino_key_init(c, &key1, inum);
699-
err = ubifs_tnc_lookup(c, &key1, ino);
698+
ino_key_init(c, &key, inum);
699+
err = ubifs_tnc_lookup(c, &key, ino);
700700
if (err && err != -ENOENT)
701701
goto out_free;
702702

@@ -708,10 +708,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
708708
dbg_rcvry("deleting orphaned inode %lu",
709709
(unsigned long)inum);
710710

711-
lowest_ino_key(c, &key1, inum);
712-
highest_ino_key(c, &key2, inum);
713-
714-
err = ubifs_tnc_remove_range(c, &key1, &key2);
711+
err = ubifs_tnc_remove_ino(c, inum);
715712
if (err)
716713
goto out_ro;
717714
}

0 commit comments

Comments
 (0)