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

Configure Feed

Select the types of activity you want to include in your feed.

cifs: fix inode leak in cifs_get_inode_info_unix

Try this:

mount a share with unix extensions
create a file on it
umount the share

You'll get the following message in the ring buffer:

VFS: Busy inodes after unmount of cifs. Self-destruct in 5 seconds. Have a
nice day...

...the problem is that cifs_get_inode_info_unix is creating and hashing
a new inode even when it's going to return error anyway. The first
lookup when creating a file returns an error so we end up leaking this
inode before we do the actual create. This appears to be a regression
caused by commit 0e4bbde94fdc33f5b3d793166b21bf768ca3e098.

The following patch seems to fix it for me, and fixes a minor
formatting nit as well.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Steven French <sfrench@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jeff Layton and committed by
Linus Torvalds
e911d0cc d3297a64

+10 -10
+10 -10
fs/cifs/inode.c
··· 219 219 rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, 220 220 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 221 221 CIFS_MOUNT_MAP_SPECIAL_CHR); 222 - if (rc) { 223 - if (rc == -EREMOTE && !is_dfs_referral) { 224 - is_dfs_referral = true; 225 - cFYI(DBG2, ("DFS ref")); 226 - /* for DFS, server does not give us real inode data */ 227 - fill_fake_finddataunix(&find_data, sb); 228 - rc = 0; 229 - } 230 - } 222 + if (rc == -EREMOTE && !is_dfs_referral) { 223 + is_dfs_referral = true; 224 + cFYI(DBG2, ("DFS ref")); 225 + /* for DFS, server does not give us real inode data */ 226 + fill_fake_finddataunix(&find_data, sb); 227 + rc = 0; 228 + } else if (rc) 229 + goto cgiiu_exit; 230 + 231 231 num_of_bytes = le64_to_cpu(find_data.NumOfBytes); 232 232 end_of_file = le64_to_cpu(find_data.EndOfFile); 233 233 ··· 236 236 *pinode = new_inode(sb); 237 237 if (*pinode == NULL) { 238 238 rc = -ENOMEM; 239 - goto cgiiu_exit; 239 + goto cgiiu_exit; 240 240 } 241 241 /* Is an i_ino of zero legal? */ 242 242 /* note ino incremented to unique num in new_inode */