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 int 673 p9_client_unlink(struct p9_fid *dfid, const char *name, int32_t flags) 674 { 675 int error; 676 struct p9_client *clnt; 677 struct p9_req_t *req; 678 679 error = 0; 680 clnt = dfid->clnt; 681 682 req = p9_client_request(clnt, P9PROTO_TUNLINKAT, &error, "dsd", 683 dfid->fid, name, flags); 684 if (error != 0) { 685 P9_DEBUG(PROTO, "RUNLINKAT fid %d\n", dfid->fid); 686 return (error); 687 } 688 689 p9_free_req(clnt, req); 690 return (error); 691 } 692 693 /* Inform the file server that the current file represented by fid is no longer 694 * needed by the client. Any allocated fid on the server needs a clunk to be 695 * destroyed. 696 */ 697 int 698 p9_client_clunk(struct p9_fid *fid) 699 { 700 int error; 701 struct p9_client *clnt; 702 struct p9_req_t *req; 703 704 error = 0; 705 706 if (fid == NULL) { 707 P9_DEBUG(ERROR, "%s: clunk with NULL fid is bad\n", __func__); 708 return (0); 709 } 710 711 P9_DEBUG(PROTO, "TCLUNK fid %d \n", fid->fid); 712 713 clnt = fid->clnt; 714 req = p9_client_request(clnt, P9PROTO_TCLUNK, &error, "d", fid->fid); 715 if (req != NULL) { 716 P9_DEBUG(PROTO, "RCLUNK fid %d\n", fid->fid); 717 p9_free_req(clnt, req); 718 } 719 720 p9_fid_destroy(fid); 721 return (error); 722 } 723 724 /* 725 * Client_walk is for searching any component name in a directory. 726 * This is usually called on lookups. Also when we need a new open fid 727 * as 9p needs to have an open fid for every file to fileops, we call this 728 * validate the component of the file and return the newfid(openfid) created. 729 */ 730 struct p9_fid * 731 p9_client_walk(struct p9_fid *oldfid, uint16_t nwnames, char **wnames, 732 int clone, int *error) 733 { 734 struct p9_client *clnt; 735 struct p9_fid *fid; 736 struct p9_qid *wqids; 737 struct p9_req_t *req; 738 uint16_t nwqids, count; 739 740 clnt = oldfid->clnt; 741 wqids = NULL; 742 nwqids = 0; 743 744 /* 745 * Before, we go and create fid, make sure we are not tearing 746 * down. Only then we create. 747 * Allow only cleanup clunk messages once we are starting to teardown. 748 */ 749 if (clnt->trans_status != P9FS_CONNECT) { 750 *error = EIO; 751 return (NULL); 752 } 753 754 if (clone) { 755 fid = p9_fid_create(clnt); 756 if (fid == NULL) { 757 *error = ENOMEM; 758 return (NULL); 759 } 760 fid->uid = oldfid->uid; 761 } else 762 fid = oldfid; 763 764 P9_DEBUG(PROTO, "TWALK fids %d,%d nwnames %u wname %s\n", 765 oldfid->fid, fid->fid, nwnames, 766 wnames != NULL ? wnames[nwnames-1] : NULL); 767 768 /* 769 * The newfid is for the component in search. We are preallocating as 770 * qemu on other side allocates or returns a fid if it sees a match 771 */ 772 req = p9_client_request(clnt, P9PROTO_TWALK, error, "ddT", oldfid->fid, 773 fid->fid, wnames, nwnames); 774 if (*error != 0) { 775 if (fid != oldfid) 776 p9_fid_destroy(fid); 777 return (NULL); 778 } 779 780 *error = p9_buf_readf(req->rc, clnt->proto_version, "R", &nwqids, 781 &wqids); 782 if (*error != 0) 783 goto out; 784 785 P9_DEBUG(PROTO, "RWALK nwqid %d:\n", nwqids); 786 787 if (nwqids != nwnames) { 788 *error = ENOENT; 789 goto out; 790 } 791 792 for (count = 0; count < nwqids; count++) 793 P9_DEBUG(TRANS, "%s: [%d] %x.%llx.%x\n", 794 __func__, count, wqids[count].type, 795 (unsigned long long)wqids[count].path, 796 wqids[count].version); 797 798 if (nwnames) 799 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); 800 else 801 fid->qid = oldfid->qid; 802 803 p9_free_req(clnt, req); 804 free(wqids, M_TEMP); 805 return (fid); 806 807 out: 808 p9_free_req(clnt, req); 809 if (wqids) 810 free(wqids, M_TEMP); 811 if (fid && fid != oldfid) 812 p9_client_clunk(fid); 813 return (NULL); 814 } 815 816 /* Open a file with given fid and mode */ 817 int 818 p9_client_open(struct p9_fid *fid, int mode) 819 { 820 int error, mtu; 821 struct p9_client *clnt; 822 struct p9_req_t *req; 823 824 error = 0; 825 clnt = fid->clnt; 826 mtu = 0; 827 828 P9_DEBUG(PROTO, "%s fid %d mode %d\n", 829 p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", 830 fid->fid, mode); 831 832 if (fid->mode != -1) 833 return (EINVAL); 834 835 if (p9_is_proto_dotl(clnt)) 836 req = p9_client_request(clnt, P9PROTO_TLOPEN, &error, "dd", 837 fid->fid, mode); 838 else 839 req = p9_client_request(clnt, P9PROTO_TOPEN, &error, "db", 840 fid->fid, mode); 841 842 if (error != 0) 843 return (error); 844 845 error = p9_buf_readf(req->rc, clnt->proto_version, "Qd", &fid->qid, 846 &mtu); 847 if (error != 0) 848 goto out; 849 850 P9_DEBUG(PROTO, "%s qid %x.%llx.%x mtu %x\n", 851 p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", 852 (fid->qid).type, (unsigned long long)(fid->qid).path, 853 (fid->qid).version, mtu); 854 855 fid->mode = mode; 856 fid->mtu = mtu; 857 out: 858 p9_free_req(clnt, req); 859 return (error); 860 } 861 862 /* Request to get directory entries */ 863 int 864 p9_client_readdir(struct p9_fid *fid, char *data, uint64_t offset, 865 uint32_t count) 866 { 867 int error; 868 uint32_t rsize; 869 struct p9_client *clnt; 870 struct p9_req_t *req; 871 char *dataptr; 872 873 P9_DEBUG(PROTO, "TREADDIR fid %d offset %llu count %d\n", 874 fid->fid, (unsigned long long) offset, count); 875 876 error = 0; 877 rsize = fid->mtu; 878 clnt = fid->clnt; 879 880 if (rsize == 0 || rsize > clnt->msize) 881 rsize = clnt->msize; 882 883 if (count < rsize) 884 rsize = count; 885 886 req = p9_client_request(clnt, P9PROTO_TREADDIR, &error, "dqd", 887 fid->fid, offset, rsize); 888 889 if (error != 0) { 890 P9_DEBUG(ERROR, "%s: couldn't allocate req in client_readdir\n", 891 __func__); 892 return (-error); 893 } 894 895 error = p9_buf_readf(req->rc, clnt->proto_version, "D", &count, 896 &dataptr); 897 if (error != 0) { 898 P9_DEBUG(ERROR, "%s: p0_buf_readf failed: %d\n", 899 __func__, error); 900 p9_free_req(clnt, req); 901 return (-error); 902 } 903 904 P9_DEBUG(PROTO, "RREADDIR count %u\n", count); 905 906 /* Copy back the data into the input buffer. */ 907 memmove(data, dataptr, count); 908 p9_free_req(clnt, req); 909 return (count); 910 } 911 912 /* 913 * Read count bytes from offset for the file fid into the character 914 * buffer data. This buffer is handed over to p9fs to process into user 915 * buffers. Note that this function typically returns the number of bytes read 916 * so in case of an error we return -error so that we can distinguish between 917 * error codes and bytes. 918 */ 919 int 920 p9_client_read(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data) 921 { 922 struct p9_client *clnt; 923 struct p9_req_t *req; 924 char *dataptr; 925 int error, rsize; 926 927 clnt = fid->clnt; 928 rsize = fid->mtu; 929 error = 0; 930 931 P9_DEBUG(PROTO, "TREAD fid %d offset %llu %u\n", 932 fid->fid, (unsigned long long) offset, count); 933 934 if (!rsize || rsize > clnt->msize) 935 rsize = clnt->msize; 936 937 if (count < rsize) 938 rsize = count; 939 940 /* At this stage, we only have 8K buffers so only transfer */ 941 req = p9_client_request(clnt, P9PROTO_TREAD, &error, "dqd", fid->fid, 942 offset, rsize); 943 if (error != 0) { 944 P9_DEBUG(ERROR, "%s: failed allocate request\n", __func__); 945 return (-error); 946 } 947 948 error = p9_buf_readf(req->rc, clnt->proto_version, "D", &count, 949 &dataptr); 950 if (error != 0) { 951 P9_DEBUG(ERROR, "%s: p9_buf_readf failed: %d\n", 952 __func__, error); 953 goto out; 954 } 955 956 if (rsize < count) { 957 P9_DEBUG(PROTO, "RREAD count (%d > %d)\n", count, rsize); 958 count = rsize; 959 } 960 961 P9_DEBUG(PROTO, "RREAD count %d\n", count); 962 963 if (count == 0) { 964 error = -EIO; 965 P9_DEBUG(ERROR, "%s: EIO error in client_read \n", __func__); 966 goto out; 967 } 968 969 /* Copy back the data into the input buffer. */ 970 memmove(data, dataptr, count); 971 p9_free_req(clnt, req); 972 return (count); 973 out: 974 p9_free_req(clnt, req); 975 return (-error); 976 } 977 978 /* 979 * Write count bytes from buffer to the offset for the file fid 980 * Note that this function typically returns the number of bytes written 981 * so in case of an error we return -error so that we can distinguish between 982 * error codes and bytes. 983 */ 984 985 int 986 p9_client_write(struct p9_fid *fid, uint64_t offset, uint32_t count, char *data) 987 { 988 struct p9_client *clnt; 989 struct p9_req_t *req; 990 int ret, error, rsize; 991 992 clnt = fid->clnt; 993 rsize = fid->mtu; 994 ret = 0; 995 error = 0; 996 997 P9_DEBUG(PROTO, "TWRITE fid %d offset %llu %u\n", 998 fid->fid, (unsigned long long) offset, count); 999 1000 if (!rsize || rsize > clnt->msize) 1001 rsize = clnt->msize; 1002 1003 /* Limit set by Qemu ,8168 */ 1004 if (count > rsize) { 1005 count = rsize; 1006 } 1007 1008 /* 1009 * Doing the Data blob instead. If at all we add the zerocopy, we can 1010 * change it to uio direct copy 1011 */ 1012 req = p9_client_request(clnt, P9PROTO_TWRITE, &error, "dqD", fid->fid, 1013 offset, count, data); 1014 if (error != 0) { 1015 P9_DEBUG(ERROR, "%s: failed allocate request: %d\n", 1016 __func__, error); 1017 return (-error); 1018 } 1019 1020 error = p9_buf_readf(req->rc, clnt->proto_version, "d", &ret); 1021 if (error != 0) { 1022 P9_DEBUG(ERROR, "%s: p9_buf_readf error: %d\n", 1023 __func__, error); 1024 goto out; 1025 } 1026 1027 if (count < ret) { 1028 P9_DEBUG(PROTO, "RWRITE count (%d > %d)\n", count, ret); 1029 ret = count; 1030 } 1031 P9_DEBUG(PROTO, "RWRITE count %d\n", ret); 1032 1033 if (count == 0) { 1034 error = EIO; 1035 P9_DEBUG(ERROR, "%s: EIO error\n", __func__); 1036 goto out; 1037 } 1038 1039 p9_free_req(clnt, req); 1040 return (ret); 1041 out: 1042 p9_free_req(clnt, req); 1043 return (-error); 1044 } 1045 1046 1047 /* Create file under directory fid, with name, permissions, mode. */ 1048 int 1049 p9_client_file_create(struct p9_fid *fid, char *name, uint32_t perm, int mode, 1050 char *extension) 1051 { 1052 int error; 1053 struct p9_client *clnt; 1054 struct p9_req_t *req; 1055 struct p9_qid qid; 1056 int mtu; 1057 1058 P9_DEBUG(PROTO, "TCREATE fid %d name %s perm %d mode %d\n", 1059 fid->fid, name, perm, mode); 1060 1061 clnt = fid->clnt; 1062 error = 0; 1063 1064 if (fid->mode != -1) 1065 return (EINVAL); 1066 1067 req = p9_client_request(clnt, P9PROTO_TCREATE, &error, "dsdb?s", 1068 fid->fid, name, perm, mode, extension); 1069 if (error != 0) 1070 return (error); 1071 1072 error = p9_buf_readf(req->rc, clnt->proto_version, "Qd", &qid, &mtu); 1073 if (error != 0) 1074 goto out; 1075 1076 P9_DEBUG(PROTO, "RCREATE qid %x.%jx.%x mtu %x\n", 1077 qid.type, (uintmax_t)qid.path, qid.version, mtu); 1078 fid->mode = mode; 1079 fid->mtu = mtu; 1080 1081 out: 1082 p9_free_req(clnt, req); 1083 return (error); 1084 } 1085 1086 /* Request file system information of the file system */ 1087 int 1088 p9_client_statfs(struct p9_fid *fid, struct p9_statfs *stat) 1089 { 1090 int error; 1091 struct p9_req_t *req; 1092 struct p9_client *clnt; 1093 1094 error = 0; 1095 clnt = fid->clnt; 1096 1097 P9_DEBUG(PROTO, "TSTATFS fid %d\n", fid->fid); 1098 1099 req = p9_client_request(clnt, P9PROTO_TSTATFS, &error, "d", fid->fid); 1100 if (error != 0) { 1101 return (error); 1102 } 1103 1104 error = p9_buf_readf(req->rc, clnt->proto_version, "ddqqqqqqd", 1105 &stat->type, &stat->bsize, &stat->blocks, &stat->bfree, 1106 &stat->bavail, &stat->files, &stat->ffree, &stat->fsid, 1107 &stat->namelen); 1108 1109 if (error != 0) 1110 goto out; 1111 1112 P9_DEBUG(PROTO, "RSTATFS fid %d type 0x%jx bsize %ju " 1113 "blocks %ju bfree %ju bavail %ju files %ju ffree %ju " 1114 "fsid %ju namelen %ju\n", 1115 fid->fid, (uintmax_t)stat->type, 1116 (uintmax_t)stat->bsize, (uintmax_t)stat->blocks, 1117 (uintmax_t)stat->bfree, (uintmax_t)stat->bavail, 1118 (uintmax_t)stat->files, (uintmax_t)stat->ffree, 1119 (uintmax_t)stat->fsid, (uintmax_t)stat->namelen); 1120 1121 out: 1122 p9_free_req(clnt, req); 1123 return (error); 1124 } 1125 1126 /* Rename file referenced by the fid */ 1127 int 1128 p9_client_renameat(struct p9_fid *oldfid, char *oldname, struct p9_fid *newfid, 1129 char *newname) 1130 { 1131 int error; 1132 struct p9_client *clnt; 1133 struct p9_req_t *req; 1134 1135 P9_DEBUG(PROTO, "TRENAMEAT oldfid %d oldname %s newfid %d newfid %s", 1136 oldfid->fid, oldname, newfid->fid, newname); 1137 1138 error = 0; 1139 clnt = oldfid->clnt; 1140 1141 /* 1142 * we are calling the request with TRENAMEAT tag and not TRENAME with 1143 * the 9p protocol version 9p2000.u as the QEMU version supports this 1144 * version of renaming 1145 */ 1146 req = p9_client_request(clnt, P9PROTO_TRENAMEAT, &error, "dsds", 1147 oldfid->fid, oldname, newfid->fid, newname); 1148 1149 if (error != 0) 1150 return (error); 1151 1152 p9_free_req(clnt, req); 1153 return (error); 1154 } 1155 1156 /* Request to create symbolic link */ 1157 int 1158 p9_create_symlink(struct p9_fid *fid, char *name, char *symtgt, gid_t gid) 1159 { 1160 int error; 1161 struct p9_req_t *req; 1162 struct p9_client *clnt; 1163 struct p9_qid qid; 1164 1165 error = 0; 1166 clnt = fid->clnt; 1167 1168 P9_DEBUG(PROTO, "TSYMLINK fid %d name %s\n", fid->fid, name); 1169 1170 req = p9_client_request(clnt, P9PROTO_TSYMLINK, &error, "dssd", 1171 fid->fid, name, symtgt, gid); 1172 1173 if (error != 0) 1174 return (error); 1175 1176 error = p9_buf_readf(req->rc, clnt->proto_version, "Q", &qid); 1177 if (error != 0) { 1178 P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, error); 1179 return (error); 1180 } 1181 1182 P9_DEBUG(PROTO, "RSYMLINK qid %x.%jx.%x\n", 1183 qid.type, (uintmax_t)qid.path, qid.version); 1184 1185 p9_free_req(clnt, req); 1186 return (0); 1187 } 1188 1189 /* Request to create hard link */ 1190 int 1191 p9_create_hardlink(struct p9_fid *dfid, struct p9_fid *oldfid, char *name) 1192 { 1193 int error; 1194 struct p9_req_t *req; 1195 struct p9_client *clnt; 1196 1197 error = 0; 1198 clnt = dfid->clnt; 1199 1200 P9_DEBUG(PROTO, "TLINK dfid %d oldfid %d name %s\n", 1201 dfid->fid, oldfid->fid, name); 1202 1203 req = p9_client_request(clnt, P9PROTO_TLINK, &error, "dds", dfid->fid, 1204 oldfid->fid, name); 1205 if (error != 0) 1206 return (error); 1207 1208 p9_free_req(clnt, req); 1209 return (0); 1210 } 1211 1212 /* Request to read contents of symbolic link */ 1213 int 1214 p9_readlink(struct p9_fid *fid, char **target) 1215 { 1216 int error; 1217 struct p9_client *clnt; 1218 struct p9_req_t *req; 1219 1220 error = 0; 1221 clnt = fid->clnt; 1222 1223 P9_DEBUG(PROTO, "TREADLINK fid %d\n", fid->fid); 1224 1225 req = p9_client_request(clnt, P9PROTO_TREADLINK, &error, "d", fid->fid); 1226 if (error != 0) 1227 return (error); 1228 1229 error = p9_buf_readf(req->rc, clnt->proto_version, "s", target); 1230 if (error != 0) { 1231 P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, error); 1232 return (error); 1233 } 1234 1235 P9_DEBUG(PROTO, "RREADLINK target %s \n", *target); 1236 1237 p9_free_req(clnt, req); 1238 return (0); 1239 } 1240 1241 /* Get file attributes of the file referenced by the fid */ 1242 int 1243 p9_client_getattr(struct p9_fid *fid, struct p9_stat_dotl *stat_dotl, 1244 uint64_t request_mask) 1245 { 1246 int err; 1247 struct p9_client *clnt; 1248 struct p9_req_t *req; 1249 1250 err = 0; 1251 1252 P9_DEBUG(PROTO, "TGETATTR fid %d mask %ju\n", 1253 fid->fid, (uintmax_t)request_mask); 1254 1255 clnt = fid->clnt; 1256 req = p9_client_request(clnt, P9PROTO_TGETATTR, &err, "dq", fid->fid, 1257 request_mask); 1258 if (req == NULL) { 1259 P9_DEBUG(ERROR, "%s: allocation failed %d", __func__, err); 1260 goto error; 1261 } 1262 1263 err = p9_buf_readf(req->rc, clnt->proto_version, "A", stat_dotl); 1264 if (err != 0) { 1265 P9_DEBUG(ERROR, "%s: buf_readf failed %d\n", __func__, err); 1266 goto error; 1267 } 1268 1269 p9_free_req(clnt, req); 1270 P9_DEBUG(PROTO, "RGETATTR fid %d qid %x.%jx.%x st_mode %8.8x " 1271 "uid %d gid %d nlink %ju rdev %jx st_size %jx blksize %ju " 1272 "blocks %ju st_atime_sec %ju, st_atime_nsec %ju " 1273 "st_mtime_sec %ju, st_mtime_nsec %ju st_ctime_sec %ju " 1274 "st_ctime_nsec %ju st_btime_sec %ju, st_btime_nsec %ju " 1275 "st_stat %ju, st_data_version %ju \n", fid->fid, 1276 stat_dotl->qid.type, (uintmax_t)stat_dotl->qid.path, 1277 stat_dotl->qid.version, stat_dotl->st_mode, stat_dotl->st_uid, 1278 stat_dotl->st_gid, (uintmax_t)stat_dotl->st_nlink, 1279 (uintmax_t)stat_dotl->st_rdev, (uintmax_t)stat_dotl->st_size, 1280 (uintmax_t)stat_dotl->st_blksize, 1281 (uintmax_t)stat_dotl->st_blocks, (uintmax_t)stat_dotl->st_atime_sec, 1282 (uintmax_t)stat_dotl->st_atime_nsec, (uintmax_t)stat_dotl->st_mtime_sec, 1283 (uintmax_t)stat_dotl->st_mtime_nsec, (uintmax_t)stat_dotl->st_ctime_sec, 1284 (uintmax_t)stat_dotl->st_ctime_nsec, (uintmax_t)stat_dotl->st_btime_sec, 1285 (uintmax_t)stat_dotl->st_btime_nsec, (uintmax_t)stat_dotl->st_gen, 1286 (uintmax_t)stat_dotl->st_data_version); 1287 1288 return (err); 1289 1290 error: 1291 if (req != NULL) 1292 p9_free_req(clnt, req); 1293 1294 return (err); 1295 } 1296 1297 /* Set file attributes of the file referenced by the fid */ 1298 int 1299 p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) 1300 { 1301 int err; 1302 struct p9_req_t *req; 1303 struct p9_client *clnt; 1304 1305 err = 0; 1306 1307 P9_DEBUG(PROTO, "TSETATTR fid %d" 1308 " valid %x mode %x uid %d gid %d size %ju" 1309 " atime_sec %ju atime_nsec %ju" 1310 " mtime_sec %ju mtime_nsec %ju\n", 1311 fid->fid, 1312 p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid, 1313 (uintmax_t)p9attr->size, (uintmax_t)p9attr->atime_sec, 1314 (uintmax_t)p9attr->atime_nsec, (uintmax_t)p9attr->mtime_sec, 1315 (uintmax_t)p9attr->mtime_nsec); 1316 1317 clnt = fid->clnt; 1318 1319 /* Any client_request error is converted to req == NULL error*/ 1320 req = p9_client_request(clnt, P9PROTO_TSETATTR, &err, "dA", fid->fid, 1321 p9attr); 1322 1323 if (req == NULL) { 1324 P9_DEBUG(ERROR, "%s: allocation failed %d\n", __func__, err); 1325 goto error; 1326 } 1327 1328 p9_free_req(clnt, req); 1329 error: 1330 return (err); 1331 } 1332 1333