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

Merge branch 'for-linus' of git://github.com/ericvh/linux

* 'for-linus' of git://github.com/ericvh/linux:
9p: fix 9p.txt to advertise msize instead of maxdata
net/9p: Convert net/9p protocol dumps to tracepoints
fs/9p: change an int to unsigned int
fs/9p: Cleanup option parsing in 9p
9p: move dereference after NULL check
fs/9p: inode file operation is properly initialized init_special_inode
fs/9p: Update zero-copy implementation in 9p

+789 -469
+1 -1
Documentation/filesystems/9p.txt
··· 92 92 93 93 wfdno=n the file descriptor for writing with trans=fd 94 94 95 - maxdata=n the number of bytes to use for 9p packet payload (msize) 95 + msize=n the number of bytes to use for 9p packet payload 96 96 97 97 port=n port to connect to on the remote server 98 98
+26 -7
fs/9p/v9fs.c
··· 132 132 options = tmp_options; 133 133 134 134 while ((p = strsep(&options, ",")) != NULL) { 135 - int token; 135 + int token, r; 136 136 if (!*p) 137 137 continue; 138 138 token = match_token(p, tokens, args); 139 - if (token < Opt_uname) { 140 - int r = match_int(&args[0], &option); 139 + switch (token) { 140 + case Opt_debug: 141 + r = match_int(&args[0], &option); 141 142 if (r < 0) { 142 143 P9_DPRINTK(P9_DEBUG_ERROR, 143 - "integer field, but no integer?\n"); 144 + "integer field, but no integer?\n"); 144 145 ret = r; 145 146 continue; 146 147 } 147 - } 148 - switch (token) { 149 - case Opt_debug: 150 148 v9ses->debug = option; 151 149 #ifdef CONFIG_NET_9P_DEBUG 152 150 p9_debug_level = option; ··· 152 154 break; 153 155 154 156 case Opt_dfltuid: 157 + r = match_int(&args[0], &option); 158 + if (r < 0) { 159 + P9_DPRINTK(P9_DEBUG_ERROR, 160 + "integer field, but no integer?\n"); 161 + ret = r; 162 + continue; 163 + } 155 164 v9ses->dfltuid = option; 156 165 break; 157 166 case Opt_dfltgid: 167 + r = match_int(&args[0], &option); 168 + if (r < 0) { 169 + P9_DPRINTK(P9_DEBUG_ERROR, 170 + "integer field, but no integer?\n"); 171 + ret = r; 172 + continue; 173 + } 158 174 v9ses->dfltgid = option; 159 175 break; 160 176 case Opt_afid: 177 + r = match_int(&args[0], &option); 178 + if (r < 0) { 179 + P9_DPRINTK(P9_DEBUG_ERROR, 180 + "integer field, but no integer?\n"); 181 + ret = r; 182 + continue; 183 + } 161 184 v9ses->afid = option; 162 185 break; 163 186 case Opt_uname:
+6 -8
fs/9p/vfs_dir.c
··· 165 165 } 166 166 while (rdir->head < rdir->tail) { 167 167 p9stat_init(&st); 168 - err = p9stat_read(rdir->buf + rdir->head, 169 - rdir->tail - rdir->head, &st, 170 - fid->clnt->proto_version); 168 + err = p9stat_read(fid->clnt, rdir->buf + rdir->head, 169 + rdir->tail - rdir->head, &st); 171 170 if (err) { 172 171 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 173 172 err = -EIO; ··· 230 231 while (err == 0) { 231 232 if (rdir->tail == rdir->head) { 232 233 err = p9_client_readdir(fid, rdir->buf, buflen, 233 - filp->f_pos); 234 + filp->f_pos); 234 235 if (err <= 0) 235 236 goto unlock_and_exit; 236 237 ··· 240 241 241 242 while (rdir->head < rdir->tail) { 242 243 243 - err = p9dirent_read(rdir->buf + rdir->head, 244 - rdir->tail - rdir->head, 245 - &curdirent, 246 - fid->clnt->proto_version); 244 + err = p9dirent_read(fid->clnt, rdir->buf + rdir->head, 245 + rdir->tail - rdir->head, 246 + &curdirent); 247 247 if (err < 0) { 248 248 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 249 249 err = -EIO;
-2
fs/9p/vfs_inode.c
··· 278 278 case S_IFSOCK: 279 279 if (v9fs_proto_dotl(v9ses)) { 280 280 inode->i_op = &v9fs_file_inode_operations_dotl; 281 - inode->i_fop = &v9fs_file_operations_dotl; 282 281 } else if (v9fs_proto_dotu(v9ses)) { 283 282 inode->i_op = &v9fs_file_inode_operations; 284 - inode->i_fop = &v9fs_file_operations; 285 283 } else { 286 284 P9_DPRINTK(P9_DEBUG_ERROR, 287 285 "special files without extended mode\n");
+3 -11
include/net/9p/9p.h
··· 76 76 } \ 77 77 } while (0) 78 78 79 - #define P9_DUMP_PKT(way, pdu) p9pdu_dump(way, pdu) 80 - 81 79 #else 82 80 #define P9_DPRINTK(level, format, arg...) do { } while (0) 83 - #define P9_DUMP_PKT(way, pdu) do { } while (0) 84 81 #endif 85 82 86 83 ··· 356 359 /* Room for readdir header */ 357 360 #define P9_READDIRHDRSZ 24 358 361 362 + /* size of header for zero copy read/write */ 363 + #define P9_ZC_HDR_SZ 4096 364 + 359 365 /** 360 366 * struct p9_qid - file system entity information 361 367 * @type: 8-bit type &p9_qid_t ··· 555 555 * @tag: transaction id of the request 556 556 * @offset: used by marshalling routines to track current position in buffer 557 557 * @capacity: used by marshalling routines to track total malloc'd capacity 558 - * @pubuf: Payload user buffer given by the caller 559 - * @pkbuf: Payload kernel buffer given by the caller 560 - * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write. 561 - * @private: For transport layer's use. 562 558 * @sdata: payload 563 559 * 564 560 * &p9_fcall represents the structure for all 9P RPC ··· 571 575 572 576 size_t offset; 573 577 size_t capacity; 574 - char __user *pubuf; 575 - char *pkbuf; 576 - size_t pbuf_size; 577 - void *private; 578 578 579 579 u8 *sdata; 580 580 };
+4 -4
include/net/9p/client.h
··· 151 151 152 152 struct p9_client { 153 153 spinlock_t lock; /* protect client structure */ 154 - int msize; 154 + unsigned int msize; 155 155 unsigned char proto_version; 156 156 struct p9_trans_module *trans_mod; 157 157 enum p9_trans_status status; ··· 240 240 int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 241 241 u64 offset, u32 count); 242 242 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); 243 - int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, 244 - int proto_version); 243 + int p9dirent_read(struct p9_client *clnt, char *buf, int len, 244 + struct p9_dirent *dirent); 245 245 struct p9_wstat *p9_client_stat(struct p9_fid *fid); 246 246 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 247 247 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr); ··· 259 259 void p9_client_cb(struct p9_client *c, struct p9_req_t *req); 260 260 261 261 int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int); 262 - int p9stat_read(char *, int, struct p9_wstat *, int); 262 + int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *); 263 263 void p9stat_free(struct p9_wstat *); 264 264 265 265 int p9_is_proto_dotu(struct p9_client *clnt);
+2 -8
include/net/9p/transport.h
··· 26 26 #ifndef NET_9P_TRANSPORT_H 27 27 #define NET_9P_TRANSPORT_H 28 28 29 - #define P9_TRANS_PREF_PAYLOAD_MASK 0x1 30 - 31 - /* Default. Add Payload to PDU before sending it down to transport layer */ 32 - #define P9_TRANS_PREF_PAYLOAD_DEF 0x0 33 - /* Send pay load separately to transport layer along with PDU.*/ 34 - #define P9_TRANS_PREF_PAYLOAD_SEP 0x1 35 - 36 29 /** 37 30 * struct p9_trans_module - transport module interface 38 31 * @list: used to maintain a list of currently available transports ··· 49 56 struct list_head list; 50 57 char *name; /* name of transport */ 51 58 int maxsize; /* max message size of transport */ 52 - int pref; /* Preferences of this transport */ 53 59 int def; /* this transport should be default */ 54 60 struct module *owner; 55 61 int (*create)(struct p9_client *, const char *, char *); 56 62 void (*close) (struct p9_client *); 57 63 int (*request) (struct p9_client *, struct p9_req_t *req); 58 64 int (*cancel) (struct p9_client *, struct p9_req_t *req); 65 + int (*zc_request)(struct p9_client *, struct p9_req_t *, 66 + char *, char *, int , int, int, int); 59 67 }; 60 68 61 69 void v9fs_register_trans(struct p9_trans_module *m);
+176
include/trace/events/9p.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM 9p 3 + 4 + #if !defined(_TRACE_9P_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_9P_H 6 + 7 + #include <linux/tracepoint.h> 8 + 9 + #define show_9p_op(type) \ 10 + __print_symbolic(type, \ 11 + { P9_TLERROR, "P9_TLERROR" }, \ 12 + { P9_RLERROR, "P9_RLERROR" }, \ 13 + { P9_TSTATFS, "P9_TSTATFS" }, \ 14 + { P9_RSTATFS, "P9_RSTATFS" }, \ 15 + { P9_TLOPEN, "P9_TLOPEN" }, \ 16 + { P9_RLOPEN, "P9_RLOPEN" }, \ 17 + { P9_TLCREATE, "P9_TLCREATE" }, \ 18 + { P9_RLCREATE, "P9_RLCREATE" }, \ 19 + { P9_TSYMLINK, "P9_TSYMLINK" }, \ 20 + { P9_RSYMLINK, "P9_RSYMLINK" }, \ 21 + { P9_TMKNOD, "P9_TMKNOD" }, \ 22 + { P9_RMKNOD, "P9_RMKNOD" }, \ 23 + { P9_TRENAME, "P9_TRENAME" }, \ 24 + { P9_RRENAME, "P9_RRENAME" }, \ 25 + { P9_TREADLINK, "P9_TREADLINK" }, \ 26 + { P9_RREADLINK, "P9_RREADLINK" }, \ 27 + { P9_TGETATTR, "P9_TGETATTR" }, \ 28 + { P9_RGETATTR, "P9_RGETATTR" }, \ 29 + { P9_TSETATTR, "P9_TSETATTR" }, \ 30 + { P9_RSETATTR, "P9_RSETATTR" }, \ 31 + { P9_TXATTRWALK, "P9_TXATTRWALK" }, \ 32 + { P9_RXATTRWALK, "P9_RXATTRWALK" }, \ 33 + { P9_TXATTRCREATE, "P9_TXATTRCREATE" }, \ 34 + { P9_RXATTRCREATE, "P9_RXATTRCREATE" }, \ 35 + { P9_TREADDIR, "P9_TREADDIR" }, \ 36 + { P9_RREADDIR, "P9_RREADDIR" }, \ 37 + { P9_TFSYNC, "P9_TFSYNC" }, \ 38 + { P9_RFSYNC, "P9_RFSYNC" }, \ 39 + { P9_TLOCK, "P9_TLOCK" }, \ 40 + { P9_RLOCK, "P9_RLOCK" }, \ 41 + { P9_TGETLOCK, "P9_TGETLOCK" }, \ 42 + { P9_RGETLOCK, "P9_RGETLOCK" }, \ 43 + { P9_TLINK, "P9_TLINK" }, \ 44 + { P9_RLINK, "P9_RLINK" }, \ 45 + { P9_TMKDIR, "P9_TMKDIR" }, \ 46 + { P9_RMKDIR, "P9_RMKDIR" }, \ 47 + { P9_TRENAMEAT, "P9_TRENAMEAT" }, \ 48 + { P9_RRENAMEAT, "P9_RRENAMEAT" }, \ 49 + { P9_TUNLINKAT, "P9_TUNLINKAT" }, \ 50 + { P9_RUNLINKAT, "P9_RUNLINKAT" }, \ 51 + { P9_TVERSION, "P9_TVERSION" }, \ 52 + { P9_RVERSION, "P9_RVERSION" }, \ 53 + { P9_TAUTH, "P9_TAUTH" }, \ 54 + { P9_RAUTH, "P9_RAUTH" }, \ 55 + { P9_TATTACH, "P9_TATTACH" }, \ 56 + { P9_RATTACH, "P9_RATTACH" }, \ 57 + { P9_TERROR, "P9_TERROR" }, \ 58 + { P9_RERROR, "P9_RERROR" }, \ 59 + { P9_TFLUSH, "P9_TFLUSH" }, \ 60 + { P9_RFLUSH, "P9_RFLUSH" }, \ 61 + { P9_TWALK, "P9_TWALK" }, \ 62 + { P9_RWALK, "P9_RWALK" }, \ 63 + { P9_TOPEN, "P9_TOPEN" }, \ 64 + { P9_ROPEN, "P9_ROPEN" }, \ 65 + { P9_TCREATE, "P9_TCREATE" }, \ 66 + { P9_RCREATE, "P9_RCREATE" }, \ 67 + { P9_TREAD, "P9_TREAD" }, \ 68 + { P9_RREAD, "P9_RREAD" }, \ 69 + { P9_TWRITE, "P9_TWRITE" }, \ 70 + { P9_RWRITE, "P9_RWRITE" }, \ 71 + { P9_TCLUNK, "P9_TCLUNK" }, \ 72 + { P9_RCLUNK, "P9_RCLUNK" }, \ 73 + { P9_TREMOVE, "P9_TREMOVE" }, \ 74 + { P9_RREMOVE, "P9_RREMOVE" }, \ 75 + { P9_TSTAT, "P9_TSTAT" }, \ 76 + { P9_RSTAT, "P9_RSTAT" }, \ 77 + { P9_TWSTAT, "P9_TWSTAT" }, \ 78 + { P9_RWSTAT, "P9_RWSTAT" }) 79 + 80 + TRACE_EVENT(9p_client_req, 81 + TP_PROTO(struct p9_client *clnt, int8_t type, int tag), 82 + 83 + TP_ARGS(clnt, type, tag), 84 + 85 + TP_STRUCT__entry( 86 + __field( void *, clnt ) 87 + __field( __u8, type ) 88 + __field( __u32, tag ) 89 + ), 90 + 91 + TP_fast_assign( 92 + __entry->clnt = clnt; 93 + __entry->type = type; 94 + __entry->tag = tag; 95 + ), 96 + 97 + TP_printk("client %lu request %s tag %d", 98 + (long)__entry->clnt, show_9p_op(__entry->type), 99 + __entry->tag) 100 + ); 101 + 102 + TRACE_EVENT(9p_client_res, 103 + TP_PROTO(struct p9_client *clnt, int8_t type, int tag, int err), 104 + 105 + TP_ARGS(clnt, type, tag, err), 106 + 107 + TP_STRUCT__entry( 108 + __field( void *, clnt ) 109 + __field( __u8, type ) 110 + __field( __u32, tag ) 111 + __field( __u32, err ) 112 + ), 113 + 114 + TP_fast_assign( 115 + __entry->clnt = clnt; 116 + __entry->type = type; 117 + __entry->tag = tag; 118 + __entry->err = err; 119 + ), 120 + 121 + TP_printk("client %lu response %s tag %d err %d", 122 + (long)__entry->clnt, show_9p_op(__entry->type), 123 + __entry->tag, __entry->err) 124 + ); 125 + 126 + /* dump 32 bytes of protocol data */ 127 + #define P9_PROTO_DUMP_SZ 32 128 + TRACE_EVENT(9p_protocol_dump, 129 + TP_PROTO(struct p9_client *clnt, struct p9_fcall *pdu), 130 + 131 + TP_ARGS(clnt, pdu), 132 + 133 + TP_STRUCT__entry( 134 + __field( void *, clnt ) 135 + __field( __u8, type ) 136 + __field( __u16, tag ) 137 + __array( unsigned char, line, P9_PROTO_DUMP_SZ ) 138 + ), 139 + 140 + TP_fast_assign( 141 + __entry->clnt = clnt; 142 + __entry->type = pdu->id; 143 + __entry->tag = pdu->tag; 144 + memcpy(__entry->line, pdu->sdata, P9_PROTO_DUMP_SZ); 145 + ), 146 + TP_printk("clnt %lu %s(tag = %d)\n%.3x: " 147 + "%02x %02x %02x %02x %02x %02x %02x %02x " 148 + "%02x %02x %02x %02x %02x %02x %02x %02x\n" 149 + "%.3x: " 150 + "%02x %02x %02x %02x %02x %02x %02x %02x " 151 + "%02x %02x %02x %02x %02x %02x %02x %02x\n", 152 + (long)__entry->clnt, show_9p_op(__entry->type), 153 + __entry->tag, 0, 154 + __entry->line[0], __entry->line[1], 155 + __entry->line[2], __entry->line[3], 156 + __entry->line[4], __entry->line[5], 157 + __entry->line[6], __entry->line[7], 158 + __entry->line[8], __entry->line[9], 159 + __entry->line[10], __entry->line[11], 160 + __entry->line[12], __entry->line[13], 161 + __entry->line[14], __entry->line[15], 162 + 16, 163 + __entry->line[16], __entry->line[17], 164 + __entry->line[18], __entry->line[19], 165 + __entry->line[20], __entry->line[21], 166 + __entry->line[22], __entry->line[23], 167 + __entry->line[24], __entry->line[25], 168 + __entry->line[26], __entry->line[27], 169 + __entry->line[28], __entry->line[29], 170 + __entry->line[30], __entry->line[31]) 171 + ); 172 + 173 + #endif /* _TRACE_9P_H */ 174 + 175 + /* This part must be outside protection */ 176 + #include <trace/define_trace.h>
+342 -147
net/9p/client.c
··· 38 38 #include <net/9p/transport.h> 39 39 #include "protocol.h" 40 40 41 + #define CREATE_TRACE_POINTS 42 + #include <trace/events/9p.h> 43 + 41 44 /* 42 45 * Client Option Parsing (code inspired by NFS code) 43 46 * - a little lazy - parse all client options ··· 126 123 options = tmp_options; 127 124 128 125 while ((p = strsep(&options, ",")) != NULL) { 129 - int token; 126 + int token, r; 130 127 if (!*p) 131 128 continue; 132 129 token = match_token(p, tokens, args); 133 - if (token < Opt_trans) { 134 - int r = match_int(&args[0], &option); 130 + switch (token) { 131 + case Opt_msize: 132 + r = match_int(&args[0], &option); 135 133 if (r < 0) { 136 134 P9_DPRINTK(P9_DEBUG_ERROR, 137 - "integer field, but no integer?\n"); 135 + "integer field, but no integer?\n"); 138 136 ret = r; 139 137 continue; 140 138 } 141 - } 142 - switch (token) { 143 - case Opt_msize: 144 139 clnt->msize = option; 145 140 break; 146 141 case Opt_trans: ··· 204 203 * 205 204 */ 206 205 207 - static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) 206 + static struct p9_req_t * 207 + p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) 208 208 { 209 209 unsigned long flags; 210 210 int row, col; 211 211 struct p9_req_t *req; 212 + int alloc_msize = min(c->msize, max_size); 212 213 213 214 /* This looks up the original request by tag so we know which 214 215 * buffer to read the data into */ ··· 248 245 return ERR_PTR(-ENOMEM); 249 246 } 250 247 init_waitqueue_head(req->wq); 251 - if ((c->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == 252 - P9_TRANS_PREF_PAYLOAD_SEP) { 253 - int alloc_msize = min(c->msize, 4096); 254 - req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, 255 - GFP_NOFS); 256 - req->tc->capacity = alloc_msize; 257 - req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, 258 - GFP_NOFS); 259 - req->rc->capacity = alloc_msize; 260 - } else { 261 - req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, 262 - GFP_NOFS); 263 - req->tc->capacity = c->msize; 264 - req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, 265 - GFP_NOFS); 266 - req->rc->capacity = c->msize; 267 - } 248 + req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, 249 + GFP_NOFS); 250 + req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, 251 + GFP_NOFS); 268 252 if ((!req->tc) || (!req->rc)) { 269 253 printk(KERN_ERR "Couldn't grow tag array\n"); 270 254 kfree(req->tc); ··· 261 271 req->wq = NULL; 262 272 return ERR_PTR(-ENOMEM); 263 273 } 274 + req->tc->capacity = alloc_msize; 275 + req->rc->capacity = alloc_msize; 264 276 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); 265 277 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); 266 278 } ··· 467 475 int ecode; 468 476 469 477 err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 478 + /* 479 + * dump the response from server 480 + * This should be after check errors which poplulate pdu_fcall. 481 + */ 482 + trace_9p_protocol_dump(c, req->rc); 470 483 if (err) { 471 484 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); 472 485 return err; 473 486 } 474 - 475 487 if (type != P9_RERROR && type != P9_RLERROR) 476 488 return 0; 477 489 478 490 if (!p9_is_proto_dotl(c)) { 479 491 char *ename; 480 - 481 - if (req->tc->pbuf_size) { 482 - /* Handle user buffers */ 483 - size_t len = req->rc->size - req->rc->offset; 484 - if (req->tc->pubuf) { 485 - /* User Buffer */ 486 - err = copy_from_user( 487 - &req->rc->sdata[req->rc->offset], 488 - req->tc->pubuf, len); 489 - if (err) { 490 - err = -EFAULT; 491 - goto out_err; 492 - } 493 - } else { 494 - /* Kernel Buffer */ 495 - memmove(&req->rc->sdata[req->rc->offset], 496 - req->tc->pkbuf, len); 497 - } 498 - } 499 492 err = p9pdu_readf(req->rc, c->proto_version, "s?d", 500 - &ename, &ecode); 493 + &ename, &ecode); 501 494 if (err) 502 495 goto out_err; 503 496 ··· 492 515 if (!err || !IS_ERR_VALUE(err)) { 493 516 err = p9_errstr2errno(ename, strlen(ename)); 494 517 495 - P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, 496 - ename); 497 - 498 - kfree(ename); 518 + P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", 519 + -ecode, ename); 499 520 } 521 + kfree(ename); 500 522 } else { 501 523 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); 502 524 err = -ecode; ··· 503 527 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); 504 528 } 505 529 506 - 507 530 return err; 508 531 509 532 out_err: 510 533 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); 511 534 535 + return err; 536 + } 537 + 538 + /** 539 + * p9_check_zc_errors - check 9p packet for error return and process it 540 + * @c: current client instance 541 + * @req: request to parse and check for error conditions 542 + * @in_hdrlen: Size of response protocol buffer. 543 + * 544 + * returns error code if one is discovered, otherwise returns 0 545 + * 546 + * this will have to be more complicated if we have multiple 547 + * error packet types 548 + */ 549 + 550 + static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, 551 + char *uidata, int in_hdrlen, int kern_buf) 552 + { 553 + int err; 554 + int ecode; 555 + int8_t type; 556 + char *ename = NULL; 557 + 558 + err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 559 + /* 560 + * dump the response from server 561 + * This should be after parse_header which poplulate pdu_fcall. 562 + */ 563 + trace_9p_protocol_dump(c, req->rc); 564 + if (err) { 565 + P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); 566 + return err; 567 + } 568 + 569 + if (type != P9_RERROR && type != P9_RLERROR) 570 + return 0; 571 + 572 + if (!p9_is_proto_dotl(c)) { 573 + /* Error is reported in string format */ 574 + uint16_t len; 575 + /* 7 = header size for RERROR, 2 is the size of string len; */ 576 + int inline_len = in_hdrlen - (7 + 2); 577 + 578 + /* Read the size of error string */ 579 + err = p9pdu_readf(req->rc, c->proto_version, "w", &len); 580 + if (err) 581 + goto out_err; 582 + 583 + ename = kmalloc(len + 1, GFP_NOFS); 584 + if (!ename) { 585 + err = -ENOMEM; 586 + goto out_err; 587 + } 588 + if (len <= inline_len) { 589 + /* We have error in protocol buffer itself */ 590 + if (pdu_read(req->rc, ename, len)) { 591 + err = -EFAULT; 592 + goto out_free; 593 + 594 + } 595 + } else { 596 + /* 597 + * Part of the data is in user space buffer. 598 + */ 599 + if (pdu_read(req->rc, ename, inline_len)) { 600 + err = -EFAULT; 601 + goto out_free; 602 + 603 + } 604 + if (kern_buf) { 605 + memcpy(ename + inline_len, uidata, 606 + len - inline_len); 607 + } else { 608 + err = copy_from_user(ename + inline_len, 609 + uidata, len - inline_len); 610 + if (err) { 611 + err = -EFAULT; 612 + goto out_free; 613 + } 614 + } 615 + } 616 + ename[len] = 0; 617 + if (p9_is_proto_dotu(c)) { 618 + /* For dotu we also have error code */ 619 + err = p9pdu_readf(req->rc, 620 + c->proto_version, "d", &ecode); 621 + if (err) 622 + goto out_free; 623 + err = -ecode; 624 + } 625 + if (!err || !IS_ERR_VALUE(err)) { 626 + err = p9_errstr2errno(ename, strlen(ename)); 627 + 628 + P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", 629 + -ecode, ename); 630 + } 631 + kfree(ename); 632 + } else { 633 + err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); 634 + err = -ecode; 635 + 636 + P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); 637 + } 638 + return err; 639 + 640 + out_free: 641 + kfree(ename); 642 + out_err: 643 + P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); 512 644 return err; 513 645 } 514 646 ··· 663 579 return 0; 664 580 } 665 581 582 + static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, 583 + int8_t type, int req_size, 584 + const char *fmt, va_list ap) 585 + { 586 + int tag, err; 587 + struct p9_req_t *req; 588 + 589 + P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 590 + 591 + /* we allow for any status other than disconnected */ 592 + if (c->status == Disconnected) 593 + return ERR_PTR(-EIO); 594 + 595 + /* if status is begin_disconnected we allow only clunk request */ 596 + if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) 597 + return ERR_PTR(-EIO); 598 + 599 + tag = P9_NOTAG; 600 + if (type != P9_TVERSION) { 601 + tag = p9_idpool_get(c->tagpool); 602 + if (tag < 0) 603 + return ERR_PTR(-ENOMEM); 604 + } 605 + 606 + req = p9_tag_alloc(c, tag, req_size); 607 + if (IS_ERR(req)) 608 + return req; 609 + 610 + /* marshall the data */ 611 + p9pdu_prepare(req->tc, tag, type); 612 + err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 613 + if (err) 614 + goto reterr; 615 + p9pdu_finalize(c, req->tc); 616 + trace_9p_client_req(c, type, tag); 617 + return req; 618 + reterr: 619 + p9_free_req(c, req); 620 + return ERR_PTR(err); 621 + } 622 + 666 623 /** 667 624 * p9_client_rpc - issue a request and wait for a response 668 625 * @c: client session ··· 717 592 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) 718 593 { 719 594 va_list ap; 720 - int tag, err; 721 - struct p9_req_t *req; 595 + int sigpending, err; 722 596 unsigned long flags; 723 - int sigpending; 597 + struct p9_req_t *req; 724 598 725 - P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 726 - 727 - /* we allow for any status other than disconnected */ 728 - if (c->status == Disconnected) 729 - return ERR_PTR(-EIO); 730 - 731 - /* if status is begin_disconnected we allow only clunk request */ 732 - if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) 733 - return ERR_PTR(-EIO); 599 + va_start(ap, fmt); 600 + req = p9_client_prepare_req(c, type, c->msize, fmt, ap); 601 + va_end(ap); 602 + if (IS_ERR(req)) 603 + return req; 734 604 735 605 if (signal_pending(current)) { 736 606 sigpending = 1; ··· 733 613 } else 734 614 sigpending = 0; 735 615 736 - tag = P9_NOTAG; 737 - if (type != P9_TVERSION) { 738 - tag = p9_idpool_get(c->tagpool); 739 - if (tag < 0) 740 - return ERR_PTR(-ENOMEM); 741 - } 742 - 743 - req = p9_tag_alloc(c, tag); 744 - if (IS_ERR(req)) 745 - return req; 746 - 747 - /* marshall the data */ 748 - p9pdu_prepare(req->tc, tag, type); 749 - va_start(ap, fmt); 750 - err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 751 - va_end(ap); 752 - if (err) 753 - goto reterr; 754 - p9pdu_finalize(req->tc); 755 - 756 616 err = c->trans_mod->request(c, req); 757 617 if (err < 0) { 758 618 if (err != -ERESTARTSYS && err != -EFAULT) 759 619 c->status = Disconnected; 760 620 goto reterr; 761 621 } 762 - 763 - P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); 622 + /* Wait for the response */ 764 623 err = wait_event_interruptible(*req->wq, 765 - req->status >= REQ_STATUS_RCVD); 766 - P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", 767 - req->wq, tag, err); 624 + req->status >= REQ_STATUS_RCVD); 768 625 769 626 if (req->status == REQ_STATUS_ERROR) { 770 627 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 771 628 err = req->t_err; 772 629 } 773 - 774 630 if ((err == -ERESTARTSYS) && (c->status == Connected)) { 775 631 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); 776 632 sigpending = 1; ··· 759 663 if (req->status == REQ_STATUS_RCVD) 760 664 err = 0; 761 665 } 762 - 763 666 if (sigpending) { 764 667 spin_lock_irqsave(&current->sighand->siglock, flags); 765 668 recalc_sigpending(); 766 669 spin_unlock_irqrestore(&current->sighand->siglock, flags); 767 670 } 768 - 769 671 if (err < 0) 770 672 goto reterr; 771 673 772 674 err = p9_check_errors(c, req); 773 - if (!err) { 774 - P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); 675 + trace_9p_client_res(c, type, req->rc->tag, err); 676 + if (!err) 775 677 return req; 776 - } 777 - 778 678 reterr: 779 - P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type, 780 - err); 679 + p9_free_req(c, req); 680 + return ERR_PTR(err); 681 + } 682 + 683 + /** 684 + * p9_client_zc_rpc - issue a request and wait for a response 685 + * @c: client session 686 + * @type: type of request 687 + * @uidata: user bffer that should be ued for zero copy read 688 + * @uodata: user buffer that shoud be user for zero copy write 689 + * @inlen: read buffer size 690 + * @olen: write buffer size 691 + * @hdrlen: reader header size, This is the size of response protocol data 692 + * @fmt: protocol format string (see protocol.c) 693 + * 694 + * Returns request structure (which client must free using p9_free_req) 695 + */ 696 + static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, 697 + char *uidata, char *uodata, 698 + int inlen, int olen, int in_hdrlen, 699 + int kern_buf, const char *fmt, ...) 700 + { 701 + va_list ap; 702 + int sigpending, err; 703 + unsigned long flags; 704 + struct p9_req_t *req; 705 + 706 + va_start(ap, fmt); 707 + /* 708 + * We allocate a inline protocol data of only 4k bytes. 709 + * The actual content is passed in zero-copy fashion. 710 + */ 711 + req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); 712 + va_end(ap); 713 + if (IS_ERR(req)) 714 + return req; 715 + 716 + if (signal_pending(current)) { 717 + sigpending = 1; 718 + clear_thread_flag(TIF_SIGPENDING); 719 + } else 720 + sigpending = 0; 721 + 722 + /* If we are called with KERNEL_DS force kern_buf */ 723 + if (segment_eq(get_fs(), KERNEL_DS)) 724 + kern_buf = 1; 725 + 726 + err = c->trans_mod->zc_request(c, req, uidata, uodata, 727 + inlen, olen, in_hdrlen, kern_buf); 728 + if (err < 0) { 729 + if (err == -EIO) 730 + c->status = Disconnected; 731 + goto reterr; 732 + } 733 + if (req->status == REQ_STATUS_ERROR) { 734 + P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 735 + err = req->t_err; 736 + } 737 + if ((err == -ERESTARTSYS) && (c->status == Connected)) { 738 + P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); 739 + sigpending = 1; 740 + clear_thread_flag(TIF_SIGPENDING); 741 + 742 + if (c->trans_mod->cancel(c, req)) 743 + p9_client_flush(c, req); 744 + 745 + /* if we received the response anyway, don't signal error */ 746 + if (req->status == REQ_STATUS_RCVD) 747 + err = 0; 748 + } 749 + if (sigpending) { 750 + spin_lock_irqsave(&current->sighand->siglock, flags); 751 + recalc_sigpending(); 752 + spin_unlock_irqrestore(&current->sighand->siglock, flags); 753 + } 754 + if (err < 0) 755 + goto reterr; 756 + 757 + err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf); 758 + trace_9p_client_res(c, type, req->rc->tag, err); 759 + if (!err) 760 + return req; 761 + reterr: 781 762 p9_free_req(c, req); 782 763 return ERR_PTR(err); 783 764 } ··· 942 769 err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); 943 770 if (err) { 944 771 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); 945 - P9_DUMP_PKT(1, req->rc); 772 + trace_9p_protocol_dump(c, req->rc); 946 773 goto error; 947 774 } 948 775 ··· 1079 906 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 1080 907 char *uname, u32 n_uname, char *aname) 1081 908 { 1082 - int err; 909 + int err = 0; 1083 910 struct p9_req_t *req; 1084 911 struct p9_fid *fid; 1085 912 struct p9_qid qid; 1086 913 1087 - P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", 1088 - afid ? afid->fid : -1, uname, aname); 1089 - err = 0; 1090 914 915 + P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", 916 + afid ? afid->fid : -1, uname, aname); 1091 917 fid = p9_fid_create(clnt); 1092 918 if (IS_ERR(fid)) { 1093 919 err = PTR_ERR(fid); ··· 1103 931 1104 932 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); 1105 933 if (err) { 1106 - P9_DUMP_PKT(1, req->rc); 934 + trace_9p_protocol_dump(clnt, req->rc); 1107 935 p9_free_req(clnt, req); 1108 936 goto error; 1109 937 } ··· 1163 991 1164 992 err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); 1165 993 if (err) { 1166 - P9_DUMP_PKT(1, req->rc); 994 + trace_9p_protocol_dump(clnt, req->rc); 1167 995 p9_free_req(clnt, req); 1168 996 goto clunk_fid; 1169 997 } ··· 1230 1058 1231 1059 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 1232 1060 if (err) { 1233 - P9_DUMP_PKT(1, req->rc); 1061 + trace_9p_protocol_dump(clnt, req->rc); 1234 1062 goto free_and_error; 1235 1063 } 1236 1064 ··· 1273 1101 1274 1102 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit); 1275 1103 if (err) { 1276 - P9_DUMP_PKT(1, req->rc); 1104 + trace_9p_protocol_dump(clnt, req->rc); 1277 1105 goto free_and_error; 1278 1106 } 1279 1107 ··· 1318 1146 1319 1147 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 1320 1148 if (err) { 1321 - P9_DUMP_PKT(1, req->rc); 1149 + trace_9p_protocol_dump(clnt, req->rc); 1322 1150 goto free_and_error; 1323 1151 } 1324 1152 ··· 1357 1185 1358 1186 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 1359 1187 if (err) { 1360 - P9_DUMP_PKT(1, req->rc); 1188 + trace_9p_protocol_dump(clnt, req->rc); 1361 1189 goto free_and_error; 1362 1190 } 1363 1191 ··· 1502 1330 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1503 1331 u32 count) 1504 1332 { 1505 - int err, rsize; 1506 - struct p9_client *clnt; 1507 - struct p9_req_t *req; 1508 1333 char *dataptr; 1334 + int kernel_buf = 0; 1335 + struct p9_req_t *req; 1336 + struct p9_client *clnt; 1337 + int err, rsize, non_zc = 0; 1509 1338 1510 - P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid, 1511 - (long long unsigned) offset, count); 1339 + 1340 + P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", 1341 + fid->fid, (long long unsigned) offset, count); 1512 1342 err = 0; 1513 1343 clnt = fid->clnt; 1514 1344 ··· 1522 1348 rsize = count; 1523 1349 1524 1350 /* Don't bother zerocopy for small IO (< 1024) */ 1525 - if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == 1526 - P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) { 1527 - req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset, 1528 - rsize, data, udata); 1351 + if (clnt->trans_mod->zc_request && rsize > 1024) { 1352 + char *indata; 1353 + if (data) { 1354 + kernel_buf = 1; 1355 + indata = data; 1356 + } else 1357 + indata = (char *)udata; 1358 + /* 1359 + * response header len is 11 1360 + * PDU Header(7) + IO Size (4) 1361 + */ 1362 + req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0, 1363 + 11, kernel_buf, "dqd", fid->fid, 1364 + offset, rsize); 1529 1365 } else { 1366 + non_zc = 1; 1530 1367 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, 1531 - rsize); 1368 + rsize); 1532 1369 } 1533 1370 if (IS_ERR(req)) { 1534 1371 err = PTR_ERR(req); ··· 1548 1363 1549 1364 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1550 1365 if (err) { 1551 - P9_DUMP_PKT(1, req->rc); 1366 + trace_9p_protocol_dump(clnt, req->rc); 1552 1367 goto free_and_error; 1553 1368 } 1554 1369 1555 1370 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1556 - P9_DUMP_PKT(1, req->rc); 1557 1371 1558 - if (!req->tc->pbuf_size) { 1372 + if (non_zc) { 1559 1373 if (data) { 1560 1374 memmove(data, dataptr, count); 1561 1375 } else { ··· 1580 1396 u64 offset, u32 count) 1581 1397 { 1582 1398 int err, rsize; 1399 + int kernel_buf = 0; 1583 1400 struct p9_client *clnt; 1584 1401 struct p9_req_t *req; 1585 1402 ··· 1596 1411 if (count < rsize) 1597 1412 rsize = count; 1598 1413 1599 - /* Don't bother zerocopy form small IO (< 1024) */ 1600 - if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == 1601 - P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) { 1602 - req = p9_client_rpc(clnt, P9_TWRITE, "dqE", fid->fid, offset, 1603 - rsize, data, udata); 1414 + /* Don't bother zerocopy for small IO (< 1024) */ 1415 + if (clnt->trans_mod->zc_request && rsize > 1024) { 1416 + char *odata; 1417 + if (data) { 1418 + kernel_buf = 1; 1419 + odata = data; 1420 + } else 1421 + odata = (char *)udata; 1422 + req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize, 1423 + P9_ZC_HDR_SZ, kernel_buf, "dqd", 1424 + fid->fid, offset, rsize); 1604 1425 } else { 1605 - 1606 1426 if (data) 1607 1427 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, 1608 - offset, rsize, data); 1428 + offset, rsize, data); 1609 1429 else 1610 1430 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, 1611 - offset, rsize, udata); 1431 + offset, rsize, udata); 1612 1432 } 1613 1433 if (IS_ERR(req)) { 1614 1434 err = PTR_ERR(req); ··· 1622 1432 1623 1433 err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); 1624 1434 if (err) { 1625 - P9_DUMP_PKT(1, req->rc); 1435 + trace_9p_protocol_dump(clnt, req->rc); 1626 1436 goto free_and_error; 1627 1437 } 1628 1438 ··· 1662 1472 1663 1473 err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); 1664 1474 if (err) { 1665 - P9_DUMP_PKT(1, req->rc); 1475 + trace_9p_protocol_dump(clnt, req->rc); 1666 1476 p9_free_req(clnt, req); 1667 1477 goto error; 1668 1478 } ··· 1713 1523 1714 1524 err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); 1715 1525 if (err) { 1716 - P9_DUMP_PKT(1, req->rc); 1526 + trace_9p_protocol_dump(clnt, req->rc); 1717 1527 p9_free_req(clnt, req); 1718 1528 goto error; 1719 1529 } ··· 1861 1671 &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, 1862 1672 &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); 1863 1673 if (err) { 1864 - P9_DUMP_PKT(1, req->rc); 1674 + trace_9p_protocol_dump(clnt, req->rc); 1865 1675 p9_free_req(clnt, req); 1866 1676 goto error; 1867 1677 } ··· 1968 1778 } 1969 1779 err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size); 1970 1780 if (err) { 1971 - P9_DUMP_PKT(1, req->rc); 1781 + trace_9p_protocol_dump(clnt, req->rc); 1972 1782 p9_free_req(clnt, req); 1973 1783 goto clunk_fid; 1974 1784 } ··· 2014 1824 2015 1825 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) 2016 1826 { 2017 - int err, rsize; 1827 + int err, rsize, non_zc = 0; 2018 1828 struct p9_client *clnt; 2019 1829 struct p9_req_t *req; 2020 1830 char *dataptr; ··· 2032 1842 if (count < rsize) 2033 1843 rsize = count; 2034 1844 2035 - if ((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) == 2036 - P9_TRANS_PREF_PAYLOAD_SEP) { 2037 - req = p9_client_rpc(clnt, P9_TREADDIR, "dqF", fid->fid, 2038 - offset, rsize, data); 1845 + /* Don't bother zerocopy for small IO (< 1024) */ 1846 + if (clnt->trans_mod->zc_request && rsize > 1024) { 1847 + /* 1848 + * response header len is 11 1849 + * PDU Header(7) + IO Size (4) 1850 + */ 1851 + req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0, 1852 + 11, 1, "dqd", fid->fid, offset, rsize); 2039 1853 } else { 1854 + non_zc = 1; 2040 1855 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, 2041 - offset, rsize); 1856 + offset, rsize); 2042 1857 } 2043 1858 if (IS_ERR(req)) { 2044 1859 err = PTR_ERR(req); ··· 2052 1857 2053 1858 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 2054 1859 if (err) { 2055 - P9_DUMP_PKT(1, req->rc); 1860 + trace_9p_protocol_dump(clnt, req->rc); 2056 1861 goto free_and_error; 2057 1862 } 2058 1863 2059 1864 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); 2060 1865 2061 - if (!req->tc->pbuf_size && data) 1866 + if (non_zc) 2062 1867 memmove(data, dataptr, count); 2063 1868 2064 1869 p9_free_req(clnt, req); ··· 2089 1894 2090 1895 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 2091 1896 if (err) { 2092 - P9_DUMP_PKT(1, req->rc); 1897 + trace_9p_protocol_dump(clnt, req->rc); 2093 1898 goto error; 2094 1899 } 2095 1900 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, ··· 2120 1925 2121 1926 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 2122 1927 if (err) { 2123 - P9_DUMP_PKT(1, req->rc); 1928 + trace_9p_protocol_dump(clnt, req->rc); 2124 1929 goto error; 2125 1930 } 2126 1931 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, ··· 2155 1960 2156 1961 err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); 2157 1962 if (err) { 2158 - P9_DUMP_PKT(1, req->rc); 1963 + trace_9p_protocol_dump(clnt, req->rc); 2159 1964 goto error; 2160 1965 } 2161 1966 P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); ··· 2188 1993 &glock->start, &glock->length, &glock->proc_id, 2189 1994 &glock->client_id); 2190 1995 if (err) { 2191 - P9_DUMP_PKT(1, req->rc); 1996 + trace_9p_protocol_dump(clnt, req->rc); 2192 1997 goto error; 2193 1998 } 2194 1999 P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " ··· 2216 2021 2217 2022 err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); 2218 2023 if (err) { 2219 - P9_DUMP_PKT(1, req->rc); 2024 + trace_9p_protocol_dump(clnt, req->rc); 2220 2025 goto error; 2221 2026 } 2222 2027 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
+13 -86
net/9p/protocol.c
··· 37 37 #include <net/9p/client.h> 38 38 #include "protocol.h" 39 39 40 + #include <trace/events/9p.h> 41 + 40 42 static int 41 43 p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 42 - 43 - #ifdef CONFIG_NET_9P_DEBUG 44 - void 45 - p9pdu_dump(int way, struct p9_fcall *pdu) 46 - { 47 - int len = pdu->size; 48 - 49 - if ((p9_debug_level & P9_DEBUG_VPKT) != P9_DEBUG_VPKT) { 50 - if ((p9_debug_level & P9_DEBUG_PKT) == P9_DEBUG_PKT) { 51 - if (len > 32) 52 - len = 32; 53 - } else { 54 - /* shouldn't happen */ 55 - return; 56 - } 57 - } 58 - 59 - if (way) 60 - print_hex_dump_bytes("[9P] ", DUMP_PREFIX_OFFSET, pdu->sdata, 61 - len); 62 - else 63 - print_hex_dump_bytes("]9P[ ", DUMP_PREFIX_OFFSET, pdu->sdata, 64 - len); 65 - } 66 - #else 67 - void 68 - p9pdu_dump(int way, struct p9_fcall *pdu) 69 - { 70 - } 71 - #endif 72 - EXPORT_SYMBOL(p9pdu_dump); 73 44 74 45 void p9stat_free(struct p9_wstat *stbuf) 75 46 { ··· 52 81 } 53 82 EXPORT_SYMBOL(p9stat_free); 54 83 55 - static size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) 84 + size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) 56 85 { 57 86 size_t len = min(pdu->size - pdu->offset, size); 58 87 memcpy(data, &pdu->sdata[pdu->offset], len); ··· 77 106 78 107 pdu->size += len; 79 108 return size - len; 80 - } 81 - 82 - static size_t 83 - pdu_write_urw(struct p9_fcall *pdu, const char *kdata, const char __user *udata, 84 - size_t size) 85 - { 86 - BUG_ON(pdu->size > P9_IOHDRSZ); 87 - pdu->pubuf = (char __user *)udata; 88 - pdu->pkbuf = (char *)kdata; 89 - pdu->pbuf_size = size; 90 - return 0; 91 - } 92 - 93 - static size_t 94 - pdu_write_readdir(struct p9_fcall *pdu, const char *kdata, size_t size) 95 - { 96 - BUG_ON(pdu->size > P9_READDIRHDRSZ); 97 - pdu->pkbuf = (char *)kdata; 98 - pdu->pbuf_size = size; 99 - return 0; 100 109 } 101 110 102 111 /* ··· 410 459 errcode = -EFAULT; 411 460 } 412 461 break; 413 - case 'E':{ 414 - int32_t cnt = va_arg(ap, int32_t); 415 - const char *k = va_arg(ap, const void *); 416 - const char __user *u = va_arg(ap, 417 - const void __user *); 418 - errcode = p9pdu_writef(pdu, proto_version, "d", 419 - cnt); 420 - if (!errcode && pdu_write_urw(pdu, k, u, cnt)) 421 - errcode = -EFAULT; 422 - } 423 - break; 424 - case 'F':{ 425 - int32_t cnt = va_arg(ap, int32_t); 426 - const char *k = va_arg(ap, const void *); 427 - errcode = p9pdu_writef(pdu, proto_version, "d", 428 - cnt); 429 - if (!errcode && pdu_write_readdir(pdu, k, cnt)) 430 - errcode = -EFAULT; 431 - } 432 - break; 433 462 case 'U':{ 434 463 int32_t count = va_arg(ap, int32_t); 435 464 const char __user *udata = ··· 522 591 return ret; 523 592 } 524 593 525 - int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version) 594 + int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) 526 595 { 527 596 struct p9_fcall fake_pdu; 528 597 int ret; ··· 532 601 fake_pdu.sdata = buf; 533 602 fake_pdu.offset = 0; 534 603 535 - ret = p9pdu_readf(&fake_pdu, proto_version, "S", st); 604 + ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st); 536 605 if (ret) { 537 606 P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 538 - P9_DUMP_PKT(0, &fake_pdu); 607 + trace_9p_protocol_dump(clnt, &fake_pdu); 539 608 } 540 609 541 610 return ret; ··· 548 617 return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); 549 618 } 550 619 551 - int p9pdu_finalize(struct p9_fcall *pdu) 620 + int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) 552 621 { 553 622 int size = pdu->size; 554 623 int err; ··· 557 626 err = p9pdu_writef(pdu, 0, "d", size); 558 627 pdu->size = size; 559 628 560 - P9_DUMP_PKT(0, pdu); 629 + trace_9p_protocol_dump(clnt, pdu); 561 630 P9_DPRINTK(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", pdu->size, 562 631 pdu->id, pdu->tag); 563 632 ··· 568 637 { 569 638 pdu->offset = 0; 570 639 pdu->size = 0; 571 - pdu->private = NULL; 572 - pdu->pubuf = NULL; 573 - pdu->pkbuf = NULL; 574 - pdu->pbuf_size = 0; 575 640 } 576 641 577 - int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, 578 - int proto_version) 642 + int p9dirent_read(struct p9_client *clnt, char *buf, int len, 643 + struct p9_dirent *dirent) 579 644 { 580 645 struct p9_fcall fake_pdu; 581 646 int ret; ··· 582 655 fake_pdu.sdata = buf; 583 656 fake_pdu.offset = 0; 584 657 585 - ret = p9pdu_readf(&fake_pdu, proto_version, "Qqbs", &dirent->qid, 586 - &dirent->d_off, &dirent->d_type, &nameptr); 658 + ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid, 659 + &dirent->d_off, &dirent->d_type, &nameptr); 587 660 if (ret) { 588 661 P9_DPRINTK(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); 589 - P9_DUMP_PKT(1, &fake_pdu); 662 + trace_9p_protocol_dump(clnt, &fake_pdu); 590 663 goto out; 591 664 } 592 665
+2 -2
net/9p/protocol.h
··· 29 29 va_list ap); 30 30 int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); 31 31 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); 32 - int p9pdu_finalize(struct p9_fcall *pdu); 33 - void p9pdu_dump(int, struct p9_fcall *); 32 + int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu); 34 33 void p9pdu_reset(struct p9_fcall *pdu); 34 + size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size);
+15 -38
net/9p/trans_common.c
··· 21 21 22 22 /** 23 23 * p9_release_req_pages - Release pages after the transaction. 24 - * @*private: PDU's private page of struct trans_rpage_info 25 24 */ 26 - void 27 - p9_release_req_pages(struct trans_rpage_info *rpinfo) 25 + void p9_release_pages(struct page **pages, int nr_pages) 28 26 { 29 27 int i = 0; 30 - 31 - while (rpinfo->rp_data[i] && rpinfo->rp_nr_pages--) { 32 - put_page(rpinfo->rp_data[i]); 28 + while (pages[i] && nr_pages--) { 29 + put_page(pages[i]); 33 30 i++; 34 31 } 35 32 } 36 - EXPORT_SYMBOL(p9_release_req_pages); 33 + EXPORT_SYMBOL(p9_release_pages); 37 34 38 35 /** 39 36 * p9_nr_pages - Return number of pages needed to accommodate the payload. 40 37 */ 41 - int 42 - p9_nr_pages(struct p9_req_t *req) 38 + int p9_nr_pages(char *data, int len) 43 39 { 44 40 unsigned long start_page, end_page; 45 - start_page = (unsigned long)req->tc->pubuf >> PAGE_SHIFT; 46 - end_page = ((unsigned long)req->tc->pubuf + req->tc->pbuf_size + 47 - PAGE_SIZE - 1) >> PAGE_SHIFT; 41 + start_page = (unsigned long)data >> PAGE_SHIFT; 42 + end_page = ((unsigned long)data + len + PAGE_SIZE - 1) >> PAGE_SHIFT; 48 43 return end_page - start_page; 49 44 } 50 45 EXPORT_SYMBOL(p9_nr_pages); ··· 53 58 * @nr_pages: number of pages to accommodate the payload 54 59 * @rw: Indicates if the pages are for read or write. 55 60 */ 56 - int 57 - p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len, 58 - int nr_pages, u8 rw) 61 + 62 + int p9_payload_gup(char *data, int *nr_pages, struct page **pages, int write) 59 63 { 60 - uint32_t first_page_bytes = 0; 61 - int32_t pdata_mapped_pages; 62 - struct trans_rpage_info *rpinfo; 64 + int nr_mapped_pages; 63 65 64 - *pdata_off = (__force size_t)req->tc->pubuf & (PAGE_SIZE-1); 66 + nr_mapped_pages = get_user_pages_fast((unsigned long)data, 67 + *nr_pages, write, pages); 68 + if (nr_mapped_pages <= 0) 69 + return nr_mapped_pages; 65 70 66 - if (*pdata_off) 67 - first_page_bytes = min(((size_t)PAGE_SIZE - *pdata_off), 68 - req->tc->pbuf_size); 69 - 70 - rpinfo = req->tc->private; 71 - pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf, 72 - nr_pages, rw, &rpinfo->rp_data[0]); 73 - if (pdata_mapped_pages <= 0) 74 - return pdata_mapped_pages; 75 - 76 - rpinfo->rp_nr_pages = pdata_mapped_pages; 77 - if (*pdata_off) { 78 - *pdata_len = first_page_bytes; 79 - *pdata_len += min((req->tc->pbuf_size - *pdata_len), 80 - ((size_t)pdata_mapped_pages - 1) << PAGE_SHIFT); 81 - } else { 82 - *pdata_len = min(req->tc->pbuf_size, 83 - (size_t)pdata_mapped_pages << PAGE_SHIFT); 84 - } 71 + *nr_pages = nr_mapped_pages; 85 72 return 0; 86 73 } 87 74 EXPORT_SYMBOL(p9_payload_gup);
+3 -18
net/9p/trans_common.h
··· 12 12 * 13 13 */ 14 14 15 - /* TRUE if it is user context */ 16 - #define P9_IS_USER_CONTEXT (!segment_eq(get_fs(), KERNEL_DS)) 17 - 18 - /** 19 - * struct trans_rpage_info - To store mapped page information in PDU. 20 - * @rp_alloc:Set if this structure is allocd, not a reuse unused space in pdu. 21 - * @rp_nr_pages: Number of mapped pages 22 - * @rp_data: Array of page pointers 23 - */ 24 - struct trans_rpage_info { 25 - u8 rp_alloc; 26 - int rp_nr_pages; 27 - struct page *rp_data[0]; 28 - }; 29 - 30 - void p9_release_req_pages(struct trans_rpage_info *); 31 - int p9_payload_gup(struct p9_req_t *, size_t *, int *, int, u8); 32 - int p9_nr_pages(struct p9_req_t *); 15 + void p9_release_pages(struct page **, int); 16 + int p9_payload_gup(char *, int *, struct page **, int); 17 + int p9_nr_pages(char *, int);
+196 -137
net/9p/trans_virtio.c
··· 150 150 while (1) { 151 151 spin_lock_irqsave(&chan->lock, flags); 152 152 rc = virtqueue_get_buf(chan->vq, &len); 153 - 154 153 if (rc == NULL) { 155 154 spin_unlock_irqrestore(&chan->lock, flags); 156 155 break; 157 156 } 158 - 159 157 chan->ring_bufs_avail = 1; 160 158 spin_unlock_irqrestore(&chan->lock, flags); 161 159 /* Wakeup if anyone waiting for VirtIO ring space. */ ··· 161 163 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 162 164 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 163 165 req = p9_tag_lookup(chan->client, rc->tag); 164 - if (req->tc->private) { 165 - struct trans_rpage_info *rp = req->tc->private; 166 - int p = rp->rp_nr_pages; 167 - /*Release pages */ 168 - p9_release_req_pages(rp); 169 - atomic_sub(p, &vp_pinned); 170 - wake_up(&vp_wq); 171 - if (rp->rp_alloc) 172 - kfree(rp); 173 - req->tc->private = NULL; 174 - } 175 166 req->status = REQ_STATUS_RCVD; 176 167 p9_client_cb(chan->client, req); 177 168 } ··· 180 193 * 181 194 */ 182 195 183 - static int 184 - pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, 185 - int count) 196 + static int pack_sg_list(struct scatterlist *sg, int start, 197 + int limit, char *data, int count) 186 198 { 187 199 int s; 188 200 int index = start; ··· 210 224 * this takes a list of pages. 211 225 * @sg: scatter/gather list to pack into 212 226 * @start: which segment of the sg_list to start at 213 - * @pdata_off: Offset into the first page 214 227 * @**pdata: a list of pages to add into sg. 228 + * @nr_pages: number of pages to pack into the scatter/gather list 229 + * @data: data to pack into scatter/gather list 215 230 * @count: amount of data to pack into the scatter/gather list 216 231 */ 217 232 static int 218 - pack_sg_list_p(struct scatterlist *sg, int start, int limit, size_t pdata_off, 219 - struct page **pdata, int count) 233 + pack_sg_list_p(struct scatterlist *sg, int start, int limit, 234 + struct page **pdata, int nr_pages, char *data, int count) 220 235 { 221 - int s; 222 - int i = 0; 236 + int i = 0, s; 237 + int data_off; 223 238 int index = start; 224 239 225 - if (pdata_off) { 226 - s = min((int)(PAGE_SIZE - pdata_off), count); 227 - sg_set_page(&sg[index++], pdata[i++], s, pdata_off); 240 + BUG_ON(nr_pages > (limit - start)); 241 + /* 242 + * if the first page doesn't start at 243 + * page boundary find the offset 244 + */ 245 + data_off = offset_in_page(data); 246 + while (nr_pages) { 247 + s = rest_of_page(data); 248 + if (s > count) 249 + s = count; 250 + sg_set_page(&sg[index++], pdata[i++], s, data_off); 251 + data_off = 0; 252 + data += s; 228 253 count -= s; 254 + nr_pages--; 229 255 } 230 - 231 - while (count) { 232 - BUG_ON(index > limit); 233 - s = min((int)PAGE_SIZE, count); 234 - sg_set_page(&sg[index++], pdata[i++], s, 0); 235 - count -= s; 236 - } 237 - return index-start; 256 + return index - start; 238 257 } 239 258 240 259 /** ··· 252 261 static int 253 262 p9_virtio_request(struct p9_client *client, struct p9_req_t *req) 254 263 { 255 - int in, out, inp, outp; 256 - struct virtio_chan *chan = client->trans; 264 + int err; 265 + int in, out; 257 266 unsigned long flags; 258 - size_t pdata_off = 0; 259 - struct trans_rpage_info *rpinfo = NULL; 260 - int err, pdata_len = 0; 267 + struct virtio_chan *chan = client->trans; 261 268 262 269 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 263 270 264 271 req->status = REQ_STATUS_SENT; 265 - 266 - if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) { 267 - int nr_pages = p9_nr_pages(req); 268 - int rpinfo_size = sizeof(struct trans_rpage_info) + 269 - sizeof(struct page *) * nr_pages; 270 - 271 - if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { 272 - err = wait_event_interruptible(vp_wq, 273 - atomic_read(&vp_pinned) < chan->p9_max_pages); 274 - if (err == -ERESTARTSYS) 275 - return err; 276 - P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n"); 277 - } 278 - 279 - if (rpinfo_size <= (req->tc->capacity - req->tc->size)) { 280 - /* We can use sdata */ 281 - req->tc->private = req->tc->sdata + req->tc->size; 282 - rpinfo = (struct trans_rpage_info *)req->tc->private; 283 - rpinfo->rp_alloc = 0; 284 - } else { 285 - req->tc->private = kmalloc(rpinfo_size, GFP_NOFS); 286 - if (!req->tc->private) { 287 - P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: " 288 - "private kmalloc returned NULL"); 289 - return -ENOMEM; 290 - } 291 - rpinfo = (struct trans_rpage_info *)req->tc->private; 292 - rpinfo->rp_alloc = 1; 293 - } 294 - 295 - err = p9_payload_gup(req, &pdata_off, &pdata_len, nr_pages, 296 - req->tc->id == P9_TREAD ? 1 : 0); 297 - if (err < 0) { 298 - if (rpinfo->rp_alloc) 299 - kfree(rpinfo); 300 - return err; 301 - } else { 302 - atomic_add(rpinfo->rp_nr_pages, &vp_pinned); 303 - } 304 - } 305 - 306 - req_retry_pinned: 272 + req_retry: 307 273 spin_lock_irqsave(&chan->lock, flags); 308 274 309 275 /* Handle out VirtIO ring buffers */ 310 - out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, 311 - req->tc->size); 276 + out = pack_sg_list(chan->sg, 0, 277 + VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); 312 278 313 - if (req->tc->pbuf_size && (req->tc->id == P9_TWRITE)) { 314 - /* We have additional write payload buffer to take care */ 315 - if (req->tc->pubuf && P9_IS_USER_CONTEXT) { 316 - outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, 317 - pdata_off, rpinfo->rp_data, pdata_len); 318 - } else { 319 - char *pbuf; 320 - if (req->tc->pubuf) 321 - pbuf = (__force char *) req->tc->pubuf; 322 - else 323 - pbuf = req->tc->pkbuf; 324 - outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf, 325 - req->tc->pbuf_size); 326 - } 327 - out += outp; 328 - } 329 - 330 - /* Handle in VirtIO ring buffers */ 331 - if (req->tc->pbuf_size && 332 - ((req->tc->id == P9_TREAD) || (req->tc->id == P9_TREADDIR))) { 333 - /* 334 - * Take care of additional Read payload. 335 - * 11 is the read/write header = PDU Header(7) + IO Size (4). 336 - * Arrange in such a way that server places header in the 337 - * alloced memory and payload onto the user buffer. 338 - */ 339 - inp = pack_sg_list(chan->sg, out, 340 - VIRTQUEUE_NUM, req->rc->sdata, 11); 341 - /* 342 - * Running executables in the filesystem may result in 343 - * a read request with kernel buffer as opposed to user buffer. 344 - */ 345 - if (req->tc->pubuf && P9_IS_USER_CONTEXT) { 346 - in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM, 347 - pdata_off, rpinfo->rp_data, pdata_len); 348 - } else { 349 - char *pbuf; 350 - if (req->tc->pubuf) 351 - pbuf = (__force char *) req->tc->pubuf; 352 - else 353 - pbuf = req->tc->pkbuf; 354 - 355 - in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM, 356 - pbuf, req->tc->pbuf_size); 357 - } 358 - in += inp; 359 - } else { 360 - in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, 361 - req->rc->sdata, req->rc->capacity); 362 - } 279 + in = pack_sg_list(chan->sg, out, 280 + VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity); 363 281 364 282 err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); 365 283 if (err < 0) { ··· 281 381 return err; 282 382 283 383 P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); 284 - goto req_retry_pinned; 384 + goto req_retry; 285 385 } else { 286 386 spin_unlock_irqrestore(&chan->lock, flags); 287 387 P9_DPRINTK(P9_DEBUG_TRANS, 288 388 "9p debug: " 289 389 "virtio rpc add_buf returned failure"); 290 - if (rpinfo && rpinfo->rp_alloc) 291 - kfree(rpinfo); 292 390 return -EIO; 293 391 } 294 392 } 295 - 296 393 virtqueue_kick(chan->vq); 297 394 spin_unlock_irqrestore(&chan->lock, flags); 298 395 299 396 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 300 397 return 0; 398 + } 399 + 400 + static int p9_get_mapped_pages(struct virtio_chan *chan, 401 + struct page **pages, char *data, 402 + int nr_pages, int write, int kern_buf) 403 + { 404 + int err; 405 + if (!kern_buf) { 406 + /* 407 + * We allow only p9_max_pages pinned. We wait for the 408 + * Other zc request to finish here 409 + */ 410 + if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { 411 + err = wait_event_interruptible(vp_wq, 412 + (atomic_read(&vp_pinned) < chan->p9_max_pages)); 413 + if (err == -ERESTARTSYS) 414 + return err; 415 + } 416 + err = p9_payload_gup(data, &nr_pages, pages, write); 417 + if (err < 0) 418 + return err; 419 + atomic_add(nr_pages, &vp_pinned); 420 + } else { 421 + /* kernel buffer, no need to pin pages */ 422 + int s, index = 0; 423 + int count = nr_pages; 424 + while (nr_pages) { 425 + s = rest_of_page(data); 426 + pages[index++] = virt_to_page(data); 427 + data += s; 428 + nr_pages--; 429 + } 430 + nr_pages = count; 431 + } 432 + return nr_pages; 433 + } 434 + 435 + /** 436 + * p9_virtio_zc_request - issue a zero copy request 437 + * @client: client instance issuing the request 438 + * @req: request to be issued 439 + * @uidata: user bffer that should be ued for zero copy read 440 + * @uodata: user buffer that shoud be user for zero copy write 441 + * @inlen: read buffer size 442 + * @olen: write buffer size 443 + * @hdrlen: reader header size, This is the size of response protocol data 444 + * 445 + */ 446 + static int 447 + p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, 448 + char *uidata, char *uodata, int inlen, 449 + int outlen, int in_hdr_len, int kern_buf) 450 + { 451 + int in, out, err; 452 + unsigned long flags; 453 + int in_nr_pages = 0, out_nr_pages = 0; 454 + struct page **in_pages = NULL, **out_pages = NULL; 455 + struct virtio_chan *chan = client->trans; 456 + 457 + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 458 + 459 + if (uodata) { 460 + out_nr_pages = p9_nr_pages(uodata, outlen); 461 + out_pages = kmalloc(sizeof(struct page *) * out_nr_pages, 462 + GFP_NOFS); 463 + if (!out_pages) { 464 + err = -ENOMEM; 465 + goto err_out; 466 + } 467 + out_nr_pages = p9_get_mapped_pages(chan, out_pages, uodata, 468 + out_nr_pages, 0, kern_buf); 469 + if (out_nr_pages < 0) { 470 + err = out_nr_pages; 471 + kfree(out_pages); 472 + out_pages = NULL; 473 + goto err_out; 474 + } 475 + } 476 + if (uidata) { 477 + in_nr_pages = p9_nr_pages(uidata, inlen); 478 + in_pages = kmalloc(sizeof(struct page *) * in_nr_pages, 479 + GFP_NOFS); 480 + if (!in_pages) { 481 + err = -ENOMEM; 482 + goto err_out; 483 + } 484 + in_nr_pages = p9_get_mapped_pages(chan, in_pages, uidata, 485 + in_nr_pages, 1, kern_buf); 486 + if (in_nr_pages < 0) { 487 + err = in_nr_pages; 488 + kfree(in_pages); 489 + in_pages = NULL; 490 + goto err_out; 491 + } 492 + } 493 + req->status = REQ_STATUS_SENT; 494 + req_retry_pinned: 495 + spin_lock_irqsave(&chan->lock, flags); 496 + /* out data */ 497 + out = pack_sg_list(chan->sg, 0, 498 + VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); 499 + 500 + if (out_pages) 501 + out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, 502 + out_pages, out_nr_pages, uodata, outlen); 503 + /* 504 + * Take care of in data 505 + * For example TREAD have 11. 506 + * 11 is the read/write header = PDU Header(7) + IO Size (4). 507 + * Arrange in such a way that server places header in the 508 + * alloced memory and payload onto the user buffer. 509 + */ 510 + in = pack_sg_list(chan->sg, out, 511 + VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len); 512 + if (in_pages) 513 + in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, 514 + in_pages, in_nr_pages, uidata, inlen); 515 + 516 + err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); 517 + if (err < 0) { 518 + if (err == -ENOSPC) { 519 + chan->ring_bufs_avail = 0; 520 + spin_unlock_irqrestore(&chan->lock, flags); 521 + err = wait_event_interruptible(*chan->vc_wq, 522 + chan->ring_bufs_avail); 523 + if (err == -ERESTARTSYS) 524 + goto err_out; 525 + 526 + P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); 527 + goto req_retry_pinned; 528 + } else { 529 + spin_unlock_irqrestore(&chan->lock, flags); 530 + P9_DPRINTK(P9_DEBUG_TRANS, 531 + "9p debug: " 532 + "virtio rpc add_buf returned failure"); 533 + err = -EIO; 534 + goto err_out; 535 + } 536 + } 537 + virtqueue_kick(chan->vq); 538 + spin_unlock_irqrestore(&chan->lock, flags); 539 + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 540 + err = wait_event_interruptible(*req->wq, 541 + req->status >= REQ_STATUS_RCVD); 542 + /* 543 + * Non kernel buffers are pinned, unpin them 544 + */ 545 + err_out: 546 + if (!kern_buf) { 547 + if (in_pages) { 548 + p9_release_pages(in_pages, in_nr_pages); 549 + atomic_sub(in_nr_pages, &vp_pinned); 550 + } 551 + if (out_pages) { 552 + p9_release_pages(out_pages, out_nr_pages); 553 + atomic_sub(out_nr_pages, &vp_pinned); 554 + } 555 + /* wakeup anybody waiting for slots to pin pages */ 556 + wake_up(&vp_wq); 557 + } 558 + kfree(in_pages); 559 + kfree(out_pages); 560 + return err; 301 561 } 302 562 303 563 static ssize_t p9_mount_tag_show(struct device *dev, ··· 651 591 .create = p9_virtio_create, 652 592 .close = p9_virtio_close, 653 593 .request = p9_virtio_request, 594 + .zc_request = p9_virtio_zc_request, 654 595 .cancel = p9_virtio_cancel, 655 - 656 596 /* 657 597 * We leave one entry for input and one entry for response 658 598 * headers. We also skip one more entry to accomodate, address ··· 660 600 * page in zero copy. 661 601 */ 662 602 .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), 663 - .pref = P9_TRANS_PREF_PAYLOAD_SEP, 664 603 .def = 0, 665 604 .owner = THIS_MODULE, 666 605 };