Commit e911d0cc authored by Jeff Layton's avatar Jeff Layton Committed by Linus Torvalds

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 0e4bbde9.

The following patch seems to fix it for me, and fixes a minor
formatting nit as well.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Acked-by: default avatarSteven French <sfrench@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d3297a64
...@@ -219,15 +219,15 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -219,15 +219,15 @@ int cifs_get_inode_info_unix(struct inode **pinode,
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) { if (rc == -EREMOTE && !is_dfs_referral) {
if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true;
is_dfs_referral = true; cFYI(DBG2, ("DFS ref"));
cFYI(DBG2, ("DFS ref")); /* for DFS, server does not give us real inode data */
/* for DFS, server does not give us real inode data */ fill_fake_finddataunix(&find_data, sb);
fill_fake_finddataunix(&find_data, sb); rc = 0;
rc = 0; } else if (rc)
} goto cgiiu_exit;
}
num_of_bytes = le64_to_cpu(find_data.NumOfBytes); num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
end_of_file = le64_to_cpu(find_data.EndOfFile); end_of_file = le64_to_cpu(find_data.EndOfFile);
...@@ -236,7 +236,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -236,7 +236,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
*pinode = new_inode(sb); *pinode = new_inode(sb);
if (*pinode == NULL) { if (*pinode == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto cgiiu_exit; goto cgiiu_exit;
} }
/* Is an i_ino of zero legal? */ /* Is an i_ino of zero legal? */
/* note ino incremented to unique num in new_inode */ /* note ino incremented to unique num in new_inode */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment