aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/v9fs.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@opteron.(none)>2007-10-17 15:31:07 -0400
committerEric Van Hensbergen <ericvh@ericvh-desktop.austin.ibm.com>2007-10-17 15:31:07 -0400
commita80d923e1321a7ed69a0918de37e39871bb536a0 (patch)
tree8294e5f14a0e938ae4675ef912a32fbade0f832b /fs/9p/v9fs.c
parent0eafaae84e21ac033815cc9f33c3ae889cd7ccfe (diff)
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 <ericvh@gmail.com>
Diffstat (limited to 'fs/9p/v9fs.c')
-rw-r--r--fs/9p/v9fs.c149
1 files changed, 72 insertions, 77 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 0a7068e30ecb..08d880fb5b6a 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -37,18 +37,58 @@
37#include "v9fs_vfs.h" 37#include "v9fs_vfs.h"
38 38
39/* 39/*
40 * Dynamic Transport Registration Routines
41 *
42 */
43
44static LIST_HEAD(v9fs_trans_list);
45static struct p9_trans_module *v9fs_default_trans;
46
47/**
48 * v9fs_register_trans - register a new transport with 9p
49 * @m - structure describing the transport module and entry points
50 *
51 */
52void v9fs_register_trans(struct p9_trans_module *m)
53{
54 list_add_tail(&m->list, &v9fs_trans_list);
55 if (m->def)
56 v9fs_default_trans = m;
57}
58EXPORT_SYMBOL(v9fs_register_trans);
59
60/**
61 * v9fs_match_trans - match transport versus registered transports
62 * @arg: string identifying transport
63 *
64 */
65static struct p9_trans_module *v9fs_match_trans(const substring_t *name)
66{
67 struct list_head *p;
68 struct p9_trans_module *t = NULL;
69
70 list_for_each(p, &v9fs_trans_list) {
71 t = list_entry(p, struct p9_trans_module, list);
72 if (strncmp(t->name, name->from, name->to-name->from) == 0) {
73 P9_DPRINTK(P9_DEBUG_TRANS, "trans=%s\n", t->name);
74 break;
75 }
76 }
77 return t;
78}
79
80/*
40 * Option Parsing (code inspired by NFS code) 81 * Option Parsing (code inspired by NFS code)
41 * 82 * NOTE: each transport will parse its own options
42 */ 83 */
43 84
44enum { 85enum {
45 /* Options that take integer arguments */ 86 /* Options that take integer arguments */
46 Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, 87 Opt_debug, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
47 Opt_rfdno, Opt_wfdno,
48 /* String options */ 88 /* String options */
49 Opt_uname, Opt_remotename, 89 Opt_uname, Opt_remotename, Opt_trans,
50 /* Options that take no arguments */ 90 /* Options that take no arguments */
51 Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci, 91 Opt_legacy, Opt_nodevmap,
52 /* Cache options */ 92 /* Cache options */
53 Opt_cache_loose, 93 Opt_cache_loose,
54 /* Error token */ 94 /* Error token */
@@ -57,24 +97,13 @@ enum {
57 97
58static match_table_t tokens = { 98static match_table_t tokens = {
59 {Opt_debug, "debug=%x"}, 99 {Opt_debug, "debug=%x"},
60 {Opt_port, "port=%u"},
61 {Opt_msize, "msize=%u"}, 100 {Opt_msize, "msize=%u"},
62 {Opt_uid, "uid=%u"}, 101 {Opt_uid, "uid=%u"},
63 {Opt_gid, "gid=%u"}, 102 {Opt_gid, "gid=%u"},
64 {Opt_afid, "afid=%u"}, 103 {Opt_afid, "afid=%u"},
65 {Opt_rfdno, "rfdno=%u"},
66 {Opt_wfdno, "wfdno=%u"},
67 {Opt_uname, "uname=%s"}, 104 {Opt_uname, "uname=%s"},
68 {Opt_remotename, "aname=%s"}, 105 {Opt_remotename, "aname=%s"},
69 {Opt_unix, "proto=unix"}, 106 {Opt_trans, "trans=%s"},
70 {Opt_tcp, "proto=tcp"},
71 {Opt_fd, "proto=fd"},
72#ifdef CONFIG_PCI_9P
73 {Opt_pci, "proto=pci"},
74#endif
75 {Opt_tcp, "tcp"},
76 {Opt_unix, "unix"},
77 {Opt_fd, "fd"},
78 {Opt_legacy, "noextend"}, 107 {Opt_legacy, "noextend"},
79 {Opt_nodevmap, "nodevmap"}, 108 {Opt_nodevmap, "nodevmap"},
80 {Opt_cache_loose, "cache=loose"}, 109 {Opt_cache_loose, "cache=loose"},
@@ -82,12 +111,6 @@ static match_table_t tokens = {
82 {Opt_err, NULL} 111 {Opt_err, NULL}
83}; 112};
84 113
85extern struct p9_transport *p9pci_trans_create(void);
86
87/*
88 * Parse option string.
89 */
90
91/** 114/**
92 * v9fs_parse_options - parse mount options into session structure 115 * v9fs_parse_options - parse mount options into session structure
93 * @options: options string passed from mount 116 * @options: options string passed from mount
@@ -95,23 +118,21 @@ extern struct p9_transport *p9pci_trans_create(void);
95 * 118 *
96 */ 119 */
97 120
98static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) 121static void v9fs_parse_options(struct v9fs_session_info *v9ses)
99{ 122{
100 char *p; 123 char *options = v9ses->options;
101 substring_t args[MAX_OPT_ARGS]; 124 substring_t args[MAX_OPT_ARGS];
125 char *p;
102 int option; 126 int option;
103 int ret; 127 int ret;
104 128
105 /* setup defaults */ 129 /* setup defaults */
106 v9ses->port = V9FS_PORT; 130 v9ses->maxdata = 8192;
107 v9ses->maxdata = 9000;
108 v9ses->proto = PROTO_TCP;
109 v9ses->extended = 1; 131 v9ses->extended = 1;
110 v9ses->afid = ~0; 132 v9ses->afid = ~0;
111 v9ses->debug = 0; 133 v9ses->debug = 0;
112 v9ses->rfdno = ~0;
113 v9ses->wfdno = ~0;
114 v9ses->cache = 0; 134 v9ses->cache = 0;
135 v9ses->trans = v9fs_default_trans;
115 136
116 if (!options) 137 if (!options)
117 return; 138 return;
@@ -135,9 +156,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
135 p9_debug_level = option; 156 p9_debug_level = option;
136#endif 157#endif
137 break; 158 break;
138 case Opt_port:
139 v9ses->port = option;
140 break;
141 case Opt_msize: 159 case Opt_msize:
142 v9ses->maxdata = option; 160 v9ses->maxdata = option;
143 break; 161 break;
@@ -150,23 +168,8 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
150 case Opt_afid: 168 case Opt_afid:
151 v9ses->afid = option; 169 v9ses->afid = option;
152 break; 170 break;
153 case Opt_rfdno: 171 case Opt_trans:
154 v9ses->rfdno = option; 172 v9ses->trans = v9fs_match_trans(&args[0]);
155 break;
156 case Opt_wfdno:
157 v9ses->wfdno = option;
158 break;
159 case Opt_tcp:
160 v9ses->proto = PROTO_TCP;
161 break;
162 case Opt_unix:
163 v9ses->proto = PROTO_UNIX;
164 break;
165 case Opt_pci:
166 v9ses->proto = PROTO_PCI;
167 break;
168 case Opt_fd:
169 v9ses->proto = PROTO_FD;
170 break; 173 break;
171 case Opt_uname: 174 case Opt_uname:
172 match_strcpy(v9ses->name, &args[0]); 175 match_strcpy(v9ses->name, &args[0]);
@@ -201,7 +204,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
201 const char *dev_name, char *data) 204 const char *dev_name, char *data)
202{ 205{
203 int retval = -EINVAL; 206 int retval = -EINVAL;
204 struct p9_transport *trans; 207 struct p9_trans *trans = NULL;
205 struct p9_fid *fid; 208 struct p9_fid *fid;
206 209
207 v9ses->name = __getname(); 210 v9ses->name = __getname();
@@ -217,39 +220,30 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
217 strcpy(v9ses->name, V9FS_DEFUSER); 220 strcpy(v9ses->name, V9FS_DEFUSER);
218 strcpy(v9ses->remotename, V9FS_DEFANAME); 221 strcpy(v9ses->remotename, V9FS_DEFANAME);
219 222
220 v9fs_parse_options(data, v9ses); 223 v9ses->options = kstrdup(data, GFP_KERNEL);
221 224 v9fs_parse_options(v9ses);
222 switch (v9ses->proto) { 225
223 case PROTO_TCP: 226 if ((v9ses->trans == NULL) && !list_empty(&v9fs_trans_list))
224 trans = p9_trans_create_tcp(dev_name, v9ses->port); 227 v9ses->trans = list_first_entry(&v9fs_trans_list,
225 break; 228 struct p9_trans_module, list);
226 case PROTO_UNIX: 229
227 trans = p9_trans_create_unix(dev_name); 230 if (v9ses->trans == NULL) {
228 *v9ses->remotename = 0; 231 retval = -EPROTONOSUPPORT;
229 break; 232 P9_DPRINTK(P9_DEBUG_ERROR,
230 case PROTO_FD: 233 "No transport defined or default transport\n");
231 trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
232 *v9ses->remotename = 0;
233 break;
234#ifdef CONFIG_PCI_9P
235 case PROTO_PCI:
236 trans = p9pci_trans_create();
237 *v9ses->remotename = 0;
238 break;
239#endif
240 default:
241 printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
242 retval = -ENOPROTOOPT;
243 goto error; 234 goto error;
244 }; 235 }
245 236
237 trans = v9ses->trans->create(dev_name, v9ses->options);
246 if (IS_ERR(trans)) { 238 if (IS_ERR(trans)) {
247 retval = PTR_ERR(trans); 239 retval = PTR_ERR(trans);
248 trans = NULL; 240 trans = NULL;
249 goto error; 241 goto error;
250 } 242 }
243 if ((v9ses->maxdata+P9_IOHDRSZ) > v9ses->trans->maxsize)
244 v9ses->maxdata = v9ses->trans->maxsize-P9_IOHDRSZ;
251 245
252 v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ, 246 v9ses->clnt = p9_client_create(trans, v9ses->maxdata+P9_IOHDRSZ,
253 v9ses->extended); 247 v9ses->extended);
254 248
255 if (IS_ERR(v9ses->clnt)) { 249 if (IS_ERR(v9ses->clnt)) {
@@ -290,6 +284,7 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
290 284
291 __putname(v9ses->name); 285 __putname(v9ses->name);
292 __putname(v9ses->remotename); 286 __putname(v9ses->remotename);
287 kfree(v9ses->options);
293} 288}
294 289
295/** 290/**
@@ -311,7 +306,7 @@ extern int v9fs_error_init(void);
311static int __init init_v9fs(void) 306static int __init init_v9fs(void)
312{ 307{
313 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); 308 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
314 309 /* TODO: Setup list of registered trasnport modules */
315 return register_filesystem(&v9fs_fs_type); 310 return register_filesystem(&v9fs_fs_type);
316} 311}
317 312