aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-04-05 16:42:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-04-05 16:42:54 -0400
commit749d229761ff0135cc4e16b8a28b41ae2f6b2c35 (patch)
tree25551c8cfb38319211f5ee59e78462a0f6fb85c4
parent795d580baec0d5386b83a8b557df47c20810e86b (diff)
parent3dc9fef67f6292692dba181a6d0fd0211bd0a607 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9p: saving negative to unsigned char 9p: return on mutex_lock_interruptible() 9p: Creating files with names too long should fail with ENAMETOOLONG. 9p: Make sure we are able to clunk the cached fid on umount 9p: drop nlink remove fs/9p: Clunk the fid resulting from partial walk of the name 9p: documentation update 9p: Fix setting of protocol flags in v9fs_session_info structure.
-rw-r--r--Documentation/filesystems/9p.txt18
-rw-r--r--fs/9p/fid.c12
-rw-r--r--fs/9p/v9fs.c21
-rw-r--r--fs/9p/v9fs.h1
-rw-r--r--fs/9p/vfs_dir.c2
-rw-r--r--fs/9p/vfs_inode.c9
-rw-r--r--fs/9p/vfs_super.c3
-rw-r--r--include/net/9p/client.h2
-rw-r--r--net/9p/client.c23
9 files changed, 78 insertions, 13 deletions
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index 57e0b80a5274..c0236e753bc8 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -37,6 +37,15 @@ For Plan 9 From User Space applications (http://swtch.com/plan9)
37 37
38 mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER 38 mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER
39 39
40For server running on QEMU host with virtio transport:
41
42 mount -t 9p -o trans=virtio <mount_tag> /mnt/9
43
44where mount_tag is the tag associated by the server to each of the exported
45mount points. Each 9P export is seen by the client as a virtio device with an
46associated "mount_tag" property. Available mount tags can be
47seen by reading /sys/bus/virtio/drivers/9pnet_virtio/virtio<n>/mount_tag files.
48
40OPTIONS 49OPTIONS
41======= 50=======
42 51
@@ -47,7 +56,7 @@ OPTIONS
47 fd - used passed file descriptors for connection 56 fd - used passed file descriptors for connection
48 (see rfdno and wfdno) 57 (see rfdno and wfdno)
49 virtio - connect to the next virtio channel available 58 virtio - connect to the next virtio channel available
50 (from lguest or KVM with trans_virtio module) 59 (from QEMU with trans_virtio module)
51 rdma - connect to a specified RDMA channel 60 rdma - connect to a specified RDMA channel
52 61
53 uname=name user name to attempt mount as on the remote server. The 62 uname=name user name to attempt mount as on the remote server. The
@@ -85,7 +94,12 @@ OPTIONS
85 94
86 port=n port to connect to on the remote server 95 port=n port to connect to on the remote server
87 96
88 noextend force legacy mode (no 9p2000.u semantics) 97 noextend force legacy mode (no 9p2000.u or 9p2000.L semantics)
98
99 version=name Select 9P protocol version. Valid options are:
100 9p2000 - Legacy mode (same as noextend)
101 9p2000.u - Use 9P2000.u protocol
102 9p2000.L - Use 9P2000.L protocol
89 103
90 dfltuid attempt to mount as a particular uid 104 dfltuid attempt to mount as a particular uid
91 105
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 82ee460e534d..7317b39b2815 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -111,7 +111,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
111{ 111{
112 int i, n, l, clone, any, access; 112 int i, n, l, clone, any, access;
113 u32 uid; 113 u32 uid;
114 struct p9_fid *fid; 114 struct p9_fid *fid, *old_fid = NULL;
115 struct dentry *d, *ds; 115 struct dentry *d, *ds;
116 struct v9fs_session_info *v9ses; 116 struct v9fs_session_info *v9ses;
117 char **wnames, *uname; 117 char **wnames, *uname;
@@ -184,10 +184,18 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
184 l = min(n - i, P9_MAXWELEM); 184 l = min(n - i, P9_MAXWELEM);
185 fid = p9_client_walk(fid, l, &wnames[i], clone); 185 fid = p9_client_walk(fid, l, &wnames[i], clone);
186 if (IS_ERR(fid)) { 186 if (IS_ERR(fid)) {
187 if (old_fid) {
188 /*
189 * If we fail, clunk fid which are mapping
190 * to path component and not the last component
191 * of the path.
192 */
193 p9_client_clunk(old_fid);
194 }
187 kfree(wnames); 195 kfree(wnames);
188 return fid; 196 return fid;
189 } 197 }
190 198 old_fid = fid;
191 i += l; 199 i += l;
192 clone = 0; 200 clone = 0;
193 } 201 }
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index cb57d3326182..5c5bc8480070 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -242,7 +242,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
242 list_add(&v9ses->slist, &v9fs_sessionlist); 242 list_add(&v9ses->slist, &v9fs_sessionlist);
243 spin_unlock(&v9fs_sessionlist_lock); 243 spin_unlock(&v9fs_sessionlist_lock);
244 244
245 v9ses->flags = V9FS_PROTO_2000U | V9FS_ACCESS_USER; 245 v9ses->flags = V9FS_ACCESS_USER;
246 strcpy(v9ses->uname, V9FS_DEFUSER); 246 strcpy(v9ses->uname, V9FS_DEFUSER);
247 strcpy(v9ses->aname, V9FS_DEFANAME); 247 strcpy(v9ses->aname, V9FS_DEFANAME);
248 v9ses->uid = ~0; 248 v9ses->uid = ~0;
@@ -263,8 +263,10 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
263 goto error; 263 goto error;
264 } 264 }
265 265
266 if (!p9_is_proto_dotu(v9ses->clnt)) 266 if (p9_is_proto_dotl(v9ses->clnt))
267 v9ses->flags &= ~V9FS_PROTO_2000U; 267 v9ses->flags |= V9FS_PROTO_2000L;
268 else if (p9_is_proto_dotu(v9ses->clnt))
269 v9ses->flags |= V9FS_PROTO_2000U;
268 270
269 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 271 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
270 272
@@ -341,6 +343,19 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
341 p9_client_disconnect(v9ses->clnt); 343 p9_client_disconnect(v9ses->clnt);
342} 344}
343 345
346/**
347 * v9fs_session_begin_cancel - Begin terminate of a session
348 * @v9ses: session to terminate
349 *
350 * After this call we don't allow any request other than clunk.
351 */
352
353void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
354{
355 P9_DPRINTK(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses);
356 p9_client_begin_disconnect(v9ses->clnt);
357}
358
344extern int v9fs_error_init(void); 359extern int v9fs_error_init(void);
345 360
346static struct kobject *v9fs_kobj; 361static struct kobject *v9fs_kobj;
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 6b801d1ddf4b..a0a8d3dd1361 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -108,6 +108,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
108 char *); 108 char *);
109void v9fs_session_close(struct v9fs_session_info *v9ses); 109void v9fs_session_close(struct v9fs_session_info *v9ses);
110void v9fs_session_cancel(struct v9fs_session_info *v9ses); 110void v9fs_session_cancel(struct v9fs_session_info *v9ses);
111void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
111 112
112#define V9FS_MAGIC 0x01021997 113#define V9FS_MAGIC 0x01021997
113 114
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 909711f57c0d..0adfd64dfcee 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -131,6 +131,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
131 rdir = (struct p9_rdir *) fid->rdir; 131 rdir = (struct p9_rdir *) fid->rdir;
132 132
133 err = mutex_lock_interruptible(&rdir->mutex); 133 err = mutex_lock_interruptible(&rdir->mutex);
134 if (err)
135 return err;
134 while (err == 0) { 136 while (err == 0) {
135 if (rdir->tail == rdir->head) { 137 if (rdir->tail == rdir->head) {
136 err = v9fs_file_readn(filp, rdir->buf, NULL, 138 err = v9fs_file_readn(filp, rdir->buf, NULL,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 63c2b5af268a..f2434fc9d2c4 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -432,6 +432,7 @@ error:
432 432
433static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 433static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
434{ 434{
435 int retval;
435 struct inode *file_inode; 436 struct inode *file_inode;
436 struct v9fs_session_info *v9ses; 437 struct v9fs_session_info *v9ses;
437 struct p9_fid *v9fid; 438 struct p9_fid *v9fid;
@@ -445,7 +446,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
445 if (IS_ERR(v9fid)) 446 if (IS_ERR(v9fid))
446 return PTR_ERR(v9fid); 447 return PTR_ERR(v9fid);
447 448
448 return p9_client_remove(v9fid); 449 retval = p9_client_remove(v9fid);
450 if (!retval)
451 drop_nlink(file_inode);
452 return retval;
449} 453}
450 454
451static int 455static int
@@ -657,6 +661,9 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
657 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 661 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
658 dir, dentry->d_name.name, dentry, nameidata); 662 dir, dentry->d_name.name, dentry, nameidata);
659 663
664 if (dentry->d_name.len > NAME_MAX)
665 return ERR_PTR(-ENAMETOOLONG);
666
660 sb = dir->i_sb; 667 sb = dir->i_sb;
661 v9ses = v9fs_inode2v9ses(dir); 668 v9ses = v9fs_inode2v9ses(dir);
662 dfid = v9fs_fid_lookup(dentry->d_parent); 669 dfid = v9fs_fid_lookup(dentry->d_parent);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index a271549d9e21..491108bd6e0d 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -194,6 +194,7 @@ static void v9fs_kill_super(struct super_block *s)
194 194
195 kill_anon_super(s); 195 kill_anon_super(s);
196 196
197 v9fs_session_cancel(v9ses);
197 v9fs_session_close(v9ses); 198 v9fs_session_close(v9ses);
198 kfree(v9ses); 199 kfree(v9ses);
199 s->s_fs_info = NULL; 200 s->s_fs_info = NULL;
@@ -206,7 +207,7 @@ v9fs_umount_begin(struct super_block *sb)
206 struct v9fs_session_info *v9ses; 207 struct v9fs_session_info *v9ses;
207 208
208 v9ses = sb->s_fs_info; 209 v9ses = sb->s_fs_info;
209 v9fs_session_cancel(v9ses); 210 v9fs_session_begin_cancel(v9ses);
210} 211}
211 212
212static const struct super_operations v9fs_super_ops = { 213static const struct super_operations v9fs_super_ops = {
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index f076dfa75ae8..4f3760afc20f 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -54,6 +54,7 @@ enum p9_proto_versions{
54 54
55enum p9_trans_status { 55enum p9_trans_status {
56 Connected, 56 Connected,
57 BeginDisconnect,
57 Disconnected, 58 Disconnected,
58 Hung, 59 Hung,
59}; 60};
@@ -198,6 +199,7 @@ int p9_client_version(struct p9_client *);
198struct p9_client *p9_client_create(const char *dev_name, char *options); 199struct p9_client *p9_client_create(const char *dev_name, char *options);
199void p9_client_destroy(struct p9_client *clnt); 200void p9_client_destroy(struct p9_client *clnt);
200void p9_client_disconnect(struct p9_client *clnt); 201void p9_client_disconnect(struct p9_client *clnt);
202void p9_client_begin_disconnect(struct p9_client *clnt);
201struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 203struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
202 char *uname, u32 n_uname, char *aname); 204 char *uname, u32 n_uname, char *aname);
203struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, 205struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
diff --git a/net/9p/client.c b/net/9p/client.c
index 6e6b928a5972..0aa79faa9850 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -72,9 +72,10 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
72EXPORT_SYMBOL(p9_is_proto_dotu); 72EXPORT_SYMBOL(p9_is_proto_dotu);
73 73
74/* Interpret mount option for protocol version */ 74/* Interpret mount option for protocol version */
75static unsigned char get_protocol_version(const substring_t *name) 75static int get_protocol_version(const substring_t *name)
76{ 76{
77 unsigned char version = -EINVAL; 77 int version = -EINVAL;
78
78 if (!strncmp("9p2000", name->from, name->to-name->from)) { 79 if (!strncmp("9p2000", name->from, name->to-name->from)) {
79 version = p9_proto_legacy; 80 version = p9_proto_legacy;
80 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n"); 81 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
@@ -534,7 +535,12 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
534 535
535 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 536 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
536 537
537 if (c->status != Connected) 538 /* we allow for any status other than disconnected */
539 if (c->status == Disconnected)
540 return ERR_PTR(-EIO);
541
542 /* if status is begin_disconnected we allow only clunk request */
543 if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
538 return ERR_PTR(-EIO); 544 return ERR_PTR(-EIO);
539 545
540 if (signal_pending(current)) { 546 if (signal_pending(current)) {
@@ -800,8 +806,10 @@ void p9_client_destroy(struct p9_client *clnt)
800 806
801 v9fs_put_trans(clnt->trans_mod); 807 v9fs_put_trans(clnt->trans_mod);
802 808
803 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) 809 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
810 printk(KERN_INFO "Found fid %d not clunked\n", fid->fid);
804 p9_fid_destroy(fid); 811 p9_fid_destroy(fid);
812 }
805 813
806 if (clnt->fidpool) 814 if (clnt->fidpool)
807 p9_idpool_destroy(clnt->fidpool); 815 p9_idpool_destroy(clnt->fidpool);
@@ -819,6 +827,13 @@ void p9_client_disconnect(struct p9_client *clnt)
819} 827}
820EXPORT_SYMBOL(p9_client_disconnect); 828EXPORT_SYMBOL(p9_client_disconnect);
821 829
830void p9_client_begin_disconnect(struct p9_client *clnt)
831{
832 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
833 clnt->status = BeginDisconnect;
834}
835EXPORT_SYMBOL(p9_client_begin_disconnect);
836
822struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 837struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
823 char *uname, u32 n_uname, char *aname) 838 char *uname, u32 n_uname, char *aname)
824{ 839{