]>
Commit | Line | Data |
---|---|---|
57140883 GKH |
1 | From 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 Mon Sep 17 00:00:00 2001 |
2 | From: Jeff Layton <jlayton@redhat.com> | |
3 | Date: Wed, 25 Jul 2012 14:59:54 -0400 | |
4 | Subject: cifs: ensure that we always do cifsFileInfo_get under the spinlock | |
5 | ||
6 | From: Jeff Layton <jlayton@redhat.com> | |
7 | ||
8 | commit 764a1b1acecedfe204cb2e80d8e2cc7c6df1b0b8 upstream. | |
9 | ||
10 | The readpages bug is a regression that was introduced in 6993f74a5. | |
11 | This also fixes a couple of similar bugs in the uncached read and write | |
12 | codepaths. | |
13 | ||
14 | Also, prevent this sort of thing in the future by having cifsFileInfo_get | |
15 | take the spinlock itself, and adding a _locked variant for use in places | |
16 | that are already holding the lock. The _put code has always done that | |
17 | so this makes for a less confusing interface. | |
18 | ||
19 | Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> | |
20 | Signed-off-by: Jeff Layton <jlayton@redhat.com> | |
21 | Signed-off-by: Steve French <smfrench@gmail.com> | |
22 | Signed-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; |