Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cifs: Fix memory leak on the deferred close

xfstests on smb21 report kmemleak as below:

unreferenced object 0xffff8881767d6200 (size 64):
comm "xfs_io", pid 1284, jiffies 4294777434 (age 20.789s)
hex dump (first 32 bytes):
80 5a d0 11 81 88 ff ff 78 8a aa 63 81 88 ff ff .Z......x..c....
00 71 99 76 81 88 ff ff 00 00 00 00 00 00 00 00 .q.v............
backtrace:
[<00000000ad04e6ea>] cifs_close+0x92/0x2c0
[<0000000028b93c82>] __fput+0xff/0x3f0
[<00000000d8116851>] task_work_run+0x85/0xc0
[<0000000027e14f9e>] do_exit+0x5e5/0x1240
[<00000000fb492b95>] do_group_exit+0x58/0xe0
[<00000000129a32d9>] __x64_sys_exit_group+0x28/0x30
[<00000000e3f7d8e9>] do_syscall_64+0x35/0x80
[<00000000102e8a0b>] entry_SYSCALL_64_after_hwframe+0x46/0xb0

When cancel the deferred close work, we should also cleanup the struct
cifs_deferred_close.

Fixes: 9e992755be8f2 ("cifs: Call close synchronously during unlink/rename/lease break.")
Fixes: e3fc065682ebb ("cifs: Deferred close performance improvements")
Cc: stable@vger.kernel.org
Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Zhang Xiaoxu and committed by
Steve French
ca08d0ea 400d0ad6

+6
+6
fs/cifs/misc.c
··· 737 737 list_for_each_entry(cfile, &cifs_inode->openFileList, flist) { 738 738 if (delayed_work_pending(&cfile->deferred)) { 739 739 if (cancel_delayed_work(&cfile->deferred)) { 740 + cifs_del_deferred_close(cfile); 741 + 740 742 tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); 741 743 if (tmp_list == NULL) 742 744 break; ··· 768 766 list_for_each_entry(cfile, &tcon->openFileList, tlist) { 769 767 if (delayed_work_pending(&cfile->deferred)) { 770 768 if (cancel_delayed_work(&cfile->deferred)) { 769 + cifs_del_deferred_close(cfile); 770 + 771 771 tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); 772 772 if (tmp_list == NULL) 773 773 break; ··· 803 799 if (strstr(full_path, path)) { 804 800 if (delayed_work_pending(&cfile->deferred)) { 805 801 if (cancel_delayed_work(&cfile->deferred)) { 802 + cifs_del_deferred_close(cfile); 803 + 806 804 tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); 807 805 if (tmp_list == NULL) 808 806 break;