]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.5.1/cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.5.1 / cifs-ensure-that-we-always-do-cifsfileinfo_get-under-the-spinlock.patch
CommitLineData
57140883
GKH
1From 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 Mon Sep 17 00:00:00 2001
2From: Jeff Layton <jlayton@redhat.com>
3Date: Wed, 25 Jul 2012 14:59:54 -0400
4Subject: cifs: ensure that we always do cifsFileInfo_get under the spinlock
5
6From: Jeff Layton <jlayton@redhat.com>
7
8commit 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 upstream.
9
10The readpages bug is a regression that was introduced in 6993f74a5.
11This also fixes a couple of similar bugs in the uncached read and write
12codepaths.
13
14Also, prevent this sort of thing in the future by having cifsFileInfo_get
15take the spinlock itself, and adding a _locked variant for use in places
16that are already holding the lock. The _put code has always done that
17so this makes for a less confusing interface.
18
19Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org>
20Signed-off-by: Jeff Layton <jlayton@redhat.com>
21Signed-off-by: Steve French <smfrench@gmail.com>
22Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24---
25 fs/cifs/cifsglob.h | 6 +++---
26 fs/cifs/file.c | 17 ++++++++++++-----
27 2 files changed, 15 insertions(+), 8 deletions(-)
28
29--- a/fs/cifs/cifsglob.h
30+++ b/fs/cifs/cifsglob.h
31@@ -657,13 +657,13 @@ struct cifs_io_parms {
32 * Take a reference on the file private data. Must be called with
33 * cifs_file_list_lock held.
34 */
35-static inline
36-struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file)
37+static inline void
38+cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
39 {
40 ++cifs_file->count;
41- return cifs_file;
42 }
43
44+struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
45 void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
46
47 /*
48--- a/fs/cifs/file.c
49+++ b/fs/cifs/file.c
50@@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, stru
51
52 static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
53
54+struct cifsFileInfo *
55+cifsFileInfo_get(struct cifsFileInfo *cifs_file)
56+{
57+ spin_lock(&cifs_file_list_lock);
58+ cifsFileInfo_get_locked(cifs_file);
59+ spin_unlock(&cifs_file_list_lock);
60+ return cifs_file;
61+}
62+
63 /*
64 * Release a reference on the file private data. This may involve closing
65 * the filehandle out on the server. Must be called without holding
66@@ -1563,7 +1572,7 @@ struct cifsFileInfo *find_readable_file(
67 if (!open_file->invalidHandle) {
68 /* found a good file */
69 /* lock it so it will not be closed on us */
70- cifsFileInfo_get(open_file);
71+ cifsFileInfo_get_locked(open_file);
72 spin_unlock(&cifs_file_list_lock);
73 return open_file;
74 } /* else might as well continue, and look for
75@@ -1615,7 +1624,7 @@ refind_writable:
76 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
77 if (!open_file->invalidHandle) {
78 /* found a good writable file */
79- cifsFileInfo_get(open_file);
80+ cifsFileInfo_get_locked(open_file);
81 spin_unlock(&cifs_file_list_lock);
82 return open_file;
83 } else {
84@@ -1632,7 +1641,7 @@ refind_writable:
85
86 if (inv_file) {
87 any_available = false;
88- cifsFileInfo_get(inv_file);
89+ cifsFileInfo_get_locked(inv_file);
90 }
91
92 spin_unlock(&cifs_file_list_lock);
93@@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *f
94 break;
95 }
96
97- spin_lock(&cifs_file_list_lock);
98- spin_unlock(&cifs_file_list_lock);
99 rdata->cfile = cifsFileInfo_get(open_file);
100 rdata->mapping = mapping;
101 rdata->offset = offset;