diff options
| author | Jeff Layton <jlayton@redhat.com> | 2010-06-16 13:40:17 -0400 |
|---|---|---|
| committer | Jeff Layton <jlayton@redhat.com> | 2010-06-16 13:40:17 -0400 |
| commit | 47c78b7f40a9931a264e3c9bddccacdf8dfb9a30 (patch) | |
| tree | 2b4cc492dee33f47836b252a4a1819006e5d0644 | |
| parent | d9d5d8df953a98621be5b8889e05043d6e32052e (diff) | |
cifs: don't call cifs_new_fileinfo unless cifs_open succeeds
It's currently possible for cifs_open to fail after it has already
called cifs_new_fileinfo. In that situation, the new fileinfo will be
leaked as the caller doesn't call fput. That in turn leads to a busy
inodes after umount problem since the fileinfo holds an extra inode
reference now. Shuffle cifs_open around a bit so that it only calls
cifs_new_fileinfo if it's going to succeed.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-and-Tested-by: Suresh Jayaraman <sjayaraman@suse.de>
| -rw-r--r-- | fs/cifs/file.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 02a2df9cdd9c..409e4f523e61 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -268,17 +268,20 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 268 | /* no need for special case handling of setting mode | 268 | /* no need for special case handling of setting mode |
| 269 | on read only files needed here */ | 269 | on read only files needed here */ |
| 270 | 270 | ||
| 271 | rc = cifs_posix_open_inode_helper(inode, file, | ||
| 272 | pCifsInode, oplock, netfid); | ||
| 273 | if (rc != 0) { | ||
| 274 | CIFSSMBClose(xid, tcon, netfid); | ||
| 275 | goto out; | ||
| 276 | } | ||
| 277 | |||
| 271 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, | 278 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, |
| 272 | file->f_path.mnt, | 279 | file->f_path.mnt, |
| 273 | oflags); | 280 | oflags); |
| 274 | if (pCifsFile == NULL) { | 281 | if (pCifsFile == NULL) { |
| 275 | CIFSSMBClose(xid, tcon, netfid); | 282 | CIFSSMBClose(xid, tcon, netfid); |
| 276 | rc = -ENOMEM; | 283 | rc = -ENOMEM; |
| 277 | goto out; | ||
| 278 | } | 284 | } |
| 279 | |||
| 280 | rc = cifs_posix_open_inode_helper(inode, file, | ||
| 281 | pCifsInode, oplock, netfid); | ||
| 282 | goto out; | 285 | goto out; |
| 283 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 286 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
| 284 | if (tcon->ses->serverNOS) | 287 | if (tcon->ses->serverNOS) |
| @@ -359,6 +362,10 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 359 | goto out; | 362 | goto out; |
| 360 | } | 363 | } |
| 361 | 364 | ||
| 365 | rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); | ||
| 366 | if (rc != 0) | ||
| 367 | goto out; | ||
| 368 | |||
| 362 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, | 369 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, |
| 363 | file->f_flags); | 370 | file->f_flags); |
| 364 | if (pCifsFile == NULL) { | 371 | if (pCifsFile == NULL) { |
| @@ -366,8 +373,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 366 | goto out; | 373 | goto out; |
| 367 | } | 374 | } |
| 368 | 375 | ||
| 369 | rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); | ||
| 370 | |||
| 371 | if (oplock & CIFS_CREATE_ACTION) { | 376 | if (oplock & CIFS_CREATE_ACTION) { |
| 372 | /* time to set mode which we can not set earlier due to | 377 | /* time to set mode which we can not set earlier due to |
| 373 | problems creating new read-only files */ | 378 | problems creating new read-only files */ |
