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

Configure Feed

Select the types of activity you want to include in your feed.

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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
9p: fix put_data error handling
9p: use an IS_ERR test rather than a NULL test
9p: introduce missing kfree
9p-trans_fd: fix and clean up module init/exit paths
9p-trans_fd: don't do fs segment mangling in p9_fd_poll()
9p-trans_fd: clean up p9_conn_create()
9p-trans_fd: fix trans_fd::p9_conn_destroy()
9p: implement proper trans module refcounting and unregistration

+127 -100
+1 -2
fs/9p/vfs_inode.c
··· 626 626 return NULL; 627 627 628 628 error: 629 - if (fid) 630 - p9_client_clunk(fid); 629 + p9_client_clunk(fid); 631 630 632 631 return ERR_PTR(result); 633 632 }
+1
include/net/9p/9p.h
··· 596 596 int p9_error_init(void); 597 597 int p9_errstr2errno(char *, int); 598 598 int p9_trans_fd_init(void); 599 + void p9_trans_fd_exit(void); 599 600 #endif /* NET_9P_H */
+7 -2
include/net/9p/transport.h
··· 26 26 #ifndef NET_9P_TRANSPORT_H 27 27 #define NET_9P_TRANSPORT_H 28 28 29 + #include <linux/module.h> 30 + 29 31 /** 30 32 * enum p9_trans_status - different states of underlying transports 31 33 * @Connected: transport is connected and healthy ··· 93 91 int maxsize; /* max message size of transport */ 94 92 int def; /* this transport should be default */ 95 93 struct p9_trans * (*create)(const char *, char *, int, unsigned char); 94 + struct module *owner; 96 95 }; 97 96 98 97 void v9fs_register_trans(struct p9_trans_module *m); 99 - struct p9_trans_module *v9fs_match_trans(const substring_t *name); 100 - struct p9_trans_module *v9fs_default_trans(void); 98 + void v9fs_unregister_trans(struct p9_trans_module *m); 99 + struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name); 100 + struct p9_trans_module *v9fs_get_default_trans(void); 101 + void v9fs_put_trans(struct p9_trans_module *m); 101 102 #endif /* NET_9P_TRANSPORT_H */
+8 -2
net/9p/client.c
··· 75 75 int option; 76 76 int ret = 0; 77 77 78 - clnt->trans_mod = v9fs_default_trans(); 79 78 clnt->dotu = 1; 80 79 clnt->msize = 8192; 81 80 ··· 107 108 clnt->msize = option; 108 109 break; 109 110 case Opt_trans: 110 - clnt->trans_mod = v9fs_match_trans(&args[0]); 111 + clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); 111 112 break; 112 113 case Opt_legacy: 113 114 clnt->dotu = 0; ··· 116 117 continue; 117 118 } 118 119 } 120 + 121 + if (!clnt->trans_mod) 122 + clnt->trans_mod = v9fs_get_default_trans(); 123 + 119 124 kfree(options); 120 125 return ret; 121 126 } ··· 153 150 if (!clnt) 154 151 return ERR_PTR(-ENOMEM); 155 152 153 + clnt->trans_mod = NULL; 156 154 clnt->trans = NULL; 157 155 spin_lock_init(&clnt->lock); 158 156 INIT_LIST_HEAD(&clnt->fidlist); ··· 238 234 kfree(clnt->trans); 239 235 clnt->trans = NULL; 240 236 } 237 + 238 + v9fs_put_trans(clnt->trans_mod); 241 239 242 240 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) 243 241 p9_fid_destroy(fid);
+5 -1
net/9p/conv.c
··· 451 451 unsigned char **pdata) 452 452 { 453 453 *pdata = buf_alloc(bufp, count); 454 + if (*pdata == NULL) 455 + return -ENOMEM; 454 456 memmove(*pdata, data, count); 455 - return count; 457 + return 0; 456 458 } 457 459 458 460 static int ··· 462 460 unsigned char **pdata) 463 461 { 464 462 *pdata = buf_alloc(bufp, count); 463 + if (*pdata == NULL) 464 + return -ENOMEM; 465 465 return copy_from_user(*pdata, data, count); 466 466 } 467 467
+67 -25
net/9p/mod.c
··· 31 31 #include <linux/parser.h> 32 32 #include <net/9p/transport.h> 33 33 #include <linux/list.h> 34 + #include <linux/spinlock.h> 34 35 35 36 #ifdef CONFIG_NET_9P_DEBUG 36 37 unsigned int p9_debug_level = 0; /* feature-rific global debug level */ ··· 45 44 * 46 45 */ 47 46 47 + static DEFINE_SPINLOCK(v9fs_trans_lock); 48 48 static LIST_HEAD(v9fs_trans_list); 49 - static struct p9_trans_module *v9fs_default_transport; 50 49 51 50 /** 52 51 * v9fs_register_trans - register a new transport with 9p ··· 55 54 */ 56 55 void v9fs_register_trans(struct p9_trans_module *m) 57 56 { 57 + spin_lock(&v9fs_trans_lock); 58 58 list_add_tail(&m->list, &v9fs_trans_list); 59 - if (m->def) 60 - v9fs_default_transport = m; 59 + spin_unlock(&v9fs_trans_lock); 61 60 } 62 61 EXPORT_SYMBOL(v9fs_register_trans); 63 62 64 63 /** 65 - * v9fs_match_trans - match transport versus registered transports 64 + * v9fs_unregister_trans - unregister a 9p transport 65 + * @m: the transport to remove 66 + * 67 + */ 68 + void v9fs_unregister_trans(struct p9_trans_module *m) 69 + { 70 + spin_lock(&v9fs_trans_lock); 71 + list_del_init(&m->list); 72 + spin_unlock(&v9fs_trans_lock); 73 + } 74 + EXPORT_SYMBOL(v9fs_unregister_trans); 75 + 76 + /** 77 + * v9fs_get_trans_by_name - get transport with the matching name 66 78 * @name: string identifying transport 67 79 * 68 80 */ 69 - struct p9_trans_module *v9fs_match_trans(const substring_t *name) 81 + struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name) 70 82 { 71 - struct list_head *p; 72 - struct p9_trans_module *t = NULL; 83 + struct p9_trans_module *t, *found = NULL; 73 84 74 - list_for_each(p, &v9fs_trans_list) { 75 - t = list_entry(p, struct p9_trans_module, list); 76 - if (strncmp(t->name, name->from, name->to-name->from) == 0) 77 - return t; 78 - } 79 - return NULL; 85 + spin_lock(&v9fs_trans_lock); 86 + 87 + list_for_each_entry(t, &v9fs_trans_list, list) 88 + if (strncmp(t->name, name->from, name->to-name->from) == 0 && 89 + try_module_get(t->owner)) { 90 + found = t; 91 + break; 92 + } 93 + 94 + spin_unlock(&v9fs_trans_lock); 95 + return found; 80 96 } 81 - EXPORT_SYMBOL(v9fs_match_trans); 97 + EXPORT_SYMBOL(v9fs_get_trans_by_name); 82 98 83 99 /** 84 - * v9fs_default_trans - returns pointer to default transport 100 + * v9fs_get_default_trans - get the default transport 85 101 * 86 102 */ 87 103 88 - struct p9_trans_module *v9fs_default_trans(void) 104 + struct p9_trans_module *v9fs_get_default_trans(void) 89 105 { 90 - if (v9fs_default_transport) 91 - return v9fs_default_transport; 92 - else if (!list_empty(&v9fs_trans_list)) 93 - return list_first_entry(&v9fs_trans_list, 94 - struct p9_trans_module, list); 95 - else 96 - return NULL; 97 - } 98 - EXPORT_SYMBOL(v9fs_default_trans); 106 + struct p9_trans_module *t, *found = NULL; 99 107 108 + spin_lock(&v9fs_trans_lock); 109 + 110 + list_for_each_entry(t, &v9fs_trans_list, list) 111 + if (t->def && try_module_get(t->owner)) { 112 + found = t; 113 + break; 114 + } 115 + 116 + if (!found) 117 + list_for_each_entry(t, &v9fs_trans_list, list) 118 + if (try_module_get(t->owner)) { 119 + found = t; 120 + break; 121 + } 122 + 123 + spin_unlock(&v9fs_trans_lock); 124 + return found; 125 + } 126 + EXPORT_SYMBOL(v9fs_get_default_trans); 127 + 128 + /** 129 + * v9fs_put_trans - put trans 130 + * @m: transport to put 131 + * 132 + */ 133 + void v9fs_put_trans(struct p9_trans_module *m) 134 + { 135 + if (m) 136 + module_put(m->owner); 137 + } 100 138 101 139 /** 102 140 * v9fs_init - Initialize module ··· 160 120 static void __exit exit_p9(void) 161 121 { 162 122 printk(KERN_INFO "Unloading 9P2000 support\n"); 123 + 124 + p9_trans_fd_exit(); 163 125 } 164 126 165 127 module_init(init_p9)
+36 -68
net/9p/trans_fd.c
··· 151 151 * @trans: reference to transport instance for this connection 152 152 * @tagpool: id accounting for transactions 153 153 * @err: error state 154 - * @equeue: event wait_q (?) 155 154 * @req_list: accounting for requests which have been sent 156 155 * @unsent_req_list: accounting for requests that haven't been sent 157 156 * @rcall: current response &p9_fcall structure ··· 177 178 struct p9_trans *trans; 178 179 struct p9_idpool *tagpool; 179 180 int err; 180 - wait_queue_head_t equeue; 181 181 struct list_head req_list; 182 182 struct list_head unsent_req_list; 183 183 struct p9_fcall *rcall; ··· 237 239 #endif /* P9_NONBLOCK */ 238 240 239 241 static void p9_conn_cancel(struct p9_conn *m, int err); 240 - 241 - static int p9_mux_global_init(void) 242 - { 243 - int i; 244 - 245 - for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) 246 - p9_mux_poll_tasks[i].task = NULL; 247 - 248 - p9_mux_wq = create_workqueue("v9fs"); 249 - if (!p9_mux_wq) { 250 - printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); 251 - return -ENOMEM; 252 - } 253 - 254 - return 0; 255 - } 256 242 257 243 static u16 p9_mux_get_tag(struct p9_conn *m) 258 244 { ··· 391 409 static struct p9_conn *p9_conn_create(struct p9_trans *trans) 392 410 { 393 411 int i, n; 394 - struct p9_conn *m, *mtmp; 412 + struct p9_conn *m; 395 413 396 414 P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, 397 415 trans->msize); 398 - m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); 416 + m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); 399 417 if (!m) 400 418 return ERR_PTR(-ENOMEM); 401 419 ··· 406 424 m->trans = trans; 407 425 m->tagpool = p9_idpool_create(); 408 426 if (IS_ERR(m->tagpool)) { 409 - mtmp = ERR_PTR(-ENOMEM); 410 427 kfree(m); 411 - return mtmp; 428 + return ERR_PTR(-ENOMEM); 412 429 } 413 430 414 - m->err = 0; 415 - init_waitqueue_head(&m->equeue); 416 431 INIT_LIST_HEAD(&m->req_list); 417 432 INIT_LIST_HEAD(&m->unsent_req_list); 418 - m->rcall = NULL; 419 - m->rpos = 0; 420 - m->rbuf = NULL; 421 - m->wpos = m->wsize = 0; 422 - m->wbuf = NULL; 423 433 INIT_WORK(&m->rq, p9_read_work); 424 434 INIT_WORK(&m->wq, p9_write_work); 425 - m->wsched = 0; 426 - memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 427 - m->poll_task = NULL; 428 435 n = p9_mux_poll_start(m); 429 436 if (n) { 430 437 kfree(m); ··· 434 463 for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 435 464 if (IS_ERR(m->poll_waddr[i])) { 436 465 p9_mux_poll_stop(m); 437 - mtmp = (void *)m->poll_waddr; /* the error code */ 438 466 kfree(m); 439 - m = mtmp; 440 - break; 467 + return (void *)m->poll_waddr; /* the error code */ 441 468 } 442 469 } 443 470 ··· 452 483 { 453 484 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, 454 485 m->mux_list.prev, m->mux_list.next); 455 - p9_conn_cancel(m, -ECONNRESET); 456 - 457 - if (!list_empty(&m->req_list)) { 458 - /* wait until all processes waiting on this session exit */ 459 - P9_DPRINTK(P9_DEBUG_MUX, 460 - "mux %p waiting for empty request queue\n", m); 461 - wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); 462 - P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, 463 - list_empty(&m->req_list)); 464 - } 465 486 466 487 p9_mux_poll_stop(m); 488 + cancel_work_sync(&m->rq); 489 + cancel_work_sync(&m->wq); 490 + 491 + p9_conn_cancel(m, -ECONNRESET); 492 + 467 493 m->trans = NULL; 468 494 p9_idpool_destroy(m->tagpool); 469 495 kfree(m); ··· 804 840 (*req->cb) (req, req->cba); 805 841 else 806 842 kfree(req->rcall); 807 - 808 - wake_up(&m->equeue); 809 843 } 810 844 } else { 811 845 if (err >= 0 && rcall->id != P9_RFLUSH) ··· 870 908 else 871 909 n = p9_mux_get_tag(m); 872 910 873 - if (n < 0) 911 + if (n < 0) { 912 + kfree(req); 874 913 return ERR_PTR(-ENOMEM); 914 + } 875 915 876 916 p9_set_tag(tc, n); 877 917 ··· 948 984 (*req->cb) (req, req->cba); 949 985 else 950 986 kfree(req->rcall); 951 - 952 - wake_up(&m->equeue); 953 987 } 954 988 955 989 kfree(freq->tcall); ··· 1153 1191 else 1154 1192 kfree(req->rcall); 1155 1193 } 1156 - 1157 - wake_up(&m->equeue); 1158 1194 } 1159 1195 1160 1196 /** ··· 1330 1370 { 1331 1371 int ret, n; 1332 1372 struct p9_trans_fd *ts = NULL; 1333 - mm_segment_t oldfs; 1334 1373 1335 1374 if (trans && trans->status == Connected) 1336 1375 ts = trans->priv; ··· 1343 1384 if (!ts->wr->f_op || !ts->wr->f_op->poll) 1344 1385 return -EIO; 1345 1386 1346 - oldfs = get_fs(); 1347 - set_fs(get_ds()); 1348 - 1349 1387 ret = ts->rd->f_op->poll(ts->rd, pt); 1350 1388 if (ret < 0) 1351 - goto end; 1389 + return ret; 1352 1390 1353 1391 if (ts->rd != ts->wr) { 1354 1392 n = ts->wr->f_op->poll(ts->wr, pt); 1355 - if (n < 0) { 1356 - ret = n; 1357 - goto end; 1358 - } 1393 + if (n < 0) 1394 + return n; 1359 1395 ret = (ret & ~POLLOUT) | (n & ~POLLIN); 1360 1396 } 1361 1397 1362 - end: 1363 - set_fs(oldfs); 1364 1398 return ret; 1365 1399 } 1366 1400 ··· 1581 1629 .maxsize = MAX_SOCK_BUF, 1582 1630 .def = 1, 1583 1631 .create = p9_trans_create_tcp, 1632 + .owner = THIS_MODULE, 1584 1633 }; 1585 1634 1586 1635 static struct p9_trans_module p9_unix_trans = { ··· 1589 1636 .maxsize = MAX_SOCK_BUF, 1590 1637 .def = 0, 1591 1638 .create = p9_trans_create_unix, 1639 + .owner = THIS_MODULE, 1592 1640 }; 1593 1641 1594 1642 static struct p9_trans_module p9_fd_trans = { ··· 1597 1643 .maxsize = MAX_SOCK_BUF, 1598 1644 .def = 0, 1599 1645 .create = p9_trans_create_fd, 1646 + .owner = THIS_MODULE, 1600 1647 }; 1601 1648 1602 1649 int p9_trans_fd_init(void) 1603 1650 { 1604 - int ret = p9_mux_global_init(); 1605 - if (ret) { 1606 - printk(KERN_WARNING "9p: starting mux failed\n"); 1607 - return ret; 1651 + int i; 1652 + 1653 + for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) 1654 + p9_mux_poll_tasks[i].task = NULL; 1655 + 1656 + p9_mux_wq = create_workqueue("v9fs"); 1657 + if (!p9_mux_wq) { 1658 + printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); 1659 + return -ENOMEM; 1608 1660 } 1609 1661 1610 1662 v9fs_register_trans(&p9_tcp_trans); ··· 1619 1659 1620 1660 return 0; 1621 1661 } 1622 - EXPORT_SYMBOL(p9_trans_fd_init); 1662 + 1663 + void p9_trans_fd_exit(void) 1664 + { 1665 + v9fs_unregister_trans(&p9_tcp_trans); 1666 + v9fs_unregister_trans(&p9_unix_trans); 1667 + v9fs_unregister_trans(&p9_fd_trans); 1668 + 1669 + destroy_workqueue(p9_mux_wq); 1670 + }
+2
net/9p/trans_virtio.c
··· 528 528 .create = p9_virtio_create, 529 529 .maxsize = PAGE_SIZE*16, 530 530 .def = 0, 531 + .owner = THIS_MODULE, 531 532 }; 532 533 533 534 /* The standard init function */ ··· 546 545 static void __exit p9_virtio_cleanup(void) 547 546 { 548 547 unregister_virtio_driver(&p9_virtio_drv); 548 + v9fs_unregister_trans(&p9_virtio_trans); 549 549 } 550 550 551 551 module_init(p9_virtio_init);