diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-07-25 14:59:54 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-07-25 15:51:30 -0400 |
commit | 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 (patch) | |
tree | af7744be5e620a924d057a8593babea75be5799d /fs/cifs/file.c | |
parent | 29e20f9c65fae245d6fd4fce31cc5d01cde3d93f (diff) |
cifs: ensure that we always do cifsFileInfo_get under the spinlock
The readpages bug is a regression that was introduced in 6993f74a5.
This also fixes a couple of similar bugs in the uncached read and write
codepaths.
Also, prevent this sort of thing in the future by having cifsFileInfo_get
take the spinlock itself, and adding a _locked variant for use in places
that are already holding the lock. The _put code has always done that
so this makes for a less confusing interface.
Cc: <stable@vger.kernel.org> # 3.5.x
Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 07e9d41cade7..9154192b0683 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
284 | 284 | ||
285 | static void cifs_del_lock_waiters(struct cifsLockInfo *lock); | 285 | static void cifs_del_lock_waiters(struct cifsLockInfo *lock); |
286 | 286 | ||
287 | struct cifsFileInfo * | ||
288 | cifsFileInfo_get(struct cifsFileInfo *cifs_file) | ||
289 | { | ||
290 | spin_lock(&cifs_file_list_lock); | ||
291 | cifsFileInfo_get_locked(cifs_file); | ||
292 | spin_unlock(&cifs_file_list_lock); | ||
293 | return cifs_file; | ||
294 | } | ||
295 | |||
287 | /* | 296 | /* |
288 | * Release a reference on the file private data. This may involve closing | 297 | * Release a reference on the file private data. This may involve closing |
289 | * the filehandle out on the server. Must be called without holding | 298 | * the filehandle out on the server. Must be called without holding |
@@ -1562,7 +1571,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | |||
1562 | if (!open_file->invalidHandle) { | 1571 | if (!open_file->invalidHandle) { |
1563 | /* found a good file */ | 1572 | /* found a good file */ |
1564 | /* lock it so it will not be closed on us */ | 1573 | /* lock it so it will not be closed on us */ |
1565 | cifsFileInfo_get(open_file); | 1574 | cifsFileInfo_get_locked(open_file); |
1566 | spin_unlock(&cifs_file_list_lock); | 1575 | spin_unlock(&cifs_file_list_lock); |
1567 | return open_file; | 1576 | return open_file; |
1568 | } /* else might as well continue, and look for | 1577 | } /* else might as well continue, and look for |
@@ -1614,7 +1623,7 @@ refind_writable: | |||
1614 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { | 1623 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
1615 | if (!open_file->invalidHandle) { | 1624 | if (!open_file->invalidHandle) { |
1616 | /* found a good writable file */ | 1625 | /* found a good writable file */ |
1617 | cifsFileInfo_get(open_file); | 1626 | cifsFileInfo_get_locked(open_file); |
1618 | spin_unlock(&cifs_file_list_lock); | 1627 | spin_unlock(&cifs_file_list_lock); |
1619 | return open_file; | 1628 | return open_file; |
1620 | } else { | 1629 | } else { |
@@ -1631,7 +1640,7 @@ refind_writable: | |||
1631 | 1640 | ||
1632 | if (inv_file) { | 1641 | if (inv_file) { |
1633 | any_available = false; | 1642 | any_available = false; |
1634 | cifsFileInfo_get(inv_file); | 1643 | cifsFileInfo_get_locked(inv_file); |
1635 | } | 1644 | } |
1636 | 1645 | ||
1637 | spin_unlock(&cifs_file_list_lock); | 1646 | spin_unlock(&cifs_file_list_lock); |
@@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3082 | break; | 3091 | break; |
3083 | } | 3092 | } |
3084 | 3093 | ||
3085 | spin_lock(&cifs_file_list_lock); | ||
3086 | spin_unlock(&cifs_file_list_lock); | ||
3087 | rdata->cfile = cifsFileInfo_get(open_file); | 3094 | rdata->cfile = cifsFileInfo_get(open_file); |
3088 | rdata->mapping = mapping; | 3095 | rdata->mapping = mapping; |
3089 | rdata->offset = offset; | 3096 | rdata->offset = offset; |