Commit 7ffdea7ea36cd1efebab65d1b221f05deaab00cd
Committed by
Eric Van Hensbergen
1 parent
836dc9e3fb
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
locking in fs/9p ->readdir()
... is really excessive. First of all, ->readdir() is serialized by file->f_path.dentry->d_inode->i_mutex; playing with file->f_path.dentry->d_lock is not buying you anything. Moreover, rdir->mutex is pointless for exactly the same reason - you'll never see contention on it. While we are at it, there's no point in having rdir->buf a pointer - you have it point just past the end of rdir, so it might as well be a flex array (and no, it's not a gccism). Absolutely untested patch follows: Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Showing 1 changed file with 23 additions and 69 deletions Side-by-side Diff
fs/9p/vfs_dir.c
... | ... | @@ -52,10 +52,9 @@ |
52 | 52 | */ |
53 | 53 | |
54 | 54 | struct p9_rdir { |
55 | - struct mutex mutex; | |
56 | 55 | int head; |
57 | 56 | int tail; |
58 | - uint8_t *buf; | |
57 | + uint8_t buf[]; | |
59 | 58 | }; |
60 | 59 | |
61 | 60 | /** |
62 | 61 | |
... | ... | @@ -93,33 +92,12 @@ |
93 | 92 | * |
94 | 93 | */ |
95 | 94 | |
96 | -static int v9fs_alloc_rdir_buf(struct file *filp, int buflen) | |
95 | +static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen) | |
97 | 96 | { |
98 | - struct p9_rdir *rdir; | |
99 | - struct p9_fid *fid; | |
100 | - int err = 0; | |
101 | - | |
102 | - fid = filp->private_data; | |
103 | - if (!fid->rdir) { | |
104 | - rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); | |
105 | - | |
106 | - if (rdir == NULL) { | |
107 | - err = -ENOMEM; | |
108 | - goto exit; | |
109 | - } | |
110 | - spin_lock(&filp->f_dentry->d_lock); | |
111 | - if (!fid->rdir) { | |
112 | - rdir->buf = (uint8_t *)rdir + sizeof(struct p9_rdir); | |
113 | - mutex_init(&rdir->mutex); | |
114 | - rdir->head = rdir->tail = 0; | |
115 | - fid->rdir = (void *) rdir; | |
116 | - rdir = NULL; | |
117 | - } | |
118 | - spin_unlock(&filp->f_dentry->d_lock); | |
119 | - kfree(rdir); | |
120 | - } | |
121 | -exit: | |
122 | - return err; | |
97 | + struct p9_fid *fid = filp->private_data; | |
98 | + if (!fid->rdir) | |
99 | + fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); | |
100 | + return fid->rdir; | |
123 | 101 | } |
124 | 102 | |
125 | 103 | /** |
126 | 104 | |
127 | 105 | |
... | ... | @@ -145,20 +123,16 @@ |
145 | 123 | |
146 | 124 | buflen = fid->clnt->msize - P9_IOHDRSZ; |
147 | 125 | |
148 | - err = v9fs_alloc_rdir_buf(filp, buflen); | |
149 | - if (err) | |
150 | - goto exit; | |
151 | - rdir = (struct p9_rdir *) fid->rdir; | |
126 | + rdir = v9fs_alloc_rdir_buf(filp, buflen); | |
127 | + if (!rdir) | |
128 | + return -ENOMEM; | |
152 | 129 | |
153 | - err = mutex_lock_interruptible(&rdir->mutex); | |
154 | - if (err) | |
155 | - return err; | |
156 | - while (err == 0) { | |
130 | + while (1) { | |
157 | 131 | if (rdir->tail == rdir->head) { |
158 | 132 | err = v9fs_file_readn(filp, rdir->buf, NULL, |
159 | 133 | buflen, filp->f_pos); |
160 | 134 | if (err <= 0) |
161 | - goto unlock_and_exit; | |
135 | + return err; | |
162 | 136 | |
163 | 137 | rdir->head = 0; |
164 | 138 | rdir->tail = err; |
165 | 139 | |
... | ... | @@ -169,9 +143,8 @@ |
169 | 143 | rdir->tail - rdir->head, &st); |
170 | 144 | if (err) { |
171 | 145 | p9_debug(P9_DEBUG_VFS, "returned %d\n", err); |
172 | - err = -EIO; | |
173 | 146 | p9stat_free(&st); |
174 | - goto unlock_and_exit; | |
147 | + return -EIO; | |
175 | 148 | } |
176 | 149 | reclen = st.size+2; |
177 | 150 | |
178 | 151 | |
... | ... | @@ -180,19 +153,13 @@ |
180 | 153 | |
181 | 154 | p9stat_free(&st); |
182 | 155 | |
183 | - if (over) { | |
184 | - err = 0; | |
185 | - goto unlock_and_exit; | |
186 | - } | |
156 | + if (over) | |
157 | + return 0; | |
158 | + | |
187 | 159 | rdir->head += reclen; |
188 | 160 | filp->f_pos += reclen; |
189 | 161 | } |
190 | 162 | } |
191 | - | |
192 | -unlock_and_exit: | |
193 | - mutex_unlock(&rdir->mutex); | |
194 | -exit: | |
195 | - return err; | |
196 | 163 | } |
197 | 164 | |
198 | 165 | /** |
199 | 166 | |
200 | 167 | |
... | ... | @@ -218,21 +185,16 @@ |
218 | 185 | |
219 | 186 | buflen = fid->clnt->msize - P9_READDIRHDRSZ; |
220 | 187 | |
221 | - err = v9fs_alloc_rdir_buf(filp, buflen); | |
222 | - if (err) | |
223 | - goto exit; | |
224 | - rdir = (struct p9_rdir *) fid->rdir; | |
188 | + rdir = v9fs_alloc_rdir_buf(filp, buflen); | |
189 | + if (!rdir) | |
190 | + return -ENOMEM; | |
225 | 191 | |
226 | - err = mutex_lock_interruptible(&rdir->mutex); | |
227 | - if (err) | |
228 | - return err; | |
229 | - | |
230 | - while (err == 0) { | |
192 | + while (1) { | |
231 | 193 | if (rdir->tail == rdir->head) { |
232 | 194 | err = p9_client_readdir(fid, rdir->buf, buflen, |
233 | 195 | filp->f_pos); |
234 | 196 | if (err <= 0) |
235 | - goto unlock_and_exit; | |
197 | + return err; | |
236 | 198 | |
237 | 199 | rdir->head = 0; |
238 | 200 | rdir->tail = err; |
... | ... | @@ -245,8 +207,7 @@ |
245 | 207 | &curdirent); |
246 | 208 | if (err < 0) { |
247 | 209 | p9_debug(P9_DEBUG_VFS, "returned %d\n", err); |
248 | - err = -EIO; | |
249 | - goto unlock_and_exit; | |
210 | + return -EIO; | |
250 | 211 | } |
251 | 212 | |
252 | 213 | /* d_off in dirent structure tracks the offset into |
253 | 214 | |
... | ... | @@ -261,20 +222,13 @@ |
261 | 222 | curdirent.d_type); |
262 | 223 | oldoffset = curdirent.d_off; |
263 | 224 | |
264 | - if (over) { | |
265 | - err = 0; | |
266 | - goto unlock_and_exit; | |
267 | - } | |
225 | + if (over) | |
226 | + return 0; | |
268 | 227 | |
269 | 228 | filp->f_pos = curdirent.d_off; |
270 | 229 | rdir->head += err; |
271 | 230 | } |
272 | 231 | } |
273 | - | |
274 | -unlock_and_exit: | |
275 | - mutex_unlock(&rdir->mutex); | |
276 | -exit: | |
277 | - return err; | |
278 | 232 | } |
279 | 233 | |
280 | 234 |