diff options
author | Eric Van Hensbergen <ericvh@opteron.(none)> | 2007-10-17 15:31:07 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@ericvh-desktop.austin.ibm.com> | 2007-10-17 15:31:07 -0400 |
commit | a80d923e1321a7ed69a0918de37e39871bb536a0 (patch) | |
tree | 8294e5f14a0e938ae4675ef912a32fbade0f832b /fs/9p | |
parent | 0eafaae84e21ac033815cc9f33c3ae889cd7ccfe (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')
-rw-r--r-- | fs/9p/v9fs.c | 149 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 15 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 19 |
3 files changed, 75 insertions, 108 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 | |||
44 | static LIST_HEAD(v9fs_trans_list); | ||
45 | static 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 | */ | ||
52 | void 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 | } | ||
58 | EXPORT_SYMBOL(v9fs_register_trans); | ||
59 | |||
60 | /** | ||
61 | * v9fs_match_trans - match transport versus registered transports | ||
62 | * @arg: string identifying transport | ||
63 | * | ||
64 | */ | ||
65 | static 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 | ||
44 | enum { | 85 | enum { |
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 | ||
58 | static match_table_t tokens = { | 98 | static 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 | ||
85 | extern 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 | ||
98 | static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses) | 121 | static 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); | |||
311 | static int __init init_v9fs(void) | 306 | static 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 | ||
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index abc4b1668ace..7eb135cf60ca 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -31,31 +31,20 @@ struct v9fs_session_info { | |||
31 | unsigned int maxdata; | 31 | unsigned int maxdata; |
32 | unsigned char extended; /* set to 1 if we are using UNIX extensions */ | 32 | unsigned char extended; /* set to 1 if we are using UNIX extensions */ |
33 | unsigned char nodev; /* set to 1 if no disable device mapping */ | 33 | unsigned char nodev; /* set to 1 if no disable device mapping */ |
34 | unsigned short port; /* port to connect to */ | ||
35 | unsigned short debug; /* debug level */ | 34 | unsigned short debug; /* debug level */ |
36 | unsigned short proto; /* protocol to use */ | ||
37 | unsigned int afid; /* authentication fid */ | 35 | unsigned int afid; /* authentication fid */ |
38 | unsigned int rfdno; /* read file descriptor number */ | ||
39 | unsigned int wfdno; /* write file descriptor number */ | ||
40 | unsigned int cache; /* cache mode */ | 36 | unsigned int cache; /* cache mode */ |
41 | 37 | ||
38 | char *options; /* copy of mount options */ | ||
42 | char *name; /* user name to mount as */ | 39 | char *name; /* user name to mount as */ |
43 | char *remotename; /* name of remote hierarchy being mounted */ | 40 | char *remotename; /* name of remote hierarchy being mounted */ |
44 | unsigned int uid; /* default uid/muid for legacy support */ | 41 | unsigned int uid; /* default uid/muid for legacy support */ |
45 | unsigned int gid; /* default gid for legacy support */ | 42 | unsigned int gid; /* default gid for legacy support */ |
46 | 43 | struct p9_trans_module *trans; /* 9p transport */ | |
47 | struct p9_client *clnt; /* 9p client */ | 44 | struct p9_client *clnt; /* 9p client */ |
48 | struct dentry *debugfs_dir; | 45 | struct dentry *debugfs_dir; |
49 | }; | 46 | }; |
50 | 47 | ||
51 | /* possible values of ->proto */ | ||
52 | enum { | ||
53 | PROTO_TCP, | ||
54 | PROTO_UNIX, | ||
55 | PROTO_FD, | ||
56 | PROTO_PCI, | ||
57 | }; | ||
58 | |||
59 | /* possible values of ->cache */ | 48 | /* possible values of ->cache */ |
60 | /* eventually support loose, tight, time, session, default always none */ | 49 | /* eventually support loose, tight, time, session, default always none */ |
61 | enum { | 50 | enum { |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index ba904371218b..bb0cef9a6b8a 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) | |||
216 | { | 216 | { |
217 | struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; | 217 | struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; |
218 | 218 | ||
219 | if (v9ses->debug != 0) | 219 | seq_printf(m, "%s", v9ses->options); |
220 | seq_printf(m, ",debug=%x", v9ses->debug); | ||
221 | if (v9ses->port != V9FS_PORT) | ||
222 | seq_printf(m, ",port=%u", v9ses->port); | ||
223 | if (v9ses->maxdata != 9000) | ||
224 | seq_printf(m, ",msize=%u", v9ses->maxdata); | ||
225 | if (v9ses->afid != ~0) | ||
226 | seq_printf(m, ",afid=%u", v9ses->afid); | ||
227 | if (v9ses->proto == PROTO_UNIX) | ||
228 | seq_puts(m, ",proto=unix"); | ||
229 | if (v9ses->extended == 0) | ||
230 | seq_puts(m, ",noextend"); | ||
231 | if (v9ses->nodev == 1) | ||
232 | seq_puts(m, ",nodevmap"); | ||
233 | seq_printf(m, ",name=%s", v9ses->name); | ||
234 | seq_printf(m, ",aname=%s", v9ses->remotename); | ||
235 | seq_printf(m, ",uid=%u", v9ses->uid); | ||
236 | seq_printf(m, ",gid=%u", v9ses->gid); | ||
237 | return 0; | 220 | return 0; |
238 | } | 221 | } |
239 | 222 | ||