Commit 940e3a8dd6683a3787faf769b3df7a06f1c2fa31

Authored by Linus Torvalds

Merge tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

Pull v9fs update from Eric Van Hensbergen.

* tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  9P: Fix race between p9_write_work() and p9_fd_request()
  9P: Fix race in p9_write_work()
  9P: fix test at the end of p9_write_work()
  9P: Fix race in p9_read_work()
  9p: don't use __getname/__putname for uname/aname
  net/9p: Check errno validity
  fs/9p: avoid debug OOPS when reading a long symlink

Showing 4 changed files Side-by-side Diff

... ... @@ -184,10 +184,20 @@
184 184 v9ses->afid = option;
185 185 break;
186 186 case Opt_uname:
187   - match_strlcpy(v9ses->uname, &args[0], PATH_MAX);
  187 + kfree(v9ses->uname);
  188 + v9ses->uname = match_strdup(&args[0]);
  189 + if (!v9ses->uname) {
  190 + ret = -ENOMEM;
  191 + goto free_and_return;
  192 + }
188 193 break;
189 194 case Opt_remotename:
190   - match_strlcpy(v9ses->aname, &args[0], PATH_MAX);
  195 + kfree(v9ses->aname);
  196 + v9ses->aname = match_strdup(&args[0]);
  197 + if (!v9ses->aname) {
  198 + ret = -ENOMEM;
  199 + goto free_and_return;
  200 + }
191 201 break;
192 202 case Opt_nodevmap:
193 203 v9ses->nodev = 1;
194 204  
195 205  
196 206  
... ... @@ -287,21 +297,21 @@
287 297 struct p9_fid *fid;
288 298 int rc;
289 299  
290   - v9ses->uname = __getname();
  300 + v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
291 301 if (!v9ses->uname)
292 302 return ERR_PTR(-ENOMEM);
293 303  
294   - v9ses->aname = __getname();
  304 + v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
295 305 if (!v9ses->aname) {
296   - __putname(v9ses->uname);
  306 + kfree(v9ses->uname);
297 307 return ERR_PTR(-ENOMEM);
298 308 }
299 309 init_rwsem(&v9ses->rename_sem);
300 310  
301 311 rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
302 312 if (rc) {
303   - __putname(v9ses->aname);
304   - __putname(v9ses->uname);
  313 + kfree(v9ses->aname);
  314 + kfree(v9ses->uname);
305 315 return ERR_PTR(rc);
306 316 }
307 317  
... ... @@ -309,8 +319,6 @@
309 319 list_add(&v9ses->slist, &v9fs_sessionlist);
310 320 spin_unlock(&v9fs_sessionlist_lock);
311 321  
312   - strcpy(v9ses->uname, V9FS_DEFUSER);
313   - strcpy(v9ses->aname, V9FS_DEFANAME);
314 322 v9ses->uid = ~0;
315 323 v9ses->dfltuid = V9FS_DEFUID;
316 324 v9ses->dfltgid = V9FS_DEFGID;
... ... @@ -412,8 +420,8 @@
412 420 kfree(v9ses->cachetag);
413 421 }
414 422 #endif
415   - __putname(v9ses->uname);
416   - __putname(v9ses->aname);
  423 + kfree(v9ses->uname);
  424 + kfree(v9ses->aname);
417 425  
418 426 bdi_destroy(&v9ses->bdi);
419 427  
... ... @@ -1276,12 +1276,12 @@
1276 1276 }
1277 1277  
1278 1278 /* copy extension buffer into buffer */
1279   - strncpy(buffer, st->extension, buflen);
  1279 + retval = min(strlen(st->extension)+1, (size_t)buflen);
  1280 + memcpy(buffer, st->extension, retval);
1280 1281  
1281   - p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n",
1282   - dentry->d_name.name, st->extension, buffer);
  1282 + p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
  1283 + dentry->d_name.name, st->extension, buflen, buffer);
