aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/cache.c1
-rw-r--r--fs/9p/fid.c13
-rw-r--r--fs/9p/v9fs.c32
-rw-r--r--fs/9p/v9fs.h9
-rw-r--r--fs/9p/vfs_dentry.c1
-rw-r--r--fs/9p/vfs_dir.c14
-rw-r--r--fs/9p/vfs_file.c4
-rw-r--r--fs/9p/vfs_inode.c10
-rw-r--r--fs/9p/vfs_super.c5
9 files changed, 76 insertions, 13 deletions
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index e777961939f3..0dbe0d139ac2 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -22,6 +22,7 @@
22 22
23#include <linux/jiffies.h> 23#include <linux/jiffies.h>
24#include <linux/file.h> 24#include <linux/file.h>
25#include <linux/slab.h>
25#include <linux/stat.h> 26#include <linux/stat.h>
26#include <linux/sched.h> 27#include <linux/sched.h>
27#include <linux/fs.h> 28#include <linux/fs.h>
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 08b2eb157048..7317b39b2815 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -24,6 +24,7 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/slab.h>
27#include <linux/sched.h> 28#include <linux/sched.h>
28#include <linux/idr.h> 29#include <linux/idr.h>
29#include <net/9p/9p.h> 30#include <net/9p/9p.h>
@@ -110,7 +111,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
110{ 111{
111 int i, n, l, clone, any, access; 112 int i, n, l, clone, any, access;
112 u32 uid; 113 u32 uid;
113 struct p9_fid *fid; 114 struct p9_fid *fid, *old_fid = NULL;
114 struct dentry *d, *ds; 115 struct dentry *d, *ds;
115 struct v9fs_session_info *v9ses; 116 struct v9fs_session_info *v9ses;
116 char **wnames, *uname; 117 char **wnames, *uname;
@@ -183,10 +184,18 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
183 l = min(n - i, P9_MAXWELEM); 184 l = min(n - i, P9_MAXWELEM);
184 fid = p9_client_walk(fid, l, &wnames[i], clone); 185 fid = p9_client_walk(fid, l, &wnames[i], clone);
185 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 }
186 kfree(wnames); 195 kfree(wnames);
187 return fid; 196 return fid;
188 } 197 }
189 198 old_fid = fid;
190 i += l; 199 i += l;
191 clone = 0; 200 clone = 0;
192 } 201 }
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 6c7f6a251115..f8b86e92cd66 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -29,6 +29,7 @@
29#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/parser.h> 30#include <linux/parser.h>
31#include <linux/idr.h> 31#include <linux/idr.h>
32#include <linux/slab.h>
32#include <net/9p/9p.h> 33#include <net/9p/9p.h>
33#include <net/9p/client.h> 34#include <net/9p/client.h>
34#include <net/9p/transport.h> 35#include <net/9p/transport.h>
@@ -237,11 +238,18 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
237 return ERR_PTR(-ENOMEM); 238 return ERR_PTR(-ENOMEM);
238 } 239 }
239 240
241 rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
242 if (rc) {
243 __putname(v9ses->aname);
244 __putname(v9ses->uname);
245 return ERR_PTR(rc);
246 }
247
240 spin_lock(&v9fs_sessionlist_lock); 248 spin_lock(&v9fs_sessionlist_lock);
241 list_add(&v9ses->slist, &v9fs_sessionlist); 249 list_add(&v9ses->slist, &v9fs_sessionlist);
242 spin_unlock(&v9fs_sessionlist_lock); 250 spin_unlock(&v9fs_sessionlist_lock);
243 251
244 v9ses->flags = V9FS_PROTO_2000U | V9FS_ACCESS_USER; 252 v9ses->flags = V9FS_ACCESS_USER;
245 strcpy(v9ses->uname, V9FS_DEFUSER); 253 strcpy(v9ses->uname, V9FS_DEFUSER);
246 strcpy(v9ses->aname, V9FS_DEFANAME); 254 strcpy(v9ses->aname, V9FS_DEFANAME);
247 v9ses->uid = ~0; 255 v9ses->uid = ~0;
@@ -262,8 +270,10 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
262 goto error; 270 goto error;
263 } 271 }
264 272
265 if (!p9_is_proto_dotu(v9ses->clnt)) 273 if (p9_is_proto_dotl(v9ses->clnt))
266 v9ses->flags &= ~V9FS_PROTO_2000U; 274 v9ses->flags |= V9FS_PROTO_2000L;
275 else if (p9_is_proto_dotu(v9ses->clnt))
276 v9ses->flags |= V9FS_PROTO_2000U;
267 277
268 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 278 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
269 279
@@ -298,6 +308,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
298 return fid; 308 return fid;
299 309
300error: 310error:
311 bdi_destroy(&v9ses->bdi);
301 return ERR_PTR(retval); 312 return ERR_PTR(retval);
302} 313}
303 314
@@ -323,6 +334,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
323 __putname(v9ses->uname); 334 __putname(v9ses->uname);
324 __putname(v9ses->aname); 335 __putname(v9ses->aname);
325 336
337 bdi_destroy(&v9ses->bdi);
338
326 spin_lock(&v9fs_sessionlist_lock); 339 spin_lock(&v9fs_sessionlist_lock);
327 list_del(&v9ses->slist); 340 list_del(&v9ses->slist);
328 spin_unlock(&v9fs_sessionlist_lock); 341 spin_unlock(&v9fs_sessionlist_lock);
@@ -340,6 +353,19 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
340 p9_client_disconnect(v9ses->clnt); 353 p9_client_disconnect(v9ses->clnt);
341} 354}
342 355
356/**
357 * v9fs_session_begin_cancel - Begin terminate of a session
358 * @v9ses: session to terminate
359 *
360 * After this call we don't allow any request other than clunk.
361 */
362
363void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
364{
365 P9_DPRINTK(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses);
366 p9_client_begin_disconnect(v9ses->clnt);
367}
368
343extern int v9fs_error_init(void); 369extern int v9fs_error_init(void);
344 370
345static struct kobject *v9fs_kobj; 371static struct kobject *v9fs_kobj;
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 79000bf62491..bec4d0bcb458 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -20,11 +20,12 @@
20 * Boston, MA 02111-1301 USA 20 * Boston, MA 02111-1301 USA
21 * 21 *
22 */ 22 */
23#include <linux/backing-dev.h>
23 24
24/** 25/**
25 * enum p9_session_flags - option flags for each 9P session 26 * enum p9_session_flags - option flags for each 9P session
26 * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions 27 * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions
27 * @V9FS_PROTO_2010L: whether or not to use 9P2010.l extensions 28 * @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions
28 * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy 29 * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy
29 * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) 30 * @V9FS_ACCESS_USER: a new attach will be issued for every user (default)
30 * @V9FS_ACCESS_ANY: use a single attach for all users 31 * @V9FS_ACCESS_ANY: use a single attach for all users
@@ -34,7 +35,7 @@
34 */ 35 */
35enum p9_session_flags { 36enum p9_session_flags {
36 V9FS_PROTO_2000U = 0x01, 37 V9FS_PROTO_2000U = 0x01,
37 V9FS_PROTO_2010L = 0x02, 38 V9FS_PROTO_2000L = 0x02,
38 V9FS_ACCESS_SINGLE = 0x04, 39 V9FS_ACCESS_SINGLE = 0x04,
39 V9FS_ACCESS_USER = 0x08, 40 V9FS_ACCESS_USER = 0x08,
40 V9FS_ACCESS_ANY = 0x0C, 41 V9FS_ACCESS_ANY = 0x0C,
@@ -102,12 +103,14 @@ struct v9fs_session_info {
102 u32 uid; /* if ACCESS_SINGLE, the uid that has access */ 103 u32 uid; /* if ACCESS_SINGLE, the uid that has access */
103 struct p9_client *clnt; /* 9p client */ 104 struct p9_client *clnt; /* 9p client */
104 struct list_head slist; /* list of sessions registered with v9fs */ 105 struct list_head slist; /* list of sessions registered with v9fs */
106 struct backing_dev_info bdi;
105}; 107};
106 108
107struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, 109struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
108 char *); 110 char *);
109void v9fs_session_close(struct v9fs_session_info *v9ses); 111void v9fs_session_close(struct v9fs_session_info *v9ses);
110void v9fs_session_cancel(struct v9fs_session_info *v9ses); 112void v9fs_session_cancel(struct v9fs_session_info *v9ses);
113void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
111 114
112#define V9FS_MAGIC 0x01021997 115#define V9FS_MAGIC 0x01021997
113 116
@@ -130,5 +133,5 @@ static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses)
130 133
131static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) 134static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
132{ 135{
133 return v9ses->flags & V9FS_PROTO_2010L; 136 return v9ses->flags & V9FS_PROTO_2000L;
134} 137}
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index d74325295b1e..cbf4e50f3933 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -34,6 +34,7 @@
34#include <linux/namei.h> 34#include <linux/namei.h>
35#include <linux/idr.h> 35#include <linux/idr.h>
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/slab.h>
37#include <net/9p/9p.h> 38#include <net/9p/9p.h>
38#include <net/9p/client.h> 39#include <net/9p/client.h>
39 40
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 6580aa449541..0adfd64dfcee 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -32,6 +32,7 @@
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/inet.h> 33#include <linux/inet.h>
34#include <linux/idr.h> 34#include <linux/idr.h>
35#include <linux/slab.h>
35#include <net/9p/9p.h> 36#include <net/9p/9p.h>
36#include <net/9p/client.h> 37#include <net/9p/client.h>
37 38
@@ -76,6 +77,15 @@ static inline int dt_type(struct p9_wstat *mistat)
76 return rettype; 77 return rettype;
77} 78}
78 79
80static void p9stat_init(struct p9_wstat *stbuf)
81{
82 stbuf->name = NULL;
83 stbuf->uid = NULL;
84 stbuf->gid = NULL;
85 stbuf->muid = NULL;
86 stbuf->extension = NULL;
87}
88
79/** 89/**
80 * v9fs_dir_readdir - read a directory 90 * v9fs_dir_readdir - read a directory
81 * @filp: opened file structure 91 * @filp: opened file structure
@@ -121,6 +131,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
121 rdir = (struct p9_rdir *) fid->rdir; 131 rdir = (struct p9_rdir *) fid->rdir;
122 132
123 err = mutex_lock_interruptible(&rdir->mutex); 133 err = mutex_lock_interruptible(&rdir->mutex);
134 if (err)
135 return err;
124 while (err == 0) { 136 while (err == 0) {
125 if (rdir->tail == rdir->head) { 137 if (rdir->tail == rdir->head) {
126 err = v9fs_file_readn(filp, rdir->buf, NULL, 138 err = v9fs_file_readn(filp, rdir->buf, NULL,
@@ -131,8 +143,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
131 rdir->head = 0; 143 rdir->head = 0;
132 rdir->tail = err; 144 rdir->tail = err;
133 } 145 }
134
135 while (rdir->head < rdir->tail) { 146 while (rdir->head < rdir->tail) {
147 p9stat_init(&st);
136 err = p9stat_read(rdir->buf + rdir->head, 148 err = p9stat_read(rdir->buf + rdir->head,
137 buflen - rdir->head, &st, 149 buflen - rdir->head, &st,
138 fid->clnt->proto_version); 150 fid->clnt->proto_version);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 36122683fae8..df52d488d2a6 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -114,7 +114,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
114 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 114 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
115 115
116 /* No mandatory locks */ 116 /* No mandatory locks */
117 if (__mandatory_lock(inode)) 117 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
118 return -ENOLCK; 118 return -ENOLCK;
119 119
120 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 120 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
@@ -215,7 +215,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
215 struct p9_fid *fid; 215 struct p9_fid *fid;
216 struct p9_client *clnt; 216 struct p9_client *clnt;
217 struct inode *inode = filp->f_path.dentry->d_inode; 217 struct inode *inode = filp->f_path.dentry->d_inode;
218 int origin = *offset; 218 loff_t origin = *offset;
219 unsigned long pg_start, pg_end; 219 unsigned long pg_start, pg_end;
220 220
221 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, 221 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 5fe45d692c9f..f2434fc9d2c4 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -34,6 +34,7 @@
34#include <linux/namei.h> 34#include <linux/namei.h>
35#include <linux/idr.h> 35#include <linux/idr.h>
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/slab.h>
37#include <net/9p/9p.h> 38#include <net/9p/9p.h>
38#include <net/9p/client.h> 39#include <net/9p/client.h>
39 40
@@ -431,6 +432,7 @@ error:
431 432
432static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 433static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
433{ 434{
435 int retval;
434 struct inode *file_inode; 436 struct inode *file_inode;
435 struct v9fs_session_info *v9ses; 437 struct v9fs_session_info *v9ses;
436 struct p9_fid *v9fid; 438 struct p9_fid *v9fid;
@@ -444,7 +446,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
444 if (IS_ERR(v9fid)) 446 if (IS_ERR(v9fid))
445 return PTR_ERR(v9fid); 447 return PTR_ERR(v9fid);
446 448
447 return p9_client_remove(v9fid); 449 retval = p9_client_remove(v9fid);
450 if (!retval)
451 drop_nlink(file_inode);
452 return retval;
448} 453}
449 454
450static int 455static int
@@ -656,6 +661,9 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
656 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",
657 dir, dentry->d_name.name, dentry, nameidata); 662 dir, dentry->d_name.name, dentry, nameidata);
658 663
664 if (dentry->d_name.len > NAME_MAX)
665 return ERR_PTR(-ENAMETOOLONG);
666
659 sb = dir->i_sb; 667 sb = dir->i_sb;
660 v9ses = v9fs_inode2v9ses(dir); 668 v9ses = v9fs_inode2v9ses(dir);
661 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 69357c0d9899..806da5d3b3a0 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -37,6 +37,7 @@
37#include <linux/mount.h> 37#include <linux/mount.h>
38#include <linux/idr.h> 38#include <linux/idr.h>
39#include <linux/sched.h> 39#include <linux/sched.h>
40#include <linux/slab.h>
40#include <net/9p/9p.h> 41#include <net/9p/9p.h>
41#include <net/9p/client.h> 42#include <net/9p/client.h>
42 43
@@ -76,6 +77,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
76 sb->s_blocksize = 1 << sb->s_blocksize_bits; 77 sb->s_blocksize = 1 << sb->s_blocksize_bits;
77 sb->s_magic = V9FS_MAGIC; 78 sb->s_magic = V9FS_MAGIC;
78 sb->s_op = &v9fs_super_ops; 79 sb->s_op = &v9fs_super_ops;
80 sb->s_bdi = &v9ses->bdi;
79 81
80 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | 82 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
81 MS_NOATIME; 83 MS_NOATIME;
@@ -193,6 +195,7 @@ static void v9fs_kill_super(struct super_block *s)
193 195
194 kill_anon_super(s); 196 kill_anon_super(s);
195 197
198 v9fs_session_cancel(v9ses);
196 v9fs_session_close(v9ses); 199 v9fs_session_close(v9ses);
197 kfree(v9ses); 200 kfree(v9ses);
198 s->s_fs_info = NULL; 201 s->s_fs_info = NULL;
@@ -205,7 +208,7 @@ v9fs_umount_begin(struct super_block *sb)
205 struct v9fs_session_info *v9ses; 208 struct v9fs_session_info *v9ses;
206 209
207 v9ses = sb->s_fs_info; 210 v9ses = sb->s_fs_info;
208 v9fs_session_cancel(v9ses); 211 v9fs_session_begin_cancel(v9ses);
209} 212}
210 213
211static const struct super_operations v9fs_super_ops = { 214static const struct super_operations v9fs_super_ops = {