Page MenuHomeFreeBSD

D46295.id156285.diff
No OneTemporary

D46295.id156285.diff

diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -352,6 +352,7 @@
device virtio_blk # VirtIO Block device
device virtio_scsi # VirtIO SCSI device
device virtio_balloon # VirtIO Memory Balloon device
+device virtio_fs # VirtIO File System device
# Linux KVM paravirtualization support
device kvm_clock # KVM paravirtual clock driver
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3443,6 +3443,7 @@
dev/virtio/random/virtio_random.c optional virtio_random
dev/virtio/scmi/virtio_scmi.c optional virtio_scmi
dev/virtio/scsi/virtio_scsi.c optional virtio_scsi
+dev/virtio/fs/virtio_fs.c optional virtio_fs
dev/vkbd/vkbd.c optional vkbd
dev/vmgenc/vmgenc_acpi.c optional acpi
dev/vmware/vmxnet3/if_vmx.c optional vmx
diff --git a/sys/dev/virtio/fs/virtio_fs.h b/sys/dev/virtio/fs/virtio_fs.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/virtio/fs/virtio_fs.h
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2024, Emil Tsalapatis <emil@etsalapatis.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _VIRTIO_FS_H
+#define _VIRTIO_FS_H
+
+struct vtfs_softc;
+typedef struct vtfs_softc *vtfs_instance;
+typedef void (*vtfs_fuse_cb)(void *, uint32_t);
+typedef void (*vtfs_teardown_cb)(void *);
+
+void vtfs_register_cb(vtfs_instance, vtfs_fuse_cb, vtfs_fuse_cb,
+ vtfs_teardown_cb, void *);
+int vtfs_enqueue(vtfs_instance, void *, struct sglist *, int, int, bool);
+int vtfs_find(char *, vtfs_instance *);
+void vtfs_release(vtfs_instance);
+void vtfs_drain(vtfs_instance);
+void vtfs_unregister_cb(vtfs_instance);
+
+#endif /* _VIRTIO_FS_H */
diff --git a/sys/dev/virtio/fs/virtio_fs.c b/sys/dev/virtio/fs/virtio_fs.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/virtio/fs/virtio_fs.c
@@ -0,0 +1,617 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2024, Emil Tsalapatis <emil@etsalapatis.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Device for the VirtIO file system. */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/selinfo.h>
+#include <sys/sglist.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <sys/bus.h>
+
+#include <dev/virtio/virtio.h>
+#include <dev/virtio/virtqueue.h>
+#include <dev/virtio/fs/virtio_fs.h>
+
+#include "virtio_if.h"
+#include "virtio_fs_internal.h"
+
+SYSCTL_NODE(_dev, OID_AUTO, vtfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
+ "Virtio FS paravirt device");
+
+bool vtfs_debug = false;
+SYSCTL_BOOL(_dev_vtfs, OID_AUTO, debug, CTLFLAG_RW, &vtfs_debug, false,
+ "vtfs debug logging");
+
+#define VTFS_DEBUG(fmt, ...) \
+ do { \
+ if (vtfs_debug) \
+ printf("(%s:%d) " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+
+#define VTFS_ERR(fmt, ...) \
+ do { \
+ printf("[VTFS] (%s:%d) " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+
+/* Module-wide device list. */
+
+LIST_HEAD(, vtfs_softc) vtfs_contexts = LIST_HEAD_INITIALIZER(vtfs_contexts);
+struct mtx vtfs_mod_mtx;
+MTX_SYSINIT(vtfs_mod_mtx, &vtfs_mod_mtx, "Virtio FS Global Lock", MTX_DEF);
+
+#define VTFS_LOCK() mtx_lock(&vtfs_mod_mtx)
+#define VTFS_UNLOCK() mtx_unlock(&vtfs_mod_mtx)
+
+#define FSQ_LOCK(_fsq) mtx_lock(&(_fsq)->vtfsq_mtx)
+#define FSQ_UNLOCK(_fsq) mtx_unlock(&(_fsq)->vtfsq_mtx)
+#define FSQ_WAIT(_fsq) cv_wait(&(_fsq)->vtfsq_cv, &(_fsq)->vtfsq_mtx)
+#define FSQ_KICK(_fsq) cv_broadcast(&(_fsq)->vtfsq_cv)
+
+static int vtfs_modevent(module_t, int, void *);
+
+static int vtfs_probe(device_t);
+static int vtfs_attach(device_t);
+static int vtfs_detach(device_t);
+
+static device_method_t vtfs_methods[] = {
+ DEVMETHOD(device_probe, vtfs_probe),
+ DEVMETHOD(device_attach, vtfs_attach),
+ DEVMETHOD(device_detach, vtfs_detach),
+ DEVMETHOD_END
+};
+
+static driver_t vtfs_driver = {
+ "vtfs",
+ vtfs_methods,
+ sizeof(struct vtfs_softc),
+};
+
+VIRTIO_DRIVER_MODULE(vtfs, vtfs_driver, vtfs_modevent, NULL);
+MODULE_VERSION(vtfs, 1);
+MODULE_DEPEND(vtfs, virtio, 1, 1, 1);
+
+VIRTIO_SIMPLE_PNPINFO(vtfs, VIRTIO_ID_FS, "VirtIO FS Adapter");
+
+static int
+vtfs_modevent(module_t mod, int type, void *unused)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ case MOD_UNLOAD:
+ case MOD_QUIESCE:
+ case MOD_SHUTDOWN:
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+vtfs_probe(device_t dev)
+{
+ return (VIRTIO_SIMPLE_PROBE(dev, vtfs));
+}
+
+static int
+vtfs_read_config(struct vtfs_softc *sc)
+{
+ device_t dev;
+ size_t taglen;
+#ifdef INVARIANTS
+ struct vtfs_config fscfg;
+#endif
+
+ dev = sc->vtfs_dev;
+
+ _Static_assert(sizeof(sc->vtfs_nqs) == sizeof(fscfg.num_request_queues),
+ "reading num_request_queues into wrongly typed struct");
+
+ virtio_read_device_config(dev,
+ offsetof(struct vtfs_config, num_request_queues),
+ &sc->vtfs_nqs,
+ sizeof(&sc->vtfs_nqs));
+
+ if (sc->vtfs_nqs <= 0) {
+ VTFS_ERR("read non-positive queue number from host");
+ return (EINVAL);
+ }
+
+ /* Account for the priority queue. */
+ sc->vtfs_nqs += 1;
+
+ virtio_read_device_config_array(dev,
+ offsetof(struct vtfs_config, tag),
+ sc->vtfs_tag, 1, TAG_SIZE);
+
+ /* The read tag may not be NUL-terminated. */
+ taglen = strnlen(sc->vtfs_tag, TAG_SIZE);
+ if (taglen == 0) {
+ VTFS_ERR("read empty tag");
+ return (EINVAL);
+ }
+
+ KASSERT(taglen < sizeof(sc->vtfs_tag), ("overran tag buffer"));
+ sc->vtfs_tag[taglen] = '\0';
+
+ VTFS_DEBUG("fs tag: %s, # vqs: %d", sc->vtfs_tag, sc->vtfs_nqs);
+
+ return (0);
+}
+
+static void
+vtfs_vq_intr(void *xfsq)
+{
+ struct vtfs_fsq *fsq = xfsq;
+ struct virtqueue *vq = fsq->vtfsq_vq;
+ uint32_t len;
+ void *ftick;
+
+ /* We turn off vtfs interrupts before removing the callback. */
+ KASSERT(fsq->vtfsq_cb != NULL, ("missing fuse callback"));
+
+ FSQ_LOCK(fsq);
+
+again:
+ /* Go through the tickets one by one, invoke the fuse callback. */
+ while ((ftick = virtqueue_dequeue(vq, &len)) != NULL)
+ fsq->vtfsq_cb(ftick, len);
+
+ /* If the host pushed another descriptor in the meantime, go again. */
+ if (virtqueue_enable_intr(vq) != 0) {
+ virtqueue_disable_intr(vq);
+ goto again;
+ }
+
+ FSQ_KICK(fsq);
+ FSQ_UNLOCK(fsq);
+}
+
+static int
+vtfs_init_fsq(struct vtfs_softc *sc, int id)
+{
+ struct vtfs_fsq *fsq = &sc->vtfs_fsqs[id];
+ int error;
+
+ if (id == 0) {
+ snprintf(fsq->vtfsq_name, sizeof(fsq->vtfsq_name),
+ "%s-priority", device_get_nameunit(sc->vtfs_dev));
+ } else {
+ snprintf(fsq->vtfsq_name, sizeof(fsq->vtfsq_name),
+ "%s-queue%d", device_get_nameunit(sc->vtfs_dev), id);
+ }
+
+ mtx_init(&fsq->vtfsq_mtx, fsq->vtfsq_name, NULL, MTX_DEF);
+ cv_init(&fsq->vtfsq_cv, "fsqvqcv");
+
+ fsq->vtfsq_tq = taskqueue_create("vtfsqtq", M_WAITOK,
+ taskqueue_thread_enqueue, &fsq->vtfsq_tq);
+ if (fsq->vtfsq_tq == NULL)
+ return (ENOMEM);
+
+ error = taskqueue_start_threads(&fsq->vtfsq_tq, VTFS_TQTHREAD,
+ PVM, "VirtioFS device");
+ if (error != 0)
+ return (error);
+
+ fsq->vtfsq_sc = sc;
+ VTFS_DEBUG("vq %s online", fsq->vtfsq_name);
+
+ return (0);
+}
+
+static void
+vtfs_fini_fsq(struct vtfs_fsq *fsq)
+{
+
+ if (fsq->vtfsq_sg != NULL) {
+ sglist_free(fsq->vtfsq_sg);
+ fsq->vtfsq_sg = NULL;
+ }
+
+ if (fsq->vtfsq_tq != NULL) {
+ taskqueue_drain_all(fsq->vtfsq_tq);
+ taskqueue_free(fsq->vtfsq_tq);
+ fsq->vtfsq_tq = NULL;
+ }
+
+ if (mtx_initialized(&fsq->vtfsq_mtx) != 0) {
+ cv_destroy(&fsq->vtfsq_cv);
+ mtx_destroy(&fsq->vtfsq_mtx);
+ }
+
+ VTFS_DEBUG("vq %s destroyed", fsq->vtfsq_name);
+}
+
+static int
+vtfs_alloc_fsqueues(struct vtfs_softc *sc)
+{
+ int error;
+ int nvqs;
+ int i, j;
+
+ nvqs = sc->vtfs_nqs;
+ sc->vtfs_fsqs = malloc((sizeof(*sc->vtfs_fsqs)) * nvqs, M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (sc->vtfs_fsqs == NULL)
+ return (ENOMEM);
+
+ for (i = 0; i < nvqs; i++) {
+ error = vtfs_init_fsq(sc, i);
+ if (error != 0)
+ goto fail;
+ }
+
+ return (0);
+
+fail:
+ VTFS_DEBUG("failed while initializing vq %d", i);
+
+ /* Clean up any initialized fsqs. */
+ for (j = 0; j < i; j++)
+ vtfs_fini_fsq(&sc->vtfs_fsqs[j]);
+
+ free(sc->vtfs_fsqs, M_DEVBUF);
+ sc->vtfs_fsqs = NULL;
+
+ return (error);
+}
+
+static void
+vtfs_free_fsqueues(struct vtfs_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->vtfs_nqs; i++)
+ vtfs_fini_fsq(&sc->vtfs_fsqs[i]);
+
+ free(sc->vtfs_fsqs, M_DEVBUF);
+ sc->vtfs_fsqs = NULL;
+}
+
+static int
+vtfs_alloc_virtqueues(struct vtfs_softc *sc)
+{
+ struct vq_alloc_info *vq_info;
+ struct vtfs_fsq *fsq;
+ device_t dev;
+ int error;
+ int nqs;
+ int i;
+
+ dev = sc->vtfs_dev;
+ nqs = sc->vtfs_nqs;
+
+ /*
+ * We have num_request_queues regular queues and one high-priority
+ * queue for FORGET/general priority operations.
+ */
+ KASSERT(nqs > 1, ("missing regular queues"));
+
+ vq_info = malloc(sizeof(*vq_info) * nqs, M_TEMP, M_NOWAIT);
+ if (vq_info == NULL)
+ return (ENOMEM);
+
+ for (i = 0; i < nqs; i++) {
+ fsq = &sc->vtfs_fsqs[i];
+ VQ_ALLOC_INFO_INIT(&vq_info[i], VTFS_MAXSEGS, vtfs_vq_intr,
+ fsq, &fsq->vtfsq_vq, "%s", fsq->vtfsq_name);
+ }
+
+ error = virtio_alloc_virtqueues(dev, nqs, vq_info);
+ free(vq_info, M_TEMP);
+
+ VTFS_DEBUG("virtqueues online");
+
+ return (error);
+}
+
+static int
+vtfs_enable_intr(device_t dev)
+{
+ struct vtfs_softc *sc;
+ int error;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ error = virtio_setup_intr(dev, INTR_TYPE_BIO);
+ if (error != 0)
+ return (error);
+
+ for (i = 0; i < sc->vtfs_nqs; i++)
+ virtqueue_enable_intr(sc->vtfs_fsqs[i].vtfsq_vq);
+
+
+ return (0);
+}
+
+static void
+vtfs_stop(struct vtfs_softc *sc)
+{
+ struct virtqueue *vq;
+ int i;
+
+ /* The file system should have cleared the virtqueues when umounting .*/
+ for (i = 0; i < sc->vtfs_nqs; i++) {
+ vq = sc->vtfs_fsqs[i].vtfsq_vq;
+ virtqueue_disable_intr(vq);
+ KASSERT(virtqueue_empty(vq), ("virtqueue not empty"));
+ }
+
+ virtio_stop(sc->vtfs_dev);
+
+}
+
+static void
+vtfs_add(struct vtfs_softc *sc)
+{
+ VTFS_LOCK();
+ LIST_INSERT_HEAD(&vtfs_contexts, sc, vtfs_link);
+ VTFS_UNLOCK();
+}
+static void
+vtfs_remove(struct vtfs_softc *sc)
+{
+ VTFS_LOCK();
+ LIST_REMOVE(sc, vtfs_link);
+ VTFS_UNLOCK();
+}
+
+int
+vtfs_find(char *tag, struct vtfs_softc **scp)
+{
+ struct vtfs_softc *sc;
+
+ VTFS_LOCK();
+
+ LIST_FOREACH(sc, &vtfs_contexts, vtfs_link) {
+ if (strncmp(sc->vtfs_tag, tag, sizeof(sc->vtfs_tag)) != 0)
+ continue;
+
+ if (sc->vtfs_inuse) {
+ VTFS_UNLOCK();
+ return (EALREADY);
+ }
+
+ sc->vtfs_inuse = true;
+ VTFS_UNLOCK();
+
+ *scp = sc;
+
+ return (0);
+ }
+
+ VTFS_UNLOCK();
+
+ return (EINVAL);
+}
+
+void
+vtfs_release(struct vtfs_softc *sc)
+{
+ VTFS_LOCK();
+ sc->vtfs_inuse = false;
+ VTFS_UNLOCK();
+}
+
+static int
+vtfs_attach(device_t dev)
+{
+ struct vtfs_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->vtfs_dev = dev;
+ sc->vtfs_inuse = false;
+
+ error = vtfs_read_config(sc);
+ if (error != 0)
+ goto fail;
+
+ error = vtfs_alloc_fsqueues(sc);
+ if (error != 0)
+ goto fail;
+
+ error = vtfs_alloc_virtqueues(sc);
+ if (error != 0)
+ goto fail;
+
+ error = vtfs_enable_intr(dev);
+ if (error != 0)
+ goto fail;
+
+ vtfs_add(sc);
+
+ return (0);
+
+fail:
+ vtfs_detach(dev);
+
+ return (error);
+}
+
+
+static int
+vtfs_detach(device_t dev)
+{
+ struct vtfs_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ vtfs_remove(sc);
+
+ /* Kill any active FUSE session. */
+ if (sc->vtfs_detach_cb)
+ sc->vtfs_detach_cb(sc->vtfs_detach_cb_arg);
+
+ vtfs_drain(sc);
+
+ vtfs_stop(sc);
+ vtfs_free_fsqueues(sc);
+
+ VTFS_DEBUG("device detached");
+
+ return (0);
+}
+
+void
+vtfs_register_cb(struct vtfs_softc *sc, vtfs_fuse_cb forget_cb,
+ vtfs_fuse_cb regular_cb, vtfs_teardown_cb detach_cb,
+ void *detach_cb_arg)
+{
+ struct vtfs_fsq *fsq;
+ int i;
+
+ sc->vtfs_detach_cb = detach_cb;
+ sc->vtfs_detach_cb_arg = detach_cb_arg;
+
+ for (i = 0; i < sc->vtfs_nqs; i++) {
+ fsq = &sc->vtfs_fsqs[i];
+ FSQ_LOCK(fsq);
+ if (i == VTFS_FORGET_FSQ)
+ fsq->vtfsq_cb = forget_cb;
+ else
+ fsq->vtfsq_cb = regular_cb;
+ FSQ_UNLOCK(fsq);
+ }
+
+}
+
+void
+vtfs_unregister_cb(struct vtfs_softc *sc)
+{
+ struct vtfs_fsq *fsq;
+ int i;
+
+ for (i = 0; i < sc->vtfs_nqs; i++) {
+ fsq = &sc->vtfs_fsqs[i];
+
+ FSQ_LOCK(fsq);
+ fsq->vtfsq_cb = NULL;
+ FSQ_UNLOCK(fsq);
+ }
+
+ sc->vtfs_detach_cb_arg = NULL;
+ sc->vtfs_detach_cb = NULL;
+}
+
+int
+vtfs_enqueue(struct vtfs_softc *sc, void *ftick, struct sglist *sg,
+ int readable, int writable, bool urgent)
+{
+ struct virtqueue *vq;
+ struct vtfs_fsq *fsq;
+ int error;
+
+ if (urgent)
+ fsq = &sc->vtfs_fsqs[VTFS_FORGET_FSQ];
+ else
+ fsq = &sc->vtfs_fsqs[VTFS_REGULAR_FSQ];
+
+ FSQ_LOCK(fsq);
+ vq = fsq->vtfsq_vq;
+
+ KASSERT(sg->sg_nseg == readable + writable, ("inconsistent segmentation"));
+
+ error = virtqueue_enqueue(vq, ftick, sg, readable, writable);
+ while (error == ENOSPC) {
+ FSQ_WAIT(fsq);
+ error = virtqueue_enqueue(vq, ftick, sg, readable, writable);
+ }
+
+ if (error != 0) {
+ FSQ_UNLOCK(fsq);
+ return (error);
+ }
+
+ virtqueue_notify(vq);
+
+ FSQ_UNLOCK(fsq);
+ sglist_free(sg);
+
+ return (0);
+}
+
+static void
+vtfs_drain_vq(struct vtfs_fsq *fsq)
+{
+ struct virtqueue *vq = fsq->vtfsq_vq;
+ uint32_t len;
+ void *ftick;
+
+ /*
+ * If there is no callback, we don't have an
+ * upper-level FUSE session.
+ */
+ if (fsq->vtfsq_cb == NULL) {
+ KASSERT(virtqueue_empty(vq), ("virtqueue not empty"));
+ return;
+ }
+
+ vq = fsq->vtfsq_vq;
+
+ while ((ftick = virtqueue_dequeue(vq, &len)) != NULL) {
+ fsq->vtfsq_cb(ftick, len);
+ }
+
+ KASSERT(virtqueue_empty(vq), ("virtqueue not empty"));
+}
+
+void
+vtfs_drain(struct vtfs_softc *sc)
+{
+ struct vtfs_fsq *fsq;
+ int i;
+
+ for (i = 0; i < sc->vtfs_nqs; i++) {
+ fsq = &sc->vtfs_fsqs[i];
+ FSQ_LOCK(fsq);
+ virtqueue_disable_intr(fsq->vtfsq_vq);
+ vtfs_drain_vq(fsq);
+ FSQ_UNLOCK(fsq);
+ }
+}
diff --git a/sys/dev/virtio/fs/virtio_fs_internal.h b/sys/dev/virtio/fs/virtio_fs_internal.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/virtio/fs/virtio_fs_internal.h
@@ -0,0 +1,50 @@
+#ifndef _VIRTIO_FS_INTERNAL_
+#define _VIRTIO_FS_INTERNAL_
+
+/* Protocol-specified file system tag size. */
+#define TAG_SIZE (36)
+#define FSQ_NAME_SIZE (16)
+
+/* Struct for the file system instance. Provided by the host. */
+struct vtfs_config {
+ /* UTF-8 File system tag. */
+ uint8_t tag[TAG_SIZE];
+ /* Number of request queues. */
+ uint32_t num_request_queues;
+ /* Minimum # bytes for each buffer in the notification queue. */
+ uint32_t notify_buf_size;
+} __packed;
+
+/* A queue structure belonging to a virtio fs device. */
+struct vtfs_fsq {
+ struct mtx vtfsq_mtx;
+ struct cv vtfsq_cv;
+ struct virtqueue *vtfsq_vq;
+ struct taskqueue *vtfsq_tq;
+ struct sglist *vtfsq_sg;
+ char vtfsq_name[FSQ_NAME_SIZE];
+ struct vtfs_softc *vtfsq_sc;
+ vtfs_fuse_cb vtfsq_cb;
+};
+
+/* A single virtio fs device instance. */
+struct vtfs_softc {
+ device_t vtfs_dev;
+ struct mtx vtfs_mtx;
+ struct vtfs_fsq *vtfs_fsqs;
+ bool vtfs_inuse; /* protected by the vtfs modulelock */
+ vtfs_teardown_cb vtfs_detach_cb;
+ void *vtfs_detach_cb_arg;
+ /* Host-provided config state. */
+ uint8_t vtfs_tag[TAG_SIZE + 1];
+ uint32_t vtfs_nqs;
+ LIST_ENTRY(vtfs_softc) vtfs_link;
+};
+
+#define VTFS_FORGET_FSQ (0)
+#define VTFS_REGULAR_FSQ (1)
+
+#define VTFS_MAXSEGS (16)
+#define VTFS_TQTHREAD (4)
+
+#endif /* _VIRTIO_FS_INTERNAL_ */
diff --git a/sys/modules/virtio/Makefile b/sys/modules/virtio/Makefile
--- a/sys/modules/virtio/Makefile
+++ b/sys/modules/virtio/Makefile
@@ -22,6 +22,6 @@
# SUCH DAMAGE.
#
-SUBDIR= virtio pci network block balloon scsi random console p9fs
+SUBDIR= virtio pci network block balloon scsi random console p9fs fs
.include <bsd.subdir.mk>
diff --git a/sys/modules/virtio/Makefile b/sys/modules/virtio/fs/Makefile
copy from sys/modules/virtio/Makefile
copy to sys/modules/virtio/fs/Makefile
--- a/sys/modules/virtio/Makefile
+++ b/sys/modules/virtio/fs/Makefile
@@ -1,5 +1,3 @@
-#
-#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
@@ -22,6 +20,11 @@
# SUCH DAMAGE.
#
-SUBDIR= virtio pci network block balloon scsi random console p9fs
+.PATH: ${SRCTOP}/sys/dev/virtio/fs
+
+KMOD= vtfs
+SRCS= virtio_fs.c
+SRCS+= virtio_bus_if.h virtio_if.h
+SRCS+= bus_if.h device_if.h
-.include <bsd.subdir.mk>
+.include <bsd.kmod.mk>

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 8, 7:32 PM (12 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28489477
Default Alt Text
D46295.id156285.diff (18 KB)

Event Timeline