1283 1284  
1284   - retval = strnlen(buffer, buflen);
1285 1285 done:
1286 1286 p9stat_free(st);
1287 1287 kfree(st);
... ... @@ -76,6 +76,20 @@
76 76 }
77 77 EXPORT_SYMBOL(p9_is_proto_dotu);
78 78  
  79 +/*
  80 + * Some error codes are taken directly from the server replies,
  81 + * make sure they are valid.
  82 + */
  83 +static int safe_errno(int err)
  84 +{
  85 + if ((err > 0) || (err < -MAX_ERRNO)) {
  86 + p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err);
  87 + return -EPROTO;
  88 + }
  89 + return err;
  90 +}
  91 +
  92 +
79 93 /* Interpret mount option for protocol version */
80 94 static int get_protocol_version(char *s)
81 95 {
... ... @@ -782,7 +796,7 @@
782 796 return req;
783 797 reterr:
784 798 p9_free_req(c, req);
785   - return ERR_PTR(err);
  799 + return ERR_PTR(safe_errno(err));
786 800 }
787 801  
788 802 /**
... ... @@ -865,7 +879,7 @@
865 879 return req;
866 880 reterr:
867 881 p9_free_req(c, req);
868   - return ERR_PTR(err);
  882 + return ERR_PTR(safe_errno(err));
869 883 }
870 884  
871 885 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
... ... @@ -316,8 +316,7 @@
316 316 m->rsize - m->rpos);
317 317 p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
318 318 if (err == -EAGAIN) {
319   - clear_bit(Rworksched, &m->wsched);
320   - return;
  319 + goto end_clear;
321 320 }
322 321  
323 322 if (err <= 0)
324 323  
325 324  
... ... @@ -379,19 +378,20 @@
379 378 m->req = NULL;
380 379 }
381 380  
  381 +end_clear:
  382 + clear_bit(Rworksched, &m->wsched);
  383 +
382 384 if (!list_empty(&m->req_list)) {
383 385 if (test_and_clear_bit(Rpending, &m->wsched))
384 386 n = POLLIN;
385 387 else
386 388 n = p9_fd_poll(m->client, NULL);
387 389  
388   - if (n & POLLIN) {
  390 + if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) {
389 391 p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
390 392 schedule_work(&m->rq);
391   - } else
392   - clear_bit(Rworksched, &m->wsched);
393   - } else
394   - clear_bit(Rworksched, &m->wsched);
  393 + }
  394 + }
395 395  
396 396 return;
397 397 error:
398 398  
399 399  
... ... @@ -453,12 +453,13 @@
453 453 }
454 454  
455 455 if (!m->wsize) {
  456 + spin_lock(&m->client->lock);
456 457 if (list_empty(&m->unsent_req_list)) {
457 458 clear_bit(Wworksched, &m->wsched);
  459 + spin_unlock(&m->client->lock);
458 460 return;
459 461 }
460 462  
461   - spin_lock(&m->client->lock);
462 463 req = list_entry(m->unsent_req_list.next, struct p9_req_t,
463 464 req_list);
464 465 req->status = REQ_STATUS_SENT;
465 466  
... ... @@ -476,11 +477,10 @@
476 477 clear_bit(Wpending, &m->wsched);
477 478 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
478 479 p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
479   - if (err == -EAGAIN) {
480   - clear_bit(Wworksched, &m->wsched);
481   - return;
482   - }
  480 + if (err == -EAGAIN)
  481 + goto end_clear;
483 482  
  483 +
484 484 if (err < 0)
485 485 goto error;
486 486 else if (err == 0) {
487 487  
488 488  
... ... @@ -492,19 +492,21 @@
492 492 if (m->wpos == m->wsize)
493 493 m->wpos = m->wsize = 0;
494 494  
495   - if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
  495 +end_clear:
  496 + clear_bit(Wworksched, &m->wsched);
  497 +
  498 + if (m->wsize || !list_empty(&m->unsent_req_list)) {
496 499 if (test_and_clear_bit(Wpending, &m->wsched))
497 500 n = POLLOUT;
498 501 else
499 502 n = p9_fd_poll(m->client, NULL);
500 503  
501   - if (n & POLLOUT) {
  504 + if ((n & POLLOUT) &&
  505 + !test_and_set_bit(Wworksched, &m->wsched)) {
502 506 p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
503 507 schedule_work(&m->wq);
504   - } else
505   - clear_bit(Wworksched, &m->wsched);
506   - } else
507   - clear_bit(Wworksched, &m->wsched);
  508 + }
  509 + }
508 510  
509 511 return;
510 512