|
From: Latchesar I. <li...@gm...> - 2010-08-29 16:30:42
|
Implements 9P transport that uses misc character device (major 10,
minor 237). The transport is an example on how to use the scatterlist
support.
Signed-off-by: Latchesar Ionkov <lu...@io...>
---
include/linux/miscdevice.h | 1 +
include/net/9p/client.h | 2 +
net/9p/Kconfig | 6 +
net/9p/Makefile | 5 +
net/9p/trans_dev.c | 678 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 692 insertions(+), 0 deletions(-)
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 18fd130..08a5f23 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -40,6 +40,7 @@
#define BTRFS_MINOR 234
#define AUTOFS_MINOR 235
#define MAPPER_CTRL_MINOR 236
+#define P9_MINOR 237
#define MISC_DYNAMIC_MINOR 255
struct device;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index d1aa2cf..ded9dd9 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -64,6 +64,7 @@ enum p9_trans_status {
* @REQ_STATUS_IDLE: request slot unused
* @REQ_STATUS_ALLOC: request has been allocated but not sent
* @REQ_STATUS_UNSENT: request waiting to be sent
+ * @REQ_STATUS_SENDING: request in process of being sent
* @REQ_STATUS_SENT: request sent to server
* @REQ_STATUS_FLSH: a flush has been sent for this request
* @REQ_STATUS_RCVD: response received from server
@@ -80,6 +81,7 @@ enum p9_req_status_t {
REQ_STATUS_IDLE,
REQ_STATUS_ALLOC,
REQ_STATUS_UNSENT,
+ REQ_STATUS_SENDING,
REQ_STATUS_SENT,
REQ_STATUS_FLSH,
REQ_STATUS_RCVD,
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index 7ed75c7..7dba1cb 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -28,6 +28,12 @@ config NET_9P_RDMA
help
This builds support for an RDMA transport.
+config NET_9P_DEV
+ depends on EXPERIMENTAL
+ tristate "9P Dev Transport (Experimental)"
+ help
+ This builds support for an 9P character device transport.
+
config NET_9P_DEBUG
bool "Debug information"
help
diff --git a/net/9p/Makefile b/net/9p/Makefile
index 198a640..477e62f 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_NET_9P) := 9pnet.o
obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
+obj-$(CONFIG_NET_9P_DEV) += 9pnet_dev.o
9pnet-objs := \
mod.o \
@@ -15,3 +16,7 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
9pnet_rdma-objs := \
trans_rdma.o \
+
+9pnet_dev-objs := \
+ trans_dev.o \
+
diff --git a/net/9p/trans_dev.c b/net/9p/trans_dev.c
new file mode 100644
index 0000000..ab181a1
--- /dev/null
+++ b/net/9p/trans_dev.c
@@ -0,0 +1,678 @@
+/*
+ * linux/fs/9p/trans_dev.c
+ *
+ * Dev transport layer.
+ *
+ * Copyright (C) 2010 by Latchesar Ionkov <lu...@io...>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include <linux/parser.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
+#include <net/9p/transport.h>
+
+struct p9dev_opts {
+ int fdno;
+};
+
+struct p9dev_trans {
+ atomic_t ref;
+ struct p9_client *client;
+ int err;
+ struct list_head req_list;
+ struct list_head unsent_req_list;
+ wait_queue_head_t wq;
+};
+
+struct file_operations p9dev_operations;
+
+/*
+ * Option Parsing (code inspired by NFS code)
+ * - a little lazy - parse all dev-transport options
+ */
+
+enum {
+ /* Options that take integer arguments */
+ Opt_fdno, Opt_err,
+};
+
+static const match_table_t tokens = {
+ {Opt_fdno, "fdno=%u"},
+ {Opt_err, NULL},
+};
+
+static struct p9_trans_module p9dev_trans;
+
+DEFINE_MUTEX(p9dev_mutex);
+DECLARE_WAIT_QUEUE_HEAD(p9dev_wq);
+
+static void p9dev_disconnect(struct p9dev_trans *ts, int err);
+
+static struct p9dev_trans *p9dev_get(struct file *filp)
+{
+ struct p9dev_trans *ts;
+
+ ts = filp->private_data;
+ if (ts)
+ atomic_inc(&ts->ref);
+
+ return ts;
+}
+
+static void p9dev_put(struct file *filp, struct p9dev_trans *ts)
+{
+ if (atomic_dec_and_test(&ts->ref)) {
+ if (filp)
+ filp->private_data = NULL;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "kfree ts\n");
+ kfree(ts);
+ }
+}
+
+/**
+ * parse_opts - parse mount options into p9_fd_opts structure
+ * @params: options string passed from mount
+ * @opts: fd transport-specific structure to parse options into
+ *
+ * Returns 0 upon success, -ERRNO upon failure
+ */
+
+static int parse_opts(char *params, struct p9dev_opts *opts)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ char *options, *tmp_options;
+ int ret;
+
+ opts->fdno = ~0;
+ if (!params)
+ return 0;
+
+ tmp_options = kstrdup(params, GFP_KERNEL);
+ if (!tmp_options) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "failed to allocate copy of option string\n");
+ return -ENOMEM;
+ }
+ options = tmp_options;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ int r;
+ if (!*p)
+ continue;
+ token = match_token(p, tokens, args);
+ if (token != Opt_err) {
+ r = match_int(&args[0], &option);
+ if (r < 0) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "integer field, but no integer?\n");
+ ret = r;
+ continue;
+ }
+ }
+ switch (token) {
+ case Opt_fdno:
+ opts->fdno = option;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ kfree(tmp_options);
+ return 0;
+}
+
+static int p9dev_create(struct p9_client *client, const char *addr, char *args)
+{
+ int err;
+ struct file *file;
+ struct p9dev_opts opts;
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "args %p %s\n", client, args);
+ err = parse_opts(args, &opts);
+ if (err < 0)
+ return err;
+
+ if (opts.fdno==-1) {
+ printk(KERN_ERR "v9fs: missing file descriptor option");
+ return -ENOPROTOOPT;
+ }
+
+ err = -EINVAL;
+ file = fget(opts.fdno);
+ if (!file) {
+ goto done;
+ }
+
+ if (file->f_op != &p9dev_operations) {
+ goto done;
+ }
+
+ ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ ts->client = client;
+ ts->err = 0;
+ atomic_set(&ts->ref, 1);
+ INIT_LIST_HEAD(&ts->req_list);
+ INIT_LIST_HEAD(&ts->unsent_req_list);
+ init_waitqueue_head(&ts->wq);
+ client->trans = ts;
+ client->status = Connected;
+
+ mutex_lock(&p9dev_mutex);
+ if (file->private_data != NULL) {
+ goto unlock_done;
+ }
+
+ file->private_data = ts;
+ fput(file);
+ err = 0;
+unlock_done:
+ mutex_unlock(&p9dev_mutex);
+
+done:
+ wake_up_all(&p9dev_wq);
+ return err;
+}
+
+static void p9dev_close(struct p9_client *client)
+{
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", client);
+ if (!client)
+ return;
+
+ ts = client->trans;
+ if (!ts)
+ return;
+
+ p9dev_disconnect(ts, -ECONNRESET);
+ client->status = Disconnected;
+ p9dev_put(NULL, ts);
+}
+
+static void p9dev_disconnect(struct p9dev_trans *ts, int err)
+{
+ struct p9_req_t *req, *rtmp;
+ LIST_HEAD(reqlist);
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", ts->client);
+ spin_lock(&ts->client->lock);
+ if (ts->err) {
+ spin_unlock(&ts->client->lock);
+ return;
+ }
+
+ ts->err = err;
+ list_for_each_entry_safe(req, rtmp, &ts->unsent_req_list, req_list) {
+ req->status = REQ_STATUS_ERROR;
+ req->t_err = err;
+ list_move_tail(&req->req_list, &reqlist);
+ }
+ list_for_each_entry_safe(req, rtmp, &ts->req_list, req_list) {
+ req->status = REQ_STATUS_ERROR;
+ req->t_err = err;
+ list_move_tail(&req->req_list, &reqlist);
+ }
+ spin_unlock(&ts->client->lock);
+
+ list_for_each_entry_safe(req, rtmp, &reqlist, req_list) {
+ list_del(&req->req_list);
+ p9_client_cb(ts->client, req);
+ }
+
+ wake_up_all(&ts->wq);
+}
+
+static int p9dev_request(struct p9_client *client, struct p9_req_t *req)
+{
+ int err;
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p req %p\n", client, req);
+ ts = client->trans;
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ return err;
+ }
+
+ req->status = REQ_STATUS_UNSENT;
+ list_add_tail(&req->req_list, &ts->unsent_req_list);
+ spin_unlock(&client->lock);
+ wake_up(&ts->wq);
+ return 0;
+}
+
+static int p9dev_cancel(struct p9_client *client, struct p9_req_t *req)
+{
+ int ret;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p req %p\n", client, req);
+ ret = 0;
+ spin_lock(&client->lock);
+ if (req->status == REQ_STATUS_UNSENT) {
+ list_del(&req->req_list);
+ req->status = REQ_STATUS_FLSHD;
+ } else if (req->status == REQ_STATUS_SENT || req->status == REQ_STATUS_SENDING)
+ req->status = REQ_STATUS_FLSH;
+ spin_unlock(&client->lock);
+ return ret;
+}
+
+static struct p9_trans_module p9dev_trans = {
+ .name = "dev",
+ .maxsize = 1024*1024,
+ .def = 0,
+ .flags = P9_TRANS_SG,
+ .create = p9dev_create,
+ .close = p9dev_close,
+ .request = p9dev_request,
+ .cancel = p9dev_cancel,
+ .owner = THIS_MODULE,
+};
+
+static ssize_t p9dev_copy_to_user(char __user *udata, size_t datalen,
+ struct p9_fcall *fc)
+{
+ int err, offset, len;
+ struct sg_mapping_iter miter;
+
+ if (p9_fcall_has_sg(fc)) {
+ offset = 0;
+ sg_miter_start(&miter, fc->sgpkt, fc->sgnum, SG_MITER_FROM_SG);
+ while (sg_miter_next(&miter) && offset < datalen) {
+ len = min(miter.length, datalen - offset);
+ err = copy_to_user(udata + offset, miter.addr, len);
+ if (err) {
+ err = -EINVAL;
+ break;
+ }
+
+ offset += len;
+ }
+ sg_miter_stop(&miter);
+ if (!err)
+ err = offset;
+ } else {
+ err = copy_to_user(udata, fc->sdata, fc->size);
+ if (!err)
+ err = fc->size;
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static ssize_t p9dev_read(struct file *filp, char __user *udata, size_t count,
+ loff_t * offset)
+{
+ int i, m, n, err, empty;
+ struct p9dev_trans *ts;
+ struct p9_client *client;
+ struct p9_req_t *req, *rtmp;
+ struct p9_req_t *reqs[16];
+ struct p9_fcall *tc;
+
+ while (!filp->private_data) {
+ err = wait_event_interruptible(p9dev_wq, filp->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(filp);
+ client = ts->client;
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p count %ld\n", client, count);
+
+again:
+ /* get as many requests as we can fit in the buffer */
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ goto error;
+ }
+
+ n = count;
+ m = 0;
+ empty = list_empty(&ts->unsent_req_list);
+ list_for_each_entry_safe(req, rtmp, &ts->unsent_req_list, req_list) {
+ if (n<req->tc->size || m>=ARRAY_SIZE(reqs))
+ break;
+
+ req->status = REQ_STATUS_SENDING;
+ reqs[m++] = req;
+ n -= req->tc->size;
+ }
+ spin_unlock(&client->lock);
+
+ /* if there are no request, we wait for one */
+ if (n == count) {
+ if (err < 0) {
+ return err;
+ }
+
+ if (!empty) {
+ /* there are unsent requests, but the buffer is too
+ small to fit even one */
+ err = -EINVAL;
+ goto error;
+ }
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p wait for requests\n", client);
+ err = wait_event_interruptible(ts->wq, !list_empty(&ts->unsent_req_list));
+ if (err < 0)
+ goto error;
+
+ goto again;
+ }
+
+ /* copy the data to the user buffer */
+ err = 0;
+ for(i = 0, n = count; i < m; i++) {
+ tc = reqs[i]->tc;
+ err = p9dev_copy_to_user(udata, n, tc);
+ if (err < 0)
+ break;
+
+ udata += err;
+ n -= err;
+ err = 0;
+ }
+
+ /* move the requests to the sent list */
+ spin_lock(&client->lock);
+ if (err) {
+ /* don't send anything, report the error */
+ for(i = 0; i < m; i++)
+ reqs[i]->status = REQ_STATUS_UNSENT;
+ } else {
+ for(i = 0; i < m; i++) {
+ reqs[i]->status = REQ_STATUS_SENT;
+ list_move_tail(&reqs[i]->req_list, &ts->req_list);
+ }
+ }
+ spin_unlock(&client->lock);
+
+ if (err)
+ goto error;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p total %ld\n", client, count - n);
+ *offset += count - n;
+ p9dev_put(filp, ts);
+ return count - n;
+
+error:
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p error %d\n", client, err);
+ p9dev_put(filp, ts);
+ return err;
+}
+
+static ssize_t p9dev_copy_from_user(struct p9_fcall *fc, int off,
+ const char __user *udata, size_t datalen)
+{
+ int err, offset, len;
+ struct sg_mapping_iter miter;
+
+ if (p9_fcall_has_sg(fc)) {
+ offset = 0;
+ sg_miter_start(&miter, fc->sgpkt, fc->sgnum, SG_MITER_TO_SG);
+ while (sg_miter_next(&miter) && offset < datalen) {
+ len = min(miter.length, datalen - offset);
+ P9_DPRINTK(P9_DEBUG_TRANS, "len %d miter.length %d\n", len, miter.length);
+ err = copy_from_user(miter.addr + off, udata + offset, len);
+ if (err) {
+ err = -EINVAL;
+ break;
+ }
+
+ offset += len;
+ off = 0;
+ }
+ sg_miter_stop(&miter);
+ if (err >= 0)
+ err = offset;
+ } else {
+ int i;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "datalen %d\n", datalen);
+ err = copy_from_user(fc->pkt, udata, datalen);
+ if (!err)
+ err = datalen;
+ }
+
+ return err;
+}
+
+static ssize_t p9dev_write(struct file *filp, const char __user * data,
+ size_t count, loff_t * offset)
+{
+ int err, n;
+ u8 buf[8], type;
+ u16 tag;
+ u32 size;
+ struct p9dev_trans *ts;
+ struct p9_client *client;
+ struct p9_req_t *req;
+
+ while (!filp->private_data) {
+ err = wait_event_interruptible(p9dev_wq, filp->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(filp);
+ client = ts->client;
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p count %ld\n", client, count);
+ n = count;
+ while (n >= 7) {
+ if (n >= 8)
+ err = copy_from_user(buf, data, 8);
+ else
+ err = copy_from_user(buf, data, 7);
+
+ if (err < 0)
+ goto error;
+
+ size = le32_to_cpu(*(__le32 *) &buf[0]);
+ type = buf[4];
+ tag = le16_to_cpu(*(__le32 *) &buf[5]);
+
+ if (n < size) {
+ /* we don't accept partial fcalls */
+ break;
+ }
+
+ req = p9_tag_lookup(client, tag);
+ if (!req || (req->status!=REQ_STATUS_SENT &&
+ req->status!=REQ_STATUS_FLSH)) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "unexpected packet tag %d type %d\n", tag, type);
+ err = -EIO;
+ goto error;
+ }
+
+ if (size==7)
+ memcpy(req->rc->pkt, buf, 7);
+ else {
+ err = p9dev_copy_from_user(req->rc, 0, data, size);
+ if (err < 0)
+ goto error;
+ }
+
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ goto error;
+ }
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p response for req %p\n", client, req);
+ if (req->status != REQ_STATUS_ERROR)
+ req->status = REQ_STATUS_RCVD;
+ list_del(&req->req_list);
+ spin_unlock(&client->lock);
+ p9_client_cb(client, req);
+ n -= size;
+ data += size;
+ }
+
+ /* if we can't read even one fcall, signal error */
+ if (n == count) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ *offset += count - n;
+ p9dev_put(filp, ts);
+ return count - n;
+
+error:
+ p9dev_put(filp, ts);
+ return err;
+}
+
+static unsigned int p9dev_poll(struct file *file, poll_table *wait)
+{
+ int err;
+ unsigned int mask;
+ struct p9dev_trans *ts;
+
+ mask = 0;
+
+ /* wait until the file is mounted */
+ while (!file->private_data) {
+ err = wait_event_interruptible(p9dev_wq, file->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(file);
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", ts->client);
+
+again:
+ spin_lock(&ts->client->lock);
+ if (ts->err)
+ mask |= POLLERR;
+
+ if (!list_empty(&ts->unsent_req_list))
+ mask |= POLLIN | POLLRDNORM;
+
+ if (!list_empty(&ts->req_list))
+ mask |= POLLOUT | POLLWRNORM;
+ spin_unlock(&ts->client->lock);
+
+ if (!mask) {
+ err = wait_event_interruptible(ts->wq,
+ !list_empty(&ts->unsent_req_list) ||
+ !list_empty(&ts->req_list));
+ if (err < 0) {
+ return POLLERR;
+ }
+
+ goto again;
+ }
+
+ p9dev_put(file, ts);
+ return mask;
+}
+
+static int p9dev_release(struct inode *inode, struct file *file)
+{
+ struct p9dev_trans *ts;
+
+ ts = p9dev_get(file);
+ if (!ts)
+ return 0;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "client %p\n", ts->client);
+ file->private_data = NULL;
+ p9dev_disconnect(ts, -ECONNRESET);
+ p9dev_put(file, ts);
+ return 0;
+}
+
+struct file_operations p9dev_operations = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = p9dev_read,
+ .aio_read = generic_file_aio_read,
+ .splice_read = generic_file_splice_read,
+ .write = p9dev_write,
+ .aio_write = generic_file_aio_write,
+ .splice_write = generic_file_splice_write,
+ .poll = p9dev_poll,
+ .release = p9dev_release,
+};
+EXPORT_SYMBOL_GPL(p9dev_operations);
+
+static struct miscdevice p9_miscdevice = {
+ .minor = P9_MINOR,
+ .name = "p9",
+ .fops = &p9dev_operations,
+};
+
+static int __init p9dev_init(void)
+{
+ int err;
+
+ err = misc_register(&p9_miscdevice);
+ if (err)
+ return err;
+
+ v9fs_register_trans(&p9dev_trans);
+ return 0;
+}
+
+static void __exit p9dev_exit(void)
+{
+ v9fs_unregister_trans(&p9dev_trans);
+ misc_deregister(&p9_miscdevice);
+}
+
+module_init(p9dev_init);
+module_exit(p9dev_exit);
+
+MODULE_AUTHOR("Latchesar Ionkov <lu...@io...>");
+MODULE_DESCRIPTION("9P Dev Transport");
+MODULE_LICENSE("GPL");
|
|
From: Latchesar I. <li...@gm...> - 2010-09-04 20:26:51
|
Implements 9P transport that uses misc character device (major 10,
minor 237). The transport is an example on how to use the scatterlist
support.
Signed-off-by: Latchesar Ionkov <lu...@io...>
---
include/linux/miscdevice.h | 1 +
include/net/9p/client.h | 2 +
net/9p/Kconfig | 6 +
net/9p/Makefile | 5 +
net/9p/trans_dev.c | 685 ++++++++++++++++++++++++++++++++++++++++++++
net/9p/trans_fd.c | 15 +-
6 files changed, 707 insertions(+), 7 deletions(-)
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 18fd130..08a5f23 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -40,6 +40,7 @@
#define BTRFS_MINOR 234
#define AUTOFS_MINOR 235
#define MAPPER_CTRL_MINOR 236
+#define P9_MINOR 237
#define MISC_DYNAMIC_MINOR 255
struct device;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index ccc3ab7..50a4d10 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -64,6 +64,7 @@ enum p9_trans_status {
* @REQ_STATUS_IDLE: request slot unused
* @REQ_STATUS_ALLOC: request has been allocated but not sent
* @REQ_STATUS_UNSENT: request waiting to be sent
+ * @REQ_STATUS_SENDING: request in process of being sent
* @REQ_STATUS_SENT: request sent to server
* @REQ_STATUS_FLSH: a flush has been sent for this request
* @REQ_STATUS_RCVD: response received from server
@@ -80,6 +81,7 @@ enum p9_req_status_t {
REQ_STATUS_IDLE,
REQ_STATUS_ALLOC,
REQ_STATUS_UNSENT,
+ REQ_STATUS_SENDING,
REQ_STATUS_SENT,
REQ_STATUS_FLSH,
REQ_STATUS_RCVD,
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index 7ed75c7..7dba1cb 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -28,6 +28,12 @@ config NET_9P_RDMA
help
This builds support for an RDMA transport.
+config NET_9P_DEV
+ depends on EXPERIMENTAL
+ tristate "9P Dev Transport (Experimental)"
+ help
+ This builds support for an 9P character device transport.
+
config NET_9P_DEBUG
bool "Debug information"
help
diff --git a/net/9p/Makefile b/net/9p/Makefile
index 198a640..477e62f 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_NET_9P) := 9pnet.o
obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
+obj-$(CONFIG_NET_9P_DEV) += 9pnet_dev.o
9pnet-objs := \
mod.o \
@@ -15,3 +16,7 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
9pnet_rdma-objs := \
trans_rdma.o \
+
+9pnet_dev-objs := \
+ trans_dev.o \
+
diff --git a/net/9p/trans_dev.c b/net/9p/trans_dev.c
new file mode 100644
index 0000000..2ea9718
--- /dev/null
+++ b/net/9p/trans_dev.c
@@ -0,0 +1,685 @@
+/*
+ * linux/fs/9p/trans_dev.c
+ *
+ * Dev transport layer.
+ *
+ * Copyright (C) 2010 by Latchesar Ionkov <lu...@io...>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include <linux/parser.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
+#include <net/9p/transport.h>
+
+struct p9dev_opts {
+ int fdno;
+};
+
+struct p9dev_trans {
+ atomic_t ref;
+ struct p9_client *client;
+ int err;
+ struct list_head req_list;
+ struct list_head unsent_req_list;
+ wait_queue_head_t wq;
+};
+
+struct file_operations p9dev_operations;
+
+/*
+ * Option Parsing (code inspired by NFS code)
+ * - a little lazy - parse all dev-transport options
+ */
+
+enum {
+ /* Options that take integer arguments */
+ Opt_fdno, Opt_err,
+};
+
+static const match_table_t tokens = {
+ {Opt_fdno, "fdno=%u"},
+ {Opt_err, NULL},
+};
+
+static struct p9_trans_module p9dev_trans;
+
+DEFINE_MUTEX(p9dev_mutex);
+DECLARE_WAIT_QUEUE_HEAD(p9dev_wq);
+
+static void p9dev_disconnect(struct p9dev_trans *ts, int err);
+
+static struct p9dev_trans *p9dev_get(struct file *filp)
+{
+ struct p9dev_trans *ts;
+
+ ts = filp->private_data;
+ if (ts)
+ atomic_inc(&ts->ref);
+
+ return ts;
+}
+
+static void p9dev_put(struct file *filp, struct p9dev_trans *ts)
+{
+ if (atomic_dec_and_test(&ts->ref)) {
+ if (filp)
+ filp->private_data = NULL;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "kfree ts\n");
+ kfree(ts);
+ }
+}
+
+/**
+ * parse_opts - parse mount options into p9_fd_opts structure
+ * @params: options string passed from mount
+ * @opts: fd transport-specific structure to parse options into
+ *
+ * Returns 0 upon success, -ERRNO upon failure
+ */
+
+static int parse_opts(char *params, struct p9dev_opts *opts)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int option;
+ char *options, *tmp_options;
+ int ret;
+
+ opts->fdno = ~0;
+ if (!params)
+ return 0;
+
+ tmp_options = kstrdup(params, GFP_KERNEL);
+ if (!tmp_options) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "failed to allocate copy of option string\n");
+ return -ENOMEM;
+ }
+ options = tmp_options;
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token;
+ int r;
+ if (!*p)
+ continue;
+ token = match_token(p, tokens, args);
+ if (token != Opt_err) {
+ r = match_int(&args[0], &option);
+ if (r < 0) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "integer field, but no integer?\n");
+ ret = r;
+ continue;
+ }
+ }
+ switch (token) {
+ case Opt_fdno:
+ opts->fdno = option;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ kfree(tmp_options);
+ return 0;
+}
+
+static int p9dev_create(struct p9_client *client, const char *addr, char *args)
+{
+ int err;
+ struct file *file;
+ struct p9dev_opts opts;
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "args %p %s\n", client, args);
+ err = parse_opts(args, &opts);
+ if (err < 0)
+ return err;
+
+ if (opts.fdno==-1) {
+ printk(KERN_ERR "v9fs: missing file descriptor option");
+ return -ENOPROTOOPT;
+ }
+
+ err = -EINVAL;
+ file = fget(opts.fdno);
+ if (!file) {
+ goto done;
+ }
+
+ if (file->f_op != &p9dev_operations) {
+ goto done;
+ }
+
+ ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ ts->client = client;
+ ts->err = 0;
+ atomic_set(&ts->ref, 1);
+ INIT_LIST_HEAD(&ts->req_list);
+ INIT_LIST_HEAD(&ts->unsent_req_list);
+ init_waitqueue_head(&ts->wq);
+ client->trans = ts;
+ client->status = Connected;
+
+ mutex_lock(&p9dev_mutex);
+ if (file->private_data != NULL) {
+ goto unlock_done;
+ }
+
+ file->private_data = ts;
+ fput(file);
+ err = 0;
+unlock_done:
+ mutex_unlock(&p9dev_mutex);
+
+done:
+ wake_up_all(&p9dev_wq);
+ return err;
+}
+
+static void p9dev_close(struct p9_client *client)
+{
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", client);
+ if (!client)
+ return;
+
+ ts = client->trans;
+ if (!ts)
+ return;
+
+ p9dev_disconnect(ts, -ECONNRESET);
+ client->status = Disconnected;
+ p9dev_put(NULL, ts);
+}
+
+static void p9dev_disconnect(struct p9dev_trans *ts, int err)
+{
+ struct p9_req_t *req, *rtmp;
+ LIST_HEAD(reqlist);
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", ts->client);
+ spin_lock(&ts->client->lock);
+ if (ts->err) {
+ spin_unlock(&ts->client->lock);
+ return;
+ }
+
+ ts->err = err;
+ list_for_each_entry_safe(req, rtmp, &ts->unsent_req_list, req_list) {
+ req->status = REQ_STATUS_ERROR;
+ req->t_err = err;
+ list_move_tail(&req->req_list, &reqlist);
+ }
+ list_for_each_entry_safe(req, rtmp, &ts->req_list, req_list) {
+ req->status = REQ_STATUS_ERROR;
+ req->t_err = err;
+ list_move_tail(&req->req_list, &reqlist);
+ }
+ spin_unlock(&ts->client->lock);
+
+ list_for_each_entry_safe(req, rtmp, &reqlist, req_list) {
+ list_del(&req->req_list);
+ p9_client_cb(ts->client, req);
+ }
+
+ wake_up_all(&ts->wq);
+}
+
+static int p9dev_request(struct p9_client *client, struct p9_req_t *req)
+{
+ int err;
+ struct p9dev_trans *ts;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p req %p\n", client, req);
+ ts = client->trans;
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ return err;
+ }
+
+ req->status = REQ_STATUS_UNSENT;
+ list_add_tail(&req->req_list, &ts->unsent_req_list);
+ spin_unlock(&client->lock);
+ wake_up(&ts->wq);
+ return 0;
+}
+
+static int p9dev_cancel(struct p9_client *client, struct p9_req_t *req)
+{
+ int ret;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p req %p\n", client, req);
+ ret = 0;
+ spin_lock(&client->lock);
+ if (req->status == REQ_STATUS_UNSENT) {
+ list_del(&req->req_list);
+ req->status = REQ_STATUS_FLSHD;
+ } else if (req->status == REQ_STATUS_SENT || req->status == REQ_STATUS_SENDING)
+ req->status = REQ_STATUS_FLSH;
+ spin_unlock(&client->lock);
+ return ret;
+}
+
+static struct p9_trans_module p9dev_trans = {
+ .name = "dev",
+ .maxsize = 1024*1024,
+ .def = 0,
+ .flags = P9_TRANS_SG,
+ .create = p9dev_create,
+ .close = p9dev_close,
+ .request = p9dev_request,
+ .cancel = p9dev_cancel,
+ .owner = THIS_MODULE,
+};
+
+static ssize_t p9dev_copy_to_user(char __user *udata, size_t datalen,
+ struct p9_fcall *fc)
+{
+ int err, offset, len;
+ struct sg_mapping_iter miter;
+
+ if (fc->sg) {
+ offset = 0;
+ sg_miter_start(&miter, fc->sg, fc->sgcount, SG_MITER_FROM_SG);
+ while (sg_miter_next(&miter) && offset < datalen) {
+ len = min(miter.length, datalen - offset);
+ err = copy_to_user(udata + offset, miter.addr, len);
+ if (err) {
+ err = -EINVAL;
+ break;
+ }
+
+ offset += len;
+ }
+ sg_miter_stop(&miter);
+ if (!err)
+ err = offset;
+ } else {
+ err = copy_to_user(udata, fc->buf, fc->size);
+ if (!err)
+ err = fc->size;
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static ssize_t p9dev_read(struct file *filp, char __user *udata, size_t count,
+ loff_t * offset)
+{
+ int i, m, n, err, empty;
+ struct p9dev_trans *ts;
+ struct p9_client *client;
+ struct p9_req_t *req, *rtmp;
+ struct p9_req_t *reqs[16];
+ struct p9_fcall *tc;
+
+ while (!filp->private_data) {
+ err = wait_event_interruptible(p9dev_wq, filp->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(filp);
+ client = ts->client;
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p count %ld\n", client, count);
+
+again:
+ /* get as many requests as we can fit in the buffer */
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ goto error;
+ }
+
+ n = count;
+ m = 0;
+ empty = list_empty(&ts->unsent_req_list);
+ list_for_each_entry_safe(req, rtmp, &ts->unsent_req_list, req_list) {
+ if (n<req->tc->size || m>=ARRAY_SIZE(reqs))
+ break;
+
+ req->status = REQ_STATUS_SENDING;
+ reqs[m++] = req;
+ n -= req->tc->size;
+ }
+ spin_unlock(&client->lock);
+
+ /* if there are no request, we wait for one */
+ if (n == count) {
+ if (err < 0) {
+ return err;
+ }
+
+ if (!empty) {
+ /* there are unsent requests, but the buffer is too
+ small to fit even one */
+ err = -EINVAL;
+ goto error;
+ }
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p wait for requests\n", client);
+ err = wait_event_interruptible(ts->wq, !list_empty(&ts->unsent_req_list));
+ if (err < 0)
+ goto error;
+
+ goto again;
+ }
+
+ /* copy the data to the user buffer */
+ err = 0;
+ for(i = 0, n = count; i < m; i++) {
+ tc = reqs[i]->tc;
+ err = p9dev_copy_to_user(udata, n, tc);
+ if (err < 0)
+ break;
+
+ udata += err;
+ n -= err;
+ err = 0;
+ }
+
+ /* move the requests to the sent list */
+ spin_lock(&client->lock);
+ if (err) {
+ /* don't send anything, report the error */
+ for(i = 0; i < m; i++)
+ reqs[i]->status = REQ_STATUS_UNSENT;
+ } else {
+ for(i = 0; i < m; i++) {
+ reqs[i]->status = REQ_STATUS_SENT;
+ list_move_tail(&reqs[i]->req_list, &ts->req_list);
+ }
+ }
+ spin_unlock(&client->lock);
+
+ if (err)
+ goto error;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p total %ld\n", client, count - n);
+ *offset += count - n;
+ p9dev_put(filp, ts);
+ return count - n;
+
+error:
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p error %d\n", client, err);
+ p9dev_put(filp, ts);
+ return err;
+}
+
+static ssize_t p9dev_copy_from_user(struct p9_fcall *fc, int off,
+ const char __user *udata, size_t datalen)
+{
+ int err, offset, len;
+ struct sg_mapping_iter miter;
+
+ if (fc->sg) {
+ offset = 0;
+ sg_miter_start(&miter, fc->sg, fc->sgcount, SG_MITER_TO_SG);
+ while (sg_miter_next(&miter) && offset < datalen) {
+ len = min(miter.length, datalen - offset);
+ err = copy_from_user(miter.addr + off, udata + offset, len);
+ if (err) {
+ err = -EINVAL;
+ break;
+ }
+
+ offset += len;
+ off = 0;
+ }
+ sg_miter_stop(&miter);
+ if (err >= 0)
+ err = offset;
+ } else {
+ err = copy_from_user(fc->buf, udata, datalen);
+ if (!err)
+ err = datalen;
+ }
+
+ return err;
+}
+
+static ssize_t p9dev_write(struct file *filp, const char __user * data,
+ size_t count, loff_t * offset)
+{
+ int err, n;
+ u8 buf[8], type;
+ u16 tag;
+ u32 size;
+ struct p9dev_trans *ts;
+ struct p9_client *client;
+ struct p9_req_t *req;
+
+ while (!filp->private_data) {
+ err = wait_event_interruptible(p9dev_wq, filp->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(filp);
+ client = ts->client;
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p count %ld\n", client, count);
+ n = count;
+ while (n >= 7) {
+ if (n >= 8)
+ err = copy_from_user(buf, data, 8);
+ else
+ err = copy_from_user(buf, data, 7);
+
+ if (err < 0)
+ goto error;
+
+ size = le32_to_cpu(*(__le32 *) &buf[0]);
+ type = buf[4];
+ tag = le16_to_cpu(*(__le32 *) &buf[5]);
+
+ if (n < size) {
+ /* we don't accept partial fcalls */
+ break;
+ }
+
+ req = p9_tag_lookup(client, tag);
+ if (!req || (req->status!=REQ_STATUS_SENT &&
+ req->status!=REQ_STATUS_FLSH)) {
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "unexpected packet tag %d type %d\n", tag, type);
+ err = -EIO;
+ goto error;
+ }
+
+ if (!req->rc) {
+ req->rc = p9_fcall_alloc(client, size);
+ if (!req->rc) {
+ err = -ENOMEM;
+ goto error;
+ }
+ }
+
+ if (size==7) {
+ memcpy(req->rc->buf, buf, 7);
+ req->rc->size = 7;
+ } else {
+ err = p9dev_copy_from_user(req->rc, 0, data, size);
+ if (err < 0)
+ goto error;
+
+ req->rc->size = err;
+ }
+
+ spin_lock(&client->lock);
+ if (ts->err) {
+ err = ts->err;
+ spin_unlock(&client->lock);
+ goto error;
+ }
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p response for req %p\n", client, req);
+ if (req->status != REQ_STATUS_ERROR)
+ req->status = REQ_STATUS_RCVD;
+ list_del(&req->req_list);
+ spin_unlock(&client->lock);
+ p9_client_cb(client, req);
+ n -= size;
+ data += size;
+ }
+
+ /* if we can't read even one fcall, signal error */
+ if (n == count) {
+ err = -EINVAL;
+ goto error;
+ }
+
+ *offset += count - n;
+ p9dev_put(filp, ts);
+ return count - n;
+
+error:
+ p9dev_put(filp, ts);
+ return err;
+}
+
+static unsigned int p9dev_poll(struct file *file, poll_table *wait)
+{
+ int err;
+ unsigned int mask;
+ struct p9dev_trans *ts;
+
+ mask = 0;
+
+ /* wait until the file is mounted */
+ while (!file->private_data) {
+ err = wait_event_interruptible(p9dev_wq, file->private_data != NULL);
+ if (err < 0)
+ return err;
+ }
+
+ ts = p9dev_get(file);
+ P9_DPRINTK(P9_DEBUG_TRANS, "%p\n", ts->client);
+
+again:
+ spin_lock(&ts->client->lock);
+ if (ts->err)
+ mask |= POLLERR;
+
+ if (!list_empty(&ts->unsent_req_list))
+ mask |= POLLIN | POLLRDNORM;
+
+ if (!list_empty(&ts->req_list))
+ mask |= POLLOUT | POLLWRNORM;
+ spin_unlock(&ts->client->lock);
+
+ if (!mask) {
+ err = wait_event_interruptible(ts->wq,
+ !list_empty(&ts->unsent_req_list) ||
+ !list_empty(&ts->req_list));
+ if (err < 0) {
+ return POLLERR;
+ }
+
+ goto again;
+ }
+
+ p9dev_put(file, ts);
+ return mask;
+}
+
+static int p9dev_release(struct inode *inode, struct file *file)
+{
+ struct p9dev_trans *ts;
+
+ ts = p9dev_get(file);
+ if (!ts)
+ return 0;
+
+ P9_DPRINTK(P9_DEBUG_TRANS, "client %p\n", ts->client);
+ file->private_data = NULL;
+ p9dev_disconnect(ts, -ECONNRESET);
+ p9dev_put(file, ts);
+ return 0;
+}
+
+struct file_operations p9dev_operations = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = p9dev_read,
+ .aio_read = generic_file_aio_read,
+ .splice_read = generic_file_splice_read,
+ .write = p9dev_write,
+ .aio_write = generic_file_aio_write,
+ .splice_write = generic_file_splice_write,
+ .poll = p9dev_poll,
+ .release = p9dev_release,
+};
+EXPORT_SYMBOL_GPL(p9dev_operations);
+
+static struct miscdevice p9_miscdevice = {
+ .minor = P9_MINOR,
+ .name = "p9",
+ .fops = &p9dev_operations,
+};
+
+static int __init p9dev_init(void)
+{
+ int err;
+
+ err = misc_register(&p9_miscdevice);
+ if (err)
+ return err;
+
+ v9fs_register_trans(&p9dev_trans);
+ return 0;
+}
+
+static void __exit p9dev_exit(void)
+{
+ v9fs_unregister_trans(&p9dev_trans);
+ misc_deregister(&p9_miscdevice);
+}
+
+module_init(p9dev_init);
+module_exit(p9dev_exit);
+
+MODULE_AUTHOR("Latchesar Ionkov <lu...@io...>");
+MODULE_DESCRIPTION("9P Dev Transport");
+MODULE_LICENSE("GPL");
|
|
From: Eric V. H. <er...@gm...> - 2010-08-29 18:03:53
|
On Sun, Aug 29, 2010 at 11:30 AM, Latchesar Ionkov <li...@gm...> wrote:
> Implements 9P transport that uses misc character device (major 10,
> minor 237). The transport is an example on how to use the scatterlist
> support.
>
So this is a special device just for 9P transport, kind of like a srv?
That's a pretty interesting approach -- I suppose it gives away some
of the issues with dealing with a raw file descriptor versus a socket.
The hassle of this though is that its a single instance per system --
wouldn't it be better to have a srv file system so you could support
an arbitrary number of srv files?
I guess the bigger problem is that you are still copying to/from user
space -- so you've just moved the overhead out of the 9p file system
and into the device. I suppose this is sort of unavoidable with raw
fd transports, although for sockets and pipes I was hoping to take
advantage of splice somehow.
Or am I missing something on my quick read through?
-eric
|
|
From: Latchesar I. <lu...@io...> - 2010-08-29 18:34:48
|
It is similar to the way FUSE communicates with its fs. I get up to
factor of 2 performance improvement over the standard socket
transport.
It is not exactly one instance per system, you can have multiple fs to
use it simultaneously. Each fs can open /dev/9p and pass the
(different) file descriptor to v9fs.
I need a fast way of talking to a local fs and the results with
/dev/9p are reasonable. In addition, the transport code is really
simple.
Thanks,
Lucho
On Sun, Aug 29, 2010 at 11:53 AM, Eric Van Hensbergen <er...@gm...> wrote:
> On Sun, Aug 29, 2010 at 11:30 AM, Latchesar Ionkov <li...@gm...> wrote:
>> Implements 9P transport that uses misc character device (major 10,
>> minor 237). The transport is an example on how to use the scatterlist
>> support.
>>
>
> So this is a special device just for 9P transport, kind of like a srv?
> That's a pretty interesting approach -- I suppose it gives away some
> of the issues with dealing with a raw file descriptor versus a socket.
> The hassle of this though is that its a single instance per system --
> wouldn't it be better to have a srv file system so you could support
> an arbitrary number of srv files?
>
> I guess the bigger problem is that you are still copying to/from user
> space -- so you've just moved the overhead out of the 9p file system
> and into the device. I suppose this is sort of unavoidable with raw
> fd transports, although for sockets and pipes I was hoping to take
> advantage of splice somehow.
>
> Or am I missing something on my quick read through?
>
> -eric
>
|
|
From: Eric V. H. <er...@gm...> - 2010-08-30 17:47:32
|
On Sun, Aug 29, 2010 at 1:31 PM, Latchesar Ionkov <lu...@io...> wrote:
> It is not exactly one instance per system, you can have multiple fs to
> use it simultaneously. Each fs can open /dev/9p and pass the
> (different) file descriptor to v9fs.
>
So the "server" opens /dev/9p to communicate, and then tells v9fs
where to mount with an fd that it gets from the /dev/9p open? I guess
the advantage of the srv approach is that it would allow clients in
multiple namespaces to mount the same file server -- but that might
involve a tighter coupling between dev-9p and the transport. In any
case, its something to think about -- I always though having a devsrv
like infrastructure in Linux would be nice, particularly with the
private namespace stuff.
-eric
|
|
From: Latchesar I. <lu...@io...> - 2010-08-30 18:54:23
|
devsrv wouldn't be hard to implement (as a file system), the biggest
issue I see is where to put it -- it should belong to fs/, because it
is a file system, but the only user would be net/9p :)
Pushing it into the standard kernel is another issue.
Lucho
On Mon, Aug 30, 2010 at 11:47 AM, Eric Van Hensbergen <er...@gm...> wrote:
> On Sun, Aug 29, 2010 at 1:31 PM, Latchesar Ionkov <lu...@io...> wrote:
>> It is not exactly one instance per system, you can have multiple fs to
>> use it simultaneously. Each fs can open /dev/9p and pass the
>> (different) file descriptor to v9fs.
>>
>
> So the "server" opens /dev/9p to communicate, and then tells v9fs
> where to mount with an fd that it gets from the /dev/9p open? I guess
> the advantage of the srv approach is that it would allow clients in
> multiple namespaces to mount the same file server -- but that might
> involve a tighter coupling between dev-9p and the transport. In any
> case, its something to think about -- I always though having a devsrv
> like infrastructure in Linux would be nice, particularly with the
> private namespace stuff.
>
> -eric
>
|
|
From: Eric V. H. <er...@gm...> - 2010-08-30 19:10:25
|
On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
> devsrv wouldn't be hard to implement (as a file system), the biggest
> issue I see is where to put it -- it should belong to fs/, because it
> is a file system, but the only user would be net/9p :)
>
Yeah, I was thinking about that too -- would be pretty weird perhaps
-- of course, ideally, net/9p would only be the first user. But the
point is still valid.
>
> Pushing it into the standard kernel is another issue.
>
Yeah, I don't think it would meet that much resistance if you are
getting 2x performance -- in fact it may be a good approach to
user<->kernel interfaces in general.
Although, it may be easier to get in as another file system versus a
device -- but I could be wrong there. We also need to take a look at
splice, vmsplice, etc. closer to see if there is any path there --
anthony rigged something out-of-kernel which was getting really great
performance using those abstractions, but its not as clear whether it
buys you anything for in-kernel. I'm trying to spend some time today
learning more about it.
-eric
|
|
From: Latchesar I. <lu...@io...> - 2010-08-30 19:15:09
|
I am using Go for my file servers these days and exotic stuff like
splice (and even writev/readv) is something that is out of the
possible things to play with.
BTW, for some reason I get about twice as good performance (as
measured by dbench) when using the Go version of u9fs when compared to
the npfs one.
Lucho
On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote:
> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
>> devsrv wouldn't be hard to implement (as a file system), the biggest
>> issue I see is where to put it -- it should belong to fs/, because it
>> is a file system, but the only user would be net/9p :)
>>
>
> Yeah, I was thinking about that too -- would be pretty weird perhaps
> -- of course, ideally, net/9p would only be the first user. But the
> point is still valid.
>
>>
>> Pushing it into the standard kernel is another issue.
>>
>
> Yeah, I don't think it would meet that much resistance if you are
> getting 2x performance -- in fact it may be a good approach to
> user<->kernel interfaces in general.
> Although, it may be easier to get in as another file system versus a
> device -- but I could be wrong there. We also need to take a look at
> splice, vmsplice, etc. closer to see if there is any path there --
> anthony rigged something out-of-kernel which was getting really great
> performance using those abstractions, but its not as clear whether it
> buys you anything for in-kernel. I'm trying to spend some time today
> learning more about it.
>
> -eric
>
|
|
From: Eric V. H. <er...@gm...> - 2010-08-30 19:23:50
|
On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote:
> I am using Go for my file servers these days and exotic stuff like
> splice (and even writev/readv) is something that is out of the
> possible things to play with.
>
fair enough.
> BTW, for some reason I get about twice as good performance (as
> measured by dbench) when using the Go version of u9fs when compared to
> the npfs one.
>
interesting. what changed? I thought when you measured stuff
initially, Go was like 4x worse?
-eric
|
|
From: Eric V. H. <er...@gm...> - 2011-02-07 22:05:05
|
hey, could you shoot me an example server so I can play around with
this. I'm trying to understand this better to look at merging it
upstream and also applying JV's approach to zero-copy to it.
-eric
On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote:
> I am using Go for my file servers these days and exotic stuff like
> splice (and even writev/readv) is something that is out of the
> possible things to play with.
>
> BTW, for some reason I get about twice as good performance (as
> measured by dbench) when using the Go version of u9fs when compared to
> the npfs one.
>
> Lucho
>
> On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote:
>> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
>>> devsrv wouldn't be hard to implement (as a file system), the biggest
>>> issue I see is where to put it -- it should belong to fs/, because it
>>> is a file system, but the only user would be net/9p :)
>>>
>>
>> Yeah, I was thinking about that too -- would be pretty weird perhaps
>> -- of course, ideally, net/9p would only be the first user. But the
>> point is still valid.
>>
>>>
>>> Pushing it into the standard kernel is another issue.
>>>
>>
>> Yeah, I don't think it would meet that much resistance if you are
>> getting 2x performance -- in fact it may be a good approach to
>> user<->kernel interfaces in general.
>> Although, it may be easier to get in as another file system versus a
>> device -- but I could be wrong there. We also need to take a look at
>> splice, vmsplice, etc. closer to see if there is any path there --
>> anthony rigged something out-of-kernel which was getting really great
>> performance using those abstractions, but its not as clear whether it
>> buys you anything for in-kernel. I'm trying to spend some time today
>> learning more about it.
>>
>> -eric
>>
>
|
|
From: Latchesar I. <lu...@io...> - 2011-02-08 15:17:46
|
Any 9p server should be able to use it. You just open /dev/9p and pass
it to v9fs with the rfdno/wfdno arguments. Then use it to listen for
9p messages on the same file descriptor.
Lucho
On Mon, Feb 7, 2011 at 3:04 PM, Eric Van Hensbergen <er...@gm...> wrote:
> hey, could you shoot me an example server so I can play around with
> this. I'm trying to understand this better to look at merging it
> upstream and also applying JV's approach to zero-copy to it.
>
> -eric
>
>
> On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote:
>> I am using Go for my file servers these days and exotic stuff like
>> splice (and even writev/readv) is something that is out of the
>> possible things to play with.
>>
>> BTW, for some reason I get about twice as good performance (as
>> measured by dbench) when using the Go version of u9fs when compared to
>> the npfs one.
>>
>> Lucho
>>
>> On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote:
>>> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
>>>> devsrv wouldn't be hard to implement (as a file system), the biggest
>>>> issue I see is where to put it -- it should belong to fs/, because it
>>>> is a file system, but the only user would be net/9p :)
>>>>
>>>
>>> Yeah, I was thinking about that too -- would be pretty weird perhaps
>>> -- of course, ideally, net/9p would only be the first user. But the
>>> point is still valid.
>>>
>>>>
>>>> Pushing it into the standard kernel is another issue.
>>>>
>>>
>>> Yeah, I don't think it would meet that much resistance if you are
>>> getting 2x performance -- in fact it may be a good approach to
>>> user<->kernel interfaces in general.
>>> Although, it may be easier to get in as another file system versus a
>>> device -- but I could be wrong there. We also need to take a look at
>>> splice, vmsplice, etc. closer to see if there is any path there --
>>> anthony rigged something out-of-kernel which was getting really great
>>> performance using those abstractions, but its not as clear whether it
>>> buys you anything for in-kernel. I'm trying to spend some time today
>>> learning more about it.
>>>
>>> -eric
>>>
>>
>
|
|
From: Eric V. H. <er...@gm...> - 2011-02-08 15:28:20
|
kk, was just hoping you had something canned I could use, but I'll try
and adapt an existing server...
-eric
On Tue, Feb 8, 2011 at 9:17 AM, Latchesar Ionkov <lu...@io...> wrote:
> Any 9p server should be able to use it. You just open /dev/9p and pass
> it to v9fs with the rfdno/wfdno arguments. Then use it to listen for
> 9p messages on the same file descriptor.
>
> Lucho
>
> On Mon, Feb 7, 2011 at 3:04 PM, Eric Van Hensbergen <er...@gm...> wrote:
>> hey, could you shoot me an example server so I can play around with
>> this. I'm trying to understand this better to look at merging it
>> upstream and also applying JV's approach to zero-copy to it.
>>
>> -eric
>>
>>
>> On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote:
>>> I am using Go for my file servers these days and exotic stuff like
>>> splice (and even writev/readv) is something that is out of the
>>> possible things to play with.
>>>
>>> BTW, for some reason I get about twice as good performance (as
>>> measured by dbench) when using the Go version of u9fs when compared to
>>> the npfs one.
>>>
>>> Lucho
>>>
>>> On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote:
>>>> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
>>>>> devsrv wouldn't be hard to implement (as a file system), the biggest
>>>>> issue I see is where to put it -- it should belong to fs/, because it
>>>>> is a file system, but the only user would be net/9p :)
>>>>>
>>>>
>>>> Yeah, I was thinking about that too -- would be pretty weird perhaps
>>>> -- of course, ideally, net/9p would only be the first user. But the
>>>> point is still valid.
>>>>
>>>>>
>>>>> Pushing it into the standard kernel is another issue.
>>>>>
>>>>
>>>> Yeah, I don't think it would meet that much resistance if you are
>>>> getting 2x performance -- in fact it may be a good approach to
>>>> user<->kernel interfaces in general.
>>>> Although, it may be easier to get in as another file system versus a
>>>> device -- but I could be wrong there. We also need to take a look at
>>>> splice, vmsplice, etc. closer to see if there is any path there --
>>>> anthony rigged something out-of-kernel which was getting really great
>>>> performance using those abstractions, but its not as clear whether it
>>>> buys you anything for in-kernel. I'm trying to spend some time today
>>>> learning more about it.
>>>>
>>>> -eric
>>>>
>>>
>>
>
|
|
From: Latchesar I. <lu...@io...> - 2011-02-08 16:05:04
|
I lost that stuff when I tried to install 9atom on the desktop and it
wiped the linux partition :(
Lucho
On Tue, Feb 8, 2011 at 8:28 AM, Eric Van Hensbergen <er...@gm...> wrote:
> kk, was just hoping you had something canned I could use, but I'll try
> and adapt an existing server...
>
> -eric
>
>
> On Tue, Feb 8, 2011 at 9:17 AM, Latchesar Ionkov <lu...@io...> wrote:
>> Any 9p server should be able to use it. You just open /dev/9p and pass
>> it to v9fs with the rfdno/wfdno arguments. Then use it to listen for
>> 9p messages on the same file descriptor.
>>
>> Lucho
>>
>> On Mon, Feb 7, 2011 at 3:04 PM, Eric Van Hensbergen <er...@gm...> wrote:
>>> hey, could you shoot me an example server so I can play around with
>>> this. I'm trying to understand this better to look at merging it
>>> upstream and also applying JV's approach to zero-copy to it.
>>>
>>> -eric
>>>
>>>
>>> On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote:
>>>> I am using Go for my file servers these days and exotic stuff like
>>>> splice (and even writev/readv) is something that is out of the
>>>> possible things to play with.
>>>>
>>>> BTW, for some reason I get about twice as good performance (as
>>>> measured by dbench) when using the Go version of u9fs when compared to
>>>> the npfs one.
>>>>
>>>> Lucho
>>>>
>>>> On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote:
>>>>> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote:
>>>>>> devsrv wouldn't be hard to implement (as a file system), the biggest
>>>>>> issue I see is where to put it -- it should belong to fs/, because it
>>>>>> is a file system, but the only user would be net/9p :)
>>>>>>
>>>>>
>>>>> Yeah, I was thinking about that too -- would be pretty weird perhaps
>>>>> -- of course, ideally, net/9p would only be the first user. But the
>>>>> point is still valid.
>>>>>
>>>>>>
>>>>>> Pushing it into the standard kernel is another issue.
>>>>>>
>>>>>
>>>>> Yeah, I don't think it would meet that much resistance if you are
>>>>> getting 2x performance -- in fact it may be a good approach to
>>>>> user<->kernel interfaces in general.
>>>>> Although, it may be easier to get in as another file system versus a
>>>>> device -- but I could be wrong there. We also need to take a look at
>>>>> splice, vmsplice, etc. closer to see if there is any path there --
>>>>> anthony rigged something out-of-kernel which was getting really great
>>>>> performance using those abstractions, but its not as clear whether it
>>>>> buys you anything for in-kernel. I'm trying to spend some time today
>>>>> learning more about it.
>>>>>
>>>>> -eric
>>>>>
>>>>
>>>
>>
>
> ------------------------------------------------------------------------------
> The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE:
> Pinpoint memory and threading errors before they happen.
> Find and fix more than 250 security defects in the development cycle.
> Locate bottlenecks in serial and parallel code that limit performance.
> http://p.sf.net/sfu/intel-dev2devfeb
> _______________________________________________
> V9fs-developer mailing list
> V9f...@li...
> https://lists.sourceforge.net/lists/listinfo/v9fs-developer
>
|
|
From: Eric V. H. <er...@gm...> - 2011-02-08 16:09:44
|
ouch. okay. fair enough. On Tue, Feb 8, 2011 at 10:04 AM, Latchesar Ionkov <lu...@io...> wrote: > I lost that stuff when I tried to install 9atom on the desktop and it > wiped the linux partition :( > > Lucho > > On Tue, Feb 8, 2011 at 8:28 AM, Eric Van Hensbergen <er...@gm...> wrote: >> kk, was just hoping you had something canned I could use, but I'll try >> and adapt an existing server... >> >> -eric >> >> >> On Tue, Feb 8, 2011 at 9:17 AM, Latchesar Ionkov <lu...@io...> wrote: >>> Any 9p server should be able to use it. You just open /dev/9p and pass >>> it to v9fs with the rfdno/wfdno arguments. Then use it to listen for >>> 9p messages on the same file descriptor. >>> >>> Lucho >>> >>> On Mon, Feb 7, 2011 at 3:04 PM, Eric Van Hensbergen <er...@gm...> wrote: >>>> hey, could you shoot me an example server so I can play around with >>>> this. I'm trying to understand this better to look at merging it >>>> upstream and also applying JV's approach to zero-copy to it. >>>> >>>> -eric >>>> >>>> >>>> On Mon, Aug 30, 2010 at 2:15 PM, Latchesar Ionkov <lu...@io...> wrote: >>>>> I am using Go for my file servers these days and exotic stuff like >>>>> splice (and even writev/readv) is something that is out of the >>>>> possible things to play with. >>>>> >>>>> BTW, for some reason I get about twice as good performance (as >>>>> measured by dbench) when using the Go version of u9fs when compared to >>>>> the npfs one. >>>>> >>>>> Lucho >>>>> >>>>> On Mon, Aug 30, 2010 at 1:10 PM, Eric Van Hensbergen <er...@gm...> wrote: >>>>>> On Mon, Aug 30, 2010 at 1:54 PM, Latchesar Ionkov <lu...@io...> wrote: >>>>>>> devsrv wouldn't be hard to implement (as a file system), the biggest >>>>>>> issue I see is where to put it -- it should belong to fs/, because it >>>>>>> is a file system, but the only user would be net/9p :) >>>>>>> >>>>>> >>>>>> Yeah, I was thinking about that too -- would be pretty weird perhaps >>>>>> -- of course, ideally, net/9p would only be the first user. But the >>>>>> point is still valid. >>>>>> >>>>>>> >>>>>>> Pushing it into the standard kernel is another issue. >>>>>>> >>>>>> >>>>>> Yeah, I don't think it would meet that much resistance if you are >>>>>> getting 2x performance -- in fact it may be a good approach to >>>>>> user<->kernel interfaces in general. >>>>>> Although, it may be easier to get in as another file system versus a >>>>>> device -- but I could be wrong there. We also need to take a look at >>>>>> splice, vmsplice, etc. closer to see if there is any path there -- >>>>>> anthony rigged something out-of-kernel which was getting really great >>>>>> performance using those abstractions, but its not as clear whether it >>>>>> buys you anything for in-kernel. I'm trying to spend some time today >>>>>> learning more about it. >>>>>> >>>>>> -eric >>>>>> >>>>> >>>> >>> >> >> ------------------------------------------------------------------------------ >> The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE: >> Pinpoint memory and threading errors before they happen. >> Find and fix more than 250 security defects in the development cycle. >> Locate bottlenecks in serial and parallel code that limit performance. >> http://p.sf.net/sfu/intel-dev2devfeb >> _______________________________________________ >> V9fs-developer mailing list >> V9f...@li... >> https://lists.sourceforge.net/lists/listinfo/v9fs-developer >> > |