diff options
Diffstat (limited to 'fs/9p/v9fs.c')
-rw-r--r-- | fs/9p/v9fs.c | 149 |
1 files changed, 72 insertions, 77 deletions
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 @@ -37,18 +37,58 @@ #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); } |