aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-07-25 14:59:54 -0400
committerSteve French <smfrench@gmail.com>2012-07-25 15:51:30 -0400
commit764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 (patch)
treeaf7744be5e620a924d057a8593babea75be5799d
parent29e20f9c65fae245d6fd4fce31cc5d01cde3d93f (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>
-rw-r--r--fs/cifs/cifsglob.h6
-rw-r--r--fs/cifs/file.c17
2 files changed, 15 insertions, 8 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index bcdf4d4420f1..497da5ce704c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -765,13 +765,13 @@ struct cifs_io_parms {
765 * Take a reference on the file private data. Must be called with 765 * Take a reference on the file private data. Must be called with
766 * cifs_file_list_lock held. 766 * cifs_file_list_lock held.
767 */ 767 */
768static inline 768static inline void
769struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) 769cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
770{ 770{
771 ++cifs_file->count; 771 ++cifs_file->count;
772 return cifs_file;
773} 772}
774 773
774struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
775void cifsFileInfo_put(struct cifsFileInfo *cifs_file); 775void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
776 776
777/* 777/*
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
285static void cifs_del_lock_waiters(struct cifsLockInfo *lock); 285static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
286 286
287struct cifsFileInfo *
288cifsFileInfo_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;