Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+59 -35
+19 -11
fs/9p/v9fs.c
··· 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; ··· 297 287 struct p9_fid *fid; 298 288 int rc; 299 289 300 - v9ses->uname = __getname(); 290 + v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); 301 291 if (!v9ses->uname) 302 292 return ERR_PTR(-ENOMEM); 303 293 304 - v9ses->aname = __getname(); 294 + v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); 305 295 if (!v9ses->aname) { 306 - __putname(v9ses->uname); 296 + kfree(v9ses->uname); 307 297 return ERR_PTR(-ENOMEM); 308 298 } 309 299 init_rwsem(&v9ses->rename_sem); 310 300 311 301 rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); 312 302 if (rc) { 313 - __putname(v9ses->aname); 314 - __putname(v9ses->uname); 303 + kfree(v9ses->aname); 304 + kfree(v9ses->uname); 315 305 return ERR_PTR(rc); 316 306 } 317 307 ··· 319 309 list_add(&v9ses->slist, &v9fs_sessionlist); 320 310 spin_unlock(&v9fs_sessionlist_lock); 321 311 322 - strcpy(v9ses->uname, V9FS_DEFUSER); 323 - strcpy(v9ses->aname, V9FS_DEFANAME); 324 312 v9ses->uid = ~0; 325 313 v9ses->dfltuid = V9FS_DEFUID; 326 314 v9ses->dfltgid = V9FS_DEFGID; ··· 420 412 kfree(v9ses->cachetag); 421 413 } 422 414 #endif 423 - __putname(v9ses->uname); 424 - __putname(v9ses->aname); 415 + kfree(v9ses->uname); 416 + kfree(v9ses->aname); 425 417 426 418 bdi_destroy(&v9ses->bdi); 427 419
+4 -4
fs/9p/vfs_inode.c
··· 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);
+16 -2
net/9p/client.c
··· 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 { ··· 796 782 return req; 797 783 reterr: 798 784 p9_free_req(c, req); 799 - return ERR_PTR(err); 785 + return ERR_PTR(safe_errno(err)); 800 786 } 801 787 802 788 /** ··· 879 865 return req; 880 866 reterr: 881 867 p9_free_req(c, req); 882 - return ERR_PTR(err); 868 + return ERR_PTR(safe_errno(err)); 883 869 } 884 870 885 871 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
+20 -18
net/9p/trans_fd.c
··· 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) ··· 378 379 m->req = NULL; 379 380 } 380 381 382 + end_clear: 383 + clear_bit(Rworksched, &m->wsched); 384 + 381 385 if (!list_empty(&m->req_list)) { 382 386 if (test_and_clear_bit(Rpending, &m->wsched)) 383 387 n = POLLIN; 384 388 else 385 389 n = p9_fd_poll(m->client, NULL); 386 390 387 - if (n & POLLIN) { 391 + if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) { 388 392 p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); 389 393 schedule_work(&m->rq); 390 - } else 391 - clear_bit(Rworksched, &m->wsched); 392 - } else 393 - clear_bit(Rworksched, &m->wsched); 394 + } 395 + } 394 396 395 397 return; 396 398 error: ··· 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; ··· 477 476 clear_bit(Wpending, &m->wsched); 478 477 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); 479 478 p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err); 480 - if (err == -EAGAIN) { 481 - clear_bit(Wworksched, &m->wsched); 482 - return; 483 - } 479 + if (err == -EAGAIN) 480 + goto end_clear; 481 + 484 482 485 483 if (err < 0) 486 484 goto error; ··· 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