aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-07-12 16:47:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-12 17:33:42 -0400
commite911d0cc877ff027d5bd09fc33148ab76f0fdf0e (patch)
treec2549fb1caa266f17d25c20e0c499db823578372 /fs
parentd3297a644a0ab784e0c810ceca6bf35a67868ad9 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/inode.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 722be543ceec..2e904bd111c8 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -219,15 +219,15 @@ int cifs_get_inode_info_unix(struct inode **pinode,
219 rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, 219 rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
220 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 220 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
221 CIFS_MOUNT_MAP_SPECIAL_CHR); 221 CIFS_MOUNT_MAP_SPECIAL_CHR);
222 if (rc) { 222 if (rc == -EREMOTE && !is_dfs_referral) {
223 if (rc == -EREMOTE && !is_dfs_referral) { 223 is_dfs_referral = true;
224 is_dfs_referral = true; 224 cFYI(DBG2, ("DFS ref"));
225 cFYI(DBG2, ("DFS ref")); 225 /* for DFS, server does not give us real inode data */
226 /* for DFS, server does not give us real inode data */ 226 fill_fake_finddataunix(&find_data, sb);
227 fill_fake_finddataunix(&find_data, sb); 227 rc = 0;
228 rc = 0; 228 } else if (rc)
229 } 229 goto cgiiu_exit;
230 } 230
231 num_of_bytes = le64_to_cpu(find_data.NumOfBytes); 231 num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
232 end_of_file = le64_to_cpu(find_data.EndOfFile); 232 end_of_file = le64_to_cpu(find_data.EndOfFile);
233 233
@@ -236,7 +236,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
236 *pinode = new_inode(sb); 236 *pinode = new_inode(sb);
237 if (*pinode == NULL) { 237 if (*pinode == NULL) {
238 rc = -ENOMEM; 238 rc = -ENOMEM;
239 goto cgiiu_exit; 239 goto cgiiu_exit;
240 } 240 }
241 /* Is an i_ino of zero legal? */ 241 /* Is an i_ino of zero legal? */
242 /* note ino incremented to unique num in new_inode */ 242 /* note ino incremented to unique num in new_inode */