Skip to content

Commit 8db074b

Browse files
Darrick J. Wongdchinner
authored andcommitted
xfs: don't leak xfs_buf_cancel structures when recovery fails
If log recovery fails, we free the memory used by the buffer cancellation buckets, but we don't actually traverse each bucket list to free the individual xfs_buf_cancel objects. This leads to a memory leak, as reported by kmemleak in xfs/051: unreferenced object 0xffff888103629560 (size 32): comm "mount", pid 687045, jiffies 4296935916 (age 10.752s) hex dump (first 32 bytes): 08 d3 0a 01 00 00 00 00 08 00 00 00 01 00 00 00 ................ d0 f5 0b 92 81 88 ff ff 80 64 64 25 81 88 ff ff .........dd%.... backtrace: [<ffffffffa0317c83>] kmem_alloc+0x73/0x140 [xfs] [<ffffffffa03234a9>] xlog_recover_buf_commit_pass1+0x139/0x200 [xfs] [<ffffffffa032dc27>] xlog_recover_commit_trans+0x307/0x350 [xfs] [<ffffffffa032df15>] xlog_recovery_process_trans+0xa5/0xe0 [xfs] [<ffffffffa032e12d>] xlog_recover_process_data+0x8d/0x140 [xfs] [<ffffffffa032e49d>] xlog_do_recovery_pass+0x19d/0x740 [xfs] [<ffffffffa032f22d>] xlog_do_log_recovery+0x6d/0x150 [xfs] [<ffffffffa032f343>] xlog_do_recover+0x33/0x1d0 [xfs] [<ffffffffa032faba>] xlog_recover+0xda/0x190 [xfs] [<ffffffffa03194bc>] xfs_log_mount+0x14c/0x360 [xfs] [<ffffffffa030bfed>] xfs_mountfs+0x50d/0xa60 [xfs] [<ffffffffa03124b5>] xfs_fs_fill_super+0x6a5/0x950 [xfs] [<ffffffff812b92a5>] get_tree_bdev+0x175/0x280 [<ffffffff812b7c3a>] vfs_get_tree+0x1a/0x80 [<ffffffff812e366f>] path_mount+0x6ff/0xaa0 [<ffffffff812e3b13>] __x64_sys_mount+0x103/0x140 Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Signed-off-by: Dave Chinner <[email protected]>
1 parent 2723234 commit 8db074b

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

fs/xfs/xfs_buf_item_recover.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,9 +1034,22 @@ void
10341034
xlog_free_buf_cancel_table(
10351035
struct xlog *log)
10361036
{
1037+
int i;
1038+
10371039
if (!log->l_buf_cancel_table)
10381040
return;
10391041

1042+
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) {
1043+
struct xfs_buf_cancel *bc;
1044+
1045+
while ((bc = list_first_entry_or_null(
1046+
&log->l_buf_cancel_table[i],
1047+
struct xfs_buf_cancel, bc_list))) {
1048+
list_del(&bc->bc_list);
1049+
kmem_free(bc);
1050+
}
1051+
}
1052+
10401053
kmem_free(log->l_buf_cancel_table);
10411054
log->l_buf_cancel_table = NULL;
10421055
}

0 commit comments

Comments
 (0)