1 /* 2 * Virtio 9p backend 3 * 4 * Copyright IBM, Corp. 2010 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 */ 13 14 #include "qemu/osdep.h" 15 #include <glib/gprintf.h> 16 #include "hw/virtio/virtio.h" 17 #include "qapi/error.h" 18 #include "qemu/error-report.h" 19 #include "qemu/iov.h" 20 #include "qemu/sockets.h" 21 #include "virtio-9p.h" 22 #include "fsdev/qemu-fsdev.h" 23 #include "9p-xattr.h" 24 #include "coth.h" 25 #include "trace.h" 26 #include "migration/migration.h" 27 28 int open_fd_hw; 29 int total_open_fd; 30 static int open_fd_rc; 31 32 enum { 33 Oread = 0x00, 34 Owrite = 0x01, 35 Ordwr = 0x02, 36 Oexec = 0x03, 37 Oexcl = 0x04, 38 Otrunc = 0x10, 39 Orexec = 0x20, 40 Orclose = 0x40, 41 Oappend = 0x80, 42 }; 43 44 ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) 45 { 46 ssize_t ret; 47 va_list ap; 48 49 va_start(ap, fmt); 50 ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap); 51 va_end(ap); 52 53 return ret; 54 } 55 56 ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) 57 { 58 ssize_t ret; 59 va_list ap; 60 61 va_start(ap, fmt); 62 ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap); 63 va_end(ap); 64 65 return ret; 66 } 67 68 static void pdu_push_and_notify(V9fsPDU *pdu) 69 { 70 virtio_9p_push_and_notify(pdu); 71 } 72 73 static int omode_to_uflags(int8_t mode) 74 { 75 int ret = 0; 76 77 switch (mode & 3) { 78 case Oread: 79 ret = O_RDONLY; 80 break; 81 case Ordwr: 82 ret = O_RDWR; 83 break; 84 case Owrite: 85 ret = O_WRONLY; 86 break; 87 case Oexec: 88 ret = O_RDONLY; 89 break; 90 } 91 92 if (mode & Otrunc) { 93 ret |= O_TRUNC; 94 } 95 96 if (mode & Oappend) { 97 ret |= O_APPEND; 98 } 99 100 if (mode & Oexcl) { 101 ret |= O_EXCL; 102 } 103 104 return ret; 105 } 106 107 struct dotl_openflag_map { 108 int dotl_flag; 109 int open_flag; 110 }; 111 112 static int dotl_to_open_flags(int flags) 113 { 114 int i; 115 /* 116 * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY 117 * and P9_DOTL_NOACCESS 118 */ 119 int oflags = flags & O_ACCMODE; 120 121 struct dotl_openflag_map dotl_oflag_map[] = { 122 { P9_DOTL_CREATE, O_CREAT }, 123 { P9_DOTL_EXCL, O_EXCL }, 124 { P9_DOTL_NOCTTY , O_NOCTTY }, 125 { P9_DOTL_TRUNC, O_TRUNC }, 126 { P9_DOTL_APPEND, O_APPEND }, 127 { P9_DOTL_NONBLOCK, O_NONBLOCK } , 128 { P9_DOTL_DSYNC, O_DSYNC }, 129 { P9_DOTL_FASYNC, FASYNC }, 130 { P9_DOTL_DIRECT, O_DIRECT }, 131 { P9_DOTL_LARGEFILE, O_LARGEFILE }, 132 { P9_DOTL_DIRECTORY, O_DIRECTORY }, 133 { P9_DOTL_NOFOLLOW, O_NOFOLLOW }, 134 { P9_DOTL_NOATIME, O_NOATIME }, 135 { P9_DOTL_SYNC, O_SYNC }, 136 }; 137 138 for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { 139 if (flags & dotl_oflag_map[i].dotl_flag) { 140 oflags |= dotl_oflag_map[i].open_flag; 141 } 142 } 143 144 return oflags; 145 } 146 147 void cred_init(FsCred *credp) 148 { 149 credp->fc_uid = -1; 150 credp->fc_gid = -1; 151 credp->fc_mode = -1; 152 credp->fc_rdev = -1; 153 } 154 155 static int get_dotl_openflags(V9fsState *s, int oflags) 156 { 157 int flags; 158 /* 159 * Filter the client open flags 160 */ 161 flags = dotl_to_open_flags(oflags); 162 flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT); 163 /* 164 * Ignore direct disk access hint until the server supports it. 165 */ 166 flags &= ~O_DIRECT; 167 return flags; 168 } 169 170 void v9fs_path_init(V9fsPath *path) 171 { 172 path->data = NULL; 173 path->size = 0; 174 } 175 176 void v9fs_path_free(V9fsPath *path) 177 { 178 g_free(path->data); 179 path->data = NULL; 180 path->size = 0; 181 } 182 183 184 void GCC_FMT_ATTR(2, 3) 185 v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...) 186 { 187 va_list ap; 188 189 v9fs_path_free(path); 190 191 va_start(ap, fmt); 192 /* Bump the size for including terminating NULL */ 193 path->size = g_vasprintf(&path->data, fmt, ap) + 1; 194 va_end(ap); 195 } 196 197 void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs) 198 { 199 v9fs_path_free(lhs); 200 lhs->data = g_malloc(rhs->size); 201 memcpy(lhs->data, rhs->data, rhs->size); 202 lhs->size = rhs->size; 203 } 204 205 int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, 206 const char *name, V9fsPath *path) 207 { 208 int err; 209 err = s->ops->name_to_path(&s->ctx, dirpath, name, path); 210 if (err < 0) { 211 err = -errno; 212 } 213 return err; 214 } 215 216 /* 217 * Return TRUE if s1 is an ancestor of s2. 218 * 219 * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d". 220 * As a special case, We treat s1 as ancestor of s2 if they are same! 221 */ 222 static int v9fs_path_is_ancestor(V9fsPath *s1, V9fsPath *s2) 223 { 224 if (!strncmp(s1->data, s2->data, s1->size - 1)) { 225 if (s2->data[s1->size - 1] == '\0' || s2->data[s1->size - 1] == '/') { 226 return 1; 227 } 228 } 229 return 0; 230 } 231 232 static size_t v9fs_string_size(V9fsString *str) 233 { 234 return str->size; 235 } 236 237 /* 238 * returns 0 if fid got re-opened, 1 if not, < 0 on error */ 239 static int coroutine_fn v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f) 240 { 241 int err = 1; 242 if (f->fid_type == P9_FID_FILE) { 243 if (f->fs.fd == -1) { 244 do { 245 err = v9fs_co_open(pdu, f, f->open_flags); 246 } while (err == -EINTR && !pdu->cancelled); 247 } 248 } else if (f->fid_type == P9_FID_DIR) { 249 if (f->fs.dir.stream == NULL) { 250 do { 251 err = v9fs_co_opendir(pdu, f); 252 } while (err == -EINTR && !pdu->cancelled); 253 } 254 } 255 return err; 256 } 257 258 static V9fsFidState *coroutine_fn get_fid(V9fsPDU *pdu, int32_t fid) 259 { 260 int err; 261 V9fsFidState *f; 262 V9fsState *s = pdu->s; 263 264 for (f = s->fid_list; f; f = f->next) { 265 BUG_ON(f->clunked); 266 if (f->fid == fid) { 267 /* 268 * Update the fid ref upfront so that 269 * we don't get reclaimed when we yield 270 * in open later. 271 */ 272 f->ref++; 273 /* 274 * check whether we need to reopen the 275 * file. We might have closed the fd 276 * while trying to free up some file 277 * descriptors. 278 */ 279 err = v9fs_reopen_fid(pdu, f); 280 if (err < 0) { 281 f->ref--; 282 return NULL; 283 } 284 /* 285 * Mark the fid as referenced so that the LRU 286 * reclaim won't close the file descriptor 287 */ 288 f->flags |= FID_REFERENCED; 289 return f; 290 } 291 } 292 return NULL; 293 } 294 295 static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) 296 { 297 V9fsFidState *f; 298 299 for (f = s->fid_list; f; f = f->next) { 300 /* If fid is already there return NULL */ 301 BUG_ON(f->clunked); 302 if (f->fid == fid) { 303 return NULL; 304 } 305 } 306 f = g_malloc0(sizeof(V9fsFidState)); 307 f->fid = fid; 308 f->fid_type = P9_FID_NONE; 309 f->ref = 1; 310 /* 311 * Mark the fid as referenced so that the LRU 312 * reclaim won't close the file descriptor 313 */ 314 f->flags |= FID_REFERENCED; 315 f->next = s->fid_list; 316 s->fid_list = f; 317 318 v9fs_readdir_init(&f->fs.dir); 319 v9fs_readdir_init(&f->fs_reclaim.dir); 320 321 return f; 322 } 323 324 static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp) 325 { 326 int retval = 0; 327 328 if (fidp->fs.xattr.copied_len == -1) { 329 /* getxattr/listxattr fid */ 330 goto free_value; 331 } 332 /* 333 * if this is fid for setxattr. clunk should 334 * result in setxattr localcall 335 */ 336 if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) { 337 /* clunk after partial write */ 338 retval = -EINVAL; 339 goto free_out; 340 } 341 if (fidp->fs.xattr.len) { 342 retval = v9fs_co_lsetxattr(pdu, &fidp->path, &fidp->fs.xattr.name, 343 fidp->fs.xattr.value, 344 fidp->fs.xattr.len, 345 fidp->fs.xattr.flags); 346 } else { 347 retval = v9fs_co_lremovexattr(pdu, &fidp->path, &fidp->fs.xattr.name); 348 } 349 free_out: 350 v9fs_string_free(&fidp->fs.xattr.name); 351 free_value: 352 g_free(fidp->fs.xattr.value); 353 return retval; 354 } 355 356 static int coroutine_fn free_fid(V9fsPDU *pdu, V9fsFidState *fidp) 357 { 358 int retval = 0; 359 360 if (fidp->fid_type == P9_FID_FILE) { 361 /* If we reclaimed the fd no need to close */ 362 if (fidp->fs.fd != -1) { 363 retval = v9fs_co_close(pdu, &fidp->fs); 364 } 365 } else if (fidp->fid_type == P9_FID_DIR) { 366 if (fidp->fs.dir.stream != NULL) { 367 retval = v9fs_co_closedir(pdu, &fidp->fs); 368 } 369 } else if (fidp->fid_type == P9_FID_XATTR) { 370 retval = v9fs_xattr_fid_clunk(pdu, fidp); 371 } 372 v9fs_path_free(&fidp->path); 373 g_free(fidp); 374 return retval; 375 } 376 377 static int coroutine_fn put_fid(V9fsPDU *pdu, V9fsFidState *fidp) 378 { 379 BUG_ON(!fidp->ref); 380 fidp->ref--; 381 /* 382 * Don't free the fid if it is in reclaim list 383 */ 384 if (!fidp->ref && fidp->clunked) { 385 if (fidp->fid == pdu->s->root_fid) { 386 /* 387 * if the clunked fid is root fid then we 388 * have unmounted the fs on the client side. 389 * delete the migration blocker. Ideally, this 390 * should be hooked to transport close notification 391 */ 392 if (pdu->s->migration_blocker) { 393 migrate_del_blocker(pdu->s->migration_blocker); 394 error_free(pdu->s->migration_blocker); 395 pdu->s->migration_blocker = NULL; 396 } 397 } 398 return free_fid(pdu, fidp); 399 } 400 return 0; 401 } 402 403 static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid) 404 { 405 V9fsFidState **fidpp, *fidp; 406 407 for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) { 408 if ((*fidpp)->fid == fid) { 409 break; 410 } 411 } 412 if (*fidpp == NULL) { 413 return NULL; 414 } 415 fidp = *fidpp; 416 *fidpp = fidp->next; 417 fidp->clunked = 1; 418 return fidp; 419 } 420 421 void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu) 422 { 423 int reclaim_count = 0; 424 V9fsState *s = pdu->s; 425 V9fsFidState *f, *reclaim_list = NULL; 426 427 for (f = s->fid_list; f; f = f->next) { 428 /* 429 * Unlink fids cannot be reclaimed. Check 430 * for them and skip them. Also skip fids 431 * currently being operated on. 432 */ 433 if (f->ref || f->flags & FID_NON_RECLAIMABLE) { 434 continue; 435 } 436 /* 437 * if it is a recently referenced fid 438 * we leave the fid untouched and clear the 439 * reference bit. We come back to it later 440 * in the next iteration. (a simple LRU without 441 * moving list elements around) 442 */ 443 if (f->flags & FID_REFERENCED) { 444 f->flags &= ~FID_REFERENCED; 445 continue; 446 } 447 /* 448 * Add fids to reclaim list. 449 */ 450 if (f->fid_type == P9_FID_FILE) { 451 if (f->fs.fd != -1) { 452 /* 453 * Up the reference count so that 454 * a clunk request won't free this fid 455 */ 456 f->ref++; 457 f->rclm_lst = reclaim_list; 458 reclaim_list = f; 459 f->fs_reclaim.fd = f->fs.fd; 460 f->fs.fd = -1; 461 reclaim_count++; 462 } 463 } else if (f->fid_type == P9_FID_DIR) { 464 if (f->fs.dir.stream != NULL) { 465 /* 466 * Up the reference count so that 467 * a clunk request won't free this fid 468 */ 469 f->ref++; 470 f->rclm_lst = reclaim_list; 471 reclaim_list = f; 472 f->fs_reclaim.dir.stream = f->fs.dir.stream; 473 f->fs.dir.stream = NULL; 474 reclaim_count++; 475 } 476 } 477 if (reclaim_count >= open_fd_rc) { 478 break; 479 } 480 } 481 /* 482 * Now close the fid in reclaim list. Free them if they 483 * are already clunked. 484 */ 485 while (reclaim_list) { 486 f = reclaim_list; 487 reclaim_list = f->rclm_lst; 488 if (f->fid_type == P9_FID_FILE) { 489 v9fs_co_close(pdu, &f->fs_reclaim); 490 } else if (f->fid_type == P9_FID_DIR) { 491 v9fs_co_closedir(pdu, &f->fs_reclaim); 492 } 493 f->rclm_lst = NULL; 494 /* 495 * Now drop the fid reference, free it 496 * if clunked. 497 */ 498 put_fid(pdu, f); 499 } 500 } 501 502 static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) 503 { 504 int err; 505 V9fsState *s = pdu->s; 506 V9fsFidState *fidp, head_fid; 507 508 head_fid.next = s->fid_list; 509 for (fidp = s->fid_list; fidp; fidp = fidp->next) { 510 if (fidp->path.size != path->size) { 511 continue; 512 } 513 if (!memcmp(fidp->path.data, path->data, path->size)) { 514 /* Mark the fid non reclaimable. */ 515 fidp->flags |= FID_NON_RECLAIMABLE; 516 517 /* reopen the file/dir if already closed */ 518 err = v9fs_reopen_fid(pdu, fidp); 519 if (err < 0) { 520 return -1; 521 } 522 /* 523 * Go back to head of fid list because 524 * the list could have got updated when 525 * switched to the worker thread 526 */ 527 if (err == 0) { 528 fidp = &head_fid; 529 } 530 } 531 } 532 return 0; 533 } 534 535 static void coroutine_fn virtfs_reset(V9fsPDU *pdu) 536 { 537 V9fsState *s = pdu->s; 538 V9fsFidState *fidp = NULL; 539 540 /* Free all fids */ 541 while (s->fid_list) { 542 fidp = s->fid_list; 543 s->fid_list = fidp->next; 544 545 if (fidp->ref) { 546 fidp->clunked = 1; 547 } else { 548 free_fid(pdu, fidp); 549 } 550 } 551 if (fidp) { 552 /* One or more unclunked fids found... */ 553 error_report("9pfs:%s: One or more uncluncked fids " 554 "found during reset", __func__); 555 } 556 } 557 558 #define P9_QID_TYPE_DIR 0x80 559 #define P9_QID_TYPE_SYMLINK 0x02 560 561 #define P9_STAT_MODE_DIR 0x80000000 562 #define P9_STAT_MODE_APPEND 0x40000000 563 #define P9_STAT_MODE_EXCL 0x20000000 564 #define P9_STAT_MODE_MOUNT 0x10000000 565 #define P9_STAT_MODE_AUTH 0x08000000 566 #define P9_STAT_MODE_TMP 0x04000000 567 #define P9_STAT_MODE_SYMLINK 0x02000000 568 #define P9_STAT_MODE_LINK 0x01000000 569 #define P9_STAT_MODE_DEVICE 0x00800000 570 #define P9_STAT_MODE_NAMED_PIPE 0x00200000 571 #define P9_STAT_MODE_SOCKET 0x00100000 572 #define P9_STAT_MODE_SETUID 0x00080000 573 #define P9_STAT_MODE_SETGID 0x00040000 574 #define P9_STAT_MODE_SETVTX 0x00010000 575 576 #define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR | \ 577 P9_STAT_MODE_SYMLINK | \ 578 P9_STAT_MODE_LINK | \ 579 P9_STAT_MODE_DEVICE | \ 580 P9_STAT_MODE_NAMED_PIPE | \ 581 P9_STAT_MODE_SOCKET) 582 583 /* This is the algorithm from ufs in spfs */ 584 static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) 585 { 586 size_t size; 587 588 memset(&qidp->path, 0, sizeof(qidp->path)); 589 size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); 590 memcpy(&qidp->path, &stbuf->st_ino, size); 591 qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8); 592 qidp->type = 0; 593 if (S_ISDIR(stbuf->st_mode)) { 594 qidp->type |= P9_QID_TYPE_DIR; 595 } 596 if (S_ISLNK(stbuf->st_mode)) { 597 qidp->type |= P9_QID_TYPE_SYMLINK; 598 } 599 } 600 601 static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, 602 V9fsQID *qidp) 603 { 604 struct stat stbuf; 605 int err; 606 607 err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 608 if (err < 0) { 609 return err; 610 } 611 stat_to_qid(&stbuf, qidp); 612 return 0; 613 } 614 615 V9fsPDU *pdu_alloc(V9fsState *s) 616 { 617 V9fsPDU *pdu = NULL; 618 619 if (!QLIST_EMPTY(&s->free_list)) { 620 pdu = QLIST_FIRST(&s->free_list); 621 QLIST_REMOVE(pdu, next); 622 QLIST_INSERT_HEAD(&s->active_list, pdu, next); 623 } 624 return pdu; 625 } 626 627 void pdu_free(V9fsPDU *pdu) 628 { 629 V9fsState *s = pdu->s; 630 631 g_assert(!pdu->cancelled); 632 QLIST_REMOVE(pdu, next); 633 QLIST_INSERT_HEAD(&s->free_list, pdu, next); 634 } 635 636 /* 637 * We don't do error checking for pdu_marshal/unmarshal here 638 * because we always expect to have enough space to encode 639 * error details 640 */ 641 static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len) 642 { 643 int8_t id = pdu->id + 1; /* Response */ 644 V9fsState *s = pdu->s; 645 646 if (len < 0) { 647 int err = -len; 648 len = 7; 649 650 if (s->proto_version != V9FS_PROTO_2000L) { 651 V9fsString str; 652 653 str.data = strerror(err); 654 str.size = strlen(str.data); 655 656 len += pdu_marshal(pdu, len, "s", &str); 657 id = P9_RERROR; 658 } 659 660 len += pdu_marshal(pdu, len, "d", err); 661 662 if (s->proto_version == V9FS_PROTO_2000L) { 663 id = P9_RLERROR; 664 } 665 trace_v9fs_rerror(pdu->tag, pdu->id, err); /* Trace ERROR */ 666 } 667 668 /* fill out the header */ 669 pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag); 670 671 /* keep these in sync */ 672 pdu->size = len; 673 pdu->id = id; 674 675 pdu_push_and_notify(pdu); 676 677 /* Now wakeup anybody waiting in flush for this request */ 678 if (!qemu_co_queue_next(&pdu->complete)) { 679 pdu_free(pdu); 680 } 681 } 682 683 static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) 684 { 685 mode_t ret; 686 687 ret = mode & 0777; 688 if (mode & P9_STAT_MODE_DIR) { 689 ret |= S_IFDIR; 690 } 691 692 if (mode & P9_STAT_MODE_SYMLINK) { 693 ret |= S_IFLNK; 694 } 695 if (mode & P9_STAT_MODE_SOCKET) { 696 ret |= S_IFSOCK; 697 } 698 if (mode & P9_STAT_MODE_NAMED_PIPE) { 699 ret |= S_IFIFO; 700 } 701 if (mode & P9_STAT_MODE_DEVICE) { 702 if (extension->size && extension->data[0] == 'c') { 703 ret |= S_IFCHR; 704 } else { 705 ret |= S_IFBLK; 706 } 707 } 708 709 if (!(ret&~0777)) { 710 ret |= S_IFREG; 711 } 712 713 if (mode & P9_STAT_MODE_SETUID) { 714 ret |= S_ISUID; 715 } 716 if (mode & P9_STAT_MODE_SETGID) { 717 ret |= S_ISGID; 718 } 719 if (mode & P9_STAT_MODE_SETVTX) { 720 ret |= S_ISVTX; 721 } 722 723 return ret; 724 } 725 726 static int donttouch_stat(V9fsStat *stat) 727 { 728 if (stat->type == -1 && 729 stat->dev == -1 && 730 stat->qid.type == -1 && 731 stat->qid.version == -1 && 732 stat->qid.path == -1 && 733 stat->mode == -1 && 734 stat->atime == -1 && 735 stat->mtime == -1 && 736 stat->length == -1 && 737 !stat->name.size && 738 !stat->uid.size && 739 !stat->gid.size && 740 !stat->muid.size && 741 stat->n_uid == -1 && 742 stat->n_gid == -1 && 743 stat->n_muid == -1) { 744 return 1; 745 } 746 747 return 0; 748 } 749 750 static void v9fs_stat_init(V9fsStat *stat) 751 { 752 v9fs_string_init(&stat->name); 753 v9fs_string_init(&stat->uid); 754 v9fs_string_init(&stat->gid); 755 v9fs_string_init(&stat->muid); 756 v9fs_string_init(&stat->extension); 757 } 758 759 static void v9fs_stat_free(V9fsStat *stat) 760 { 761 v9fs_string_free(&stat->name); 762 v9fs_string_free(&stat->uid); 763 v9fs_string_free(&stat->gid); 764 v9fs_string_free(&stat->muid); 765 v9fs_string_free(&stat->extension); 766 } 767 768 static uint32_t stat_to_v9mode(const struct stat *stbuf) 769 { 770 uint32_t mode; 771 772 mode = stbuf->st_mode & 0777; 773 if (S_ISDIR(stbuf->st_mode)) { 774 mode |= P9_STAT_MODE_DIR; 775 } 776 777 if (S_ISLNK(stbuf->st_mode)) { 778 mode |= P9_STAT_MODE_SYMLINK; 779 } 780 781 if (S_ISSOCK(stbuf->st_mode)) { 782 mode |= P9_STAT_MODE_SOCKET; 783 } 784 785 if (S_ISFIFO(stbuf->st_mode)) { 786 mode |= P9_STAT_MODE_NAMED_PIPE; 787 } 788 789 if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode)) { 790 mode |= P9_STAT_MODE_DEVICE; 791 } 792 793 if (stbuf->st_mode & S_ISUID) { 794 mode |= P9_STAT_MODE_SETUID; 795 } 796 797 if (stbuf->st_mode & S_ISGID) { 798 mode |= P9_STAT_MODE_SETGID; 799 } 800 801 if (stbuf->st_mode & S_ISVTX) { 802 mode |= P9_STAT_MODE_SETVTX; 803 } 804 805 return mode; 806 } 807 808 static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name, 809 const struct stat *stbuf, 810 V9fsStat *v9stat) 811 { 812 int err; 813 const char *str; 814 815 memset(v9stat, 0, sizeof(*v9stat)); 816 817 stat_to_qid(stbuf, &v9stat->qid); 818 v9stat->mode = stat_to_v9mode(stbuf); 819 v9stat->atime = stbuf->st_atime; 820 v9stat->mtime = stbuf->st_mtime; 821 v9stat->length = stbuf->st_size; 822 823 v9fs_string_free(&v9stat->uid); 824 v9fs_string_free(&v9stat->gid); 825 v9fs_string_free(&v9stat->muid); 826 827 v9stat->n_uid = stbuf->st_uid; 828 v9stat->n_gid = stbuf->st_gid; 829 v9stat->n_muid = 0; 830 831 v9fs_string_free(&v9stat->extension); 832 833 if (v9stat->mode & P9_STAT_MODE_SYMLINK) { 834 err = v9fs_co_readlink(pdu, name, &v9stat->extension); 835 if (err < 0) { 836 return err; 837 } 838 } else if (v9stat->mode & P9_STAT_MODE_DEVICE) { 839 v9fs_string_sprintf(&v9stat->extension, "%c %u %u", 840 S_ISCHR(stbuf->st_mode) ? 'c' : 'b', 841 major(stbuf->st_rdev), minor(stbuf->st_rdev)); 842 } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) { 843 v9fs_string_sprintf(&v9stat->extension, "%s %lu", 844 "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink); 845 } 846 847 str = strrchr(name->data, '/'); 848 if (str) { 849 str += 1; 850 } else { 851 str = name->data; 852 } 853 854 v9fs_string_sprintf(&v9stat->name, "%s", str); 855 856 v9stat->size = 61 + 857 v9fs_string_size(&v9stat->name) + 858 v9fs_string_size(&v9stat->uid) + 859 v9fs_string_size(&v9stat->gid) + 860 v9fs_string_size(&v9stat->muid) + 861 v9fs_string_size(&v9stat->extension); 862 return 0; 863 } 864 865 #define P9_STATS_MODE 0x00000001ULL 866 #define P9_STATS_NLINK 0x00000002ULL 867 #define P9_STATS_UID 0x00000004ULL 868 #define P9_STATS_GID 0x00000008ULL 869 #define P9_STATS_RDEV 0x00000010ULL 870 #define P9_STATS_ATIME 0x00000020ULL 871 #define P9_STATS_MTIME 0x00000040ULL 872 #define P9_STATS_CTIME 0x00000080ULL 873 #define P9_STATS_INO 0x00000100ULL 874 #define P9_STATS_SIZE 0x00000200ULL 875 #define P9_STATS_BLOCKS 0x00000400ULL 876 877 #define P9_STATS_BTIME 0x00000800ULL 878 #define P9_STATS_GEN 0x00001000ULL 879 #define P9_STATS_DATA_VERSION 0x00002000ULL 880 881 #define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */ 882 #define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */ 883 884 885 static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, 886 V9fsStatDotl *v9lstat) 887 { 888 memset(v9lstat, 0, sizeof(*v9lstat)); 889 890 v9lstat->st_mode = stbuf->st_mode; 891 v9lstat->st_nlink = stbuf->st_nlink; 892 v9lstat->st_uid = stbuf->st_uid; 893 v9lstat->st_gid = stbuf->st_gid; 894 v9lstat->st_rdev = stbuf->st_rdev; 895 v9lstat->st_size = stbuf->st_size; 896 v9lstat->st_blksize = stbuf->st_blksize; 897 v9lstat->st_blocks = stbuf->st_blocks; 898 v9lstat->st_atime_sec = stbuf->st_atime; 899 v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; 900 v9lstat->st_mtime_sec = stbuf->st_mtime; 901 v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; 902 v9lstat->st_ctime_sec = stbuf->st_ctime; 903 v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; 904 /* Currently we only support BASIC fields in stat */ 905 v9lstat->st_result_mask = P9_STATS_BASIC; 906 907 stat_to_qid(stbuf, &v9lstat->qid); 908 } 909 910 static void print_sg(struct iovec *sg, int cnt) 911 { 912 int i; 913 914 printf("sg[%d]: {", cnt); 915 for (i = 0; i < cnt; i++) { 916 if (i) { 917 printf(", "); 918 } 919 printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len); 920 } 921 printf("}\n"); 922 } 923 924 /* Will call this only for path name based fid */ 925 static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len) 926 { 927 V9fsPath str; 928 v9fs_path_init(&str); 929 v9fs_path_copy(&str, dst); 930 v9fs_path_sprintf(dst, "%s%s", src->data, str.data + len); 931 v9fs_path_free(&str); 932 } 933 934 static inline bool is_ro_export(FsContext *ctx) 935 { 936 return ctx->export_flags & V9FS_RDONLY; 937 } 938 939 static void coroutine_fn v9fs_version(void *opaque) 940 { 941 ssize_t err; 942 V9fsPDU *pdu = opaque; 943 V9fsState *s = pdu->s; 944 V9fsString version; 945 size_t offset = 7; 946 947 v9fs_string_init(&version); 948 err = pdu_unmarshal(pdu, offset, "ds", &s->msize, &version); 949 if (err < 0) { 950 offset = err; 951 goto out; 952 } 953 trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data); 954 955 virtfs_reset(pdu); 956 957 if (!strcmp(version.data, "9P2000.u")) { 958 s->proto_version = V9FS_PROTO_2000U; 959 } else if (!strcmp(version.data, "9P2000.L")) { 960 s->proto_version = V9FS_PROTO_2000L; 961 } else { 962 v9fs_string_sprintf(&version, "unknown"); 963 } 964 965 err = pdu_marshal(pdu, offset, "ds", s->msize, &version); 966 if (err < 0) { 967 offset = err; 968 goto out; 969 } 970 offset += err; 971 trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data); 972 out: 973 pdu_complete(pdu, offset); 974 v9fs_string_free(&version); 975 } 976 977 static void coroutine_fn v9fs_attach(void *opaque) 978 { 979 V9fsPDU *pdu = opaque; 980 V9fsState *s = pdu->s; 981 int32_t fid, afid, n_uname; 982 V9fsString uname, aname; 983 V9fsFidState *fidp; 984 size_t offset = 7; 985 V9fsQID qid; 986 ssize_t err; 987 988 v9fs_string_init(&uname); 989 v9fs_string_init(&aname); 990 err = pdu_unmarshal(pdu, offset, "ddssd", &fid, 991 &afid, &uname, &aname, &n_uname); 992 if (err < 0) { 993 goto out_nofid; 994 } 995 trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data); 996 997 fidp = alloc_fid(s, fid); 998 if (fidp == NULL) { 999 err = -EINVAL; 1000 goto out_nofid; 1001 } 1002 fidp->uid = n_uname; 1003 err = v9fs_co_name_to_path(pdu, NULL, "/", &fidp->path); 1004 if (err < 0) { 1005 err = -EINVAL; 1006 clunk_fid(s, fid); 1007 goto out; 1008 } 1009 err = fid_to_qid(pdu, fidp, &qid); 1010 if (err < 0) { 1011 err = -EINVAL; 1012 clunk_fid(s, fid); 1013 goto out; 1014 } 1015 err = pdu_marshal(pdu, offset, "Q", &qid); 1016 if (err < 0) { 1017 clunk_fid(s, fid); 1018 goto out; 1019 } 1020 err += offset; 1021 memcpy(&s->root_qid, &qid, sizeof(qid)); 1022 trace_v9fs_attach_return(pdu->tag, pdu->id, 1023 qid.type, qid.version, qid.path); 1024 /* 1025 * disable migration if we haven't done already. 1026 * attach could get called multiple times for the same export. 1027 */ 1028 if (!s->migration_blocker) { 1029 s->root_fid = fid; 1030 error_setg(&s->migration_blocker, 1031 "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'", 1032 s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag); 1033 migrate_add_blocker(s->migration_blocker); 1034 } 1035 out: 1036 put_fid(pdu, fidp); 1037 out_nofid: 1038 pdu_complete(pdu, err); 1039 v9fs_string_free(&uname); 1040 v9fs_string_free(&aname); 1041 } 1042 1043 static void coroutine_fn v9fs_stat(void *opaque) 1044 { 1045 int32_t fid; 1046 V9fsStat v9stat; 1047 ssize_t err = 0; 1048 size_t offset = 7; 1049 struct stat stbuf; 1050 V9fsFidState *fidp; 1051 V9fsPDU *pdu = opaque; 1052 1053 err = pdu_unmarshal(pdu, offset, "d", &fid); 1054 if (err < 0) { 1055 goto out_nofid; 1056 } 1057 trace_v9fs_stat(pdu->tag, pdu->id, fid); 1058 1059 fidp = get_fid(pdu, fid); 1060 if (fidp == NULL) { 1061 err = -ENOENT; 1062 goto out_nofid; 1063 } 1064 err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 1065 if (err < 0) { 1066 goto out; 1067 } 1068 err = stat_to_v9stat(pdu, &fidp->path, &stbuf, &v9stat); 1069 if (err < 0) { 1070 goto out; 1071 } 1072 err = pdu_marshal(pdu, offset, "wS", 0, &v9stat); 1073 if (err < 0) { 1074 v9fs_stat_free(&v9stat); 1075 goto out; 1076 } 1077 trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode, 1078 v9stat.atime, v9stat.mtime, v9stat.length); 1079 err += offset; 1080 v9fs_stat_free(&v9stat); 1081 out: 1082 put_fid(pdu, fidp); 1083 out_nofid: 1084 pdu_complete(pdu, err); 1085 } 1086 1087 static void coroutine_fn v9fs_getattr(void *opaque) 1088 { 1089 int32_t fid; 1090 size_t offset = 7; 1091 ssize_t retval = 0; 1092 struct stat stbuf; 1093 V9fsFidState *fidp; 1094 uint64_t request_mask; 1095 V9fsStatDotl v9stat_dotl; 1096 V9fsPDU *pdu = opaque; 1097 V9fsState *s = pdu->s; 1098 1099 retval = pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask); 1100 if (retval < 0) { 1101 goto out_nofid; 1102 } 1103 trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask); 1104 1105 fidp = get_fid(pdu, fid); 1106 if (fidp == NULL) { 1107 retval = -ENOENT; 1108 goto out_nofid; 1109 } 1110 /* 1111 * Currently we only support BASIC fields in stat, so there is no 1112 * need to look at request_mask. 1113 */ 1114 retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 1115 if (retval < 0) { 1116 goto out; 1117 } 1118 stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl); 1119 1120 /* fill st_gen if requested and supported by underlying fs */ 1121 if (request_mask & P9_STATS_GEN) { 1122 retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl); 1123 switch (retval) { 1124 case 0: 1125 /* we have valid st_gen: update result mask */ 1126 v9stat_dotl.st_result_mask |= P9_STATS_GEN; 1127 break; 1128 case -EINTR: 1129 /* request cancelled, e.g. by Tflush */ 1130 goto out; 1131 default: 1132 /* failed to get st_gen: not fatal, ignore */ 1133 break; 1134 } 1135 } 1136 retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl); 1137 if (retval < 0) { 1138 goto out; 1139 } 1140 retval += offset; 1141 trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask, 1142 v9stat_dotl.st_mode, v9stat_dotl.st_uid, 1143 v9stat_dotl.st_gid); 1144 out: 1145 put_fid(pdu, fidp); 1146 out_nofid: 1147 pdu_complete(pdu, retval); 1148 } 1149 1150 /* Attribute flags */ 1151 #define P9_ATTR_MODE (1 << 0) 1152 #define P9_ATTR_UID (1 << 1) 1153 #define P9_ATTR_GID (1 << 2) 1154 #define P9_ATTR_SIZE (1 << 3) 1155 #define P9_ATTR_ATIME (1 << 4) 1156 #define P9_ATTR_MTIME (1 << 5) 1157 #define P9_ATTR_CTIME (1 << 6) 1158 #define P9_ATTR_ATIME_SET (1 << 7) 1159 #define P9_ATTR_MTIME_SET (1 << 8) 1160 1161 #define P9_ATTR_MASK 127 1162 1163 static void coroutine_fn v9fs_setattr(void *opaque) 1164 { 1165 int err = 0; 1166 int32_t fid; 1167 V9fsFidState *fidp; 1168 size_t offset = 7; 1169 V9fsIattr v9iattr; 1170 V9fsPDU *pdu = opaque; 1171 1172 err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr); 1173 if (err < 0) { 1174 goto out_nofid; 1175 } 1176 1177 fidp = get_fid(pdu, fid); 1178 if (fidp == NULL) { 1179 err = -EINVAL; 1180 goto out_nofid; 1181 } 1182 if (v9iattr.valid & P9_ATTR_MODE) { 1183 err = v9fs_co_chmod(pdu, &fidp->path, v9iattr.mode); 1184 if (err < 0) { 1185 goto out; 1186 } 1187 } 1188 if (v9iattr.valid & (P9_ATTR_ATIME | P9_ATTR_MTIME)) { 1189 struct timespec times[2]; 1190 if (v9iattr.valid & P9_ATTR_ATIME) { 1191 if (v9iattr.valid & P9_ATTR_ATIME_SET) { 1192 times[0].tv_sec = v9iattr.atime_sec; 1193 times[0].tv_nsec = v9iattr.atime_nsec; 1194 } else { 1195 times[0].tv_nsec = UTIME_NOW; 1196 } 1197 } else { 1198 times[0].tv_nsec = UTIME_OMIT; 1199 } 1200 if (v9iattr.valid & P9_ATTR_MTIME) { 1201 if (v9iattr.valid & P9_ATTR_MTIME_SET) { 1202 times[1].tv_sec = v9iattr.mtime_sec; 1203 times[1].tv_nsec = v9iattr.mtime_nsec; 1204 } else { 1205 times[1].tv_nsec = UTIME_NOW; 1206 } 1207 } else { 1208 times[1].tv_nsec = UTIME_OMIT; 1209 } 1210 err = v9fs_co_utimensat(pdu, &fidp->path, times); 1211 if (err < 0) { 1212 goto out; 1213 } 1214 } 1215 /* 1216 * If the only valid entry in iattr is ctime we can call 1217 * chown(-1,-1) to update the ctime of the file 1218 */ 1219 if ((v9iattr.valid & (P9_ATTR_UID | P9_ATTR_GID)) || 1220 ((v9iattr.valid & P9_ATTR_CTIME) 1221 && !((v9iattr.valid & P9_ATTR_MASK) & ~P9_ATTR_CTIME))) { 1222 if (!(v9iattr.valid & P9_ATTR_UID)) { 1223 v9iattr.uid = -1; 1224 } 1225 if (!(v9iattr.valid & P9_ATTR_GID)) { 1226 v9iattr.gid = -1; 1227 } 1228 err = v9fs_co_chown(pdu, &fidp->path, v9iattr.uid, 1229 v9iattr.gid); 1230 if (err < 0) { 1231 goto out; 1232 } 1233 } 1234 if (v9iattr.valid & (P9_ATTR_SIZE)) { 1235 err = v9fs_co_truncate(pdu, &fidp->path, v9iattr.size); 1236 if (err < 0) { 1237 goto out; 1238 } 1239 } 1240 err = offset; 1241 out: 1242 put_fid(pdu, fidp); 1243 out_nofid: 1244 pdu_complete(pdu, err); 1245 } 1246 1247 static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) 1248 { 1249 int i; 1250 ssize_t err; 1251 size_t offset = 7; 1252 1253 err = pdu_marshal(pdu, offset, "w", nwnames); 1254 if (err < 0) { 1255 return err; 1256 } 1257 offset += err; 1258 for (i = 0; i < nwnames; i++) { 1259 err = pdu_marshal(pdu, offset, "Q", &qids[i]); 1260 if (err < 0) { 1261 return err; 1262 } 1263 offset += err; 1264 } 1265 return offset; 1266 } 1267 1268 static bool name_is_illegal(const char *name) 1269 { 1270 return !*name || strchr(name, '/') != NULL; 1271 } 1272 1273 static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) 1274 { 1275 return 1276 qid1->type != qid2->type || 1277 qid1->version != qid2->version || 1278 qid1->path != qid2->path; 1279 } 1280 1281 static void coroutine_fn v9fs_walk(void *opaque) 1282 { 1283 int name_idx; 1284 V9fsQID *qids = NULL; 1285 int i, err = 0; 1286 V9fsPath dpath, path; 1287 uint16_t nwnames; 1288 struct stat stbuf; 1289 size_t offset = 7; 1290 int32_t fid, newfid; 1291 V9fsString *wnames = NULL; 1292 V9fsFidState *fidp; 1293 V9fsFidState *newfidp = NULL; 1294 V9fsPDU *pdu = opaque; 1295 V9fsState *s = pdu->s; 1296 V9fsQID qid; 1297 1298 err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); 1299 if (err < 0) { 1300 pdu_complete(pdu, err); 1301 return ; 1302 } 1303 offset += err; 1304 1305 trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames); 1306 1307 if (nwnames && nwnames <= P9_MAXWELEM) { 1308 wnames = g_malloc0(sizeof(wnames[0]) * nwnames); 1309 qids = g_malloc0(sizeof(qids[0]) * nwnames); 1310 for (i = 0; i < nwnames; i++) { 1311 err = pdu_unmarshal(pdu, offset, "s", &wnames[i]); 1312 if (err < 0) { 1313 goto out_nofid; 1314 } 1315 if (name_is_illegal(wnames[i].data)) { 1316 err = -ENOENT; 1317 goto out_nofid; 1318 } 1319 offset += err; 1320 } 1321 } else if (nwnames > P9_MAXWELEM) { 1322 err = -EINVAL; 1323 goto out_nofid; 1324 } 1325 fidp = get_fid(pdu, fid); 1326 if (fidp == NULL) { 1327 err = -ENOENT; 1328 goto out_nofid; 1329 } 1330 1331 v9fs_path_init(&dpath); 1332 v9fs_path_init(&path); 1333 1334 err = fid_to_qid(pdu, fidp, &qid); 1335 if (err < 0) { 1336 goto out; 1337 } 1338 1339 /* 1340 * Both dpath and path initially poin to fidp. 1341 * Needed to handle request with nwnames == 0 1342 */ 1343 v9fs_path_copy(&dpath, &fidp->path); 1344 v9fs_path_copy(&path, &fidp->path); 1345 for (name_idx = 0; name_idx < nwnames; name_idx++) { 1346 if (not_same_qid(&pdu->s->root_qid, &qid) || 1347 strcmp("..", wnames[name_idx].data)) { 1348 err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, 1349 &path); 1350 if (err < 0) { 1351 goto out; 1352 } 1353 1354 err = v9fs_co_lstat(pdu, &path, &stbuf); 1355 if (err < 0) { 1356 goto out; 1357 } 1358 stat_to_qid(&stbuf, &qid); 1359 v9fs_path_copy(&dpath, &path); 1360 } 1361 memcpy(&qids[name_idx], &qid, sizeof(qid)); 1362 } 1363 if (fid == newfid) { 1364 BUG_ON(fidp->fid_type != P9_FID_NONE); 1365 v9fs_path_copy(&fidp->path, &path); 1366 } else { 1367 newfidp = alloc_fid(s, newfid); 1368 if (newfidp == NULL) { 1369 err = -EINVAL; 1370 goto out; 1371 } 1372 newfidp->uid = fidp->uid; 1373 v9fs_path_copy(&newfidp->path, &path); 1374 } 1375 err = v9fs_walk_marshal(pdu, nwnames, qids); 1376 trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids); 1377 out: 1378 put_fid(pdu, fidp); 1379 if (newfidp) { 1380 put_fid(pdu, newfidp); 1381 } 1382 v9fs_path_free(&dpath); 1383 v9fs_path_free(&path); 1384 out_nofid: 1385 pdu_complete(pdu, err); 1386 if (nwnames && nwnames <= P9_MAXWELEM) { 1387 for (name_idx = 0; name_idx < nwnames; name_idx++) { 1388 v9fs_string_free(&wnames[name_idx]); 1389 } 1390 g_free(wnames); 1391 g_free(qids); 1392 } 1393 } 1394 1395 static int32_t coroutine_fn get_iounit(V9fsPDU *pdu, V9fsPath *path) 1396 { 1397 struct statfs stbuf; 1398 int32_t iounit = 0; 1399 V9fsState *s = pdu->s; 1400 1401 /* 1402 * iounit should be multiples of f_bsize (host filesystem block size 1403 * and as well as less than (client msize - P9_IOHDRSZ)) 1404 */ 1405 if (!v9fs_co_statfs(pdu, path, &stbuf)) { 1406 iounit = stbuf.f_bsize; 1407 iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize; 1408 } 1409 if (!iounit) { 1410 iounit = s->msize - P9_IOHDRSZ; 1411 } 1412 return iounit; 1413 } 1414 1415 static void coroutine_fn v9fs_open(void *opaque) 1416 { 1417 int flags; 1418 int32_t fid; 1419 int32_t mode; 1420 V9fsQID qid; 1421 int iounit = 0; 1422 ssize_t err = 0; 1423 size_t offset = 7; 1424 struct stat stbuf; 1425 V9fsFidState *fidp; 1426 V9fsPDU *pdu = opaque; 1427 V9fsState *s = pdu->s; 1428 1429 if (s->proto_version == V9FS_PROTO_2000L) { 1430 err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode); 1431 } else { 1432 uint8_t modebyte; 1433 err = pdu_unmarshal(pdu, offset, "db", &fid, &modebyte); 1434 mode = modebyte; 1435 } 1436 if (err < 0) { 1437 goto out_nofid; 1438 } 1439 trace_v9fs_open(pdu->tag, pdu->id, fid, mode); 1440 1441 fidp = get_fid(pdu, fid); 1442 if (fidp == NULL) { 1443 err = -ENOENT; 1444 goto out_nofid; 1445 } 1446 BUG_ON(fidp->fid_type != P9_FID_NONE); 1447 1448 err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 1449 if (err < 0) { 1450 goto out; 1451 } 1452 stat_to_qid(&stbuf, &qid); 1453 if (S_ISDIR(stbuf.st_mode)) { 1454 err = v9fs_co_opendir(pdu, fidp); 1455 if (err < 0) { 1456 goto out; 1457 } 1458 fidp->fid_type = P9_FID_DIR; 1459 err = pdu_marshal(pdu, offset, "Qd", &qid, 0); 1460 if (err < 0) { 1461 goto out; 1462 } 1463 err += offset; 1464 } else { 1465 if (s->proto_version == V9FS_PROTO_2000L) { 1466 flags = get_dotl_openflags(s, mode); 1467 } else { 1468 flags = omode_to_uflags(mode); 1469 } 1470 if (is_ro_export(&s->ctx)) { 1471 if (mode & O_WRONLY || mode & O_RDWR || 1472 mode & O_APPEND || mode & O_TRUNC) { 1473 err = -EROFS; 1474 goto out; 1475 } 1476 } 1477 err = v9fs_co_open(pdu, fidp, flags); 1478 if (err < 0) { 1479 goto out; 1480 } 1481 fidp->fid_type = P9_FID_FILE; 1482 fidp->open_flags = flags; 1483 if (flags & O_EXCL) { 1484 /* 1485 * We let the host file system do O_EXCL check 1486 * We should not reclaim such fd 1487 */ 1488 fidp->flags |= FID_NON_RECLAIMABLE; 1489 } 1490 iounit = get_iounit(pdu, &fidp->path); 1491 err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); 1492 if (err < 0) { 1493 goto out; 1494 } 1495 err += offset; 1496 } 1497 trace_v9fs_open_return(pdu->tag, pdu->id, 1498 qid.type, qid.version, qid.path, iounit); 1499 out: 1500 put_fid(pdu, fidp); 1501 out_nofid: 1502 pdu_complete(pdu, err); 1503 } 1504 1505 static void coroutine_fn v9fs_lcreate(void *opaque) 1506 { 1507 int32_t dfid, flags, mode; 1508 gid_t gid; 1509 ssize_t err = 0; 1510 ssize_t offset = 7; 1511 V9fsString name; 1512 V9fsFidState *fidp; 1513 struct stat stbuf; 1514 V9fsQID qid; 1515 int32_t iounit; 1516 V9fsPDU *pdu = opaque; 1517 1518 v9fs_string_init(&name); 1519 err = pdu_unmarshal(pdu, offset, "dsddd", &dfid, 1520 &name, &flags, &mode, &gid); 1521 if (err < 0) { 1522 goto out_nofid; 1523 } 1524 trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid); 1525 1526 if (name_is_illegal(name.data)) { 1527 err = -ENOENT; 1528 goto out_nofid; 1529 } 1530 1531 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 1532 err = -EEXIST; 1533 goto out_nofid; 1534 } 1535 1536 fidp = get_fid(pdu, dfid); 1537 if (fidp == NULL) { 1538 err = -ENOENT; 1539 goto out_nofid; 1540 } 1541 1542 flags = get_dotl_openflags(pdu->s, flags); 1543 err = v9fs_co_open2(pdu, fidp, &name, gid, 1544 flags | O_CREAT, mode, &stbuf); 1545 if (err < 0) { 1546 goto out; 1547 } 1548 fidp->fid_type = P9_FID_FILE; 1549 fidp->open_flags = flags; 1550 if (flags & O_EXCL) { 1551 /* 1552 * We let the host file system do O_EXCL check 1553 * We should not reclaim such fd 1554 */ 1555 fidp->flags |= FID_NON_RECLAIMABLE; 1556 } 1557 iounit = get_iounit(pdu, &fidp->path); 1558 stat_to_qid(&stbuf, &qid); 1559 err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); 1560 if (err < 0) { 1561 goto out; 1562 } 1563 err += offset; 1564 trace_v9fs_lcreate_return(pdu->tag, pdu->id, 1565 qid.type, qid.version, qid.path, iounit); 1566 out: 1567 put_fid(pdu, fidp); 1568 out_nofid: 1569 pdu_complete(pdu, err); 1570 v9fs_string_free(&name); 1571 } 1572 1573 static void v9fs_fsync(void *opaque) 1574 { 1575 int err; 1576 int32_t fid; 1577 int datasync; 1578 size_t offset = 7; 1579 V9fsFidState *fidp; 1580 V9fsPDU *pdu = opaque; 1581 1582 err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync); 1583 if (err < 0) { 1584 goto out_nofid; 1585 } 1586 trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync); 1587 1588 fidp = get_fid(pdu, fid); 1589 if (fidp == NULL) { 1590 err = -ENOENT; 1591 goto out_nofid; 1592 } 1593 err = v9fs_co_fsync(pdu, fidp, datasync); 1594 if (!err) { 1595 err = offset; 1596 } 1597 put_fid(pdu, fidp); 1598 out_nofid: 1599 pdu_complete(pdu, err); 1600 } 1601 1602 static void coroutine_fn v9fs_clunk(void *opaque) 1603 { 1604 int err; 1605 int32_t fid; 1606 size_t offset = 7; 1607 V9fsFidState *fidp; 1608 V9fsPDU *pdu = opaque; 1609 V9fsState *s = pdu->s; 1610 1611 err = pdu_unmarshal(pdu, offset, "d", &fid); 1612 if (err < 0) { 1613 goto out_nofid; 1614 } 1615 trace_v9fs_clunk(pdu->tag, pdu->id, fid); 1616 1617 fidp = clunk_fid(s, fid); 1618 if (fidp == NULL) { 1619 err = -ENOENT; 1620 goto out_nofid; 1621 } 1622 /* 1623 * Bump the ref so that put_fid will 1624 * free the fid. 1625 */ 1626 fidp->ref++; 1627 err = put_fid(pdu, fidp); 1628 if (!err) { 1629 err = offset; 1630 } 1631 out_nofid: 1632 pdu_complete(pdu, err); 1633 } 1634 1635 static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, 1636 uint64_t off, uint32_t max_count) 1637 { 1638 ssize_t err; 1639 size_t offset = 7; 1640 int read_count; 1641 int64_t xattr_len; 1642 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); 1643 VirtQueueElement *elem = v->elems[pdu->idx]; 1644 1645 xattr_len = fidp->fs.xattr.len; 1646 read_count = xattr_len - off; 1647 if (read_count > max_count) { 1648 read_count = max_count; 1649 } else if (read_count < 0) { 1650 /* 1651 * read beyond XATTR value 1652 */ 1653 read_count = 0; 1654 } 1655 err = pdu_marshal(pdu, offset, "d", read_count); 1656 if (err < 0) { 1657 return err; 1658 } 1659 offset += err; 1660 1661 err = v9fs_pack(elem->in_sg, elem->in_num, offset, 1662 ((char *)fidp->fs.xattr.value) + off, 1663 read_count); 1664 if (err < 0) { 1665 return err; 1666 } 1667 offset += err; 1668 return offset; 1669 } 1670 1671 static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu, 1672 V9fsFidState *fidp, 1673 uint32_t max_count) 1674 { 1675 V9fsPath path; 1676 V9fsStat v9stat; 1677 int len, err = 0; 1678 int32_t count = 0; 1679 struct stat stbuf; 1680 off_t saved_dir_pos; 1681 struct dirent *dent; 1682 1683 /* save the directory position */ 1684 saved_dir_pos = v9fs_co_telldir(pdu, fidp); 1685 if (saved_dir_pos < 0) { 1686 return saved_dir_pos; 1687 } 1688 1689 while (1) { 1690 v9fs_path_init(&path); 1691 1692 v9fs_readdir_lock(&fidp->fs.dir); 1693 1694 err = v9fs_co_readdir(pdu, fidp, &dent); 1695 if (err || !dent) { 1696 break; 1697 } 1698 err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path); 1699 if (err < 0) { 1700 break; 1701 } 1702 err = v9fs_co_lstat(pdu, &path, &stbuf); 1703 if (err < 0) { 1704 break; 1705 } 1706 err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat); 1707 if (err < 0) { 1708 break; 1709 } 1710 /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ 1711 len = pdu_marshal(pdu, 11 + count, "S", &v9stat); 1712 1713 v9fs_readdir_unlock(&fidp->fs.dir); 1714 1715 if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) { 1716 /* Ran out of buffer. Set dir back to old position and return */ 1717 v9fs_co_seekdir(pdu, fidp, saved_dir_pos); 1718 v9fs_stat_free(&v9stat); 1719 v9fs_path_free(&path); 1720 return count; 1721 } 1722 count += len; 1723 v9fs_stat_free(&v9stat); 1724 v9fs_path_free(&path); 1725 saved_dir_pos = dent->d_off; 1726 } 1727 1728 v9fs_readdir_unlock(&fidp->fs.dir); 1729 1730 v9fs_path_free(&path); 1731 if (err < 0) { 1732 return err; 1733 } 1734 return count; 1735 } 1736 1737 /* 1738 * Create a QEMUIOVector for a sub-region of PDU iovecs 1739 * 1740 * @qiov: uninitialized QEMUIOVector 1741 * @skip: number of bytes to skip from beginning of PDU 1742 * @size: number of bytes to include 1743 * @is_write: true - write, false - read 1744 * 1745 * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up 1746 * with qemu_iovec_destroy(). 1747 */ 1748 static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, 1749 size_t skip, size_t size, 1750 bool is_write) 1751 { 1752 QEMUIOVector elem; 1753 struct iovec *iov; 1754 unsigned int niov; 1755 1756 virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write); 1757 1758 qemu_iovec_init_external(&elem, iov, niov); 1759 qemu_iovec_init(qiov, niov); 1760 qemu_iovec_concat(qiov, &elem, skip, size); 1761 } 1762 1763 static void coroutine_fn v9fs_read(void *opaque) 1764 { 1765 int32_t fid; 1766 uint64_t off; 1767 ssize_t err = 0; 1768 int32_t count = 0; 1769 size_t offset = 7; 1770 uint32_t max_count; 1771 V9fsFidState *fidp; 1772 V9fsPDU *pdu = opaque; 1773 V9fsState *s = pdu->s; 1774 1775 err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count); 1776 if (err < 0) { 1777 goto out_nofid; 1778 } 1779 trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count); 1780 1781 fidp = get_fid(pdu, fid); 1782 if (fidp == NULL) { 1783 err = -EINVAL; 1784 goto out_nofid; 1785 } 1786 if (fidp->fid_type == P9_FID_DIR) { 1787 1788 if (off == 0) { 1789 v9fs_co_rewinddir(pdu, fidp); 1790 } 1791 count = v9fs_do_readdir_with_stat(pdu, fidp, max_count); 1792 if (count < 0) { 1793 err = count; 1794 goto out; 1795 } 1796 err = pdu_marshal(pdu, offset, "d", count); 1797 if (err < 0) { 1798 goto out; 1799 } 1800 err += offset + count; 1801 } else if (fidp->fid_type == P9_FID_FILE) { 1802 QEMUIOVector qiov_full; 1803 QEMUIOVector qiov; 1804 int32_t len; 1805 1806 v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false); 1807 qemu_iovec_init(&qiov, qiov_full.niov); 1808 do { 1809 qemu_iovec_reset(&qiov); 1810 qemu_iovec_concat(&qiov, &qiov_full, count, qiov_full.size - count); 1811 if (0) { 1812 print_sg(qiov.iov, qiov.niov); 1813 } 1814 /* Loop in case of EINTR */ 1815 do { 1816 len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off); 1817 if (len >= 0) { 1818 off += len; 1819 count += len; 1820 } 1821 } while (len == -EINTR && !pdu->cancelled); 1822 if (len < 0) { 1823 /* IO error return the error */ 1824 err = len; 1825 goto out_free_iovec; 1826 } 1827 } while (count < max_count && len > 0); 1828 err = pdu_marshal(pdu, offset, "d", count); 1829 if (err < 0) { 1830 goto out_free_iovec; 1831 } 1832 err += offset + count; 1833 out_free_iovec: 1834 qemu_iovec_destroy(&qiov); 1835 qemu_iovec_destroy(&qiov_full); 1836 } else if (fidp->fid_type == P9_FID_XATTR) { 1837 err = v9fs_xattr_read(s, pdu, fidp, off, max_count); 1838 } else { 1839 err = -EINVAL; 1840 } 1841 trace_v9fs_read_return(pdu->tag, pdu->id, count, err); 1842 out: 1843 put_fid(pdu, fidp); 1844 out_nofid: 1845 pdu_complete(pdu, err); 1846 } 1847 1848 static size_t v9fs_readdir_data_size(V9fsString *name) 1849 { 1850 /* 1851 * Size of each dirent on the wire: size of qid (13) + size of offset (8) 1852 * size of type (1) + size of name.size (2) + strlen(name.data) 1853 */ 1854 return 24 + v9fs_string_size(name); 1855 } 1856 1857 static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, 1858 int32_t max_count) 1859 { 1860 size_t size; 1861 V9fsQID qid; 1862 V9fsString name; 1863 int len, err = 0; 1864 int32_t count = 0; 1865 off_t saved_dir_pos; 1866 struct dirent *dent; 1867 1868 /* save the directory position */ 1869 saved_dir_pos = v9fs_co_telldir(pdu, fidp); 1870 if (saved_dir_pos < 0) { 1871 return saved_dir_pos; 1872 } 1873 1874 while (1) { 1875 v9fs_readdir_lock(&fidp->fs.dir); 1876 1877 err = v9fs_co_readdir(pdu, fidp, &dent); 1878 if (err || !dent) { 1879 break; 1880 } 1881 v9fs_string_init(&name); 1882 v9fs_string_sprintf(&name, "%s", dent->d_name); 1883 if ((count + v9fs_readdir_data_size(&name)) > max_count) { 1884 v9fs_readdir_unlock(&fidp->fs.dir); 1885 1886 /* Ran out of buffer. Set dir back to old position and return */ 1887 v9fs_co_seekdir(pdu, fidp, saved_dir_pos); 1888 v9fs_string_free(&name); 1889 return count; 1890 } 1891 /* 1892 * Fill up just the path field of qid because the client uses 1893 * only that. To fill the entire qid structure we will have 1894 * to stat each dirent found, which is expensive 1895 */ 1896 size = MIN(sizeof(dent->d_ino), sizeof(qid.path)); 1897 memcpy(&qid.path, &dent->d_ino, size); 1898 /* Fill the other fields with dummy values */ 1899 qid.type = 0; 1900 qid.version = 0; 1901 1902 /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ 1903 len = pdu_marshal(pdu, 11 + count, "Qqbs", 1904 &qid, dent->d_off, 1905 dent->d_type, &name); 1906 1907 v9fs_readdir_unlock(&fidp->fs.dir); 1908 1909 if (len < 0) { 1910 v9fs_co_seekdir(pdu, fidp, saved_dir_pos); 1911 v9fs_string_free(&name); 1912 return len; 1913 } 1914 count += len; 1915 v9fs_string_free(&name); 1916 saved_dir_pos = dent->d_off; 1917 } 1918 1919 v9fs_readdir_unlock(&fidp->fs.dir); 1920 1921 if (err < 0) { 1922 return err; 1923 } 1924 return count; 1925 } 1926 1927 static void coroutine_fn v9fs_readdir(void *opaque) 1928 { 1929 int32_t fid; 1930 V9fsFidState *fidp; 1931 ssize_t retval = 0; 1932 size_t offset = 7; 1933 uint64_t initial_offset; 1934 int32_t count; 1935 uint32_t max_count; 1936 V9fsPDU *pdu = opaque; 1937 1938 retval = pdu_unmarshal(pdu, offset, "dqd", &fid, 1939 &initial_offset, &max_count); 1940 if (retval < 0) { 1941 goto out_nofid; 1942 } 1943 trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count); 1944 1945 fidp = get_fid(pdu, fid); 1946 if (fidp == NULL) { 1947 retval = -EINVAL; 1948 goto out_nofid; 1949 } 1950 if (!fidp->fs.dir.stream) { 1951 retval = -EINVAL; 1952 goto out; 1953 } 1954 if (initial_offset == 0) { 1955 v9fs_co_rewinddir(pdu, fidp); 1956 } else { 1957 v9fs_co_seekdir(pdu, fidp, initial_offset); 1958 } 1959 count = v9fs_do_readdir(pdu, fidp, max_count); 1960 if (count < 0) { 1961 retval = count; 1962 goto out; 1963 } 1964 retval = pdu_marshal(pdu, offset, "d", count); 1965 if (retval < 0) { 1966 goto out; 1967 } 1968 retval += count + offset; 1969 trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); 1970 out: 1971 put_fid(pdu, fidp); 1972 out_nofid: 1973 pdu_complete(pdu, retval); 1974 } 1975 1976 static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, 1977 uint64_t off, uint32_t count, 1978 struct iovec *sg, int cnt) 1979 { 1980 int i, to_copy; 1981 ssize_t err = 0; 1982 int write_count; 1983 int64_t xattr_len; 1984 size_t offset = 7; 1985 1986 1987 xattr_len = fidp->fs.xattr.len; 1988 write_count = xattr_len - off; 1989 if (write_count > count) { 1990 write_count = count; 1991 } else if (write_count < 0) { 1992 /* 1993 * write beyond XATTR value len specified in 1994 * xattrcreate 1995 */ 1996 err = -ENOSPC; 1997 goto out; 1998 } 1999 err = pdu_marshal(pdu, offset, "d", write_count); 2000 if (err < 0) { 2001 return err; 2002 } 2003 err += offset; 2004 fidp->fs.xattr.copied_len += write_count; 2005 /* 2006 * Now copy the content from sg list 2007 */ 2008 for (i = 0; i < cnt; i++) { 2009 if (write_count > sg[i].iov_len) { 2010 to_copy = sg[i].iov_len; 2011 } else { 2012 to_copy = write_count; 2013 } 2014 memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy); 2015 /* updating vs->off since we are not using below */ 2016 off += to_copy; 2017 write_count -= to_copy; 2018 } 2019 out: 2020 return err; 2021 } 2022 2023 static void coroutine_fn v9fs_write(void *opaque) 2024 { 2025 ssize_t err; 2026 int32_t fid; 2027 uint64_t off; 2028 uint32_t count; 2029 int32_t len = 0; 2030 int32_t total = 0; 2031 size_t offset = 7; 2032 V9fsFidState *fidp; 2033 V9fsPDU *pdu = opaque; 2034 V9fsState *s = pdu->s; 2035 QEMUIOVector qiov_full; 2036 QEMUIOVector qiov; 2037 2038 err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count); 2039 if (err < 0) { 2040 pdu_complete(pdu, err); 2041 return; 2042 } 2043 offset += err; 2044 v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true); 2045 trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov); 2046 2047 fidp = get_fid(pdu, fid); 2048 if (fidp == NULL) { 2049 err = -EINVAL; 2050 goto out_nofid; 2051 } 2052 if (fidp->fid_type == P9_FID_FILE) { 2053 if (fidp->fs.fd == -1) { 2054 err = -EINVAL; 2055 goto out; 2056 } 2057 } else if (fidp->fid_type == P9_FID_XATTR) { 2058 /* 2059 * setxattr operation 2060 */ 2061 err = v9fs_xattr_write(s, pdu, fidp, off, count, 2062 qiov_full.iov, qiov_full.niov); 2063 goto out; 2064 } else { 2065 err = -EINVAL; 2066 goto out; 2067 } 2068 qemu_iovec_init(&qiov, qiov_full.niov); 2069 do { 2070 qemu_iovec_reset(&qiov); 2071 qemu_iovec_concat(&qiov, &qiov_full, total, qiov_full.size - total); 2072 if (0) { 2073 print_sg(qiov.iov, qiov.niov); 2074 } 2075 /* Loop in case of EINTR */ 2076 do { 2077 len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off); 2078 if (len >= 0) { 2079 off += len; 2080 total += len; 2081 } 2082 } while (len == -EINTR && !pdu->cancelled); 2083 if (len < 0) { 2084 /* IO error return the error */ 2085 err = len; 2086 goto out_qiov; 2087 } 2088 } while (total < count && len > 0); 2089 2090 offset = 7; 2091 err = pdu_marshal(pdu, offset, "d", total); 2092 if (err < 0) { 2093 goto out_qiov; 2094 } 2095 err += offset; 2096 trace_v9fs_write_return(pdu->tag, pdu->id, total, err); 2097 out_qiov: 2098 qemu_iovec_destroy(&qiov); 2099 out: 2100 put_fid(pdu, fidp); 2101 out_nofid: 2102 qemu_iovec_destroy(&qiov_full); 2103 pdu_complete(pdu, err); 2104 } 2105 2106 static void coroutine_fn v9fs_create(void *opaque) 2107 { 2108 int32_t fid; 2109 int err = 0; 2110 size_t offset = 7; 2111 V9fsFidState *fidp; 2112 V9fsQID qid; 2113 int32_t perm; 2114 int8_t mode; 2115 V9fsPath path; 2116 struct stat stbuf; 2117 V9fsString name; 2118 V9fsString extension; 2119 int iounit; 2120 V9fsPDU *pdu = opaque; 2121 2122 v9fs_path_init(&path); 2123 v9fs_string_init(&name); 2124 v9fs_string_init(&extension); 2125 err = pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name, 2126 &perm, &mode, &extension); 2127 if (err < 0) { 2128 goto out_nofid; 2129 } 2130 trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode); 2131 2132 if (name_is_illegal(name.data)) { 2133 err = -ENOENT; 2134 goto out_nofid; 2135 } 2136 2137 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 2138 err = -EEXIST; 2139 goto out_nofid; 2140 } 2141 2142 fidp = get_fid(pdu, fid); 2143 if (fidp == NULL) { 2144 err = -EINVAL; 2145 goto out_nofid; 2146 } 2147 if (perm & P9_STAT_MODE_DIR) { 2148 err = v9fs_co_mkdir(pdu, fidp, &name, perm & 0777, 2149 fidp->uid, -1, &stbuf); 2150 if (err < 0) { 2151 goto out; 2152 } 2153 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2154 if (err < 0) { 2155 goto out; 2156 } 2157 v9fs_path_copy(&fidp->path, &path); 2158 err = v9fs_co_opendir(pdu, fidp); 2159 if (err < 0) { 2160 goto out; 2161 } 2162 fidp->fid_type = P9_FID_DIR; 2163 } else if (perm & P9_STAT_MODE_SYMLINK) { 2164 err = v9fs_co_symlink(pdu, fidp, &name, 2165 extension.data, -1 , &stbuf); 2166 if (err < 0) { 2167 goto out; 2168 } 2169 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2170 if (err < 0) { 2171 goto out; 2172 } 2173 v9fs_path_copy(&fidp->path, &path); 2174 } else if (perm & P9_STAT_MODE_LINK) { 2175 int32_t ofid = atoi(extension.data); 2176 V9fsFidState *ofidp = get_fid(pdu, ofid); 2177 if (ofidp == NULL) { 2178 err = -EINVAL; 2179 goto out; 2180 } 2181 err = v9fs_co_link(pdu, ofidp, fidp, &name); 2182 put_fid(pdu, ofidp); 2183 if (err < 0) { 2184 goto out; 2185 } 2186 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2187 if (err < 0) { 2188 fidp->fid_type = P9_FID_NONE; 2189 goto out; 2190 } 2191 v9fs_path_copy(&fidp->path, &path); 2192 err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 2193 if (err < 0) { 2194 fidp->fid_type = P9_FID_NONE; 2195 goto out; 2196 } 2197 } else if (perm & P9_STAT_MODE_DEVICE) { 2198 char ctype; 2199 uint32_t major, minor; 2200 mode_t nmode = 0; 2201 2202 if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) { 2203 err = -errno; 2204 goto out; 2205 } 2206 2207 switch (ctype) { 2208 case 'c': 2209 nmode = S_IFCHR; 2210 break; 2211 case 'b': 2212 nmode = S_IFBLK; 2213 break; 2214 default: 2215 err = -EIO; 2216 goto out; 2217 } 2218 2219 nmode |= perm & 0777; 2220 err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, 2221 makedev(major, minor), nmode, &stbuf); 2222 if (err < 0) { 2223 goto out; 2224 } 2225 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2226 if (err < 0) { 2227 goto out; 2228 } 2229 v9fs_path_copy(&fidp->path, &path); 2230 } else if (perm & P9_STAT_MODE_NAMED_PIPE) { 2231 err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, 2232 0, S_IFIFO | (perm & 0777), &stbuf); 2233 if (err < 0) { 2234 goto out; 2235 } 2236 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2237 if (err < 0) { 2238 goto out; 2239 } 2240 v9fs_path_copy(&fidp->path, &path); 2241 } else if (perm & P9_STAT_MODE_SOCKET) { 2242 err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, 2243 0, S_IFSOCK | (perm & 0777), &stbuf); 2244 if (err < 0) { 2245 goto out; 2246 } 2247 err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path); 2248 if (err < 0) { 2249 goto out; 2250 } 2251 v9fs_path_copy(&fidp->path, &path); 2252 } else { 2253 err = v9fs_co_open2(pdu, fidp, &name, -1, 2254 omode_to_uflags(mode)|O_CREAT, perm, &stbuf); 2255 if (err < 0) { 2256 goto out; 2257 } 2258 fidp->fid_type = P9_FID_FILE; 2259 fidp->open_flags = omode_to_uflags(mode); 2260 if (fidp->open_flags & O_EXCL) { 2261 /* 2262 * We let the host file system do O_EXCL check 2263 * We should not reclaim such fd 2264 */ 2265 fidp->flags |= FID_NON_RECLAIMABLE; 2266 } 2267 } 2268 iounit = get_iounit(pdu, &fidp->path); 2269 stat_to_qid(&stbuf, &qid); 2270 err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); 2271 if (err < 0) { 2272 goto out; 2273 } 2274 err += offset; 2275 trace_v9fs_create_return(pdu->tag, pdu->id, 2276 qid.type, qid.version, qid.path, iounit); 2277 out: 2278 put_fid(pdu, fidp); 2279 out_nofid: 2280 pdu_complete(pdu, err); 2281 v9fs_string_free(&name); 2282 v9fs_string_free(&extension); 2283 v9fs_path_free(&path); 2284 } 2285 2286 static void coroutine_fn v9fs_symlink(void *opaque) 2287 { 2288 V9fsPDU *pdu = opaque; 2289 V9fsString name; 2290 V9fsString symname; 2291 V9fsFidState *dfidp; 2292 V9fsQID qid; 2293 struct stat stbuf; 2294 int32_t dfid; 2295 int err = 0; 2296 gid_t gid; 2297 size_t offset = 7; 2298 2299 v9fs_string_init(&name); 2300 v9fs_string_init(&symname); 2301 err = pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid); 2302 if (err < 0) { 2303 goto out_nofid; 2304 } 2305 trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid); 2306 2307 if (name_is_illegal(name.data)) { 2308 err = -ENOENT; 2309 goto out_nofid; 2310 } 2311 2312 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 2313 err = -EEXIST; 2314 goto out_nofid; 2315 } 2316 2317 dfidp = get_fid(pdu, dfid); 2318 if (dfidp == NULL) { 2319 err = -EINVAL; 2320 goto out_nofid; 2321 } 2322 err = v9fs_co_symlink(pdu, dfidp, &name, symname.data, gid, &stbuf); 2323 if (err < 0) { 2324 goto out; 2325 } 2326 stat_to_qid(&stbuf, &qid); 2327 err = pdu_marshal(pdu, offset, "Q", &qid); 2328 if (err < 0) { 2329 goto out; 2330 } 2331 err += offset; 2332 trace_v9fs_symlink_return(pdu->tag, pdu->id, 2333 qid.type, qid.version, qid.path); 2334 out: 2335 put_fid(pdu, dfidp); 2336 out_nofid: 2337 pdu_complete(pdu, err); 2338 v9fs_string_free(&name); 2339 v9fs_string_free(&symname); 2340 } 2341 2342 static void v9fs_flush(void *opaque) 2343 { 2344 ssize_t err; 2345 int16_t tag; 2346 size_t offset = 7; 2347 V9fsPDU *cancel_pdu; 2348 V9fsPDU *pdu = opaque; 2349 V9fsState *s = pdu->s; 2350 2351 err = pdu_unmarshal(pdu, offset, "w", &tag); 2352 if (err < 0) { 2353 pdu_complete(pdu, err); 2354 return; 2355 } 2356 trace_v9fs_flush(pdu->tag, pdu->id, tag); 2357 2358 QLIST_FOREACH(cancel_pdu, &s->active_list, next) { 2359 if (cancel_pdu->tag == tag) { 2360 break; 2361 } 2362 } 2363 if (cancel_pdu) { 2364 cancel_pdu->cancelled = 1; 2365 /* 2366 * Wait for pdu to complete. 2367 */ 2368 qemu_co_queue_wait(&cancel_pdu->complete); 2369 cancel_pdu->cancelled = 0; 2370 pdu_free(cancel_pdu); 2371 } 2372 pdu_complete(pdu, 7); 2373 } 2374 2375 static void coroutine_fn v9fs_link(void *opaque) 2376 { 2377 V9fsPDU *pdu = opaque; 2378 int32_t dfid, oldfid; 2379 V9fsFidState *dfidp, *oldfidp; 2380 V9fsString name; 2381 size_t offset = 7; 2382 int err = 0; 2383 2384 v9fs_string_init(&name); 2385 err = pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name); 2386 if (err < 0) { 2387 goto out_nofid; 2388 } 2389 trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data); 2390 2391 if (name_is_illegal(name.data)) { 2392 err = -ENOENT; 2393 goto out_nofid; 2394 } 2395 2396 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 2397 err = -EEXIST; 2398 goto out_nofid; 2399 } 2400 2401 dfidp = get_fid(pdu, dfid); 2402 if (dfidp == NULL) { 2403 err = -ENOENT; 2404 goto out_nofid; 2405 } 2406 2407 oldfidp = get_fid(pdu, oldfid); 2408 if (oldfidp == NULL) { 2409 err = -ENOENT; 2410 goto out; 2411 } 2412 err = v9fs_co_link(pdu, oldfidp, dfidp, &name); 2413 if (!err) { 2414 err = offset; 2415 } 2416 put_fid(pdu, oldfidp); 2417 out: 2418 put_fid(pdu, dfidp); 2419 out_nofid: 2420 v9fs_string_free(&name); 2421 pdu_complete(pdu, err); 2422 } 2423 2424 /* Only works with path name based fid */ 2425 static void coroutine_fn v9fs_remove(void *opaque) 2426 { 2427 int32_t fid; 2428 int err = 0; 2429 size_t offset = 7; 2430 V9fsFidState *fidp; 2431 V9fsPDU *pdu = opaque; 2432 2433 err = pdu_unmarshal(pdu, offset, "d", &fid); 2434 if (err < 0) { 2435 goto out_nofid; 2436 } 2437 trace_v9fs_remove(pdu->tag, pdu->id, fid); 2438 2439 fidp = get_fid(pdu, fid); 2440 if (fidp == NULL) { 2441 err = -EINVAL; 2442 goto out_nofid; 2443 } 2444 /* if fs driver is not path based, return EOPNOTSUPP */ 2445 if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) { 2446 err = -EOPNOTSUPP; 2447 goto out_err; 2448 } 2449 /* 2450 * IF the file is unlinked, we cannot reopen 2451 * the file later. So don't reclaim fd 2452 */ 2453 err = v9fs_mark_fids_unreclaim(pdu, &fidp->path); 2454 if (err < 0) { 2455 goto out_err; 2456 } 2457 err = v9fs_co_remove(pdu, &fidp->path); 2458 if (!err) { 2459 err = offset; 2460 } 2461 out_err: 2462 /* For TREMOVE we need to clunk the fid even on failed remove */ 2463 clunk_fid(pdu->s, fidp->fid); 2464 put_fid(pdu, fidp); 2465 out_nofid: 2466 pdu_complete(pdu, err); 2467 } 2468 2469 static void coroutine_fn v9fs_unlinkat(void *opaque) 2470 { 2471 int err = 0; 2472 V9fsString name; 2473 int32_t dfid, flags; 2474 size_t offset = 7; 2475 V9fsPath path; 2476 V9fsFidState *dfidp; 2477 V9fsPDU *pdu = opaque; 2478 2479 v9fs_string_init(&name); 2480 err = pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags); 2481 if (err < 0) { 2482 goto out_nofid; 2483 } 2484 2485 if (name_is_illegal(name.data)) { 2486 err = -ENOENT; 2487 goto out_nofid; 2488 } 2489 2490 if (!strcmp(".", name.data)) { 2491 err = -EINVAL; 2492 goto out_nofid; 2493 } 2494 2495 if (!strcmp("..", name.data)) { 2496 err = -ENOTEMPTY; 2497 goto out_nofid; 2498 } 2499 2500 dfidp = get_fid(pdu, dfid); 2501 if (dfidp == NULL) { 2502 err = -EINVAL; 2503 goto out_nofid; 2504 } 2505 /* 2506 * IF the file is unlinked, we cannot reopen 2507 * the file later. So don't reclaim fd 2508 */ 2509 v9fs_path_init(&path); 2510 err = v9fs_co_name_to_path(pdu, &dfidp->path, name.data, &path); 2511 if (err < 0) { 2512 goto out_err; 2513 } 2514 err = v9fs_mark_fids_unreclaim(pdu, &path); 2515 if (err < 0) { 2516 goto out_err; 2517 } 2518 err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, flags); 2519 if (!err) { 2520 err = offset; 2521 } 2522 out_err: 2523 put_fid(pdu, dfidp); 2524 v9fs_path_free(&path); 2525 out_nofid: 2526 pdu_complete(pdu, err); 2527 v9fs_string_free(&name); 2528 } 2529 2530 2531 /* Only works with path name based fid */ 2532 static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, 2533 int32_t newdirfid, 2534 V9fsString *name) 2535 { 2536 char *end; 2537 int err = 0; 2538 V9fsPath new_path; 2539 V9fsFidState *tfidp; 2540 V9fsState *s = pdu->s; 2541 V9fsFidState *dirfidp = NULL; 2542 char *old_name, *new_name; 2543 2544 v9fs_path_init(&new_path); 2545 if (newdirfid != -1) { 2546 dirfidp = get_fid(pdu, newdirfid); 2547 if (dirfidp == NULL) { 2548 err = -ENOENT; 2549 goto out_nofid; 2550 } 2551 BUG_ON(dirfidp->fid_type != P9_FID_NONE); 2552 v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); 2553 } else { 2554 old_name = fidp->path.data; 2555 end = strrchr(old_name, '/'); 2556 if (end) { 2557 end++; 2558 } else { 2559 end = old_name; 2560 } 2561 new_name = g_malloc0(end - old_name + name->size + 1); 2562 strncat(new_name, old_name, end - old_name); 2563 strncat(new_name + (end - old_name), name->data, name->size); 2564 v9fs_co_name_to_path(pdu, NULL, new_name, &new_path); 2565 g_free(new_name); 2566 } 2567 err = v9fs_co_rename(pdu, &fidp->path, &new_path); 2568 if (err < 0) { 2569 goto out; 2570 } 2571 /* 2572 * Fixup fid's pointing to the old name to 2573 * start pointing to the new name 2574 */ 2575 for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) { 2576 if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) { 2577 /* replace the name */ 2578 v9fs_fix_path(&tfidp->path, &new_path, strlen(fidp->path.data)); 2579 } 2580 } 2581 out: 2582 if (dirfidp) { 2583 put_fid(pdu, dirfidp); 2584 } 2585 v9fs_path_free(&new_path); 2586 out_nofid: 2587 return err; 2588 } 2589 2590 /* Only works with path name based fid */ 2591 static void coroutine_fn v9fs_rename(void *opaque) 2592 { 2593 int32_t fid; 2594 ssize_t err = 0; 2595 size_t offset = 7; 2596 V9fsString name; 2597 int32_t newdirfid; 2598 V9fsFidState *fidp; 2599 V9fsPDU *pdu = opaque; 2600 V9fsState *s = pdu->s; 2601 2602 v9fs_string_init(&name); 2603 err = pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name); 2604 if (err < 0) { 2605 goto out_nofid; 2606 } 2607 2608 if (name_is_illegal(name.data)) { 2609 err = -ENOENT; 2610 goto out_nofid; 2611 } 2612 2613 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 2614 err = -EISDIR; 2615 goto out_nofid; 2616 } 2617 2618 fidp = get_fid(pdu, fid); 2619 if (fidp == NULL) { 2620 err = -ENOENT; 2621 goto out_nofid; 2622 } 2623 BUG_ON(fidp->fid_type != P9_FID_NONE); 2624 /* if fs driver is not path based, return EOPNOTSUPP */ 2625 if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) { 2626 err = -EOPNOTSUPP; 2627 goto out; 2628 } 2629 v9fs_path_write_lock(s); 2630 err = v9fs_complete_rename(pdu, fidp, newdirfid, &name); 2631 v9fs_path_unlock(s); 2632 if (!err) { 2633 err = offset; 2634 } 2635 out: 2636 put_fid(pdu, fidp); 2637 out_nofid: 2638 pdu_complete(pdu, err); 2639 v9fs_string_free(&name); 2640 } 2641 2642 static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, 2643 V9fsString *old_name, 2644 V9fsPath *newdir, 2645 V9fsString *new_name) 2646 { 2647 V9fsFidState *tfidp; 2648 V9fsPath oldpath, newpath; 2649 V9fsState *s = pdu->s; 2650 2651 2652 v9fs_path_init(&oldpath); 2653 v9fs_path_init(&newpath); 2654 v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath); 2655 v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath); 2656 2657 /* 2658 * Fixup fid's pointing to the old name to 2659 * start pointing to the new name 2660 */ 2661 for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) { 2662 if (v9fs_path_is_ancestor(&oldpath, &tfidp->path)) { 2663 /* replace the name */ 2664 v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data)); 2665 } 2666 } 2667 v9fs_path_free(&oldpath); 2668 v9fs_path_free(&newpath); 2669 } 2670 2671 static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, 2672 V9fsString *old_name, 2673 int32_t newdirfid, 2674 V9fsString *new_name) 2675 { 2676 int err = 0; 2677 V9fsState *s = pdu->s; 2678 V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL; 2679 2680 olddirfidp = get_fid(pdu, olddirfid); 2681 if (olddirfidp == NULL) { 2682 err = -ENOENT; 2683 goto out; 2684 } 2685 if (newdirfid != -1) { 2686 newdirfidp = get_fid(pdu, newdirfid); 2687 if (newdirfidp == NULL) { 2688 err = -ENOENT; 2689 goto out; 2690 } 2691 } else { 2692 newdirfidp = get_fid(pdu, olddirfid); 2693 } 2694 2695 err = v9fs_co_renameat(pdu, &olddirfidp->path, old_name, 2696 &newdirfidp->path, new_name); 2697 if (err < 0) { 2698 goto out; 2699 } 2700 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 2701 /* Only for path based fid we need to do the below fixup */ 2702 v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name, 2703 &newdirfidp->path, new_name); 2704 } 2705 out: 2706 if (olddirfidp) { 2707 put_fid(pdu, olddirfidp); 2708 } 2709 if (newdirfidp) { 2710 put_fid(pdu, newdirfidp); 2711 } 2712 return err; 2713 } 2714 2715 static void coroutine_fn v9fs_renameat(void *opaque) 2716 { 2717 ssize_t err = 0; 2718 size_t offset = 7; 2719 V9fsPDU *pdu = opaque; 2720 V9fsState *s = pdu->s; 2721 int32_t olddirfid, newdirfid; 2722 V9fsString old_name, new_name; 2723 2724 v9fs_string_init(&old_name); 2725 v9fs_string_init(&new_name); 2726 err = pdu_unmarshal(pdu, offset, "dsds", &olddirfid, 2727 &old_name, &newdirfid, &new_name); 2728 if (err < 0) { 2729 goto out_err; 2730 } 2731 2732 if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) { 2733 err = -ENOENT; 2734 goto out_err; 2735 } 2736 2737 if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) || 2738 !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) { 2739 err = -EISDIR; 2740 goto out_err; 2741 } 2742 2743 v9fs_path_write_lock(s); 2744 err = v9fs_complete_renameat(pdu, olddirfid, 2745 &old_name, newdirfid, &new_name); 2746 v9fs_path_unlock(s); 2747 if (!err) { 2748 err = offset; 2749 } 2750 2751 out_err: 2752 pdu_complete(pdu, err); 2753 v9fs_string_free(&old_name); 2754 v9fs_string_free(&new_name); 2755 } 2756 2757 static void coroutine_fn v9fs_wstat(void *opaque) 2758 { 2759 int32_t fid; 2760 int err = 0; 2761 int16_t unused; 2762 V9fsStat v9stat; 2763 size_t offset = 7; 2764 struct stat stbuf; 2765 V9fsFidState *fidp; 2766 V9fsPDU *pdu = opaque; 2767 2768 v9fs_stat_init(&v9stat); 2769 err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat); 2770 if (err < 0) { 2771 goto out_nofid; 2772 } 2773 trace_v9fs_wstat(pdu->tag, pdu->id, fid, 2774 v9stat.mode, v9stat.atime, v9stat.mtime); 2775 2776 fidp = get_fid(pdu, fid); 2777 if (fidp == NULL) { 2778 err = -EINVAL; 2779 goto out_nofid; 2780 } 2781 /* do we need to sync the file? */ 2782 if (donttouch_stat(&v9stat)) { 2783 err = v9fs_co_fsync(pdu, fidp, 0); 2784 goto out; 2785 } 2786 if (v9stat.mode != -1) { 2787 uint32_t v9_mode; 2788 err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); 2789 if (err < 0) { 2790 goto out; 2791 } 2792 v9_mode = stat_to_v9mode(&stbuf); 2793 if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) != 2794 (v9_mode & P9_STAT_MODE_TYPE_BITS)) { 2795 /* Attempting to change the type */ 2796 err = -EIO; 2797 goto out; 2798 } 2799 err = v9fs_co_chmod(pdu, &fidp->path, 2800 v9mode_to_mode(v9stat.mode, 2801 &v9stat.extension)); 2802 if (err < 0) { 2803 goto out; 2804 } 2805 } 2806 if (v9stat.mtime != -1 || v9stat.atime != -1) { 2807 struct timespec times[2]; 2808 if (v9stat.atime != -1) { 2809 times[0].tv_sec = v9stat.atime; 2810 times[0].tv_nsec = 0; 2811 } else { 2812 times[0].tv_nsec = UTIME_OMIT; 2813 } 2814 if (v9stat.mtime != -1) { 2815 times[1].tv_sec = v9stat.mtime; 2816 times[1].tv_nsec = 0; 2817 } else { 2818 times[1].tv_nsec = UTIME_OMIT; 2819 } 2820 err = v9fs_co_utimensat(pdu, &fidp->path, times); 2821 if (err < 0) { 2822 goto out; 2823 } 2824 } 2825 if (v9stat.n_gid != -1 || v9stat.n_uid != -1) { 2826 err = v9fs_co_chown(pdu, &fidp->path, v9stat.n_uid, v9stat.n_gid); 2827 if (err < 0) { 2828 goto out; 2829 } 2830 } 2831 if (v9stat.name.size != 0) { 2832 err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name); 2833 if (err < 0) { 2834 goto out; 2835 } 2836 } 2837 if (v9stat.length != -1) { 2838 err = v9fs_co_truncate(pdu, &fidp->path, v9stat.length); 2839 if (err < 0) { 2840 goto out; 2841 } 2842 } 2843 err = offset; 2844 out: 2845 put_fid(pdu, fidp); 2846 out_nofid: 2847 v9fs_stat_free(&v9stat); 2848 pdu_complete(pdu, err); 2849 } 2850 2851 static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) 2852 { 2853 uint32_t f_type; 2854 uint32_t f_bsize; 2855 uint64_t f_blocks; 2856 uint64_t f_bfree; 2857 uint64_t f_bavail; 2858 uint64_t f_files; 2859 uint64_t f_ffree; 2860 uint64_t fsid_val; 2861 uint32_t f_namelen; 2862 size_t offset = 7; 2863 int32_t bsize_factor; 2864 2865 /* 2866 * compute bsize factor based on host file system block size 2867 * and client msize 2868 */ 2869 bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize; 2870 if (!bsize_factor) { 2871 bsize_factor = 1; 2872 } 2873 f_type = stbuf->f_type; 2874 f_bsize = stbuf->f_bsize; 2875 f_bsize *= bsize_factor; 2876 /* 2877 * f_bsize is adjusted(multiplied) by bsize factor, so we need to 2878 * adjust(divide) the number of blocks, free blocks and available 2879 * blocks by bsize factor 2880 */ 2881 f_blocks = stbuf->f_blocks/bsize_factor; 2882 f_bfree = stbuf->f_bfree/bsize_factor; 2883 f_bavail = stbuf->f_bavail/bsize_factor; 2884 f_files = stbuf->f_files; 2885 f_ffree = stbuf->f_ffree; 2886 fsid_val = (unsigned int) stbuf->f_fsid.__val[0] | 2887 (unsigned long long)stbuf->f_fsid.__val[1] << 32; 2888 f_namelen = stbuf->f_namelen; 2889 2890 return pdu_marshal(pdu, offset, "ddqqqqqqd", 2891 f_type, f_bsize, f_blocks, f_bfree, 2892 f_bavail, f_files, f_ffree, 2893 fsid_val, f_namelen); 2894 } 2895 2896 static void coroutine_fn v9fs_statfs(void *opaque) 2897 { 2898 int32_t fid; 2899 ssize_t retval = 0; 2900 size_t offset = 7; 2901 V9fsFidState *fidp; 2902 struct statfs stbuf; 2903 V9fsPDU *pdu = opaque; 2904 V9fsState *s = pdu->s; 2905 2906 retval = pdu_unmarshal(pdu, offset, "d", &fid); 2907 if (retval < 0) { 2908 goto out_nofid; 2909 } 2910 fidp = get_fid(pdu, fid); 2911 if (fidp == NULL) { 2912 retval = -ENOENT; 2913 goto out_nofid; 2914 } 2915 retval = v9fs_co_statfs(pdu, &fidp->path, &stbuf); 2916 if (retval < 0) { 2917 goto out; 2918 } 2919 retval = v9fs_fill_statfs(s, pdu, &stbuf); 2920 if (retval < 0) { 2921 goto out; 2922 } 2923 retval += offset; 2924 out: 2925 put_fid(pdu, fidp); 2926 out_nofid: 2927 pdu_complete(pdu, retval); 2928 } 2929 2930 static void coroutine_fn v9fs_mknod(void *opaque) 2931 { 2932 2933 int mode; 2934 gid_t gid; 2935 int32_t fid; 2936 V9fsQID qid; 2937 int err = 0; 2938 int major, minor; 2939 size_t offset = 7; 2940 V9fsString name; 2941 struct stat stbuf; 2942 V9fsFidState *fidp; 2943 V9fsPDU *pdu = opaque; 2944 2945 v9fs_string_init(&name); 2946 err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode, 2947 &major, &minor, &gid); 2948 if (err < 0) { 2949 goto out_nofid; 2950 } 2951 trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor); 2952 2953 if (name_is_illegal(name.data)) { 2954 err = -ENOENT; 2955 goto out_nofid; 2956 } 2957 2958 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 2959 err = -EEXIST; 2960 goto out_nofid; 2961 } 2962 2963 fidp = get_fid(pdu, fid); 2964 if (fidp == NULL) { 2965 err = -ENOENT; 2966 goto out_nofid; 2967 } 2968 err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, gid, 2969 makedev(major, minor), mode, &stbuf); 2970 if (err < 0) { 2971 goto out; 2972 } 2973 stat_to_qid(&stbuf, &qid); 2974 err = pdu_marshal(pdu, offset, "Q", &qid); 2975 if (err < 0) { 2976 goto out; 2977 } 2978 err += offset; 2979 trace_v9fs_mknod_return(pdu->tag, pdu->id, 2980 qid.type, qid.version, qid.path); 2981 out: 2982 put_fid(pdu, fidp); 2983 out_nofid: 2984 pdu_complete(pdu, err); 2985 v9fs_string_free(&name); 2986 } 2987 2988 /* 2989 * Implement posix byte range locking code 2990 * Server side handling of locking code is very simple, because 9p server in 2991 * QEMU can handle only one client. And most of the lock handling 2992 * (like conflict, merging) etc is done by the VFS layer itself, so no need to 2993 * do any thing in * qemu 9p server side lock code path. 2994 * So when a TLOCK request comes, always return success 2995 */ 2996 static void coroutine_fn v9fs_lock(void *opaque) 2997 { 2998 int8_t status; 2999 V9fsFlock flock; 3000 size_t offset = 7; 3001 struct stat stbuf; 3002 V9fsFidState *fidp; 3003 int32_t fid, err = 0; 3004 V9fsPDU *pdu = opaque; 3005 3006 status = P9_LOCK_ERROR; 3007 v9fs_string_init(&flock.client_id); 3008 err = pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock.type, 3009 &flock.flags, &flock.start, &flock.length, 3010 &flock.proc_id, &flock.client_id); 3011 if (err < 0) { 3012 goto out_nofid; 3013 } 3014 trace_v9fs_lock(pdu->tag, pdu->id, fid, 3015 flock.type, flock.start, flock.length); 3016 3017 3018 /* We support only block flag now (that too ignored currently) */ 3019 if (flock.flags & ~P9_LOCK_FLAGS_BLOCK) { 3020 err = -EINVAL; 3021 goto out_nofid; 3022 } 3023 fidp = get_fid(pdu, fid); 3024 if (fidp == NULL) { 3025 err = -ENOENT; 3026 goto out_nofid; 3027 } 3028 err = v9fs_co_fstat(pdu, fidp, &stbuf); 3029 if (err < 0) { 3030 goto out; 3031 } 3032 status = P9_LOCK_SUCCESS; 3033 out: 3034 put_fid(pdu, fidp); 3035 out_nofid: 3036 err = pdu_marshal(pdu, offset, "b", status); 3037 if (err > 0) { 3038 err += offset; 3039 } 3040 trace_v9fs_lock_return(pdu->tag, pdu->id, status); 3041 pdu_complete(pdu, err); 3042 v9fs_string_free(&flock.client_id); 3043 } 3044 3045 /* 3046 * When a TGETLOCK request comes, always return success because all lock 3047 * handling is done by client's VFS layer. 3048 */ 3049 static void coroutine_fn v9fs_getlock(void *opaque) 3050 { 3051 size_t offset = 7; 3052 struct stat stbuf; 3053 V9fsFidState *fidp; 3054 V9fsGetlock glock; 3055 int32_t fid, err = 0; 3056 V9fsPDU *pdu = opaque; 3057 3058 v9fs_string_init(&glock.client_id); 3059 err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type, 3060 &glock.start, &glock.length, &glock.proc_id, 3061 &glock.client_id); 3062 if (err < 0) { 3063 goto out_nofid; 3064 } 3065 trace_v9fs_getlock(pdu->tag, pdu->id, fid, 3066 glock.type, glock.start, glock.length); 3067 3068 fidp = get_fid(pdu, fid); 3069 if (fidp == NULL) { 3070 err = -ENOENT; 3071 goto out_nofid; 3072 } 3073 err = v9fs_co_fstat(pdu, fidp, &stbuf); 3074 if (err < 0) { 3075 goto out; 3076 } 3077 glock.type = P9_LOCK_TYPE_UNLCK; 3078 err = pdu_marshal(pdu, offset, "bqqds", glock.type, 3079 glock.start, glock.length, glock.proc_id, 3080 &glock.client_id); 3081 if (err < 0) { 3082 goto out; 3083 } 3084 err += offset; 3085 trace_v9fs_getlock_return(pdu->tag, pdu->id, glock.type, glock.start, 3086 glock.length, glock.proc_id); 3087 out: 3088 put_fid(pdu, fidp); 3089 out_nofid: 3090 pdu_complete(pdu, err); 3091 v9fs_string_free(&glock.client_id); 3092 } 3093 3094 static void coroutine_fn v9fs_mkdir(void *opaque) 3095 { 3096 V9fsPDU *pdu = opaque; 3097 size_t offset = 7; 3098 int32_t fid; 3099 struct stat stbuf; 3100 V9fsQID qid; 3101 V9fsString name; 3102 V9fsFidState *fidp; 3103 gid_t gid; 3104 int mode; 3105 int err = 0; 3106 3107 v9fs_string_init(&name); 3108 err = pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid); 3109 if (err < 0) { 3110 goto out_nofid; 3111 } 3112 trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid); 3113 3114 if (name_is_illegal(name.data)) { 3115 err = -ENOENT; 3116 goto out_nofid; 3117 } 3118 3119 if (!strcmp(".", name.data) || !strcmp("..", name.data)) { 3120 err = -EEXIST; 3121 goto out_nofid; 3122 } 3123 3124 fidp = get_fid(pdu, fid); 3125 if (fidp == NULL) { 3126 err = -ENOENT; 3127 goto out_nofid; 3128 } 3129 err = v9fs_co_mkdir(pdu, fidp, &name, mode, fidp->uid, gid, &stbuf); 3130 if (err < 0) { 3131 goto out; 3132 } 3133 stat_to_qid(&stbuf, &qid); 3134 err = pdu_marshal(pdu, offset, "Q", &qid); 3135 if (err < 0) { 3136 goto out; 3137 } 3138 err += offset; 3139 trace_v9fs_mkdir_return(pdu->tag, pdu->id, 3140 qid.type, qid.version, qid.path, err); 3141 out: 3142 put_fid(pdu, fidp); 3143 out_nofid: 3144 pdu_complete(pdu, err); 3145 v9fs_string_free(&name); 3146 } 3147 3148 static void coroutine_fn v9fs_xattrwalk(void *opaque) 3149 { 3150 int64_t size; 3151 V9fsString name; 3152 ssize_t err = 0; 3153 size_t offset = 7; 3154 int32_t fid, newfid; 3155 V9fsFidState *file_fidp; 3156 V9fsFidState *xattr_fidp = NULL; 3157 V9fsPDU *pdu = opaque; 3158 V9fsState *s = pdu->s; 3159 3160 v9fs_string_init(&name); 3161 err = pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name); 3162 if (err < 0) { 3163 goto out_nofid; 3164 } 3165 trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data); 3166 3167 file_fidp = get_fid(pdu, fid); 3168 if (file_fidp == NULL) { 3169 err = -ENOENT; 3170 goto out_nofid; 3171 } 3172 xattr_fidp = alloc_fid(s, newfid); 3173 if (xattr_fidp == NULL) { 3174 err = -EINVAL; 3175 goto out; 3176 } 3177 v9fs_path_copy(&xattr_fidp->path, &file_fidp->path); 3178 if (!v9fs_string_size(&name)) { 3179 /* 3180 * listxattr request. Get the size first 3181 */ 3182 size = v9fs_co_llistxattr(pdu, &xattr_fidp->path, NULL, 0); 3183 if (size < 0) { 3184 err = size; 3185 clunk_fid(s, xattr_fidp->fid); 3186 goto out; 3187 } 3188 /* 3189 * Read the xattr value 3190 */ 3191 xattr_fidp->fs.xattr.len = size; 3192 xattr_fidp->fid_type = P9_FID_XATTR; 3193 xattr_fidp->fs.xattr.copied_len = -1; 3194 if (size) { 3195 xattr_fidp->fs.xattr.value = g_malloc(size); 3196 err = v9fs_co_llistxattr(pdu, &xattr_fidp->path, 3197 xattr_fidp->fs.xattr.value, 3198 xattr_fidp->fs.xattr.len); 3199 if (err < 0) { 3200 clunk_fid(s, xattr_fidp->fid); 3201 goto out; 3202 } 3203 } 3204 err = pdu_marshal(pdu, offset, "q", size); 3205 if (err < 0) { 3206 goto out; 3207 } 3208 err += offset; 3209 } else { 3210 /* 3211 * specific xattr fid. We check for xattr 3212 * presence also collect the xattr size 3213 */ 3214 size = v9fs_co_lgetxattr(pdu, &xattr_fidp->path, 3215 &name, NULL, 0); 3216 if (size < 0) { 3217 err = size; 3218 clunk_fid(s, xattr_fidp->fid); 3219 goto out; 3220 } 3221 /* 3222 * Read the xattr value 3223 */ 3224 xattr_fidp->fs.xattr.len = size; 3225 xattr_fidp->fid_type = P9_FID_XATTR; 3226 xattr_fidp->fs.xattr.copied_len = -1; 3227 if (size) { 3228 xattr_fidp->fs.xattr.value = g_malloc(size); 3229 err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path, 3230 &name, xattr_fidp->fs.xattr.value, 3231 xattr_fidp->fs.xattr.len); 3232 if (err < 0) { 3233 clunk_fid(s, xattr_fidp->fid); 3234 goto out; 3235 } 3236 } 3237 err = pdu_marshal(pdu, offset, "q", size); 3238 if (err < 0) { 3239 goto out; 3240 } 3241 err += offset; 3242 } 3243 trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size); 3244 out: 3245 put_fid(pdu, file_fidp); 3246 if (xattr_fidp) { 3247 put_fid(pdu, xattr_fidp); 3248 } 3249 out_nofid: 3250 pdu_complete(pdu, err); 3251 v9fs_string_free(&name); 3252 } 3253 3254 static void coroutine_fn v9fs_xattrcreate(void *opaque) 3255 { 3256 int flags; 3257 int32_t fid; 3258 int64_t size; 3259 ssize_t err = 0; 3260 V9fsString name; 3261 size_t offset = 7; 3262 V9fsFidState *file_fidp; 3263 V9fsFidState *xattr_fidp; 3264 V9fsPDU *pdu = opaque; 3265 3266 v9fs_string_init(&name); 3267 err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags); 3268 if (err < 0) { 3269 goto out_nofid; 3270 } 3271 trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags); 3272 3273 file_fidp = get_fid(pdu, fid); 3274 if (file_fidp == NULL) { 3275 err = -EINVAL; 3276 goto out_nofid; 3277 } 3278 /* Make the file fid point to xattr */ 3279 xattr_fidp = file_fidp; 3280 xattr_fidp->fid_type = P9_FID_XATTR; 3281 xattr_fidp->fs.xattr.copied_len = 0; 3282 xattr_fidp->fs.xattr.len = size; 3283 xattr_fidp->fs.xattr.flags = flags; 3284 v9fs_string_init(&xattr_fidp->fs.xattr.name); 3285 v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name); 3286 g_free(xattr_fidp->fs.xattr.value); 3287 xattr_fidp->fs.xattr.value = g_malloc0(size); 3288 err = offset; 3289 put_fid(pdu, file_fidp); 3290 out_nofid: 3291 pdu_complete(pdu, err); 3292 v9fs_string_free(&name); 3293 } 3294 3295 static void coroutine_fn v9fs_readlink(void *opaque) 3296 { 3297 V9fsPDU *pdu = opaque; 3298 size_t offset = 7; 3299 V9fsString target; 3300 int32_t fid; 3301 int err = 0; 3302 V9fsFidState *fidp; 3303 3304 err = pdu_unmarshal(pdu, offset, "d", &fid); 3305 if (err < 0) { 3306 goto out_nofid; 3307 } 3308 trace_v9fs_readlink(pdu->tag, pdu->id, fid); 3309 fidp = get_fid(pdu, fid); 3310 if (fidp == NULL) { 3311 err = -ENOENT; 3312 goto out_nofid; 3313 } 3314 3315 v9fs_string_init(&target); 3316 err = v9fs_co_readlink(pdu, &fidp->path, &target); 3317 if (err < 0) { 3318 goto out; 3319 } 3320 err = pdu_marshal(pdu, offset, "s", &target); 3321 if (err < 0) { 3322 v9fs_string_free(&target); 3323 goto out; 3324 } 3325 err += offset; 3326 trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data); 3327 v9fs_string_free(&target); 3328 out: 3329 put_fid(pdu, fidp); 3330 out_nofid: 3331 pdu_complete(pdu, err); 3332 } 3333 3334 static CoroutineEntry *pdu_co_handlers[] = { 3335 [P9_TREADDIR] = v9fs_readdir, 3336 [P9_TSTATFS] = v9fs_statfs, 3337 [P9_TGETATTR] = v9fs_getattr, 3338 [P9_TSETATTR] = v9fs_setattr, 3339 [P9_TXATTRWALK] = v9fs_xattrwalk, 3340 [P9_TXATTRCREATE] = v9fs_xattrcreate, 3341 [P9_TMKNOD] = v9fs_mknod, 3342 [P9_TRENAME] = v9fs_rename, 3343 [P9_TLOCK] = v9fs_lock, 3344 [P9_TGETLOCK] = v9fs_getlock, 3345 [P9_TRENAMEAT] = v9fs_renameat, 3346 [P9_TREADLINK] = v9fs_readlink, 3347 [P9_TUNLINKAT] = v9fs_unlinkat, 3348 [P9_TMKDIR] = v9fs_mkdir, 3349 [P9_TVERSION] = v9fs_version, 3350 [P9_TLOPEN] = v9fs_open, 3351 [P9_TATTACH] = v9fs_attach, 3352 [P9_TSTAT] = v9fs_stat, 3353 [P9_TWALK] = v9fs_walk, 3354 [P9_TCLUNK] = v9fs_clunk, 3355 [P9_TFSYNC] = v9fs_fsync, 3356 [P9_TOPEN] = v9fs_open, 3357 [P9_TREAD] = v9fs_read, 3358 #if 0 3359 [P9_TAUTH] = v9fs_auth, 3360 #endif 3361 [P9_TFLUSH] = v9fs_flush, 3362 [P9_TLINK] = v9fs_link, 3363 [P9_TSYMLINK] = v9fs_symlink, 3364 [P9_TCREATE] = v9fs_create, 3365 [P9_TLCREATE] = v9fs_lcreate, 3366 [P9_TWRITE] = v9fs_write, 3367 [P9_TWSTAT] = v9fs_wstat, 3368 [P9_TREMOVE] = v9fs_remove, 3369 }; 3370 3371 static void coroutine_fn v9fs_op_not_supp(void *opaque) 3372 { 3373 V9fsPDU *pdu = opaque; 3374 pdu_complete(pdu, -EOPNOTSUPP); 3375 } 3376 3377 static void coroutine_fn v9fs_fs_ro(void *opaque) 3378 { 3379 V9fsPDU *pdu = opaque; 3380 pdu_complete(pdu, -EROFS); 3381 } 3382 3383 static inline bool is_read_only_op(V9fsPDU *pdu) 3384 { 3385 switch (pdu->id) { 3386 case P9_TREADDIR: 3387 case P9_TSTATFS: 3388 case P9_TGETATTR: 3389 case P9_TXATTRWALK: 3390 case P9_TLOCK: 3391 case P9_TGETLOCK: 3392 case P9_TREADLINK: 3393 case P9_TVERSION: 3394 case P9_TLOPEN: 3395 case P9_TATTACH: 3396 case P9_TSTAT: 3397 case P9_TWALK: 3398 case P9_TCLUNK: 3399 case P9_TFSYNC: 3400 case P9_TOPEN: 3401 case P9_TREAD: 3402 case P9_TAUTH: 3403 case P9_TFLUSH: 3404 return 1; 3405 default: 3406 return 0; 3407 } 3408 } 3409 3410 void pdu_submit(V9fsPDU *pdu) 3411 { 3412 Coroutine *co; 3413 CoroutineEntry *handler; 3414 V9fsState *s = pdu->s; 3415 3416 if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || 3417 (pdu_co_handlers[pdu->id] == NULL)) { 3418 handler = v9fs_op_not_supp; 3419 } else { 3420 handler = pdu_co_handlers[pdu->id]; 3421 } 3422 3423 if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { 3424 handler = v9fs_fs_ro; 3425 } 3426 co = qemu_coroutine_create(handler, pdu); 3427 qemu_coroutine_enter(co); 3428 } 3429 3430 /* Returns 0 on success, 1 on failure. */ 3431 int v9fs_device_realize_common(V9fsState *s, Error **errp) 3432 { 3433 V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); 3434 int i, len; 3435 struct stat stat; 3436 FsDriverEntry *fse; 3437 V9fsPath path; 3438 int rc = 1; 3439 3440 /* initialize pdu allocator */ 3441 QLIST_INIT(&s->free_list); 3442 QLIST_INIT(&s->active_list); 3443 for (i = 0; i < (MAX_REQ - 1); i++) { 3444 QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next); 3445 v->pdus[i].s = s; 3446 v->pdus[i].idx = i; 3447 } 3448 3449 v9fs_path_init(&path); 3450 3451 fse = get_fsdev_fsentry(s->fsconf.fsdev_id); 3452 3453 if (!fse) { 3454 /* We don't have a fsdev identified by fsdev_id */ 3455 error_setg(errp, "9pfs device couldn't find fsdev with the " 3456 "id = %s", 3457 s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); 3458 goto out; 3459 } 3460 3461 if (!s->fsconf.tag) { 3462 /* we haven't specified a mount_tag */ 3463 error_setg(errp, "fsdev with id %s needs mount_tag arguments", 3464 s->fsconf.fsdev_id); 3465 goto out; 3466 } 3467 3468 s->ctx.export_flags = fse->export_flags; 3469 s->ctx.fs_root = g_strdup(fse->path); 3470 s->ctx.exops.get_st_gen = NULL; 3471 len = strlen(s->fsconf.tag); 3472 if (len > MAX_TAG_LEN - 1) { 3473 error_setg(errp, "mount tag '%s' (%d bytes) is longer than " 3474 "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); 3475 goto out; 3476 } 3477 3478 s->tag = g_strdup(s->fsconf.tag); 3479 s->ctx.uid = -1; 3480 3481 s->ops = fse->ops; 3482 3483 s->fid_list = NULL; 3484 qemu_co_rwlock_init(&s->rename_lock); 3485 3486 if (s->ops->init(&s->ctx) < 0) { 3487 error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s" 3488 " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); 3489 goto out; 3490 } 3491 3492 /* 3493 * Check details of export path, We need to use fs driver 3494 * call back to do that. Since we are in the init path, we don't 3495 * use co-routines here. 3496 */ 3497 if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { 3498 error_setg(errp, 3499 "error in converting name to path %s", strerror(errno)); 3500 goto out; 3501 } 3502 if (s->ops->lstat(&s->ctx, &path, &stat)) { 3503 error_setg(errp, "share path %s does not exist", fse->path); 3504 goto out; 3505 } else if (!S_ISDIR(stat.st_mode)) { 3506 error_setg(errp, "share path %s is not a directory", fse->path); 3507 goto out; 3508 } 3509 v9fs_path_free(&path); 3510 3511 rc = 0; 3512 out: 3513 if (rc) { 3514 g_free(s->ctx.fs_root); 3515 g_free(s->tag); 3516 v9fs_path_free(&path); 3517 } 3518 return rc; 3519 } 3520 3521 void v9fs_device_unrealize_common(V9fsState *s, Error **errp) 3522 { 3523 g_free(s->ctx.fs_root); 3524 g_free(s->tag); 3525 } 3526 3527 typedef struct VirtfsCoResetData { 3528 V9fsPDU pdu; 3529 bool done; 3530 } VirtfsCoResetData; 3531 3532 static void coroutine_fn virtfs_co_reset(void *opaque) 3533 { 3534 VirtfsCoResetData *data = opaque; 3535 3536 virtfs_reset(&data->pdu); 3537 data->done = true; 3538 } 3539 3540 void v9fs_reset(V9fsState *s) 3541 { 3542 VirtfsCoResetData data = { .pdu = { .s = s }, .done = false }; 3543 Coroutine *co; 3544 3545 while (!QLIST_EMPTY(&s->active_list)) { 3546 aio_poll(qemu_get_aio_context(), true); 3547 } 3548 3549 co = qemu_coroutine_create(virtfs_co_reset, &data); 3550 qemu_coroutine_enter(co); 3551 3552 while (!data.done) { 3553 aio_poll(qemu_get_aio_context(), true); 3554 } 3555 } 3556 3557 static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) 3558 { 3559 struct rlimit rlim; 3560 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 3561 error_report("Failed to get the resource limit"); 3562 exit(1); 3563 } 3564 open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); 3565 open_fd_rc = rlim.rlim_cur/2; 3566 } 3567