From a80d923e1321a7ed69a0918de37e39871bb536a0 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: Make transports dynamic This patch abstracts out the interfaces to underlying transports so that new transports can be added as modules. This should also allow kernel configuration of transports without ifdef-hell. Signed-off-by: Eric Van Hensbergen --- Documentation/filesystems/9p.txt | 8 +- fs/9p/v9fs.c | 149 +++++++------- fs/9p/v9fs.h | 15 +- fs/9p/vfs_super.c | 19 +- include/net/9p/client.h | 4 +- include/net/9p/conn.h | 4 +- include/net/9p/transport.h | 25 ++- net/9p/Kconfig | 10 + net/9p/Makefile | 5 +- net/9p/client.c | 2 +- net/9p/mux.c | 4 +- net/9p/trans_fd.c | 419 ++++++++++++++++++++++++--------------- 12 files changed, 379 insertions(+), 285 deletions(-) diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index cda6905cbe4..1a5f50d3554 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt @@ -35,12 +35,12 @@ For remote file server: For Plan 9 From User Space applications (http://swtch.com/plan9) - mount -t 9p `namespace`/acme /mnt/9 -o proto=unix,uname=$USER + mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER OPTIONS ======= - proto=name select an alternative transport. Valid options are + trans=name select an alternative transport. Valid options are currently: unix - specifying a named pipe mount point tcp - specifying a normal TCP/IP connection @@ -68,9 +68,9 @@ OPTIONS 0x40 = display transport debug 0x80 = display allocation debug - rfdno=n the file descriptor for reading with proto=fd + rfdno=n the file descriptor for reading with trans=fd - wfdno=n the file descriptor for writing with proto=fd + wfdno=n the file descriptor for writing with trans=fd maxdata=n the number of bytes to use for 9p packet payload (msize) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 0a7068e30ec..08d880fb5b6 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -36,19 +36,59 @@ #include "v9fs.h" #include "v9fs_vfs.h" +/* + * Dynamic Transport Registration Routines + * + */ + +static LIST_HEAD(v9fs_trans_list); +static struct p9_trans_module *v9fs_default_trans; + +/** + * v9fs_register_trans - register a new transport with 9p + * @m - structure describing the transport module and entry points + * + */ +void v9fs_register_trans(struct p9_trans_module *m) +{ + list_add_tail(&m->list, &v9fs_trans_list); + if (m->def) + v9fs_default_trans = m; +} +EXPORT_SYMBOL(v9fs_register_trans); + +/** + * v9fs_match_trans - match transport versus registered transports + * @arg: string identifying transport + * + */ +static struct p9_trans_module *v9fs_match_trans(const substring_t *name) +{ + struct list_head *p; + struct p9_trans_module *t = NULL; + + list_for_each(p, &v9fs_trans_list) { + t = list_entry(p, struct p9_trans_module, list); + if (strncmp(t->name, name->from, name->to-name->from) == 0) { + P9_DPRINTK(P9_DEBUG_TRANS, "trans=%s\n", t->name); + break; + } + } + return t; +} + /* * Option Parsing (code inspired by NFS code) - * + * NOTE: each transport will parse its own options */ enum { /* Options that take integer arguments */ - Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, - Opt_rfdno, Opt_wfdno, + Opt_debug, Opt_msize, Opt_uid, Opt_gid, Opt_afid, /* String options */ - Opt_uname, Opt_remotename, + Opt_uname, Opt_remotename, Opt_trans, /* Options that take no arguments */ - Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci, + Opt_legacy, Opt_nodevmap, /* Cache options */ Opt_cache_loose, /* Error token */ @@ -57,24 +97,13 @@ enum { static match_table_t tokens = { {Opt_debug, "debug=%x"}, - {Opt_port, "port=%u"}, {Opt_msize, "msize=%u"}, {Opt_uid, "uid=%u"}, {Opt_gid, "gid=%u"}, {Opt_afid, "afid=%u"}, - {Opt_rfdno, "rfdno=%u"}, - {Opt_wfdno, "wfdno=%u"}, {Opt_uname, "uname=%s"}, {Opt_remotename, "aname=%s"}, - {Opt_unix, "proto=unix"}, - {Opt_tcp, "proto=tcp"}, - {Opt_fd, "proto=fd"}, -#ifdef CONFIG_PCI_9P - {Opt_pci, "proto=pci"}, -#endif - {Opt_tcp, "tcp"}, - {Opt_unix, "unix"}, - {Opt_fd, "fd"}, + {Opt_trans, "trans=%s"}, {Opt_legacy, "noextend"}, {Opt_nodevmap, "nodevmap"}, {Opt_cache_loose, "cache=loose"}, @@ -82,12 +111,6 @@ static match_table_t tokens = { {Opt_err, NULL} }; -extern struct p9_transport *p9pci_trans_create(void); - -/* - * Parse option string. - */ - /** * v9fs_parse_options - parse mount options into session structure * @options: options string passed from mount @@ -95,23 +118,21 @@ extern struct p9_transport *p9pci_trans_create(void); * */ -static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) +static void v9fs_parse_options(struct v9fs_session_info *v9ses) { - char *p; + char *options = v9ses->options; substring_t args[MAX_OPT_ARGS]; + char *p; int option; int ret; /* setup defaults */ - v9ses->port = V9FS_PORT; - v9ses->maxdata = 9000; - v9ses->proto = PROTO_TCP; + v9ses->maxdata = 8192; v9ses->extended = 1; v9ses->afid = ~0; v9ses->debug = 0; - v9ses->rfdno = ~0; - v9ses->wfdno = ~0; v9ses->cache = 0; + v9ses->trans = v9fs_default_trans; if (!options) return; @@ -135,9 +156,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) p9_debug_level = option; #endif break; - case Opt_port: - v9ses->port = option; - break; case Opt_msize: v9ses->maxdata = option; break; @@ -150,23 +168,8 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) case Opt_afid: v9ses->afid = option; break; - case Opt_rfdno: - v9ses->rfdno = option; - break; - case Opt_wfdno: - v9ses->wfdno = option; - break; - case Opt_tcp: - v9ses->proto = PROTO_TCP; - break; - case Opt_unix: - v9ses->proto = PROTO_UNIX; - break; - case Opt_pci: - v9ses->proto = PROTO_PCI; - break; - case Opt_fd: - v9ses->proto = PROTO_FD; + case Opt_trans: + v9ses->trans = v9fs_match_trans(&args[0]); break; case Opt_uname: match_strcpy(v9ses->name, &args[0]); @@ -201,7 +204,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, const char *dev_name, char *data) { int retval = -EINVAL; - struct p9_transport *trans; + struct p9_trans *trans = NULL; struct p9_fid *fid; v9ses->name = __getname(); @@ -217,39 +220,30 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, strcpy(v9ses->name, V9FS_DEFUSER); strcpy(v9ses->remotename, V9FS_DEFANAME); - v9fs_parse_options(data, v9ses); - - switch (v9ses->proto) { - case PROTO_TCP: - trans = p9_trans_create_tcp(dev_name, v9ses->port); - break; - case PROTO_UNIX: - trans = p9_trans_create_unix(dev_name); - *v9ses->remotename = 0; - break; - case PROTO_FD: - trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno); - *v9ses->remotename = 0; - break; -#ifdef CONFIG_PCI_9P - case PROTO_PCI: - trans = p9pci_trans_create(); - *v9ses->remotename = 0; - break; -#endif - default: - printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); - retval = -ENOPROTOOPT; + v9ses->options = kstrdup(data, GFP_KERNEL); + v9fs_parse_options(v9ses); + + if ((v9ses->trans == NULL) && !list_empty(&v9fs_trans_list)) + v9ses->trans = list_first_entry(&v9fs_trans_list, + struct p9_trans_module, list); + + if (v9ses->trans == NULL) { + retval = -EPROTONOSUPPORT; + P9_DPRINTK(P9_DEBUG_ERROR, + "No transport defined or default transport\n"); goto error; - }; + } + trans = v9ses->trans->create(dev_name, v9ses->options); if (IS_ERR(trans)) { retval = PTR_ERR(trans); trans = NULL; goto error; } + if ((v9ses->maxdata+P9_IOHDRSZ) > v9ses->trans->maxsize) + v9ses->maxdata = v9ses->trans->maxsize-P9_IOHDRSZ; - v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ, + v9ses->clnt = p9_client_create(trans, v9ses->maxdata+P9_IOHDRSZ, v9ses->extended); if (IS_ERR(v9ses->clnt)) { @@ -290,6 +284,7 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) __putname(v9ses->name); __putname(v9ses->remotename); + kfree(v9ses->options); } /** @@ -311,7 +306,7 @@ extern int v9fs_error_init(void); static int __init init_v9fs(void) { printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); - + /* TODO: Setup list of registered trasnport modules */ return register_filesystem(&v9fs_fs_type); } diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index abc4b1668ac..7eb135cf60c 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -31,31 +31,20 @@ struct v9fs_session_info { unsigned int maxdata; unsigned char extended; /* set to 1 if we are using UNIX extensions */ unsigned char nodev; /* set to 1 if no disable device mapping */ - unsigned short port; /* port to connect to */ unsigned short debug; /* debug level */ - unsigned short proto; /* protocol to use */ unsigned int afid; /* authentication fid */ - unsigned int rfdno; /* read file descriptor number */ - unsigned int wfdno; /* write file descriptor number */ unsigned int cache; /* cache mode */ + char *options; /* copy of mount options */ char *name; /* user name to mount as */ char *remotename; /* name of remote hierarchy being mounted */ unsigned int uid; /* default uid/muid for legacy support */ unsigned int gid; /* default gid for legacy support */ - + struct p9_trans_module *trans; /* 9p transport */ struct p9_client *clnt; /* 9p client */ struct dentry *debugfs_dir; }; -/* possible values of ->proto */ -enum { - PROTO_TCP, - PROTO_UNIX, - PROTO_FD, - PROTO_PCI, -}; - /* possible values of ->cache */ /* eventually support loose, tight, time, session, default always none */ enum { diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index ba904371218..bb0cef9a6b8 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -216,24 +216,7 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt) { struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; - if (v9ses->debug != 0) - seq_printf(m, ",debug=%x", v9ses->debug); - if (v9ses->port != V9FS_PORT) - seq_printf(m, ",port=%u", v9ses->port); - if (v9ses->maxdata != 9000) - seq_printf(m, ",msize=%u", v9ses->maxdata); - if (v9ses->afid != ~0) - seq_printf(m, ",afid=%u", v9ses->afid); - if (v9ses->proto == PROTO_UNIX) - seq_puts(m, ",proto=unix"); - if (v9ses->extended == 0) - seq_puts(m, ",noextend"); - if (v9ses->nodev == 1) - seq_puts(m, ",nodevmap"); - seq_printf(m, ",name=%s", v9ses->name); - seq_printf(m, ",aname=%s", v9ses->remotename); - seq_printf(m, ",uid=%u", v9ses->uid); - seq_printf(m, ",gid=%u", v9ses->gid); + seq_printf(m, "%s", v9ses->options); return 0; } diff --git a/include/net/9p/client.h b/include/net/9p/client.h index d65ed7c6906..0adafdb273f 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -29,7 +29,7 @@ struct p9_client { spinlock_t lock; /* protect client structure */ int msize; unsigned char dotu; - struct p9_transport *trans; + struct p9_trans *trans; struct p9_conn *conn; struct p9_idpool *fidpool; @@ -52,7 +52,7 @@ struct p9_fid { struct list_head dlist; /* list of all fids attached to a dentry */ }; -struct p9_client *p9_client_create(struct p9_transport *trans, int msize, +struct p9_client *p9_client_create(struct p9_trans *trans, int msize, int dotu); void p9_client_destroy(struct p9_client *clnt); void p9_client_disconnect(struct p9_client *clnt); diff --git a/include/net/9p/conn.h b/include/net/9p/conn.h index 583b6a2cb3d..756d8784f95 100644 --- a/include/net/9p/conn.h +++ b/include/net/9p/conn.h @@ -42,8 +42,8 @@ struct p9_req; */ typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); -struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, - unsigned char *dotu); +struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize, + unsigned char *dotu); void p9_conn_destroy(struct p9_conn *); int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc); diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 462d42279fb..7c68b3e8e78 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -26,24 +26,29 @@ #ifndef NET_9P_TRANSPORT_H #define NET_9P_TRANSPORT_H -enum p9_transport_status { +enum p9_trans_status { Connected, Disconnected, Hung, }; -struct p9_transport { - enum p9_transport_status status; +struct p9_trans { + enum p9_trans_status status; void *priv; + int (*write) (struct p9_trans *, void *, int); + int (*read) (struct p9_trans *, void *, int); + void (*close) (struct p9_trans *); + unsigned int (*poll)(struct p9_trans *, struct poll_table_struct *); +}; - int (*write) (struct p9_transport *, void *, int); - int (*read) (struct p9_transport *, void *, int); - void (*close) (struct p9_transport *); - unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *); +struct p9_trans_module { + struct list_head list; + char *name; /* name of transport */ + int maxsize; /* max message size of transport */ + int def; /* this transport should be default */ + struct p9_trans * (*create)(const char *devname, char *options); }; -struct p9_transport *p9_trans_create_tcp(const char *addr, int port); -struct p9_transport *p9_trans_create_unix(const char *addr); -struct p9_transport *p9_trans_create_fd(int rfd, int wfd); +void v9fs_register_trans(struct p9_trans_module *m); #endif /* NET_9P_TRANSPORT_H */ diff --git a/net/9p/Kconfig b/net/9p/Kconfig index 66821cd64a7..eecbf12f639 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig @@ -13,6 +13,16 @@ menuconfig NET_9P If unsure, say N. +config NET_9P_FD + depends on NET_9P + default y if NET_9P + tristate "9P File Descriptor Transports (Experimental)" + help + This builds support for file descriptor transports for 9p + which includes support for TCP/IP, named pipes, or passed + file descriptors. TCP/IP is the default transport for 9p, + so if you are going to use 9p, you'll likely want this. + config NET_9P_DEBUG bool "Debug information" depends on NET_9P diff --git a/net/9p/Makefile b/net/9p/Makefile index 85b3a7838ac..7b2a67abc0a 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile @@ -1,8 +1,8 @@ obj-$(CONFIG_NET_9P) := 9pnet.o +obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o 9pnet-objs := \ mod.o \ - trans_fd.o \ mux.o \ client.o \ conv.o \ @@ -11,3 +11,6 @@ obj-$(CONFIG_NET_9P) := 9pnet.o util.o \ 9pnet-$(CONFIG_SYSCTL) += sysctl.o + +9pnet_fd-objs := \ + trans_fd.o \ diff --git a/net/9p/client.c b/net/9p/client.c index cb170750337..e1610125a88 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -38,7 +38,7 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt); static void p9_fid_destroy(struct p9_fid *fid); static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu); -struct p9_client *p9_client_create(struct p9_transport *trans, int msize, +struct p9_client *p9_client_create(struct p9_trans *trans, int msize, int dotu) { int err, n; diff --git a/net/9p/mux.c b/net/9p/mux.c index 5d70558c4c6..934e2ea86e2 100644 --- a/net/9p/mux.c +++ b/net/9p/mux.c @@ -71,7 +71,7 @@ struct p9_conn { struct p9_mux_poll_task *poll_task; int msize; unsigned char *extended; - struct p9_transport *trans; + struct p9_trans *trans; struct p9_idpool *tagpool; int err; wait_queue_head_t equeue; @@ -271,7 +271,7 @@ static void p9_mux_poll_stop(struct p9_conn *m) * @msize - maximum message size * @extended - pointer to the extended flag */ -struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize, +struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize, unsigned char *extended) { int i, n; diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index fd636e94358..30269a4ff22 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -5,7 +5,7 @@ * * Copyright (C) 2006 by Russ Cox * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2005 by Eric Van Hensbergen + * Copyright (C) 2004-2007 by Eric Van Hensbergen * Copyright (C) 1997-2002 by Ron Minnich * * This program is free software; you can redistribute it and/or modify @@ -36,160 +36,114 @@ #include #include #include +#include #include #include #define P9_PORT 564 +#define MAX_SOCK_BUF (64*1024) + + +struct p9_fd_opts { + int rfd; + int wfd; + u16 port; +}; struct p9_trans_fd { struct file *rd; struct file *wr; }; -static int p9_socket_open(struct p9_transport *trans, struct socket *csocket); -static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd); -static int p9_fd_read(struct p9_transport *trans, void *v, int len); -static int p9_fd_write(struct p9_transport *trans, void *v, int len); -static unsigned int p9_fd_poll(struct p9_transport *trans, - struct poll_table_struct *pt); -static void p9_fd_close(struct p9_transport *trans); - -struct p9_transport *p9_trans_create_tcp(const char *addr, int port) -{ - int err; - struct p9_transport *trans; - struct socket *csocket; - struct sockaddr_in sin_server; - - csocket = NULL; - trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); - if (!trans) - return ERR_PTR(-ENOMEM); - - trans->write = p9_fd_write; - trans->read = p9_fd_read; - trans->close = p9_fd_close; - trans->poll = p9_fd_poll; - - sin_server.sin_family = AF_INET; - sin_server.sin_addr.s_addr = in_aton(addr); - sin_server.sin_port = htons(port); - sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); - - if (!csocket) { - P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); - err = -EIO; - goto error; - } - - err = csocket->ops->connect(csocket, - (struct sockaddr *)&sin_server, - sizeof(struct sockaddr_in), 0); - if (err < 0) { - P9_EPRINTK(KERN_ERR, - "p9_trans_tcp: problem connecting socket to %s\n", - addr); - goto error; - } - - err = p9_socket_open(trans, csocket); - if (err < 0) - goto error; +/* + * Option Parsing (code inspired by NFS code) + * - a little lazy - parse all fd-transport options + */ - return trans; +enum { + /* Options that take integer arguments */ + Opt_port, Opt_rfdno, Opt_wfdno, +}; -error: - if (csocket) - sock_release(csocket); +static match_table_t tokens = { + {Opt_port, "port=%u"}, + {Opt_rfdno, "rfdno=%u"}, + {Opt_wfdno, "wfdno=%u"}, +}; - kfree(trans); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_trans_create_tcp); +/** + * v9fs_parse_options - parse mount options into session structure + * @options: options string passed from mount + * @v9ses: existing v9fs session information + * + */ -struct p9_transport *p9_trans_create_unix(const char *addr) +static void parse_opts(char *options, struct p9_fd_opts *opts) { - int err; - struct socket *csocket; - struct sockaddr_un sun_server; - struct p9_transport *trans; - - csocket = NULL; - trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); - if (!trans) - return ERR_PTR(-ENOMEM); + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + int ret; - trans->write = p9_fd_write; - trans->read = p9_fd_read; - trans->close = p9_fd_close; - trans->poll = p9_fd_poll; + opts->port = P9_PORT; + opts->rfd = ~0; + opts->wfd = ~0; - if (strlen(addr) > UNIX_PATH_MAX) { - P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", - addr); - err = -ENAMETOOLONG; - goto error; - } + if (!options) + return; - sun_server.sun_family = PF_UNIX; - strcpy(sun_server.sun_path, addr); - sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); - err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, - sizeof(struct sockaddr_un) - 1, 0); - if (err < 0) { - P9_EPRINTK(KERN_ERR, - "p9_trans_unix: problem connecting socket: %s: %d\n", - addr, err); - goto error; + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + token = match_token(p, tokens, args); + ret = match_int(&args[0], &option); + if (ret < 0) { + P9_DPRINTK(P9_DEBUG_ERROR, + "integer field, but no integer?\n"); + continue; + } + switch (token) { + case Opt_port: + opts->port = option; + break; + case Opt_rfdno: + opts->rfd = option; + break; + case Opt_wfdno: + opts->wfd = option; + break; + default: + continue; + } } - - err = p9_socket_open(trans, csocket); - if (err < 0) - goto error; - - return trans; - -error: - if (csocket) - sock_release(csocket); - - kfree(trans); - return ERR_PTR(err); } -EXPORT_SYMBOL(p9_trans_create_unix); -struct p9_transport *p9_trans_create_fd(int rfd, int wfd) +static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) { - int err; - struct p9_transport *trans; + struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), + GFP_KERNEL); + if (!ts) + return -ENOMEM; - if (rfd == ~0 || wfd == ~0) { - printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); - return ERR_PTR(-ENOPROTOOPT); + ts->rd = fget(rfd); + ts->wr = fget(wfd); + if (!ts->rd || !ts->wr) { + if (ts->rd) + fput(ts->rd); + if (ts->wr) + fput(ts->wr); + kfree(ts); + return -EIO; } - trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL); - if (!trans) - return ERR_PTR(-ENOMEM); - - trans->write = p9_fd_write; - trans->read = p9_fd_read; - trans->close = p9_fd_close; - trans->poll = p9_fd_poll; - - err = p9_fd_open(trans, rfd, wfd); - if (err < 0) - goto error; - - return trans; + trans->priv = ts; + trans->status = Connected; -error: - kfree(trans); - return ERR_PTR(err); + return 0; } -EXPORT_SYMBOL(p9_trans_create_fd); -static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) +static int p9_socket_open(struct p9_trans *trans, struct socket *csocket) { int fd, ret; @@ -212,30 +166,6 @@ static int p9_socket_open(struct p9_transport *trans, struct socket *csocket) return 0; } -static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) -{ - struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), - GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->rd = fget(rfd); - ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } - - trans->priv = ts; - trans->status = Connected; - - return 0; -} - /** * p9_fd_read- read from a fd * @v9ses: session information @@ -243,7 +173,7 @@ static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd) * @len: size of receive buffer * */ -static int p9_fd_read(struct p9_transport *trans, void *v, int len) +static int p9_fd_read(struct p9_trans *trans, void *v, int len) { int ret; struct p9_trans_fd *ts = NULL; @@ -270,7 +200,7 @@ static int p9_fd_read(struct p9_transport *trans, void *v, int len) * @len: size of send buffer * */ -static int p9_fd_write(struct p9_transport *trans, void *v, int len) +static int p9_fd_write(struct p9_trans *trans, void *v, int len) { int ret; mm_segment_t oldfs; @@ -297,7 +227,7 @@ static int p9_fd_write(struct p9_transport *trans, void *v, int len) } static unsigned int -p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt) +p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) { int ret, n; struct p9_trans_fd *ts = NULL; @@ -341,7 +271,7 @@ end: * @trans: private socket structure * */ -static void p9_fd_close(struct p9_transport *trans) +static void p9_fd_close(struct p9_trans *trans) { struct p9_trans_fd *ts; @@ -361,3 +291,182 @@ static void p9_fd_close(struct p9_transport *trans) kfree(ts); } +static struct p9_trans *p9_trans_create_tcp(const char *addr, char *args) +{ + int err; + struct p9_trans *trans; + struct socket *csocket; + struct sockaddr_in sin_server; + struct p9_fd_opts opts; + + parse_opts(args, &opts); + + csocket = NULL; + trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + sin_server.sin_family = AF_INET; + sin_server.sin_addr.s_addr = in_aton(addr); + sin_server.sin_port = htons(opts.port); + sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); + + if (!csocket) { + P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); + err = -EIO; + goto error; + } + + err = csocket->ops->connect(csocket, + (struct sockaddr *)&sin_server, + sizeof(struct sockaddr_in), 0); + if (err < 0) { + P9_EPRINTK(KERN_ERR, + "p9_trans_tcp: problem connecting socket to %s\n", + addr); + goto error; + } + + err = p9_socket_open(trans, csocket); + if (err < 0) + goto error; + + return trans; + +error: + if (csocket) + sock_release(csocket); + + kfree(trans); + return ERR_PTR(err); +} + +static struct p9_trans *p9_trans_create_unix(const char *addr, char *args) +{ + int err; + struct socket *csocket; + struct sockaddr_un sun_server; + struct p9_trans *trans; + + csocket = NULL; + trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + if (strlen(addr) > UNIX_PATH_MAX) { + P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", + addr); + err = -ENAMETOOLONG; + goto error; + } + + sun_server.sun_family = PF_UNIX; + strcpy(sun_server.sun_path, addr); + sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); + err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, + sizeof(struct sockaddr_un) - 1, 0); + if (err < 0) { + P9_EPRINTK(KERN_ERR, + "p9_trans_unix: problem connecting socket: %s: %d\n", + addr, err); + goto error; + } + + err = p9_socket_open(trans, csocket); + if (err < 0) + goto error; + + return trans; + +error: + if (csocket) + sock_release(csocket); + + kfree(trans); + return ERR_PTR(err); +} + +static struct p9_trans *p9_trans_create_fd(const char *name, char *args) +{ + int err; + struct p9_trans *trans; + struct p9_fd_opts opts; + + parse_opts(args, &opts); + + if (opts.rfd == ~0 || opts.wfd == ~0) { + printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); + return ERR_PTR(-ENOPROTOOPT); + } + + trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); + if (!trans) + return ERR_PTR(-ENOMEM); + + trans->write = p9_fd_write; + trans->read = p9_fd_read; + trans->close = p9_fd_close; + trans->poll = p9_fd_poll; + + err = p9_fd_open(trans, opts.rfd, opts.wfd); + if (err < 0) + goto error; + + return trans; + +error: + kfree(trans); + return ERR_PTR(err); +} + +static struct p9_trans_module p9_tcp_trans = { + .name = "tcp", + .maxsize = MAX_SOCK_BUF, + .def = 1, + .create = p9_trans_create_tcp, +}; + +static struct p9_trans_module p9_unix_trans = { + .name = "unix", + .maxsize = MAX_SOCK_BUF, + .def = 0, + .create = p9_trans_create_unix, +}; + +static struct p9_trans_module p9_fd_trans = { + .name = "fd", + .maxsize = MAX_SOCK_BUF, + .def = 0, + .create = p9_trans_create_fd, +}; + +static int __init p9_trans_fd_init(void) +{ + v9fs_register_trans(&p9_tcp_trans); + v9fs_register_trans(&p9_unix_trans); + v9fs_register_trans(&p9_fd_trans); + + return 1; +} + +static void __exit p9_trans_fd_exit(void) { + printk(KERN_ERR "Removal of 9p transports not implemented\n"); + BUG(); +} + +module_init(p9_trans_fd_init); +module_exit(p9_trans_fd_exit); + +MODULE_AUTHOR("Latchesar Ionkov "); +MODULE_AUTHOR("Eric Van Hensbergen "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 2405669b253670467c5c4b4effd160881bf4fbb7 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: define session flags Create more general flags field in the v9fs_session_info struct and move the 'extended' flag as a bit in the flags. Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.c | 6 +++--- fs/9p/v9fs.h | 12 +++++++++++- fs/9p/vfs_inode.c | 26 +++++++++++++------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 08d880fb5b6..8ac246700b7 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -128,7 +128,7 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) /* setup defaults */ v9ses->maxdata = 8192; - v9ses->extended = 1; + v9ses->flags = V9FS_EXTENDED; v9ses->afid = ~0; v9ses->debug = 0; v9ses->cache = 0; @@ -178,7 +178,7 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) match_strcpy(v9ses->remotename, &args[0]); break; case Opt_legacy: - v9ses->extended = 0; + v9ses->flags &= ~V9FS_EXTENDED; break; case Opt_nodevmap: v9ses->nodev = 1; @@ -244,7 +244,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->maxdata = v9ses->trans->maxsize-P9_IOHDRSZ; v9ses->clnt = p9_client_create(trans, v9ses->maxdata+P9_IOHDRSZ, - v9ses->extended); + v9fs_extended(v9ses)); if (IS_ERR(v9ses->clnt)) { retval = PTR_ERR(v9ses->clnt); diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 7eb135cf60c..804b3ef8fea 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -29,7 +29,7 @@ struct v9fs_session_info { /* options */ unsigned int maxdata; - unsigned char extended; /* set to 1 if we are using UNIX extensions */ + unsigned char flags; /* session flags */ unsigned char nodev; /* set to 1 if no disable device mapping */ unsigned short debug; /* debug level */ unsigned int afid; /* authentication fid */ @@ -45,6 +45,11 @@ struct v9fs_session_info { struct dentry *debugfs_dir; }; +/* session flags */ +enum { + V9FS_EXTENDED, +}; + /* possible values of ->cache */ /* eventually support loose, tight, time, session, default always none */ enum { @@ -70,3 +75,8 @@ static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) { return (inode->i_sb->s_fs_info); } + +static inline int v9fs_extended(struct v9fs_session_info *v9ses) +{ + return v9ses->flags & V9FS_EXTENDED; +} diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index e5c45eed58a..2270d06ccd5 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -59,7 +59,7 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode) res = mode & 0777; if (S_ISDIR(mode)) res |= P9_DMDIR; - if (v9ses->extended) { + if (v9fs_extended(v9ses)) { if (S_ISLNK(mode)) res |= P9_DMSYMLINK; if (v9ses->nodev == 0) { @@ -99,21 +99,21 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) if ((mode & P9_DMDIR) == P9_DMDIR) res |= S_IFDIR; - else if ((mode & P9_DMSYMLINK) && (v9ses->extended)) + else if ((mode & P9_DMSYMLINK) && (v9fs_extended(v9ses))) res |= S_IFLNK; - else if ((mode & P9_DMSOCKET) && (v9ses->extended) + else if ((mode & P9_DMSOCKET) && (v9fs_extended(v9ses)) && (v9ses->nodev == 0)) res |= S_IFSOCK; - else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended) + else if ((mode & P9_DMNAMEDPIPE) && (v9fs_extended(v9ses)) && (v9ses->nodev == 0)) res |= S_IFIFO; - else if ((mode & P9_DMDEVICE) && (v9ses->extended) + else if ((mode & P9_DMDEVICE) && (v9fs_extended(v9ses)) && (v9ses->nodev == 0)) res |= S_IFBLK; else res |= S_IFREG; - if (v9ses->extended) { + if (v9fs_extended(v9ses)) { if ((mode & P9_DMSETUID) == P9_DMSETUID) res |= S_ISUID; @@ -214,7 +214,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) case S_IFBLK: case S_IFCHR: case S_IFSOCK: - if(!v9ses->extended) { + if (!v9fs_extended(v9ses)) { P9_DPRINTK(P9_DEBUG_ERROR, "special files without extended mode\n"); return ERR_PTR(-EINVAL); @@ -227,7 +227,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) inode->i_fop = &v9fs_file_operations; break; case S_IFLNK: - if(!v9ses->extended) { + if (!v9fs_extended(v9ses)) { P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used w/o 9P2000.u\n"); return ERR_PTR(-EINVAL); @@ -236,7 +236,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) break; case S_IFDIR: inc_nlink(inode); - if(v9ses->extended) + if (v9fs_extended(v9ses)) inode->i_op = &v9fs_dir_inode_operations_ext; else inode->i_op = &v9fs_dir_inode_operations; @@ -768,7 +768,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) if (iattr->ia_valid & ATTR_SIZE) wstat.length = iattr->ia_size; - if (v9ses->extended) { + if (v9fs_extended(v9ses)) { if (iattr->ia_valid & ATTR_UID) wstat.n_uid = iattr->ia_uid; @@ -808,7 +808,7 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode, inode->i_uid = v9ses->uid; inode->i_gid = v9ses->gid; - if (v9ses->extended) { + if (v9fs_extended(v9ses)) { inode->i_uid = stat->n_uid; inode->i_gid = stat->n_gid; } @@ -890,7 +890,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) if(IS_ERR(fid)) return PTR_ERR(fid); - if (!v9ses->extended) + if (!v9fs_extended(v9ses)) return -EBADF; st = p9_client_stat(fid); @@ -1011,7 +1011,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, struct p9_fid *fid; v9ses = v9fs_inode2v9ses(dir); - if (!v9ses->extended) { + if (!v9fs_extended(v9ses)) { P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); return -EPERM; } -- cgit v1.2.3 From bd32b82df9876af439f1760a599c0e2da9198bda Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: rename uid and gid parameters Change the names of 'uid' and 'gid' parameters to the more appropriate 'dfltuid' and 'dfltgid'. This also sets the default uid/gid to -2 (aka nfsnobody) Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen --- Documentation/filesystems/9p.txt | 4 ++-- fs/9p/v9fs.c | 16 +++++++++------- fs/9p/v9fs.h | 8 +++++--- fs/9p/vfs_inode.c | 4 ++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index 1a5f50d3554..e694cd1b52c 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt @@ -78,9 +78,9 @@ OPTIONS noextend force legacy mode (no 9p2000.u semantics) - uid attempt to mount as a particular uid + dfltuid attempt to mount as a particular uid - gid attempt to mount with a particular gid + dfltgid attempt to mount with a particular gid afid security channel - used by Plan 9 authentication protocols diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 8ac246700b7..68f82be3bf3 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -84,7 +84,7 @@ static struct p9_trans_module *v9fs_match_trans(const substring_t *name) enum { /* Options that take integer arguments */ - Opt_debug, Opt_msize, Opt_uid, Opt_gid, Opt_afid, + Opt_debug, Opt_msize, Opt_dfltuid, Opt_dfltgid, Opt_afid, /* String options */ Opt_uname, Opt_remotename, Opt_trans, /* Options that take no arguments */ @@ -98,8 +98,8 @@ enum { static match_table_t tokens = { {Opt_debug, "debug=%x"}, {Opt_msize, "msize=%u"}, - {Opt_uid, "uid=%u"}, - {Opt_gid, "gid=%u"}, + {Opt_dfltuid, "dfltuid=%u"}, + {Opt_dfltgid, "dfltgid=%u"}, {Opt_afid, "afid=%u"}, {Opt_uname, "uname=%s"}, {Opt_remotename, "aname=%s"}, @@ -159,11 +159,11 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) case Opt_msize: v9ses->maxdata = option; break; - case Opt_uid: - v9ses->uid = option; + case Opt_dfltuid: + v9ses->dfltuid = option; break; - case Opt_gid: - v9ses->gid = option; + case Opt_dfltgid: + v9ses->dfltgid = option; break; case Opt_afid: v9ses->afid = option; @@ -219,6 +219,8 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, strcpy(v9ses->name, V9FS_DEFUSER); strcpy(v9ses->remotename, V9FS_DEFANAME); + v9ses->dfltuid = V9FS_DEFUID; + v9ses->dfltgid = V9FS_DEFGID; v9ses->options = kstrdup(data, GFP_KERNEL); v9fs_parse_options(v9ses); diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 804b3ef8fea..8e0999b3d0c 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -38,8 +38,8 @@ struct v9fs_session_info { char *options; /* copy of mount options */ char *name; /* user name to mount as */ char *remotename; /* name of remote hierarchy being mounted */ - unsigned int uid; /* default uid/muid for legacy support */ - unsigned int gid; /* default gid for legacy support */ + unsigned int dfltuid; /* default uid/muid for legacy support */ + unsigned int dfltgid; /* default gid for legacy support */ struct p9_trans_module *trans; /* 9p transport */ struct p9_client *clnt; /* 9p client */ struct dentry *debugfs_dir; @@ -67,9 +67,11 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses); #define V9FS_MAGIC 0x01021997 /* other default globals */ -#define V9FS_PORT 564 +#define V9FS_PORT 564 #define V9FS_DEFUSER "nobody" #define V9FS_DEFANAME "" +#define V9FS_DEFUID (-2) +#define V9FS_DEFGID (-2) static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) { diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 2270d06ccd5..f08a35d2973 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -805,8 +805,8 @@ v9fs_stat2inode(struct p9_stat *stat, struct inode *inode, inode->i_mtime.tv_sec = stat->mtime; inode->i_ctime.tv_sec = stat->mtime; - inode->i_uid = v9ses->uid; - inode->i_gid = v9ses->gid; + inode->i_uid = v9ses->dfltuid; + inode->i_gid = v9ses->dfltgid; if (v9fs_extended(v9ses)) { inode->i_uid = stat->n_uid; -- cgit v1.2.3 From ba17674fe02909fef049fd4b620a2805bdb8c693 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: attach-per-user The 9P2000 protocol requires the authentication and permission checks to be done in the file server. For that reason every user that accesses the file server tree has to authenticate and attach to the server separately. Multiple users can share the same connection to the server. Currently v9fs does a single attach and executes all I/O operations as a single user. This makes using v9fs in multiuser environment unsafe as it depends on the client doing the permission checking. This patch improves the 9P2000 support by allowing every user to attach separately. The patch defines three modes of access (new mount option 'access'): - attach-per-user (access=user) (default mode for 9P2000.u) If a user tries to access a file served by v9fs for the first time, v9fs sends an attach command to the server (Tattach) specifying the user. If the attach succeeds, the user can access the v9fs tree. As there is no uname->uid (string->integer) mapping yet, this mode works only with the 9P2000.u dialect. - allow only one user to access the tree (access=) Only the user with uid can access the v9fs tree. Other users that attempt to access it will get EPERM error. - do all operations as a single user (access=any) (default for 9P2000) V9fs does a single attach and all operations are done as a single user. If this mode is selected, the v9fs behavior is identical with the current one. Signed-off-by: Latchesar Ionkov Signed-off-by: Eric Van Hensbergen --- Documentation/filesystems/9p.txt | 10 +++ fs/9p/fid.c | 157 +++++++++++++++++++++++++++++++-------- fs/9p/v9fs.c | 67 +++++++++++++---- fs/9p/v9fs.h | 11 ++- fs/9p/vfs_inode.c | 20 ++--- include/net/9p/9p.h | 7 +- include/net/9p/client.h | 5 +- net/9p/client.c | 10 ++- net/9p/conv.c | 32 +++++++- 9 files changed, 247 insertions(+), 72 deletions(-) diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index e694cd1b52c..d6fd6c6e424 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt @@ -88,6 +88,16 @@ OPTIONS This can be used to share devices/named pipes/sockets between hosts. This functionality will be expanded in later versions. + access there are three access modes. + user = if a user tries to access a file on v9fs + filesystem for the first time, v9fs sends an + attach command (Tattach) for that user. + This is the default mode. + = allows only user with uid= to access + the files on the mounted filesystem + any = v9fs does single attach and performs all + operations as one user + RESOURCES ========= diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 15e05a15b57..b364da70ff2 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -1,6 +1,7 @@ /* * V9FS FID Management * + * Copyright (C) 2007 by Latchesar Ionkov * Copyright (C) 2005, 2006 by Eric Van Hensbergen * * This program is free software; you can redistribute it and/or modify @@ -34,9 +35,9 @@ #include "fid.h" /** - * v9fs_fid_insert - add a fid to a dentry + * v9fs_fid_add - add a fid to a dentry + * @dentry: dentry that the fid is being added to * @fid: fid to add - * @dentry: dentry that it is being added to * */ @@ -66,52 +67,144 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) } /** - * v9fs_fid_lookup - return a locked fid from a dentry + * v9fs_fid_find - retrieve a fid that belongs to the specified uid * @dentry: dentry to look for fid in - * - * find a fid in the dentry, obtain its semaphore and return a reference to it. - * code calling lookup is responsible for releasing lock - * - * TODO: only match fids that have the same uid as current user + * @uid: return fid that belongs to the specified user + * @any: if non-zero, return any fid associated with the dentry * */ -struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) +static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any) { struct v9fs_dentry *dent; - struct p9_fid *fid; - - P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); - dent = dentry->d_fsdata; - if (dent) - fid = list_entry(dent->fidlist.next, struct p9_fid, dlist); - else - fid = ERR_PTR(-EBADF); + struct p9_fid *fid, *ret; + + P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", + dentry->d_iname, dentry, uid, any); + dent = (struct v9fs_dentry *) dentry->d_fsdata; + ret = NULL; + if (dent) { + spin_lock(&dent->lock); + list_for_each_entry(fid, &dent->fidlist, dlist) { + if (any || fid->uid == uid) { + ret = fid; + break; + } + } + spin_unlock(&dent->lock); + } - P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid); - return fid; + return ret; } /** - * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and - * release it + * v9fs_fid_lookup - lookup for a fid, try to walk if not found * @dentry: dentry to look for fid in * - * find a fid in the dentry and then clone to a new private fid - * - * TODO: only match fids that have the same uid as current user - * + * Look for a fid in the specified dentry for the current user. + * If no fid is found, try to create one walking from a fid from the parent + * dentry (if it has one), or the root dentry. If the user haven't accessed + * the fs yet, attach now and walk from the root. */ -struct p9_fid *v9fs_fid_clone(struct dentry *dentry) +struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) { - struct p9_fid *ofid, *fid; + int i, n, l, clone, any, access; + u32 uid; + struct p9_fid *fid; + struct dentry *d, *ds; + struct v9fs_session_info *v9ses; + char **wnames, *uname; + + v9ses = v9fs_inode2v9ses(dentry->d_inode); + access = v9ses->flags & V9FS_ACCESS_MASK; + switch (access) { + case V9FS_ACCESS_SINGLE: + case V9FS_ACCESS_USER: + uid = current->fsuid; + any = 0; + break; + + case V9FS_ACCESS_ANY: + uid = v9ses->uid; + any = 1; + break; + + default: + uid = ~0; + any = 0; + break; + } - P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); - ofid = v9fs_fid_lookup(dentry); - if (IS_ERR(ofid)) - return ofid; + fid = v9fs_fid_find(dentry, uid, any); + if (fid) + return fid; + + ds = dentry->d_parent; + fid = v9fs_fid_find(ds, uid, any); + if (!fid) { /* walk from the root */ + n = 0; + for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) + n++; + + fid = v9fs_fid_find(ds, uid, any); + if (!fid) { /* the user is not attached to the fs yet */ + if (access == V9FS_ACCESS_SINGLE) + return ERR_PTR(-EPERM); + + if (v9fs_extended(v9ses)) + uname = NULL; + else + uname = v9ses->uname; + + fid = p9_client_attach(v9ses->clnt, NULL, uname, uid, + v9ses->aname); + + if (IS_ERR(fid)) + return fid; + + v9fs_fid_add(ds, fid); + } + } else /* walk from the parent */ + n = 1; + + if (ds == dentry) + return fid; + + wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); + if (!wnames) + return ERR_PTR(-ENOMEM); + + for (d = dentry, i = n; i >= 0; i--, d = d->d_parent) + wnames[i] = (char *) d->d_name.name; + + clone = 1; + i = 0; + while (i < n) { + l = min(n - i, P9_MAXWELEM); + fid = p9_client_walk(fid, l, &wnames[i], clone); + if (!fid) { + kfree(wnames); + return fid; + } + + i += l; + clone = 0; + } - fid = p9_client_walk(ofid, 0, NULL, 1); + kfree(wnames); + v9fs_fid_add(dentry, fid); return fid; } + +struct p9_fid *v9fs_fid_clone(struct dentry *dentry) +{ + struct p9_fid *fid, *ret; + + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return fid; + + ret = p9_client_walk(fid, 0, NULL, 1); + return ret; +} diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 68f82be3bf3..89ee0bace41 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -91,6 +91,8 @@ enum { Opt_legacy, Opt_nodevmap, /* Cache options */ Opt_cache_loose, + /* Access options */ + Opt_access, /* Error token */ Opt_err }; @@ -108,6 +110,7 @@ static match_table_t tokens = { {Opt_nodevmap, "nodevmap"}, {Opt_cache_loose, "cache=loose"}, {Opt_cache_loose, "loose"}, + {Opt_access, "access=%s"}, {Opt_err, NULL} }; @@ -125,10 +128,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) char *p; int option; int ret; + char *s, *e; /* setup defaults */ v9ses->maxdata = 8192; - v9ses->flags = V9FS_EXTENDED; v9ses->afid = ~0; v9ses->debug = 0; v9ses->cache = 0; @@ -172,10 +175,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) v9ses->trans = v9fs_match_trans(&args[0]); break; case Opt_uname: - match_strcpy(v9ses->name, &args[0]); + match_strcpy(v9ses->uname, &args[0]); break; case Opt_remotename: - match_strcpy(v9ses->remotename, &args[0]); + match_strcpy(v9ses->aname, &args[0]); break; case Opt_legacy: v9ses->flags &= ~V9FS_EXTENDED; @@ -186,6 +189,22 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) case Opt_cache_loose: v9ses->cache = CACHE_LOOSE; break; + + case Opt_access: + s = match_strdup(&args[0]); + v9ses->flags &= ~V9FS_ACCESS_MASK; + if (strcmp(s, "user") == 0) + v9ses->flags |= V9FS_ACCESS_USER; + else if (strcmp(s, "any") == 0) + v9ses->flags |= V9FS_ACCESS_ANY; + else { + v9ses->flags |= V9FS_ACCESS_SINGLE; + v9ses->uid = simple_strtol(s, &e, 10); + if (*e != '\0') + v9ses->uid = ~0; + } + break; + default: continue; } @@ -207,21 +226,22 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, struct p9_trans *trans = NULL; struct p9_fid *fid; - v9ses->name = __getname(); - if (!v9ses->name) + v9ses->uname = __getname(); + if (!v9ses->uname) return ERR_PTR(-ENOMEM); - v9ses->remotename = __getname(); - if (!v9ses->remotename) { - __putname(v9ses->name); + v9ses->aname = __getname(); + if (!v9ses->aname) { + __putname(v9ses->uname); return ERR_PTR(-ENOMEM); } - strcpy(v9ses->name, V9FS_DEFUSER); - strcpy(v9ses->remotename, V9FS_DEFANAME); + v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER; + strcpy(v9ses->uname, V9FS_DEFUSER); + strcpy(v9ses->aname, V9FS_DEFANAME); + v9ses->uid = ~0; v9ses->dfltuid = V9FS_DEFUID; v9ses->dfltgid = V9FS_DEFGID; - v9ses->options = kstrdup(data, GFP_KERNEL); v9fs_parse_options(v9ses); @@ -255,8 +275,20 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, goto error; } - fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name, - v9ses->remotename); + if (!v9ses->clnt->dotu) + v9ses->flags &= ~V9FS_EXTENDED; + + /* for legacy mode, fall back to V9FS_ACCESS_ANY */ + if (!v9fs_extended(v9ses) && + ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { + + v9ses->flags &= ~V9FS_ACCESS_MASK; + v9ses->flags |= V9FS_ACCESS_ANY; + v9ses->uid = ~0; + } + + fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0, + v9ses->aname); if (IS_ERR(fid)) { retval = PTR_ERR(fid); fid = NULL; @@ -264,6 +296,11 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, goto error; } + if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE) + fid->uid = v9ses->uid; + else + fid->uid = ~0; + return fid; error: @@ -284,8 +321,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) v9ses->clnt = NULL; } - __putname(v9ses->name); - __putname(v9ses->remotename); + __putname(v9ses->uname); + __putname(v9ses->aname); kfree(v9ses->options); } diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 8e0999b3d0c..db4b4193f2e 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -36,10 +36,11 @@ struct v9fs_session_info { unsigned int cache; /* cache mode */ char *options; /* copy of mount options */ - char *name; /* user name to mount as */ - char *remotename; /* name of remote hierarchy being mounted */ + char *uname; /* user name to mount as */ + char *aname; /* name of remote hierarchy being mounted */ unsigned int dfltuid; /* default uid/muid for legacy support */ unsigned int dfltgid; /* default gid for legacy support */ + u32 uid; /* if ACCESS_SINGLE, the uid that has access */ struct p9_trans_module *trans; /* 9p transport */ struct p9_client *clnt; /* 9p client */ struct dentry *debugfs_dir; @@ -47,7 +48,11 @@ struct v9fs_session_info { /* session flags */ enum { - V9FS_EXTENDED, + V9FS_EXTENDED = 0x01, /* 9P2000.u */ + V9FS_ACCESS_MASK = 0x06, /* access mask */ + V9FS_ACCESS_SINGLE = 0x02, /* only one user can access the files */ + V9FS_ACCESS_USER = 0x04, /* attache per user */ + V9FS_ACCESS_ANY = 0x06, /* use the same attach for all users */ }; /* possible values of ->cache */ diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index f08a35d2973..175b4d9bf3f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -364,7 +364,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) file_inode = file->d_inode; v9ses = v9fs_inode2v9ses(file_inode); v9fid = v9fs_fid_clone(file); - if(IS_ERR(v9fid)) + if (IS_ERR(v9fid)) return PTR_ERR(v9fid); return p9_client_remove(v9fid); @@ -398,7 +398,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, fid = NULL; name = (char *) dentry->d_name.name; dfid = v9fs_fid_clone(dentry->d_parent); - if(IS_ERR(dfid)) { + if (IS_ERR(dfid)) { err = PTR_ERR(dfid); dfid = NULL; goto error; @@ -432,7 +432,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, goto error; } - if(v9ses->cache) + if (v9ses->cache) dentry->d_op = &v9fs_cached_dentry_operations; else dentry->d_op = &v9fs_dentry_operations; @@ -593,7 +593,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, if (result < 0) goto error; - if((fid->qid.version)&&(v9ses->cache)) + if ((fid->qid.version) && (v9ses->cache)) dentry->d_op = &v9fs_cached_dentry_operations; else dentry->d_op = &v9fs_dentry_operations; @@ -658,17 +658,17 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, old_inode = old_dentry->d_inode; v9ses = v9fs_inode2v9ses(old_inode); oldfid = v9fs_fid_lookup(old_dentry); - if(IS_ERR(oldfid)) + if (IS_ERR(oldfid)) return PTR_ERR(oldfid); olddirfid = v9fs_fid_clone(old_dentry->d_parent); - if(IS_ERR(olddirfid)) { + if (IS_ERR(olddirfid)) { retval = PTR_ERR(olddirfid); goto done; } newdirfid = v9fs_fid_clone(new_dentry->d_parent); - if(IS_ERR(newdirfid)) { + if (IS_ERR(newdirfid)) { retval = PTR_ERR(newdirfid); goto clunk_olddir; } @@ -682,7 +682,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, } v9fs_blank_wstat(&wstat); - wstat.muid = v9ses->name; + wstat.muid = v9ses->uname; wstat.name = (char *) new_dentry->d_name.name; retval = p9_client_wstat(oldfid, &wstat); @@ -887,7 +887,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) retval = -EPERM; v9ses = v9fs_inode2v9ses(dentry->d_inode); fid = v9fs_fid_lookup(dentry); - if(IS_ERR(fid)) + if (IS_ERR(fid)) return PTR_ERR(fid); if (!v9fs_extended(v9ses)) @@ -1070,7 +1070,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, old_dentry->d_name.name); oldfid = v9fs_fid_clone(old_dentry); - if(IS_ERR(oldfid)) + if (IS_ERR(oldfid)) return PTR_ERR(oldfid); name = __getname(); diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 7726ff41c3e..7a448a30e39 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -216,6 +216,7 @@ struct p9_tauth { u32 afid; struct p9_str uname; struct p9_str aname; + u32 n_uname; /* 9P2000.u extensions */ }; struct p9_rauth { @@ -239,6 +240,7 @@ struct p9_tattach { u32 afid; struct p9_str uname; struct p9_str aname; + u32 n_uname; /* 9P2000.u extensions */ }; struct p9_rattach { @@ -382,8 +384,9 @@ int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu); void p9_set_tag(struct p9_fcall *fc, u16 tag); struct p9_fcall *p9_create_tversion(u32 msize, char *version); struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname, - char *aname); -struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname); + char *aname, u32 n_uname, int dotu); +struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname, + u32 n_uname, int dotu); struct p9_fcall *p9_create_tflush(u16 oldtag); struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, char **wnames); diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 0adafdb273f..9b9221a2139 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -57,8 +57,9 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize, void p9_client_destroy(struct p9_client *clnt); void p9_client_disconnect(struct p9_client *clnt); struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, - char *uname, char *aname); -struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname); + char *uname, u32 n_uname, char *aname); +struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, + u32 n_uname, char *aname); struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, int clone); int p9_client_open(struct p9_fid *fid, int mode); diff --git a/net/9p/client.c b/net/9p/client.c index e1610125a88..d83cc1247f1 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -146,7 +146,7 @@ void p9_client_disconnect(struct p9_client *clnt) EXPORT_SYMBOL(p9_client_disconnect); struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, - char *uname, char *aname) + char *uname, u32 n_uname, char *aname) { int err; struct p9_fcall *tc, *rc; @@ -165,7 +165,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, goto error; } - tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); + tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname, + n_uname, clnt->dotu); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; @@ -190,7 +191,8 @@ error: } EXPORT_SYMBOL(p9_client_attach); -struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) +struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, + u32 n_uname, char *aname) { int err; struct p9_fcall *tc, *rc; @@ -209,7 +211,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) goto error; } - tc = p9_create_tauth(fid->fid, uname, aname); + tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu); if (IS_ERR(tc)) { err = PTR_ERR(tc); tc = NULL; diff --git a/net/9p/conv.c b/net/9p/conv.c index d979d958ea1..aa2aa9884f9 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c @@ -547,7 +547,8 @@ error: } EXPORT_SYMBOL(p9_create_tversion); -struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) +struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname, + u32 n_uname, int dotu) { int size; struct p9_fcall *fc; @@ -555,7 +556,16 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) struct cbuf *bufp = &buffer; /* afid[4] uname[s] aname[s] */ - size = 4 + 2 + strlen(uname) + 2 + strlen(aname); + size = 4 + 2 + 2; + if (uname) + size += strlen(uname); + + if (aname) + size += strlen(aname); + + if (dotu) + size += 4; /* n_uname */ + fc = p9_create_common(bufp, size, P9_TAUTH); if (IS_ERR(fc)) goto error; @@ -563,6 +573,8 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) p9_put_int32(bufp, afid, &fc->params.tauth.afid); p9_put_str(bufp, uname, &fc->params.tauth.uname); p9_put_str(bufp, aname, &fc->params.tauth.aname); + if (dotu) + p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname); if (buf_check_overflow(bufp)) { kfree(fc); @@ -574,7 +586,8 @@ error: EXPORT_SYMBOL(p9_create_tauth); struct p9_fcall * -p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) +p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname, + u32 n_uname, int dotu) { int size; struct p9_fcall *fc; @@ -582,7 +595,16 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) struct cbuf *bufp = &buffer; /* fid[4] afid[4] uname[s] aname[s] */ - size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); + size = 4 + 4 + 2 + 2; + if (uname) + size += strlen(uname); + + if (aname) + size += strlen(aname); + + if (dotu) + size += 4; /* n_uname */ + fc = p9_create_common(bufp, size, P9_TATTACH); if (IS_ERR(fc)) goto error; @@ -591,6 +613,8 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) p9_put_int32(bufp, afid, &fc->params.tattach.afid); p9_put_str(bufp, uname, &fc->params.tattach.uname); p9_put_str(bufp, aname, &fc->params.tattach.aname); + if (dotu) + p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname); error: return fc; -- cgit v1.2.3 From 50fd8010673b770f6489c9ee96680c204aefa84a Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: soften invalidation in loose_mode Loose mode in 9p utilizes the page cache without respecting coherency with the server. Any writes previously invaldiated the entire mapping for a file. This patch softens the behavior to only invalidate the region of the actual write. Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 716691689fd..ba4b1caa9c4 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -162,15 +162,17 @@ v9fs_file_write(struct file *filp, const char __user * data, fid = filp->private_data; ret = p9_client_uwrite(fid, data, *offset, count); - if (ret > 0) + if (ret > 0) { + invalidate_inode_pages2_range(inode->i_mapping, *offset, + *offset+ret); *offset += ret; + } if (*offset > inode->i_size) { inode->i_size = *offset; inode->i_blocks = (inode->i_size + 512 - 1) >> 9; } - invalidate_inode_pages2(inode->i_mapping); return ret; } -- cgit v1.2.3 From fb0466c3ae7f1c73f70072af8fd27ac166908a2f Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 17 Oct 2007 14:31:07 -0500 Subject: 9p: fix bad kconfig cross-dependency This patch moves transport dynamic registration and matching to the net module to prevent a bad Kconfig dependency between the net and fs 9p modules. Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.c | 47 +---------------------------------- include/net/9p/transport.h | 2 ++ net/9p/client.c | 1 + net/9p/mod.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ net/9p/mux.c | 1 + 5 files changed, 67 insertions(+), 46 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 89ee0bace41..873802de21c 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -36,47 +36,6 @@ #include "v9fs.h" #include "v9fs_vfs.h" -/* - * Dynamic Transport Registration Routines - * - */ - -static LIST_HEAD(v9fs_trans_list); -static struct p9_trans_module *v9fs_default_trans; - -/** - * v9fs_register_trans - register a new transport with 9p - * @m - structure describing the transport module and entry points - * - */ -void v9fs_register_trans(struct p9_trans_module *m) -{ - list_add_tail(&m->list, &v9fs_trans_list); - if (m->def) - v9fs_default_trans = m; -} -EXPORT_SYMBOL(v9fs_register_trans); - -/** - * v9fs_match_trans - match transport versus registered transports - * @arg: string identifying transport - * - */ -static struct p9_trans_module *v9fs_match_trans(const substring_t *name) -{ - struct list_head *p; - struct p9_trans_module *t = NULL; - - list_for_each(p, &v9fs_trans_list) { - t = list_entry(p, struct p9_trans_module, list); - if (strncmp(t->name, name->from, name->to-name->from) == 0) { - P9_DPRINTK(P9_DEBUG_TRANS, "trans=%s\n", t->name); - break; - } - } - return t; -} - /* * Option Parsing (code inspired by NFS code) * NOTE: each transport will parse its own options @@ -135,7 +94,7 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) v9ses->afid = ~0; v9ses->debug = 0; v9ses->cache = 0; - v9ses->trans = v9fs_default_trans; + v9ses->trans = v9fs_default_trans(); if (!options) return; @@ -245,10 +204,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->options = kstrdup(data, GFP_KERNEL); v9fs_parse_options(v9ses); - if ((v9ses->trans == NULL) && !list_empty(&v9fs_trans_list)) - v9ses->trans = list_first_entry(&v9fs_trans_list, - struct p9_trans_module, list); - if (v9ses->trans == NULL) { retval = -EPROTONOSUPPORT; P9_DPRINTK(P9_DEBUG_ERROR, diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 7c68b3e8e78..9dd4a05619a 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -50,5 +50,7 @@ struct p9_trans_module { }; void v9fs_register_trans(struct p9_trans_module *m); +struct p9_trans_module *v9fs_match_trans(const substring_t *name); +struct p9_trans_module *v9fs_default_trans(void); #endif /* NET_9P_TRANSPORT_H */ diff --git a/net/9p/client.c b/net/9p/client.c index d83cc1247f1..af919936404 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/net/9p/mod.c b/net/9p/mod.c index 4f9e1d2ac25..b8ac0635ad8 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include #ifdef CONFIG_NET_9P_DEBUG unsigned int p9_debug_level = 0; /* feature-rific global debug level */ @@ -40,6 +44,64 @@ extern void p9_mux_global_exit(void); extern int p9_sysctl_register(void); extern void p9_sysctl_unregister(void); +/* + * Dynamic Transport Registration Routines + * + */ + +static LIST_HEAD(v9fs_trans_list); +static struct p9_trans_module *v9fs_default_transport; + +/** + * v9fs_register_trans - register a new transport with 9p + * @m - structure describing the transport module and entry points + * + */ +void v9fs_register_trans(struct p9_trans_module *m) +{ + list_add_tail(&m->list, &v9fs_trans_list); + if (m->def) + v9fs_default_transport = m; +} +EXPORT_SYMBOL(v9fs_register_trans); + +/** + * v9fs_match_trans - match transport versus registered transports + * @arg: string identifying transport + * + */ +struct p9_trans_module *v9fs_match_trans(const substring_t *name) +{ + struct list_head *p; + struct p9_trans_module *t = NULL; + + list_for_each(p, &v9fs_trans_list) { + t = list_entry(p, struct p9_trans_module, list); + if (strncmp(t->name, name->from, name->to-name->from) == 0) + break; + } + return t; +} +EXPORT_SYMBOL(v9fs_match_trans); + +/** + * v9fs_default_trans - returns pointer to default transport + * + */ + +struct p9_trans_module *v9fs_default_trans(void) +{ + if (v9fs_default_transport) + return v9fs_default_transport; + else if (!list_empty(&v9fs_trans_list)) + return list_first_entry(&v9fs_trans_list, + struct p9_trans_module, list); + else + return NULL; +} +EXPORT_SYMBOL(v9fs_default_trans); + + /** * v9fs_init - Initialize module * diff --git a/net/9p/mux.c b/net/9p/mux.c index 934e2ea86e2..f14014793be 100644 --- a/net/9p/mux.c +++ b/net/9p/mux.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 982c37cfb6e61c0e64634abc2e305d757c1405b2 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 17 Oct 2007 14:35:15 -0500 Subject: 9p: remove sysctl A sysctl method was added to enable and disable debugging levels. After further review, it was decided that there are better approaches to doing this and the sysctl methodology isn't really desirable. This patch removes the sysctl code from 9p. Signed-off-by: Eric Van Hensbergen --- include/net/9p/9p.h | 14 --------- net/9p/Makefile | 2 -- net/9p/mod.c | 9 ------ net/9p/sysctl.c | 81 ----------------------------------------------------- 4 files changed, 106 deletions(-) delete mode 100644 net/9p/sysctl.c diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 7a448a30e39..686425a97b0 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -415,18 +415,4 @@ int p9_idpool_check(int id, struct p9_idpool *p); int p9_error_init(void); int p9_errstr2errno(char *, int); - -#ifdef CONFIG_SYSCTL -int __init p9_sysctl_register(void); -void __exit p9_sysctl_unregister(void); -#else -static inline int p9_sysctl_register(void) -{ - return 0; -} -static inline void p9_sysctl_unregister(void) -{ -} -#endif - #endif /* NET_9P_H */ diff --git a/net/9p/Makefile b/net/9p/Makefile index 7b2a67abc0a..5059bc06f8f 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile @@ -10,7 +10,5 @@ obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o fcprint.o \ util.o \ -9pnet-$(CONFIG_SYSCTL) += sysctl.o - 9pnet_fd-objs := \ trans_fd.o \ diff --git a/net/9p/mod.c b/net/9p/mod.c index b8ac0635ad8..41d70f47375 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -41,8 +41,6 @@ MODULE_PARM_DESC(debug, "9P debugging level"); extern int p9_mux_global_init(void); extern void p9_mux_global_exit(void); -extern int p9_sysctl_register(void); -extern void p9_sysctl_unregister(void); /* * Dynamic Transport Registration Routines @@ -118,12 +116,6 @@ static int __init init_p9(void) return ret; } - ret = p9_sysctl_register(); - if (ret) { - printk(KERN_WARNING "9p: registering sysctl failed\n"); - return ret; - } - return ret; } @@ -134,7 +126,6 @@ static int __init init_p9(void) static void __exit exit_p9(void) { - p9_sysctl_unregister(); p9_mux_global_exit(); } diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c deleted file mode 100644 index 8b61027a24e..00000000000 --- a/net/9p/sysctl.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * net/9p/sysctl.c - * - * 9P sysctl interface - * - * Copyright (C) 2007 by Latchesar Ionkov - * - * 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 -#include -#include -#include -#include - -static struct ctl_table p9_table[] = { -#ifdef CONFIG_NET_9P_DEBUG - { - .ctl_name = CTL_UNNUMBERED, - .procname = "debug", - .data = &p9_debug_level, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, -#endif - {}, -}; - -static struct ctl_table p9_net_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "9p", - .maxlen = 0, - .mode = 0555, - .child = p9_table, - }, - {}, -}; - -static struct ctl_table p9_ctl_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .maxlen = 0, - .mode = 0555, - .child = p9_net_table, - }, - {}, -}; - -static struct ctl_table_header *p9_table_header; - -int __init p9_sysctl_register(void) -{ - p9_table_header = register_sysctl_table(p9_ctl_table); - if (!p9_table_header) - return -ENOMEM; - - return 0; -} - -void __exit p9_sysctl_unregister(void) -{ - unregister_sysctl_table(p9_table_header); -} -- cgit v1.2.3