Offering: HULK hulk inclusion category: bugfix bugzilla: 188878, https://gitee.com/openeuler/kernel/issues/I76JSK
--------------------------------
During growfs, if new ag in memory has been initialized, however sb_agcount has not been updated, if an error occurs at this time it will cause ag leaks as follows, these new ags will not been freed during umount because of sb_agcount is not been updated.
unreferenced object 0xffff88810751b000 (size 1024): comm "xfs_growfs", pid 123624, jiffies 4300733989 (age 124294.081s) hex dump (first 32 bytes): 00 a0 38 16 81 88 ff ff 05 00 00 00 00 00 00 00 ..8............. 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<00000000725c8ae4>] kmem_alloc+0x92/0x1d0 [xfs] [<000000005c32d74e>] xfs_initialize_perag+0x8d/0x3b0 [xfs] [<00000000830354cf>] xfs_growfs_data_private.isra.0+0x2af/0x610 [xfs] [<0000000038a29cb1>] xfs_growfs_data+0x228/0x300 [xfs] [<0000000004937dd2>] xfs_file_ioctl+0x8f3/0x10d0 [xfs] [<000000001a5d29a8>] __se_sys_ioctl+0xeb/0x120 [<00000000cf30385a>] do_syscall_64+0x30/0x40 [<00000000e4a6fd2f>] entry_SYSCALL_64_after_hwframe+0x61/0xc6
When growfs fails, use xfs_destroy_perag() to destroy newly initialized ag in error handle path.
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_fsops.c | 5 ++++- fs/xfs/xfs_mount.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index e81e052dcb75..68ad7113ac39 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -76,7 +76,7 @@ xfs_growfs_data_private( error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); if (error) - return error; + goto destroy_perag;
/* * Write new AG headers to disk. Non-transactional, but need to be @@ -167,6 +167,9 @@ xfs_growfs_data_private(
out_trans_cancel: xfs_trans_cancel(tp); +destroy_perag: + if (nagcount > oagcount) + xfs_destroy_perag(mp, oagcount, nagcount); return error; }
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a4bdf24a070c..21547ff97b5a 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -564,6 +564,8 @@ extern void xfs_uuid_table_free(void); extern int xfs_log_sbcount(xfs_mount_t *); extern uint64_t xfs_default_resblks(xfs_mount_t *mp); extern int xfs_mountfs(xfs_mount_t *mp); +extern void xfs_destroy_perag(xfs_mount_t *mp, xfs_agnumber_t agstart, + xfs_agnumber_t agend); extern int xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount, xfs_agnumber_t *maxagi); extern void xfs_unmountfs(xfs_mount_t *);