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