Commit 7ffdea7ea36cd1efebab65d1b221f05deaab00cd

Authored by Al Viro
Committed by Eric Van Hensbergen
1 parent 836dc9e3fb

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

... ... @@ -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