aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@opteron.9grid.us>2008-05-08 21:26:37 -0400
committerEric Van Hensbergen <ericvh@opteron.9grid.us>2008-05-14 20:23:27 -0400
commit887b3ece65be7b643dfdae0d433c91a26a3f437d (patch)
tree471889dcdd3f7eb6762d863fef236014c63a0301
parent332c421e67045343de74e644cdf389f559f0d83f (diff)
9p: fix error path during early mount
There was some cleanup issues during early mount which would trigger a kernel bug for certain types of failure. This patch reorganizes the cleanup to get rid of the bad behavior. This also merges the 9pnet and 9pnet_fd modules for the purpose of configuration and initialization. Keeping the fd transport separate from the core 9pnet code seemed like a good idea at the time, but in practice has caused more harm and confusion than good. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/v9fs.c13
-rw-r--r--fs/9p/vfs_super.c34
-rw-r--r--include/net/9p/9p.h1
-rw-r--r--include/net/9p/transport.h1
-rw-r--r--net/9p/Kconfig10
-rw-r--r--net/9p/Makefile3
-rw-r--r--net/9p/mod.c1
-rw-r--r--net/9p/trans_fd.c29
8 files changed, 47 insertions, 45 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 5c1ccaf0416c..047c791427aa 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -206,12 +206,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
206 v9ses->uid = ~0; 206 v9ses->uid = ~0;
207 v9ses->dfltuid = V9FS_DEFUID; 207 v9ses->dfltuid = V9FS_DEFUID;
208 v9ses->dfltgid = V9FS_DEFGID; 208 v9ses->dfltgid = V9FS_DEFGID;
209 v9ses->options = kstrdup(data, GFP_KERNEL); 209 if (data) {
210 if (!v9ses->options) { 210 v9ses->options = kstrdup(data, GFP_KERNEL);
211 P9_DPRINTK(P9_DEBUG_ERROR, 211 if (!v9ses->options) {
212 P9_DPRINTK(P9_DEBUG_ERROR,
212 "failed to allocate copy of option string\n"); 213 "failed to allocate copy of option string\n");
213 retval = -ENOMEM; 214 retval = -ENOMEM;
214 goto error; 215 goto error;
216 }
215 } 217 }
216 218
217 rc = v9fs_parse_options(v9ses); 219 rc = v9fs_parse_options(v9ses);
@@ -260,7 +262,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
260 return fid; 262 return fid;
261 263
262error: 264error:
263 v9fs_session_close(v9ses);
264 return ERR_PTR(retval); 265 return ERR_PTR(retval);
265} 266}
266 267
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index ba10f172626d..bf59c3960494 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -128,29 +128,26 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
128 fid = v9fs_session_init(v9ses, dev_name, data); 128 fid = v9fs_session_init(v9ses, dev_name, data);
129 if (IS_ERR(fid)) { 129 if (IS_ERR(fid)) {
130 retval = PTR_ERR(fid); 130 retval = PTR_ERR(fid);
131 fid = NULL; 131 goto close_session;
132 kfree(v9ses);
133 v9ses = NULL;
134 goto error;
135 } 132 }
136 133
137 st = p9_client_stat(fid); 134 st = p9_client_stat(fid);
138 if (IS_ERR(st)) { 135 if (IS_ERR(st)) {
139 retval = PTR_ERR(st); 136 retval = PTR_ERR(st);
140 goto error; 137 goto clunk_fid;
141 } 138 }
142 139
143 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 140 sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
144 if (IS_ERR(sb)) { 141 if (IS_ERR(sb)) {
145 retval = PTR_ERR(sb); 142 retval = PTR_ERR(sb);
146 goto error; 143 goto free_stat;
147 } 144 }
148 v9fs_fill_super(sb, v9ses, flags); 145 v9fs_fill_super(sb, v9ses, flags);
149 146
150 inode = v9fs_get_inode(sb, S_IFDIR | mode); 147 inode = v9fs_get_inode(sb, S_IFDIR | mode);
151 if (IS_ERR(inode)) { 148 if (IS_ERR(inode)) {
152 retval = PTR_ERR(inode); 149 retval = PTR_ERR(inode);
153 goto error; 150 goto release_sb;
154 } 151 }
155 152
156 inode->i_uid = uid; 153 inode->i_uid = uid;
@@ -159,7 +156,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
159 root = d_alloc_root(inode); 156 root = d_alloc_root(inode);
160 if (!root) { 157 if (!root) {
161 retval = -ENOMEM; 158 retval = -ENOMEM;
162 goto error; 159 goto release_sb;
163 } 160 }
164 161
165 sb->s_root = root; 162 sb->s_root = root;
@@ -170,21 +167,22 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
170 167
171 return simple_set_mnt(mnt, sb); 168 return simple_set_mnt(mnt, sb);
172 169
173error: 170release_sb:
174 kfree(st);
175 if (fid)
176 p9_client_clunk(fid);
177
178 if (v9ses) {
179 v9fs_session_close(v9ses);
180 kfree(v9ses);
181 }
182
183 if (sb) { 171 if (sb) {
184 up_write(&sb->s_umount); 172 up_write(&sb->s_umount);
185 deactivate_super(sb); 173 deactivate_super(sb);
186 } 174 }
187 175
176free_stat:
177 kfree(st);
178
179clunk_fid:
180 p9_client_clunk(fid);
181
182close_session:
183 v9fs_session_close(v9ses);
184 kfree(v9ses);
185
188 return retval; 186 return retval;
189} 187}
190 188
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 7bfb2f2e423c..b3d3e27c6299 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -595,4 +595,5 @@ int p9_idpool_check(int id, struct p9_idpool *p);
595 595
596int p9_error_init(void); 596int p9_error_init(void);
597int p9_errstr2errno(char *, int); 597int p9_errstr2errno(char *, int);
598int p9_trans_fd_init(void);
598#endif /* NET_9P_H */ 599#endif /* NET_9P_H */
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 240e0de888c6..0db3a4038dc0 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -96,5 +96,4 @@ struct p9_trans_module {
96void v9fs_register_trans(struct p9_trans_module *m); 96void v9fs_register_trans(struct p9_trans_module *m);
97struct p9_trans_module *v9fs_match_trans(const substring_t *name); 97struct p9_trans_module *v9fs_match_trans(const substring_t *name);
98struct p9_trans_module *v9fs_default_trans(void); 98struct p9_trans_module *v9fs_default_trans(void);
99
100#endif /* NET_9P_TRANSPORT_H */ 99#endif /* NET_9P_TRANSPORT_H */
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index bafc50c9e6ff..ff34c5acc130 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -13,16 +13,6 @@ menuconfig NET_9P
13 13
14 If unsure, say N. 14 If unsure, say N.
15 15
16config NET_9P_FD
17 depends on NET_9P
18 default y if NET_9P
19 tristate "9P File Descriptor Transports (Experimental)"
20 help
21 This builds support for file descriptor transports for 9p
22 which includes support for TCP/IP, named pipes, or passed
23 file descriptors. TCP/IP is the default transport for 9p,
24 so if you are going to use 9p, you'll likely want this.
25
26config NET_9P_VIRTIO 16config NET_9P_VIRTIO
27 depends on NET_9P && EXPERIMENTAL && VIRTIO 17 depends on NET_9P && EXPERIMENTAL && VIRTIO
28 tristate "9P Virtio Transport (Experimental)" 18 tristate "9P Virtio Transport (Experimental)"
diff --git a/net/9p/Makefile b/net/9p/Makefile
index 8a1051101898..519219480db1 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -1,5 +1,4 @@
1obj-$(CONFIG_NET_9P) := 9pnet.o 1obj-$(CONFIG_NET_9P) := 9pnet.o
2obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o
3obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o 2obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
4 3
59pnet-objs := \ 49pnet-objs := \
@@ -9,8 +8,6 @@ obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
9 error.o \ 8 error.o \
10 fcprint.o \ 9 fcprint.o \
11 util.o \ 10 util.o \
12
139pnet_fd-objs := \
14 trans_fd.o \ 11 trans_fd.o \
15 12
169pnet_virtio-objs := \ 139pnet_virtio-objs := \
diff --git a/net/9p/mod.c b/net/9p/mod.c
index c6d9695949e0..bdee1fb7cc62 100644
--- a/net/9p/mod.c
+++ b/net/9p/mod.c
@@ -107,6 +107,7 @@ static int __init init_p9(void)
107 107
108 p9_error_init(); 108 p9_error_init();
109 printk(KERN_INFO "Installing 9P2000 support\n"); 109 printk(KERN_INFO "Installing 9P2000 support\n");
110 p9_trans_fd_init();
110 111
111 return ret; 112 return ret;
112} 113}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 97b103b70499..4507f744f44e 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -1433,6 +1433,23 @@ static void p9_fd_close(struct p9_trans *trans)
1433 kfree(ts); 1433 kfree(ts);
1434} 1434}
1435 1435
1436/*
1437 * stolen from NFS - maybe should be made a generic function?
1438 */
1439static inline int valid_ipaddr4(const char *buf)
1440{
1441 int rc, count, in[4];
1442
1443 rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
1444 if (rc != 4)
1445 return -EINVAL;
1446 for (count = 0; count < 4; count++) {
1447 if (in[count] > 255)
1448 return -EINVAL;
1449 }
1450 return 0;
1451}
1452
1436static struct p9_trans * 1453static struct p9_trans *
1437p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) 1454p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
1438{ 1455{
@@ -1447,6 +1464,9 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
1447 if (err < 0) 1464 if (err < 0)
1448 return ERR_PTR(err); 1465 return ERR_PTR(err);
1449 1466
1467 if (valid_ipaddr4(addr) < 0)
1468 return ERR_PTR(-EINVAL);
1469
1450 csocket = NULL; 1470 csocket = NULL;
1451 trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); 1471 trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
1452 if (!trans) 1472 if (!trans)
@@ -1625,7 +1645,7 @@ static struct p9_trans_module p9_fd_trans = {
1625 .create = p9_trans_create_fd, 1645 .create = p9_trans_create_fd,
1626}; 1646};
1627 1647
1628static int __init p9_trans_fd_init(void) 1648int p9_trans_fd_init(void)
1629{ 1649{
1630 int ret = p9_mux_global_init(); 1650 int ret = p9_mux_global_init();
1631 if (ret) { 1651 if (ret) {
@@ -1639,9 +1659,4 @@ static int __init p9_trans_fd_init(void)
1639 1659
1640 return 0; 1660 return 0;
1641} 1661}
1642 1662EXPORT_SYMBOL(p9_trans_fd_init);
1643module_init(p9_trans_fd_init);
1644
1645MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
1646MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
1647MODULE_LICENSE("GPL");