xref: /freebsd/sys/fs/p9fs/p9_client.c (revision 3b68c491d37196bb76a95bce3c02f7c6d5ba22fd)
1 /*-
2  * Copyright (c) 2017 Juniper Networks, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *	notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *	notice, this list of conditions and the following disclaimer in the
12  *	documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*
28  * This file contains 9P client functions which prepares message to be sent to
29  * the server. Every fileop typically has a function defined here to interact
30  * with the host.
31  */
32 
33 #include <vm/uma.h>
34 #include <sys/systm.h>
35 #include <sys/dirent.h>
36 #include <sys/fcntl.h>
37 #include <sys/param.h>
38 #include <sys/malloc.h>
39 #include <sys/mount.h>
40 #include <sys/sysctl.h>
41 
42 #include <fs/p9fs/p9_client.h>
43 #include <fs/p9fs/p9_debug.h>
44 #include <fs/p9fs/p9_transport.h>
45 
46 #define QEMU_HEADER 7
47 #define P9FS_MAX_FID_CNT (1024 * 1024 * 1024)
48 #define P9FS_ROOT_FID_NO 2
49 #define P9FS_MIN_TAG 1
50 #define P9FS_MAX_TAG 65535
51 #define WSTAT_SIZE 47
52 #define WSTAT_EXTENSION_SIZE 14
53 
54 static MALLOC_DEFINE(M_P9CLNT, "p9_client", "p9fs client structure");
55 static uma_zone_t p9fs_fid_zone;
56 static uma_zone_t p9fs_req_zone;
57 static uma_zone_t p9fs_buf_zone;
58 
59 SYSCTL_DECL(_vfs_p9fs);
60 int p9_debug_level = 0;
61 SYSCTL_INT(_vfs_p9fs, OID_AUTO, debug_level, CTLFLAG_RW,
62     &p9_debug_level, 0, "p9fs debug logging");
63 
64 static struct p9_req_t *p9_get_request(struct p9_client *c, int *error);
65 static struct p9_req_t *p9_client_request(
66     struct p9_client *c, int8_t type, int *error, const char *fmt, ...);
67 
68 inline int
69 p9_is_proto_dotl(struct p9_client *clnt)
70 {
71 
72 	return (clnt->proto_version == p9_proto_2000L);
73 }
74 
75 inline int
76 p9_is_proto_dotu(struct p9_client *clnt)
77 {
78 
79 	return (clnt->proto_version == p9_proto_2000u);
80 }
81 
82 /* Parse mount options into client structure */
83 static int
84 p9_parse_opts(struct mount  *mp, struct p9_client *clnt)
85 {
86 	int error, len;
87 	char *trans;
88 
89 	/*
90 	 * Default to virtio since thats the only transport we have for now.
91 	 */
92 	error = vfs_getopt(mp->mnt_optnew, "trans", (void **)&trans, &len);
93 	if (error == ENOENT)
94 		trans = "virtio";
95 
96 	/* These are defaults for now */
97 	clnt->proto_version = p9_proto_2000L;
98 	clnt->msize = 8192;
99 
100 	/* Get the default trans callback */
101 	clnt->ops = p9_get_trans_by_name(trans);
102 
103 	return (0);
104 }
105 
106 /* Allocate buffer for sending request and getting responses */
107 static struct p9_buffer *
108 p9_buffer_alloc(int alloc_msize)
109 {
110 	struct p9_buffer *fc;
111 
112 	fc = uma_zalloc(p9fs_buf_zone, M_WAITOK | M_ZERO);
113 	fc->capacity = alloc_msize;
114 	fc->offset = 0;
115 	fc->size = 0;
116 	fc->sdata = (char *)fc + sizeof(struct p9_buffer);
117 
118 	return (fc);
119 }
120 
121 /* Free memory used by request and response buffers */
122 static void
123 p9_buffer_free(struct p9_buffer **buf)
124 {
125 
126 	/* Free the sdata buffers first, then the whole structure*/
127 	uma_zfree(p9fs_buf_zone, *buf);
128 	*buf = NULL;
129 }
130 
131 /* Free the request */
132 static void
133 p9_free_req(struct p9_client *clnt, struct p9_req_t *req)
134 {
135 
136 	if (req->tc != NULL) {
137 		if (req->tc->tag != P9_NOTAG)
138 			p9_tag_destroy(clnt, req->tc->tag);
139 		p9_buffer_free(&req->tc);
140 	}
141 
142 	if (req->rc != NULL)
143 		p9_buffer_free(&req->rc);
144 
145 	uma_zfree(p9fs_req_zone, req);
146 }
147 
148 /* Allocate a request by tag */
149 static struct p9_req_t *
150 p9_get_request(struct p9_client *clnt, int *error)
151 {
152 	struct p9_req_t *req;
153 	int alloc_msize;
154 	uint16_t tag;
155 
156 	alloc_msize = P9FS_MTU;
157 
158 	req = uma_zalloc(p9fs_req_zone, M_WAITOK | M_ZERO);
159 	req->tc = p9_buffer_alloc(alloc_msize);
160 	req->rc = p9_buffer_alloc(alloc_msize);
161 
162 	tag = p9_tag_create(clnt);
163 	if (tag == P9_NOTAG) {
164 		*error = EAGAIN;
165 		req->tc->tag = P9_NOTAG;
166 		p9_free_req(clnt, req);
167 		return (NULL);
168 	}
169 	req->tc->tag = tag;
170 	return (req);
171 }
172 
173 /* Parse header arguments of the response buffer */
174 static int
175 p9_parse_receive(struct p9_buffer *buf, struct p9_client *clnt)
176 {
177 	int8_t type;
178 	int16_t tag;
179 	int32_t size;
180 	int error;
181 
182 	buf->offset = 0;
183 
184 	/* This value is set by QEMU for the header.*/
185 	if (buf->size == 0)
186 		buf->size = QEMU_HEADER;
187 
188 	/* This is the initial header. Parse size, type, and tag .*/
189 	error = p9_buf_readf(buf, 0, "dbw", &size, &type, &tag);
190 	if (error != 0)
191 		goto out;
192 
193 	buf->size = size;
194 	buf->id = type;
195 	buf->tag = tag;
196 	P9_DEBUG(TRANS, "%s: size=%d type: %d tag: %d\n",
197 	    __func__, buf->size, buf->id, buf->tag);
198 out:
199 	return (error);
200 }
201 
202 /* Check 9P response for any errors returned and process it */
203 static int
204 p9_client_check_return(struct p9_client *c, struct p9_req_t *req)
205 {
206 	int error;
207 	int ecode;
208 	char *ename;
209 
210 	/* Check what we have in the receive bufer .*/
211 	error = p9_parse_receive(req->rc, c);
212 	if (error != 0)
213 		goto out;
214 
215 	/*
216 	 * No error, We are done with the preprocessing. Return to the caller
217 	 * and process the actual data.
218 	 */
219 	if (req->rc->id != P9PROTO_RERROR && req->rc->id != P9PROTO_RLERROR)
220 		return (0);
221 
222 	/*
223 	 * Interpreting the error is done in different ways for Linux and
224 	 * Unix version. Make sure you interpret it right.
225 	 */
226 	if (req->rc->id == P9PROTO_RERROR) {
227 	        error = p9_buf_readf(req->rc, c->proto_version, "s?d", &ename, &ecode);
228 	} else if (req->rc->id == P9PROTO_RLERROR) {
229 	        error = p9_buf_readf(req->rc, c->proto_version, "d", &ecode);
230 	} else {
231 		goto out;
232 	}
233 	if (error != 0)
234 		goto out;
235 
236 	/* if there was an ecode error make this the err now */
237 	error = ecode;
238 
239 	/*
240 	 * Note this is still not completely an error, as lookups for files
241 	 * not present can hit this and return. Hence it is made a debug print.
242 	 */
243 	if (error != 0) {
244 	        if (req->rc->id == P9PROTO_RERROR) {
245 		        P9_DEBUG(PROTO, "RERROR error %d ename %s\n",
246 			    error, ename);
247 	        } else if (req->rc->id == P9PROTO_RLERROR) {
248 		        P9_DEBUG(PROTO, "RLERROR error %d\n", error);
249 		}
250 	}
251 
252 	if (req->rc->id == P9PROTO_RERROR) {
253 	        free(ename, M_TEMP);
254 	}
255 	return (error);
256 
257 out:
258 	P9_DEBUG(ERROR, "couldn't parse receive buffer error%d\n", error);
259 	return (error);
260 }
261 
262 /* State machine changing helpers */
263 void p9_client_disconnect(struct p9_client *clnt)
264 {
265 
266 	P9_DEBUG(TRANS, "%s: clnt %p\n", __func__, clnt);
267 	clnt->trans_status = P9FS_DISCONNECT;
268 }
269 
270 void p9_client_begin_disconnect(struct p9_client *clnt)
271 {
272 
273 	P9_DEBUG(TRANS, "%s: clnt %p\n", __func__, clnt);
274 	clnt->trans_status = P9FS_BEGIN_DISCONNECT;
275 }
276 
277 static struct p9_req_t *
278 p9_client_prepare_req(struct p9_client *c, int8_t type,
279     int req_size, int *error, const char *fmt, __va_list ap)
280 {
281 	struct p9_req_t *req;
282 
283 	P9_DEBUG(TRANS, "%s: client %p op %d\n", __func__, c, type);
284 
285 	/*
286 	 * Before we start with the request, check if its possible to finish
287 	 * this request. We are allowed to submit the request only if there
288 	 * are no close sessions happening or else there can be race. If the
289 	 * status is Disconnected, we stop any requests coming in after that.
290 	 */
291 	if (c->trans_status == P9FS_DISCONNECT) {
292 		*error = EIO;
293 		return (NULL);
294 	}
295 
296 	/* Allow only cleanup clunk messages once teardown has started. */
297 	if ((c->trans_status == P9FS_BEGIN_DISCONNECT) &&
298 	    (type != P9PROTO_TCLUNK)) {
299 		*error = EIO;
300 		return (NULL);
301 	}
302 
303 	/* Allocate buffer for transferring and receiving data from host */
304 	req = p9_get_request(c, error);
305 	if (*error != 0) {
306 		P9_DEBUG(ERROR, "%s: request allocation failed.\n", __func__);
307 		return (NULL);
308 	}
309 
310 	/* Marshall the data according to QEMU standards */
311 	*error = p9_buf_prepare(req->tc, type);
312 	if (*error != 0) {
313 		P9_DEBUG(ERROR, "%s: p9_buf_prepare failed: %d\n",
314 		    __func__, *error);
315 		goto out;
316 	}
317 
318 	*error = p9_buf_vwritef(req->tc, c->proto_version, fmt, ap);
319 	if (*error != 0) {
320 		P9_DEBUG(ERROR, "%s: p9_buf_vwrite failed: %d\n",
321 		    __func__, *error);
322 		goto out;
323 	}
324 
325 	*error = p9_buf_finalize(c, req->tc);
326 	if (*error != 0) {
327 		P9_DEBUG(ERROR, "%s: p9_buf_finalize failed: %d \n",
328 		    __func__, *error);
329 		goto out;
330 	}
331 
332 	return (req);
333 out:
334 	p9_free_req(c, req);
335 	return (NULL);
336 }
337 
338 /*
339  * Issue a request and wait for response. The routine takes care of preparing
340  * the 9P request header to be sent, parsing and checking for error conditions
341  * in the received buffer. It returns the request structure.
342  */
343 static struct p9_req_t *
344 p9_client_request(struct p9_client *c, int8_t type, int *error,
345     const char *fmt, ...)
346 {
347 	va_list ap;
348 	struct p9_req_t *req;
349 
350 	va_start(ap, fmt);
351 	req = p9_client_prepare_req(c, type, c->msize, error, fmt, ap);
352 	va_end(ap);
353 
354 	/* Issue with allocation of request buffer */
355 	if (*error != 0)
356 		return (NULL);
357 
358 	/* Call into the transport for submission. */
359 	*error = c->ops->request(c->handle, req);
360 	if (*error != 0) {
361 		P9_DEBUG(ERROR, "%s: failed: %d\n", __func__, *error);
362 		goto out;
363 	}
364 
365 	/*
366 	 * Before we return, pre process the header and the rc buffer before
367 	 * calling into the protocol infra to analyze the data in rc.
368 	 */
369 	*error = p9_client_check_return(c, req);
370 	if (*error != 0)
371 		goto out;
372 
373 	return (req);
374 out:
375 	p9_free_req(c, req);
376 	return (NULL);
377 }
378 
379 /* Setup tag contents and structure  */
380 uint16_t
381 p9_tag_create(struct p9_client *clnt)
382 {
383         int tag;
384 
385         tag = alloc_unr(&clnt->tagpool);
386         P9_DEBUG(LPROTO, "%s: clnt %p: tag %d\n", __func__, clnt, tag);
387 
388         /* Alloc_unr returning -1 is an error for no units left */
389         if (tag == -1) {
390                 return (P9_NOTAG);
391         }
392         return (tag);
393 }
394 
395 /* Clean up tag structures */
396 void
397 p9_tag_destroy(struct p9_client *clnt, uint16_t tag)
398 {
399 
400         P9_DEBUG(LPROTO, "%s: clnt %p: tag %d\n", __func__, clnt, tag);
401 
402         /* Release to the pool */
403         free_unr(&clnt->tagpool, tag);
404 }
405 
406 /* Allocate a new fid from the fidpool */
407 struct p9_fid *
408 p9_fid_create(struct p9_client *clnt)
409 {
410 	struct p9_fid *fid;
411 
412 
413 	fid = uma_zalloc(p9fs_fid_zone, M_WAITOK | M_ZERO);
414 	fid->fid = alloc_unr(&clnt->fidpool);
415 	P9_DEBUG(LPROTO, "%s: fid %d\n", __func__, fid->fid);
416 
417 	/* Alloc_unr returning -1 is an error for no units left */
418 	if (fid->fid == -1) {
419 		uma_zfree(p9fs_fid_zone, fid);
420 		return (NULL);
421 	}
422 	fid->mode = -1;
423 	fid->uid = -1;
424 	fid->clnt = clnt;
425 
426 	return (fid);
427 }
428 
429 /* Free the fid by releasing it to fidpool */
430 void
431 p9_fid_destroy(struct p9_fid *fid)
432 {
433 	struct p9_client *clnt;
434 
435 	P9_DEBUG(LPROTO, "%s: fid %d\n", __func__, fid->fid);
436 	clnt = fid->clnt;
437 	/* Release to the pool */
438 	free_unr(&clnt->fidpool, fid->fid);
439 	uma_zfree(p9fs_fid_zone, fid);
440 }
441 
442 /* Request the version of 9P protocol */
443 int
444 p9_client_version(struct p9_client *c)
445 {
446 	int error;
447 	struct p9_req_t *req;
448 	char *version;
449 	int msize;
450 
451 	error = 0;
452 
453 	P9_DEBUG(PROTO, "TVERSION msize %d protocol %d\n",
454 	    c->msize, c->proto_version);
455 
456 	switch (c->proto_version) {
457 	case p9_proto_2000L:
458 		req = p9_client_request(c, P9PROTO_TVERSION, &error, "ds",
459 		    c->msize, "9P2000.L");
460 		break;
461 	case p9_proto_2000u:
462 		req = p9_client_request(c, P9PROTO_TVERSION, &error, "ds",
463 		    c->msize, "9P2000.u");
464 		break;
465 	case p9_proto_legacy:
466 		req = p9_client_request(c, P9PROTO_TVERSION, &error, "ds",
467 		    c->msize, "9P2000");
468 		break;
469 	default:
470 		return (EINVAL);
471 	}
472 
473 	/*  Always return the relevant error code */
474 	if (error != 0)
475 		return (error);
476 
477 	error = p9_buf_readf(req->rc, c->proto_version, "ds", &msize, &version);
478 	if (error != 0) {
479 		P9_DEBUG(ERROR, "%s: version error: %d\n", __func__, error);
480 		goto out;
481 	}
482 
483 	P9_DEBUG(PROTO, "RVERSION msize %d %s\n", msize, version);
484 
485 	if (!strncmp(version, "9P2000.L", 8))
486 		c->proto_version = p9_proto_2000L;
487 	else if (!strncmp(version, "9P2000.u", 8))
488 		c->proto_version = p9_proto_2000u;
489 	else if (!strncmp(version, "9P2000", 6))
490 		c->proto_version = p9_proto_legacy;
491 	else {
492 		error = ENOMEM;
493 		goto out;
494 	}
495 
496 	/* limit the msize .*/
497 	if (msize < c->msize)
498 		c->msize = msize;
499 out:
500 	p9_free_req(c, req);
501 	return (error);
502 }
503 
504 /*
505  * Initialize zones for different things. This is called from Init module
506  * so that we just have them initalized once.
507  */
508 void
509 p9_init_zones(void)
510 {
511 
512 	/* Create the request and the fid zones */
513 	p9fs_fid_zone = uma_zcreate("p9fs fid zone",
514 	    sizeof(struct p9_fid), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
515 
516 	/* Create the request and the fid zones */
517 	p9fs_req_zone = uma_zcreate("p9fs req zone",
518 	    sizeof(struct p9_req_t), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
519 
520 	/* Create the buffer zone */
521 	p9fs_buf_zone = uma_zcreate("p9fs buf zone",
522 	    sizeof(struct p9_buffer) + P9FS_MTU, NULL, NULL,
523 	    NULL, NULL, UMA_ALIGN_PTR, 0);
524 }
525 
526 void
527 p9_destroy_zones(void)
528 {
529 
530 	uma_zdestroy(p9fs_fid_zone);
531 	uma_zdestroy(p9fs_req_zone);
532 	uma_zdestroy(p9fs_buf_zone);
533 }
534 
535 /* Return the client to the session in the FS to hold it */
536 struct p9_client *
537 p9_client_create(struct mount *mp, int *error, const char *mount_tag)
538 {
539 	struct p9_client *clnt;
540 
541 	clnt = malloc(sizeof(struct p9_client), M_P9CLNT, M_WAITOK | M_ZERO);
542 	mtx_init(&clnt->clnt_mtx, "p9clnt", NULL, MTX_DEF);
543 
544 	/* Parse should have set trans_mod */
545 	*error = p9_parse_opts(mp, clnt);
546 	if (*error != 0)
547 		goto out;
548 
549 	if (clnt->ops == NULL) {
550 		*error = EINVAL;
551 		P9_DEBUG(ERROR, "%s: no transport\n", __func__);
552 		goto out;
553 	}
554 
555 	/* All the structures from here are protected by the lock clnt_mtx */
556 	init_unrhdr(&clnt->fidpool, P9FS_ROOT_FID_NO, P9FS_MAX_FID_CNT,
557 	    &clnt->clnt_mtx);
558 	init_unrhdr(&clnt->tagpool, P9FS_MIN_TAG, P9FS_MAX_TAG,
559 	    &clnt->clnt_mtx);
560 
561 	P9_DEBUG(TRANS, "%s: clnt %p trans %p msize %d protocol %d\n",
562 	    __func__, clnt, clnt->ops, clnt->msize, clnt->proto_version);
563 
564 	*error = clnt->ops->create(mount_tag, &clnt->handle);
565 	if (*error != 0) {
566 		P9_DEBUG(ERROR, "%s: transport create failed .%d \n",
567 		    __func__, *error);
568 		goto out;
569 	}
570 	clnt->trans_status = P9FS_CONNECT;
571 
572 	*error = p9_client_version(clnt);
573 	if (*error != 0)
574 		goto out;
575 
576 	P9_DEBUG(TRANS, "%s: client creation succeeded.\n", __func__);
577 	return (clnt);
578 out:
579 	free(clnt, M_P9CLNT);
580 	return (NULL);
581 }
582 
583 /* Destroy the client by destroying associated fidpool and tagpool */
584 void
585 p9_client_destroy(struct p9_client *clnt)
586 {
587 
588 	P9_DEBUG(TRANS, "%s: client %p\n", __func__, clnt);
589 	clnt->ops->close(clnt->handle);
590 
591 	P9_DEBUG(TRANS, "%s : Destroying fidpool\n", __func__);
592 	clear_unrhdr(&clnt->fidpool);
593 
594 	P9_DEBUG(TRANS, "%s : Destroying tagpool\n", __func__);
595 	clear_unrhdr(&clnt->tagpool);
596 
597 	free(clnt, M_P9CLNT);
598 }
599 
600 /*
601  * Attach a user to the filesystem. Create a fid for that user to access
602  * the root of the filesystem.
603  */
604 struct p9_fid *
605 p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
606     const char *uname, uid_t n_uname, const char *aname, int *error)
607 {
608 	struct p9_req_t *req;
609 	struct p9_fid *fid;
610 	struct p9_qid qid;
611 
612 	P9_DEBUG(PROTO, "TATTACH uname=%s aname=%s, n_uname=%d\n",
613 	    uname, aname, n_uname);
614 	fid = p9_fid_create(clnt);
615 	if (fid == NULL) {
616 		*error = ENOMEM;
617 		return (NULL);
618 	}
619 	fid->uid = n_uname;
620 
621 	req = p9_client_request(clnt, P9PROTO_TATTACH, error, "ddssd", fid->fid,
622 	    P9PROTO_NOFID, uname, aname, n_uname);
623 	if (*error != 0)
624 		goto out;
625 
626 	*error = p9_buf_readf(req->rc, clnt->proto_version, "Q", &qid);
627 	if (*error != 0) {
628 		P9_DEBUG(ERROR, "%s: p9_buf_readf failed: %d \n",
629 		    __func__, *error);
630 		goto out;
631 	}
632 
633 	P9_DEBUG(PROTO, "RATTACH qid %x.%llx.%x\n",
634 	    qid.type, (unsigned long long)qid.path, qid.version);
635 
636 	memmove(&fid->qid, &qid, sizeof(struct p9_qid));
637 	p9_free_req(clnt, req);
638 
639 	return (fid);
640 out:
641 	if (req != NULL)
642 		p9_free_req(clnt, req);
643 	if (fid != NULL)
644 		p9_fid_destroy(fid);
645 
646 	return (NULL);
647 }
648 
649 /* Delete a file/directory. Corresponding fid will be cluncked too */
650 int
651 p9_client_remove(struct p9_fid *fid)
652 {
653 	int error;
654 	struct p9_client *clnt;
655 	struct p9_req_t *req;
656 
657 	P9_DEBUG(PROTO, "TREMOVE fid %d\n", fid->fid);
658 
659 	error = 0;
660 	clnt = fid->clnt;
661 
662 	req = p9_client_request(clnt, P9PROTO_TREMOVE, &error, "d", fid->fid);
663 	if (error != 0) {
664 		P9_DEBUG(PROTO, "RREMOVE fid %d\n", fid->fid);
665 		return (error);
666 	}
667 
668 	p9_free_req(clnt, req);
669 	return (error);
670 }
671 
672 /* Inform the file server that the current file represented by fid is no longer
673  * needed by the client. Any allocated fid on the server needs a clunk to be
674  * destroyed.
675  */
676 int
677 p9_client_clunk(struct p9_fid *fid)
678 {
679 	int error;
680 	struct p9_client *clnt;
681 	struct p9_req_t *req;
682 
683 	error = 0;
684 
685 	if (fid == NULL) {
686 		P9_DEBUG(ERROR, "%s: clunk with NULL fid is bad\n", __func__);
687 		return (0);
688 	}
689 
690 	P9_DEBUG(PROTO, "TCLUNK fid %d \n", fid->fid);
691 
692 	clnt = fid->clnt;
693 	req = p9_client_request(clnt, P9PROTO_TCLUNK, &error, "d", fid->fid);
694 	if (req != NULL) {
695 		P9_DEBUG(PROTO, "RCLUNK fid %d\n", fid->fid);
696 		p9_free_req(clnt, req);
697 	}
698 
699 	p9_fid_destroy(fid);
700 	return (error);
701 }
702 
703 /*
704  * Client_walk is for searching any component name in a directory.
705  * This is usually called on lookups. Also when we need a new open fid
706  * as 9p needs to have an open fid for every file to fileops, we call this
707  * validate the component of the file and return the newfid(openfid) created.
708  */
709 struct p9_fid *
710 p9_client_walk(struct p9_fid *oldfid, uint16_t nwnames, char **wnames,
711     int clone, int *error)
712 {
713 	struct p9_client *clnt;
714 	struct p9_fid *fid;
715 	struct p9_qid *wqids;
716 	struct p9_req_t *req;
717 	uint16_t nwqids, count;
718 
719 	clnt = oldfid->clnt;
720 	wqids = NULL;
721 	nwqids = 0;
722 
723 	/*
724 	 *  Before, we go and create fid, make sure we are not tearing
725 	 *  down. Only then we create.
726 	 *  Allow only cleanup clunk messages once we are starting to teardown.
727 	 */
728 	if (clnt->trans_status != P9FS_CONNECT) {
729 		*error = EIO;
730 		return (NULL);
731 	}
732 
733 	if (clone) {
734 		fid = p9_fid_create(clnt);
735 		if (fid == NULL) {
736 			*error = ENOMEM;
737 			return (NULL);
738 		}
739 		fid->uid = oldfid->uid;
740 	} else
741 		fid = oldfid;
742 
743 	P9_DEBUG(PROTO, "TWALK fids %d,%d nwnames %u wname %s\n",
744 	    oldfid->fid, fid->fid, nwnames,
745 	    wnames != NULL ? wnames[nwnames-1] : NULL);
746 
747 	/*
748 	 * The newfid is for the component in search. We are preallocating as
749 	 * qemu on other side allocates or returns a fid if it sees a match
750 	 */
751 	req = p9_client_request(clnt, P9PROTO_TWALK, error, "ddT", oldfid->fid,
752 	    fid->fid, wnames, nwnames);
753 	if (*error != 0) {
754 		if (fid != oldfid)
755 			p9_fid_destroy(fid);
756 		return (NULL);
757 	}
758 
759 	*error = p9_buf_readf(req->rc, clnt->proto_version, "R", &nwqids,
760 	    &wqids);
761 	if (*error != 0)
762 		goto out;
763 
764 	P9_DEBUG(PROTO, "RWALK nwqid %d:\n", nwqids);
765 
766 	if (nwqids != nwnames) {
767 		*error = ENOENT;
768 		goto out;
769 	}
770 
771 	for (count = 0; count < nwqids; count++)
772 		P9_DEBUG(TRANS, "%s: [%d] %x.%llx.%x\n",
773 		    __func__, count, wqids[count].type,
774 		    (unsigned long long)wqids[count].path,
775 		    wqids[count].version);
776 
777 	if (nwnames)
778 		memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
779 	else
780 		fid->qid = oldfid->qid;
781 
782 	p9_free_req(clnt, req);
783 	free(wqids, M_TEMP);
784 	return (fid);
785 
786 out:
787 	p9_free_req(clnt, req);
788 	if (wqids)
789 		free(wqids, M_TEMP);
790 	if (fid && fid != oldfid)
791 		p9_client_clunk(fid);
792 	return (NULL);
793 }
794 
795 /* Open a file with given fid and mode */
796 int
797 p9_client_open(struct p9_fid *fid, int mode)
798 {
799 	int error, mtu;
800 	struct p9_client *clnt;
801 	struct p9_req_t *req;
802 
803 	error = 0;
804 	clnt = fid->clnt;
805 	mtu = 0;
806 
807 	P9_DEBUG(PROTO, "%s fid %d mode %d\n",
808 	    p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN",
809 	    fid->fid, mode);
810 
811 	if (fid->mode != -1)
812 		return (EINVAL);
813 
814 	if (p9_is_proto_dotl(clnt))
815 		req = p9_client_request(clnt, P9PROTO_TLOPEN, &error, "dd",
816 		    fid->fid, mode);
817 	else
818 		req = p9_client_request(clnt, P9PROTO_TOPEN, &error, "db",
819 		    fid->fid, mode);
820 
821 	if (error != 0)
822 		return (error);
823 
824 	error = p9_buf_readf(req->rc, clnt->proto_version, "Qd", &fid->qid,
825 	    &mtu);
826 	if (error != 0)
827 		goto out;
828 
829 	P9_DEBUG(PROTO, "%s qid %x.%llx.%x mtu %x\n",
830 	    p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN",
831 	    (fid->qid).type, (unsigned long long)(fid->qid).path,
832 	    (fid->qid).version, mtu);
833 
834 	fid->mode = mode;
835 	fid->mtu = mtu;
836 out:
837 	p9_free_req(clnt, req);
838 	return (error);
839 }
840 
841 /* Request to get directory entries */
842 int
843 p9_client_readdir(struct p9_fid *fid, char *data, uint64_t offset,
844     uint32_t count)
845 {
846 	int error;
847 	uint32_t rsize;
848 	struct p9_client *clnt;
849 	struct p9_req_t *req;
850 	char *dataptr;
851 
852 	P9_DEBUG(PROTO, "TREADDIR fid %d offset %llu count %d\n",
853 	    fid->fid, (unsigned long long) offset, count);
854 
855 	error = 0;
856 	rsize = fid->mtu;
857 	clnt = fid->clnt;
858 
859 	if (rsize == 0 || rsize > clnt->msize)
860 		rsize = clnt->msize;
861 
862 	if (count < rsize)
863 		rsize = count;
864 
865 	req = p9_client_request(clnt, P9PROTO_TREADDIR, &error, "dqd",
866 	    fid->fid, offset, rsize);
867 
868 	if (error != 0) {
869 		P9_DEBUG(ERROR, "%s: couldn't allocate req in client_readdir\n",
870 			__func__);
871 		return (-error);
872 	}
873 
874 	error = p9_buf_readf(req->rc, clnt->proto_version, "D", &count,
875 	    &dataptr);
876 	if (error != 0) {
877 		P9_DEBUG(ERROR, "%s: p0_buf_readf failed: %d\n",
878 		    __func__, error);
879 		p9_free_req(clnt, req);
880 		return (-error);
881 	}
882 
883 	P9_DEBUG(PROTO, "RREADDIR count %u\n", count);
884 
885 	/* Copy back the data into the input buffer. */
886 	memmove(data, dataptr, count);
887 	p9_free_req(clnt, req);
888 	return (count);
889 }
890 
891 /*
892  * Read count bytes from offset for the file fid into the character
893  * buffer data. This buffer is handed over to p9fs to process into user
894  * buffers. Note that this function typically returns the number of bytes read
895  * so in case of an error we return -error so that we can distinguish between
896  * error codes and bytes.
897  */
898 int
899 p9_client_read(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data)
900 {
901 	struct p9_client *clnt;
902 	struct p9_req_t *req;
903 	char *dataptr;
904 	int error, rsize;
905 
906 	clnt = fid->clnt;
907 	rsize = fid->mtu;
908 	error = 0;
909 
910 	P9_DEBUG(PROTO, "TREAD fid %d offset %llu %u\n",
911 	    fid->fid, (unsigned long long) offset, count);
912 
913 	if (!rsize || rsize > clnt->msize)
914 		rsize = clnt->msize;
915 
916 	if (count < rsize)
917 		rsize = count;
918 
919 	/* At this stage, we only have 8K buffers so only transfer */
920 	req = p9_client_request(clnt, P9PROTO_TREAD, &error, "dqd", fid->fid,
921 	    offset, rsize);
922 	if (error != 0) {
923 		P9_DEBUG(ERROR, "%s: failed allocate request\n", __func__);
924 		return (-error);
925 	}
926 
927 	error = p9_buf_readf(req->rc, clnt->proto_version, "D", &count,
928 	    &dataptr);
929 	if (error != 0) {
930 		P9_DEBUG(ERROR, "%s: p9_buf_readf failed: %d\n",
931 		    __func__, error);
932 		goto out;
933 	}
934 
935 	if (rsize < count) {
936 		P9_DEBUG(PROTO, "RREAD count (%d > %d)\n", count, rsize);
937 		count = rsize;
938 	}
939 
940 	P9_DEBUG(PROTO, "RREAD count %d\n", count);
941 
942 	if (count == 0) {
943 		error = -EIO;
944 		P9_DEBUG(ERROR, "%s: EIO error in client_read \n", __func__);
945 		goto out;
946 	}
947 
948 	/* Copy back the data into the input buffer. */
949 	memmove(data, dataptr, count);
950 	p9_free_req(clnt, req);
951 	return (count);
952 out:
953 	p9_free_req(clnt, req);
954 	return (-error);
955 }
956 
957 /*
958  * Write count bytes from buffer to the offset for the file fid
959  * Note that this function typically returns the number of bytes written
960  * so in case of an error we return -error so that we can distinguish between
961  * error codes and bytes.
962  */
963 
964 int
965 p9_client_write(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data)
966 {
967 	struct p9_client *clnt;
968 	struct p9_req_t *req;
969 	int ret, error, rsize;
970 
971 	clnt = fid->clnt;
972 	rsize = fid->mtu;
973 	ret = 0;
974 	error = 0;
975 
976 	P9_DEBUG(PROTO, "TWRITE fid %d offset %llu  %u\n",
977 	    fid->fid, (unsigned long long) offset, count);
978 
979 	if (!rsize || rsize > clnt->msize)
980 		rsize = clnt->msize;
981 
982 	/* Limit set by Qemu ,8168 */
983 	if (count > rsize) {
984 		count = rsize;
985 	}
986 
987 	/*
988 	 * Doing the Data blob instead. If at all we add the zerocopy, we can
989 	 * change it to uio direct copy
990 	 */
991 	req = p9_client_request(clnt, P9PROTO_TWRITE, &error, "dqD", fid->fid,
992 	    offset, count, data);
993 	if (error != 0) {
994 		P9_DEBUG(ERROR, "%s: failed allocate request: %d\n",
995 		    __func__, error);
996 		return (-error);
997 	}
998 
999 	error = p9_buf_readf(req->rc, clnt->proto_version, "d", &ret);
1000 	if (error != 0) {
1001 		P9_DEBUG(ERROR, "%s: p9_buf_readf error: %d\n",
1002 		    __func__, error);
1003 		goto out;
1004 	}
1005 
1006 	if (count < ret) {
1007 		P9_DEBUG(PROTO, "RWRITE count (%d > %d)\n", count, ret);
1008 		ret = count;
1009 	}
1010 	P9_DEBUG(PROTO, "RWRITE count %d\n", ret);
1011 
1012 	if (count == 0) {
1013 		error = EIO;
1014 		P9_DEBUG(ERROR, "%s: EIO error\n", __func__);
1015 		goto out;
1016 	}
1017 
1018 	p9_free_req(clnt, req);
1019 	return (ret);
1020 out:
1021 	p9_free_req(clnt, req);
1022 	return (-error);
1023 }
1024 
1025 
1026 /* Create file under directory fid, with name, permissions, mode. */
1027 int
1028 p9_client_file_create(struct p9_fid *fid, char *name, uint32_t perm, int mode,
1029     char *extension)
1030 {
1031 	int error;
1032 	struct p9_client *clnt;
1033 	struct p9_req_t *req;
1034 	struct p9_qid qid;
1035 	int mtu;
1036 
1037 	P9_DEBUG(PROTO, "TCREATE fid %d name %s perm %d mode %d\n",
1038 	    fid->fid, name, perm, mode);
1039 
1040 	clnt = fid->clnt;
1041 	error = 0;
1042 
1043 	if (fid->mode != -1)
1044 		return (EINVAL);
1045 
1046 	req = p9_client_request(clnt, P9PROTO_TCREATE, &error, "dsdb?s",
1047 	    fid->fid, name, perm, mode, extension);
1048 	if (error != 0)
1049 		return (error);
1050 
1051 	error = p9_buf_readf(req->rc, clnt->proto_version, "Qd", &qid, &mtu);
1052 	if (error != 0)
1053 		goto out;
1054 
1055 	P9_DEBUG(PROTO, "RCREATE qid %x.%jx.%x mtu %x\n",
1056 	    qid.type, (uintmax_t)qid.path, qid.version, mtu);
1057 	fid->mode = mode;
1058 	fid->mtu = mtu;
1059 
1060 out:
1061 	p9_free_req(clnt, req);
1062 	return (error);
1063 }
1064 
1065 /* Request file system information of the file system */
1066 int
1067 p9_client_statfs(struct p9_fid *fid, struct p9_statfs *stat)
1068 {
1069 	int error;
1070 	struct p9_req_t *req;
1071 	struct p9_client *clnt;
1072 
1073 	error = 0;
1074 	clnt = fid->clnt;
1075 
1076 	P9_DEBUG(PROTO, "TSTATFS fid %d\n", fid->fid);
1077 
1078 	req = p9_client_request(clnt, P9PROTO_TSTATFS, &error, "d", fid->fid);
1079 	if (error != 0) {
1080 		return (error);
1081 	}
1082 
1083 	error = p9_buf_readf(req->rc, clnt->proto_version, "ddqqqqqqd",
1084 	    &stat->type, &stat->bsize, &stat->blocks, &stat->bfree,
1085 	    &stat->bavail, &stat->files, &stat->ffree, &stat->fsid,
1086 	    &stat->namelen);
1087 
1088 	if (error != 0)
1089 		goto out;
1090 
1091 	P9_DEBUG(PROTO, "RSTATFS fid %d type 0x%jx bsize %ju "
1092 	    "blocks %ju bfree %ju bavail %ju files %ju ffree %ju "
1093 	    "fsid %ju namelen %ju\n",
1094 	    fid->fid, (uintmax_t)stat->type,
1095 	    (uintmax_t)stat->bsize, (uintmax_t)stat->blocks,
1096 	    (uintmax_t)stat->bfree, (uintmax_t)stat->bavail,
1097 	    (uintmax_t)stat->files, (uintmax_t)stat->ffree,
1098 	    (uintmax_t)stat->fsid, (uintmax_t)stat->namelen);
1099 
1100 out:
1101 	p9_free_req(clnt, req);
1102 	return (error);
1103 }
1104 
1105 /* Rename file referenced by the fid */
1106 int
1107 p9_client_renameat(struct p9_fid *oldfid, char *oldname, struct p9_fid *newfid,
1108     char *newname)
1109 {
1110 	int error;
1111 	struct p9_client *clnt;
1112 	struct p9_req_t *req;
1113 
1114 	P9_DEBUG(PROTO, "TRENAMEAT oldfid %d oldname %s newfid %d newfid %s",
1115 	    oldfid->fid, oldname, newfid->fid, newname);
1116 
1117 	error = 0;
1118 	clnt = oldfid->clnt;
1119 
1120 	/*
1121 	 * we are calling the request with TRENAMEAT tag and not TRENAME with
1122 	 * the 9p protocol version 9p2000.u as the QEMU version supports this
1123 	 * version of renaming
1124 	 */
1125 	req = p9_client_request(clnt, P9PROTO_TRENAMEAT, &error, "dsds",
1126 	    oldfid->fid, oldname, newfid->fid, newname);
1127 
1128 	if (error != 0)
1129 		return (error);
1130 
1131 	p9_free_req(clnt, req);
1132 	return (error);
1133 }
1134 
1135 /* Request to create symbolic link */
1136 int
1137 p9_create_symlink(struct p9_fid *fid, char *name, char *symtgt, gid_t gid)
1138 {
1139 	int error;
1140 	struct p9_req_t *req;
1141 	struct p9_client *clnt;
1142 	struct p9_qid qid;
1143 
1144 	error = 0;
1145 	clnt = fid->clnt;
1146 
1147 	P9_DEBUG(PROTO, "TSYMLINK fid %d name %s\n", fid->fid, name);
1148 
1149 	req = p9_client_request(clnt, P9PROTO_TSYMLINK, &error, "dssd",
1150 	    fid->fid, name, symtgt, gid);
1151 
1152 	if (error != 0)
1153 		return (error);
1154 
1155 	error = p9_buf_readf(req->rc, clnt->proto_version, "Q", &qid);
1156 	if (error != 0) {
1157 		P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, error);
1158 		return (error);
1159 	}
1160 
1161 	P9_DEBUG(PROTO, "RSYMLINK qid %x.%jx.%x\n",
1162 	    qid.type, (uintmax_t)qid.path, qid.version);
1163 
1164 	p9_free_req(clnt, req);
1165 	return (0);
1166 }
1167 
1168 /* Request to create hard link */
1169 int
1170 p9_create_hardlink(struct p9_fid *dfid, struct p9_fid *oldfid, char *name)
1171 {
1172 	int error;
1173 	struct p9_req_t *req;
1174 	struct p9_client *clnt;
1175 
1176 	error = 0;
1177 	clnt = dfid->clnt;
1178 
1179 	P9_DEBUG(PROTO, "TLINK dfid %d oldfid %d name %s\n",
1180 	    dfid->fid, oldfid->fid, name);
1181 
1182 	req = p9_client_request(clnt, P9PROTO_TLINK, &error, "dds", dfid->fid,
1183 	    oldfid->fid, name);
1184 	if (error != 0)
1185 		return (error);
1186 
1187 	p9_free_req(clnt, req);
1188 	return (0);
1189 }
1190 
1191 /* Request to read contents of symbolic link */
1192 int
1193 p9_readlink(struct p9_fid *fid, char **target)
1194 {
1195 	int error;
1196 	struct p9_client *clnt;
1197 	struct p9_req_t *req;
1198 
1199 	error = 0;
1200 	clnt = fid->clnt;
1201 
1202 	P9_DEBUG(PROTO, "TREADLINK fid %d\n", fid->fid);
1203 
1204 	req = p9_client_request(clnt, P9PROTO_TREADLINK, &error, "d", fid->fid);
1205 	if (error != 0)
1206 		return (error);
1207 
1208 	error = p9_buf_readf(req->rc, clnt->proto_version, "s", target);
1209 	if (error != 0) {
1210 		P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, error);
1211 		return (error);
1212 	}
1213 
1214 	P9_DEBUG(PROTO, "RREADLINK target %s \n", *target);
1215 
1216 	p9_free_req(clnt, req);
1217 	return (0);
1218 }
1219 
1220 /* Get file attributes of the file referenced by the fid */
1221 int
1222 p9_client_getattr(struct p9_fid *fid, struct p9_stat_dotl *stat_dotl,
1223     uint64_t request_mask)
1224 {
1225 	int err;
1226 	struct p9_client *clnt;
1227 	struct p9_req_t *req;
1228 
1229 	err = 0;
1230 
1231 	P9_DEBUG(PROTO, "TGETATTR fid %d mask %ju\n",
1232 	    fid->fid, (uintmax_t)request_mask);
1233 
1234 	clnt = fid->clnt;
1235 	req = p9_client_request(clnt, P9PROTO_TGETATTR, &err, "dq", fid->fid,
1236 	    request_mask);
1237 	if (req == NULL) {
1238 		P9_DEBUG(ERROR, "%s: allocation failed %d", __func__, err);
1239 		goto error;
1240 	}
1241 
1242 	err = p9_buf_readf(req->rc, clnt->proto_version, "A", stat_dotl);
1243 	if (err != 0) {
1244 		P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, err);
1245 		goto error;
1246 	}
1247 
1248 	p9_free_req(clnt, req);
1249 	P9_DEBUG(PROTO, "RGETATTR fid %d qid %x.%jx.%x st_mode %8.8x "
1250 	    "uid %d gid %d nlink %ju rdev %jx st_size %jx blksize %ju "
1251 	    "blocks %ju st_atime_sec %ju, st_atime_nsec %ju "
1252 	    "st_mtime_sec %ju, st_mtime_nsec %ju st_ctime_sec %ju "
1253 	    "st_ctime_nsec %ju st_btime_sec %ju, st_btime_nsec %ju "
1254 	    "st_stat %ju, st_data_version %ju \n", fid->fid,
1255 	    stat_dotl->qid.type, (uintmax_t)stat_dotl->qid.path,
1256 	    stat_dotl->qid.version, stat_dotl->st_mode, stat_dotl->st_uid,
1257 	    stat_dotl->st_gid, (uintmax_t)stat_dotl->st_nlink,
1258 	    (uintmax_t)stat_dotl->st_rdev, (uintmax_t)stat_dotl->st_size,
1259 	    (uintmax_t)stat_dotl->st_blksize,
1260 	    (uintmax_t)stat_dotl->st_blocks, (uintmax_t)stat_dotl->st_atime_sec,
1261 	    (uintmax_t)stat_dotl->st_atime_nsec, (uintmax_t)stat_dotl->st_mtime_sec,
1262 	    (uintmax_t)stat_dotl->st_mtime_nsec, (uintmax_t)stat_dotl->st_ctime_sec,
1263 	    (uintmax_t)stat_dotl->st_ctime_nsec, (uintmax_t)stat_dotl->st_btime_sec,
1264 	    (uintmax_t)stat_dotl->st_btime_nsec, (uintmax_t)stat_dotl->st_gen,
1265 	    (uintmax_t)stat_dotl->st_data_version);
1266 
1267 	return (err);
1268 
1269 error:
1270 	if (req != NULL)
1271 		p9_free_req(clnt, req);
1272 
1273 	return (err);
1274 }
1275 
1276 /* Set file attributes of the file referenced by the fid */
1277 int
1278 p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
1279 {
1280 	int err;
1281 	struct p9_req_t *req;
1282 	struct p9_client *clnt;
1283 
1284 	err = 0;
1285 
1286 	P9_DEBUG(PROTO, "TSETATTR fid %d"
1287 	    " valid %x mode %x uid %d gid %d size %ju"
1288 	    " atime_sec %ju atime_nsec %ju"
1289 	    " mtime_sec %ju mtime_nsec %ju\n",
1290 	    fid->fid,
1291 	    p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid,
1292 	    (uintmax_t)p9attr->size, (uintmax_t)p9attr->atime_sec,
1293 	    (uintmax_t)p9attr->atime_nsec, (uintmax_t)p9attr->mtime_sec,
1294 	    (uintmax_t)p9attr->mtime_nsec);
1295 
1296 	clnt = fid->clnt;
1297 
1298 	/* Any client_request error is converted to req == NULL error*/
1299 	req = p9_client_request(clnt, P9PROTO_TSETATTR, &err, "dA", fid->fid,
1300 	    p9attr);
1301 
1302 	if (req == NULL) {
1303 		P9_DEBUG(ERROR, "%s: allocation failed %d\n", __func__, err);
1304 		goto error;
1305 	}
1306 
1307 	p9_free_req(clnt, req);
1308 error:
1309 	return (err);
1310 }
1311 
1312