]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs/repair: pin inodes that would otherwise overflow link count
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:02 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:06 +0000 (17:01 -0700)
Update userspace utilities not to allow integer overflows of inode link
counts to result in a file that is referenced by parent directories but
has zero link count.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/util.c
repair/incore_ino.c

index dc54e3ee66dbaac8810dd987bb1368527f1b3b92..74eea0fcbe0712f3f3c630829fa7a74af896987e 100644 (file)
@@ -252,7 +252,8 @@ libxfs_bumplink(
 
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
-       inc_nlink(inode);
+       if (inode->i_nlink != XFS_NLINK_PINNED)
+               inc_nlink(inode);
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
index 0dd7a2f060fb40b274f5e2f4272278804f654448..6618e534ab9f8ad44912563280dc4c76ad4fde77 100644 (file)
@@ -89,26 +89,30 @@ nlink_grow_16_to_32(ino_tree_node_t *irec)
 
 void add_inode_ref(struct ino_tree_node *irec, int ino_offset)
 {
+       union ino_nlink         *c;
+
        ASSERT(irec->ino_un.ex_data != NULL);
 
        pthread_mutex_lock(&irec->lock);
+       c = &irec->ino_un.ex_data->counted_nlinks;
        switch (irec->nlink_size) {
        case sizeof(uint8_t):
-               if (irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] < 0xff) {
-                       irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]++;
+               if (c->un8[ino_offset] < 0xff) {
+                       c->un8[ino_offset]++;
                        break;
                }
                nlink_grow_8_to_16(irec);
                /*FALLTHRU*/
        case sizeof(uint16_t):
-               if (irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] < 0xffff) {
-                       irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]++;
+               if (c->un16[ino_offset] < 0xffff) {
+                       c->un16[ino_offset]++;
                        break;
                }
                nlink_grow_16_to_32(irec);
                /*FALLTHRU*/
        case sizeof(uint32_t):
-               irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++;
+               if (c->un32[ino_offset] != XFS_NLINK_PINNED)
+                       c->un32[ino_offset]++;
                break;
        default:
                ASSERT(0);