aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/trans_fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/trans_fd.c')
-rw-r--r--net/9p/trans_fd.c204
1 files changed, 168 insertions, 36 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index f624dff76852..4507f744f44e 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -47,12 +47,29 @@
47#define SCHED_TIMEOUT 10 47#define SCHED_TIMEOUT 10
48#define MAXPOLLWADDR 2 48#define MAXPOLLWADDR 2
49 49
50/**
51 * struct p9_fd_opts - per-transport options
52 * @rfd: file descriptor for reading (trans=fd)
53 * @wfd: file descriptor for writing (trans=fd)
54 * @port: port to connect to (trans=tcp)
55 *
56 */
57
50struct p9_fd_opts { 58struct p9_fd_opts {
51 int rfd; 59 int rfd;
52 int wfd; 60 int wfd;
53 u16 port; 61 u16 port;
54}; 62};
55 63
64
65/**
66 * struct p9_trans_fd - transport state
67 * @rd: reference to file to read from
68 * @wr: reference of file to write to
69 * @conn: connection state reference
70 *
71 */
72
56struct p9_trans_fd { 73struct p9_trans_fd {
57 struct file *rd; 74 struct file *rd;
58 struct file *wr; 75 struct file *wr;
@@ -90,10 +107,24 @@ enum {
90}; 107};
91 108
92struct p9_req; 109struct p9_req;
93
94typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); 110typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
111
112/**
113 * struct p9_req - fd mux encoding of an rpc transaction
114 * @lock: protects req_list
115 * @tag: numeric tag for rpc transaction
116 * @tcall: request &p9_fcall structure
117 * @rcall: response &p9_fcall structure
118 * @err: error state
119 * @cb: callback for when response is received
120 * @cba: argument to pass to callback
121 * @flush: flag to indicate RPC has been flushed
122 * @req_list: list link for higher level objects to chain requests
123 *
124 */
125
95struct p9_req { 126struct p9_req {
96 spinlock_t lock; /* protect request structure */ 127 spinlock_t lock;
97 int tag; 128 int tag;
98 struct p9_fcall *tcall; 129 struct p9_fcall *tcall;
99 struct p9_fcall *rcall; 130 struct p9_fcall *rcall;
@@ -104,7 +135,39 @@ struct p9_req {
104 struct list_head req_list; 135 struct list_head req_list;
105}; 136};
106 137
107struct p9_mux_poll_task; 138struct p9_mux_poll_task {
139 struct task_struct *task;
140 struct list_head mux_list;
141 int muxnum;
142};
143
144/**
145 * struct p9_conn - fd mux connection state information
146 * @lock: protects mux_list (?)
147 * @mux_list: list link for mux to manage multiple connections (?)
148 * @poll_task: task polling on this connection
149 * @msize: maximum size for connection (dup)
150 * @extended: 9p2000.u flag (dup)
151 * @trans: reference to transport instance for this connection
152 * @tagpool: id accounting for transactions
153 * @err: error state
154 * @equeue: event wait_q (?)
155 * @req_list: accounting for requests which have been sent
156 * @unsent_req_list: accounting for requests that haven't been sent
157 * @rcall: current response &p9_fcall structure
158 * @rpos: read position in current frame
159 * @rbuf: current read buffer
160 * @wpos: write position for current frame
161 * @wsize: amount of data to write for current frame
162 * @wbuf: current write buffer
163 * @poll_wait: array of wait_q's for various worker threads
164 * @poll_waddr: ????
165 * @pt: poll state
166 * @rq: current read work
167 * @wq: current write work
168 * @wsched: ????
169 *
170 */
108 171
109struct p9_conn { 172struct p9_conn {
110 spinlock_t lock; /* protect lock structure */ 173 spinlock_t lock; /* protect lock structure */
@@ -132,11 +195,16 @@ struct p9_conn {
132 unsigned long wsched; 195 unsigned long wsched;
133}; 196};
134 197
135struct p9_mux_poll_task { 198/**
136 struct task_struct *task; 199 * struct p9_mux_rpc - fd mux rpc accounting structure
137 struct list_head mux_list; 200 * @m: connection this request was issued on
138 int muxnum; 201 * @err: error state
139}; 202 * @tcall: request &p9_fcall
203 * @rcall: response &p9_fcall
204 * @wqueue: wait queue that client is blocked on for this rpc
205 *
206 * Bug: isn't this information duplicated elsewhere like &p9_req
207 */
140 208
141struct p9_mux_rpc { 209struct p9_mux_rpc {
142 struct p9_conn *m; 210 struct p9_conn *m;
@@ -207,10 +275,12 @@ static void p9_mux_put_tag(struct p9_conn *m, u16 tag)
207 275
208/** 276/**
209 * p9_mux_calc_poll_procs - calculates the number of polling procs 277 * p9_mux_calc_poll_procs - calculates the number of polling procs
210 * based on the number of mounted v9fs filesystems. 278 * @muxnum: number of mounts
211 * 279 *
280 * Calculation is based on the number of mounted v9fs filesystems.
212 * The current implementation returns sqrt of the number of mounts. 281 * The current implementation returns sqrt of the number of mounts.
213 */ 282 */
283
214static int p9_mux_calc_poll_procs(int muxnum) 284static int p9_mux_calc_poll_procs(int muxnum)
215{ 285{
216 int n; 286 int n;
@@ -331,12 +401,11 @@ static void p9_mux_poll_stop(struct p9_conn *m)
331 401
332/** 402/**
333 * p9_conn_create - allocate and initialize the per-session mux data 403 * p9_conn_create - allocate and initialize the per-session mux data
334 * Creates the polling task if this is the first session. 404 * @trans: transport structure
335 * 405 *
336 * @trans - transport structure 406 * Note: Creates the polling task if this is the first session.
337 * @msize - maximum message size
338 * @extended - extended flag
339 */ 407 */
408
340static struct p9_conn *p9_conn_create(struct p9_trans *trans) 409static struct p9_conn *p9_conn_create(struct p9_trans *trans)
341{ 410{
342 int i, n; 411 int i, n;
@@ -406,7 +475,10 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans)
406 475
407/** 476/**
408 * p9_mux_destroy - cancels all pending requests and frees mux resources 477 * p9_mux_destroy - cancels all pending requests and frees mux resources
478 * @m: mux to destroy
479 *
409 */ 480 */
481
410static void p9_conn_destroy(struct p9_conn *m) 482static void p9_conn_destroy(struct p9_conn *m)
411{ 483{
412 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, 484 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
@@ -429,9 +501,14 @@ static void p9_conn_destroy(struct p9_conn *m)
429} 501}
430 502
431/** 503/**
432 * p9_pollwait - called by files poll operation to add v9fs-poll task 504 * p9_pollwait - add poll task to the wait queue
433 * to files wait queue 505 * @filp: file pointer being polled
506 * @wait_address: wait_q to block on
507 * @p: poll state
508 *
509 * called by files poll operation to add v9fs-poll task to files wait queue
434 */ 510 */
511
435static void 512static void
436p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) 513p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
437{ 514{
@@ -462,7 +539,10 @@ p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
462 539
463/** 540/**
464 * p9_poll_mux - polls a mux and schedules read or write works if necessary 541 * p9_poll_mux - polls a mux and schedules read or write works if necessary
542 * @m: connection to poll
543 *
465 */ 544 */
545
466static void p9_poll_mux(struct p9_conn *m) 546static void p9_poll_mux(struct p9_conn *m)
467{ 547{
468 int n; 548 int n;
@@ -499,9 +579,14 @@ static void p9_poll_mux(struct p9_conn *m)
499} 579}
500 580
501/** 581/**
502 * p9_poll_proc - polls all v9fs transports for new events and queues 582 * p9_poll_proc - poll worker thread
503 * the appropriate work to the work queue 583 * @a: thread state and arguments
584 *
585 * polls all v9fs transports for new events and queues the appropriate
586 * work to the work queue
587 *
504 */ 588 */
589
505static int p9_poll_proc(void *a) 590static int p9_poll_proc(void *a)
506{ 591{
507 struct p9_conn *m, *mtmp; 592 struct p9_conn *m, *mtmp;
@@ -527,7 +612,10 @@ static int p9_poll_proc(void *a)
527 612
528/** 613/**
529 * p9_write_work - called when a transport can send some data 614 * p9_write_work - called when a transport can send some data
615 * @work: container for work to be done
616 *
530 */ 617 */
618
531static void p9_write_work(struct work_struct *work) 619static void p9_write_work(struct work_struct *work)
532{ 620{
533 int n, err; 621 int n, err;
@@ -638,7 +726,10 @@ static void process_request(struct p9_conn *m, struct p9_req *req)
638 726
639/** 727/**
640 * p9_read_work - called when there is some data to be read from a transport 728 * p9_read_work - called when there is some data to be read from a transport
729 * @work: container of work to be done
730 *
641 */ 731 */
732
642static void p9_read_work(struct work_struct *work) 733static void p9_read_work(struct work_struct *work)
643{ 734{
644 int n, err; 735 int n, err;
@@ -793,7 +884,9 @@ error:
793 * @tc: request to be sent 884 * @tc: request to be sent
794 * @cb: callback function to call when response is received 885 * @cb: callback function to call when response is received
795 * @cba: parameter to pass to the callback function 886 * @cba: parameter to pass to the callback function
887 *
796 */ 888 */
889
797static struct p9_req *p9_send_request(struct p9_conn *m, 890static struct p9_req *p9_send_request(struct p9_conn *m,
798 struct p9_fcall *tc, 891 struct p9_fcall *tc,
799 p9_conn_req_callback cb, void *cba) 892 p9_conn_req_callback cb, void *cba)
@@ -961,10 +1054,12 @@ p9_conn_rpc_cb(struct p9_req *req, void *a)
961/** 1054/**
962 * p9_fd_rpc- sends 9P request and waits until a response is available. 1055 * p9_fd_rpc- sends 9P request and waits until a response is available.
963 * The function can be interrupted. 1056 * The function can be interrupted.
964 * @m: mux data 1057 * @t: transport data
965 * @tc: request to be sent 1058 * @tc: request to be sent
966 * @rc: pointer where a pointer to the response is stored 1059 * @rc: pointer where a pointer to the response is stored
1060 *
967 */ 1061 */
1062
968int 1063int
969p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) 1064p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
970{ 1065{
@@ -1041,8 +1136,10 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
1041 * @m: mux data 1136 * @m: mux data
1042 * @tc: request to be sent 1137 * @tc: request to be sent
1043 * @cb: callback function to be called when response arrives 1138 * @cb: callback function to be called when response arrives
1044 * @cba: value to pass to the callback function 1139 * @a: value to pass to the callback function
1140 *
1045 */ 1141 */
1142
1046int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, 1143int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
1047 p9_conn_req_callback cb, void *a) 1144 p9_conn_req_callback cb, void *a)
1048{ 1145{
@@ -1065,7 +1162,9 @@ int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
1065 * p9_conn_cancel - cancel all pending requests with error 1162 * p9_conn_cancel - cancel all pending requests with error
1066 * @m: mux data 1163 * @m: mux data
1067 * @err: error code 1164 * @err: error code
1165 *
1068 */ 1166 */
1167
1069void p9_conn_cancel(struct p9_conn *m, int err) 1168void p9_conn_cancel(struct p9_conn *m, int err)
1070{ 1169{
1071 struct p9_req *req, *rtmp; 1170 struct p9_req *req, *rtmp;
@@ -1097,35 +1196,46 @@ void p9_conn_cancel(struct p9_conn *m, int err)
1097} 1196}
1098 1197
1099/** 1198/**
1100 * v9fs_parse_options - parse mount options into session structure 1199 * parse_options - parse mount options into session structure
1101 * @options: options string passed from mount 1200 * @options: options string passed from mount
1102 * @v9ses: existing v9fs session information 1201 * @opts: transport-specific structure to parse options into
1103 * 1202 *
1203 * Returns 0 upon success, -ERRNO upon failure
1104 */ 1204 */
1105 1205
1106static void parse_opts(char *options, struct p9_fd_opts *opts) 1206static int parse_opts(char *params, struct p9_fd_opts *opts)
1107{ 1207{
1108 char *p; 1208 char *p;
1109 substring_t args[MAX_OPT_ARGS]; 1209 substring_t args[MAX_OPT_ARGS];
1110 int option; 1210 int option;
1211 char *options;
1111 int ret; 1212 int ret;
1112 1213
1113 opts->port = P9_PORT; 1214 opts->port = P9_PORT;
1114 opts->rfd = ~0; 1215 opts->rfd = ~0;
1115 opts->wfd = ~0; 1216 opts->wfd = ~0;
1116 1217
1117 if (!options) 1218 if (!params)
1118 return; 1219 return 0;
1220
1221 options = kstrdup(params, GFP_KERNEL);
1222 if (!options) {
1223 P9_DPRINTK(P9_DEBUG_ERROR,
1224 "failed to allocate copy of option string\n");
1225 return -ENOMEM;
1226 }
1119 1227
1120 while ((p = strsep(&options, ",")) != NULL) { 1228 while ((p = strsep(&options, ",")) != NULL) {
1121 int token; 1229 int token;
1230 int r;
1122 if (!*p) 1231 if (!*p)
1123 continue; 1232 continue;
1124 token = match_token(p, tokens, args); 1233 token = match_token(p, tokens, args);
1125 ret = match_int(&args[0], &option); 1234 r = match_int(&args[0], &option);
1126 if (ret < 0) { 1235 if (r < 0) {
1127 P9_DPRINTK(P9_DEBUG_ERROR, 1236 P9_DPRINTK(P9_DEBUG_ERROR,
1128 "integer field, but no integer?\n"); 1237 "integer field, but no integer?\n");
1238 ret = r;
1129 continue; 1239 continue;
1130 } 1240 }
1131 switch (token) { 1241 switch (token) {
@@ -1142,6 +1252,8 @@ static void parse_opts(char *options, struct p9_fd_opts *opts)
1142 continue; 1252 continue;
1143 } 1253 }
1144 } 1254 }
1255 kfree(options);
1256 return 0;
1145} 1257}
1146 1258
1147static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) 1259static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd)
@@ -1193,11 +1305,12 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
1193 1305
1194/** 1306/**
1195 * p9_fd_read- read from a fd 1307 * p9_fd_read- read from a fd
1196 * @v9ses: session information 1308 * @trans: transport instance state
1197 * @v: buffer to receive data into 1309 * @v: buffer to receive data into
1198 * @len: size of receive buffer 1310 * @len: size of receive buffer
1199 * 1311 *
1200 */ 1312 */
1313
1201static int p9_fd_read(struct p9_trans *trans, void *v, int len) 1314static int p9_fd_read(struct p9_trans *trans, void *v, int len)
1202{ 1315{
1203 int ret; 1316 int ret;
@@ -1220,11 +1333,12 @@ static int p9_fd_read(struct p9_trans *trans, void *v, int len)
1220 1333
1221/** 1334/**
1222 * p9_fd_write - write to a socket 1335 * p9_fd_write - write to a socket
1223 * @v9ses: session information 1336 * @trans: transport instance state
1224 * @v: buffer to send data from 1337 * @v: buffer to send data from
1225 * @len: size of send buffer 1338 * @len: size of send buffer
1226 * 1339 *
1227 */ 1340 */
1341
1228static int p9_fd_write(struct p9_trans *trans, void *v, int len) 1342static int p9_fd_write(struct p9_trans *trans, void *v, int len)
1229{ 1343{
1230 int ret; 1344 int ret;
@@ -1296,6 +1410,7 @@ end:
1296 * @trans: private socket structure 1410 * @trans: private socket structure
1297 * 1411 *
1298 */ 1412 */
1413
1299static void p9_fd_close(struct p9_trans *trans) 1414static void p9_fd_close(struct p9_trans *trans)
1300{ 1415{
1301 struct p9_trans_fd *ts; 1416 struct p9_trans_fd *ts;
@@ -1318,6 +1433,23 @@ static void p9_fd_close(struct p9_trans *trans)
1318 kfree(ts); 1433 kfree(ts);
1319} 1434}
1320 1435
1436/*
1437 * stolen from NFS - maybe should be made a generic function?
1438 */
1439static inline int valid_ipaddr4(const char *buf)
1440{
1441 int rc, count, in[4];
1442
1443 rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
1444 if (rc != 4)
1445 return -EINVAL;
1446 for (count = 0; count < 4; count++) {
1447 if (in[count] > 255)
1448 return -EINVAL;
1449 }
1450 return 0;
1451}
1452
1321static struct p9_trans * 1453static struct p9_trans *
1322p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) 1454p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
1323{ 1455{
@@ -1328,7 +1460,12 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
1328 struct p9_fd_opts opts; 1460 struct p9_fd_opts opts;
1329 struct p9_trans_fd *p; 1461 struct p9_trans_fd *p;
1330 1462
1331 parse_opts(args, &opts); 1463 err = parse_opts(args, &opts);
1464 if (err < 0)
1465 return ERR_PTR(err);
1466
1467 if (valid_ipaddr4(addr) < 0)
1468 return ERR_PTR(-EINVAL);
1332 1469
1333 csocket = NULL; 1470 csocket = NULL;
1334 trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); 1471 trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
@@ -1508,7 +1645,7 @@ static struct p9_trans_module p9_fd_trans = {
1508 .create = p9_trans_create_fd, 1645 .create = p9_trans_create_fd,
1509}; 1646};
1510 1647
1511static int __init p9_trans_fd_init(void) 1648int p9_trans_fd_init(void)
1512{ 1649{
1513 int ret = p9_mux_global_init(); 1650 int ret = p9_mux_global_init();
1514 if (ret) { 1651 if (ret) {
@@ -1522,9 +1659,4 @@ static int __init p9_trans_fd_init(void)
1522 1659
1523 return 0; 1660 return 0;
1524} 1661}
1525 1662EXPORT_SYMBOL(p9_trans_fd_init);
1526module_init(p9_trans_fd_init);
1527
1528MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
1529MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
1530MODULE_LICENSE("GPL");