9p.c (1a6ed33cc56997479bbe5b48337ff8da44585bd4) 9p.c (f3fe4a2d92bb4ee5b599b8b1eb781b2ae68af36c)
1/*
2 * Virtio 9p backend
3 *
4 * Copyright IBM, Corp. 2010
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *

--- 565 unchanged lines hidden (view full) ---

574 P9_STAT_MODE_SOCKET)
575
576/* creative abuse of tb_hash_func7, which is based on xxhash */
577static uint32_t qpp_hash(QppEntry e)
578{
579 return qemu_xxhash7(e.ino_prefix, e.dev, 0, 0, 0);
580}
581
1/*
2 * Virtio 9p backend
3 *
4 * Copyright IBM, Corp. 2010
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *

--- 565 unchanged lines hidden (view full) ---

574 P9_STAT_MODE_SOCKET)
575
576/* creative abuse of tb_hash_func7, which is based on xxhash */
577static uint32_t qpp_hash(QppEntry e)
578{
579 return qemu_xxhash7(e.ino_prefix, e.dev, 0, 0, 0);
580}
581
582static uint32_t qpf_hash(QpfEntry e)
583{
584 return qemu_xxhash7(e.ino, e.dev, 0, 0, 0);
585}
586
582static bool qpp_lookup_func(const void *obj, const void *userp)
583{
584 const QppEntry *e1 = obj, *e2 = userp;
585 return e1->dev == e2->dev && e1->ino_prefix == e2->ino_prefix;
586}
587
587static 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
588static void qpp_table_remove(void *p, uint32_t h, void *up)
593static bool qpf_lookup_func(const void *obj, const void *userp)
589{
594{
595 const QpfEntry *e1 = obj, *e2 = userp;
596 return e1->dev == e2->dev && e1->ino == e2->ino;
597}
598
599static void qp_table_remove(void *p, uint32_t h, void *up)
600{
590 g_free(p);
591}
592
601 g_free(p);
602}
603
593static void qpp_table_destroy(struct qht *ht)
604static void qp_table_destroy(struct qht *ht)
594{
595 if (!ht || !ht->map) {
596 return;
597 }
605{
606 if (!ht || !ht->map) {
607 return;
608 }
598 qht_iter(ht, qpp_table_remove, NULL);
609 qht_iter(ht, qp_table_remove, NULL);
599 qht_destroy(ht);
600}
601
602static void qpp_table_init(struct qht *ht)
603{
604 qht_init(ht, qpp_lookup_func, 1, QHT_MODE_AUTO_RESIZE);
605}
606
610 qht_destroy(ht);
611}
612
613static void qpp_table_init(struct qht *ht)
614{
615 qht_init(ht, qpp_lookup_func, 1, QHT_MODE_AUTO_RESIZE);
616}
617
618static void qpf_table_init(struct qht *ht)
619{
620 qht_init(ht, qpf_lookup_func, 1 << 16, QHT_MODE_AUTO_RESIZE);
621}
622
623static 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
607/*
608 * stat_to_qid needs to map inode number (64 bits) and device id (32 bits)
609 * to a unique QID path (64 bits). To avoid having to map and keep track
610 * of up to 2^64 objects, we map only the 16 highest bits of the inode plus
611 * the device id to the 16 highest bits of the QID path. The 48 lowest bits
612 * of the QID path equal to the lowest bits of the inode number.
613 *
614 * This takes advantage of the fact that inode number are usually not

--- 9 unchanged lines hidden (view full) ---

624 }, *val;
625 uint32_t hash = qpp_hash(lookup);
626
627 val = qht_lookup(&pdu->s->qpp_table, &lookup, hash);
628
629 if (!val) {
630 if (pdu->s->qp_prefix_next == 0) {
631 /* we ran out of prefixes */
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

--- 9 unchanged lines hidden (view full) ---

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 */
632 error_report_once(
633 "9p: No more prefixes available for remapping inodes from "
634 "host to guest."
687 warn_report_once(
688 "9p: Potential degraded performance of inode remapping"
635 );
636 return -ENFILE;
637 }
638
639 val = g_malloc0(sizeof(QppEntry));
640 *val = lookup;
641
642 /* new unique inode prefix and device combo */

--- 8 unchanged lines hidden (view full) ---

651static int stat_to_qid(V9fsPDU *pdu, const struct stat *stbuf, V9fsQID *qidp)
652{
653 int err;
654 size_t size;
655
656 if (pdu->s->ctx.export_flags & V9FS_REMAP_INODES) {
657 /* map inode+device to qid path (fast path) */
658 err = qid_path_prefixmap(pdu, stbuf, &qidp->path);
689 );
690 return -ENFILE;
691 }
692
693 val = g_malloc0(sizeof(QppEntry));
694 *val = lookup;
695
696 /* new unique inode prefix and device combo */

--- 8 unchanged lines hidden (view full) ---

705static 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 }
659 if (err) {
660 return err;
661 }
662 } else {
663 if (pdu->s->dev_id != stbuf->st_dev) {
664 if (pdu->s->ctx.export_flags & V9FS_FORBID_MULTIDEVS) {
665 error_report_once(
666 "9p: Multiple devices detected in same VirtFS export. "

--- 3148 unchanged lines hidden (view full) ---

3815 error_setg(errp, "share path %s is not a directory", fse->path);
3816 goto out;
3817 }
3818
3819 s->dev_id = stat.st_dev;
3820
3821 qpp_table_init(&s->qpp_table);
3822 s->qp_prefix_next = 1; /* reserve 0 to detect overflow */
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. "

--- 3148 unchanged lines hidden (view full) ---

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;
3823
3824 s->ctx.fst = &fse->fst;
3825 fsdev_throttle_init(s->ctx.fst);
3826
3827 rc = 0;
3828out:
3829 if (rc) {
3830 v9fs_device_unrealize_common(s, NULL);

--- 6 unchanged lines hidden (view full) ---

3837{
3838 if (s->ops && s->ops->cleanup) {
3839 s->ops->cleanup(&s->ctx);
3840 }
3841 if (s->ctx.fst) {
3842 fsdev_throttle_cleanup(s->ctx.fst);
3843 }
3844 g_free(s->tag);
3882
3883 s->ctx.fst = &fse->fst;
3884 fsdev_throttle_init(s->ctx.fst);
3885
3886 rc = 0;
3887out:
3888 if (rc) {
3889 v9fs_device_unrealize_common(s, NULL);

--- 6 unchanged lines hidden (view full) ---

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);
3845 qpp_table_destroy(&s->qpp_table);
3904 qp_table_destroy(&s->qpp_table);
3905 qp_table_destroy(&s->qpf_table);
3846 g_free(s->ctx.fs_root);
3847}
3848
3849typedef struct VirtfsCoResetData {
3850 V9fsPDU pdu;
3851 bool done;
3852} VirtfsCoResetData;
3853

--- 35 unchanged lines hidden ---
3906 g_free(s->ctx.fs_root);
3907}
3908
3909typedef struct VirtfsCoResetData {
3910 V9fsPDU pdu;
3911 bool done;
3912} VirtfsCoResetData;
3913

--- 35 unchanged lines hidden ---