aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/9p.txt10
-rw-r--r--fs/9p/fid.c157
-rw-r--r--fs/9p/v9fs.c67
-rw-r--r--fs/9p/v9fs.h11
-rw-r--r--fs/9p/vfs_inode.c20
-rw-r--r--include/net/9p/9p.h7
-rw-r--r--include/net/9p/client.h5
-rw-r--r--net/9p/client.c10
-rw-r--r--net/9p/conv.c32
9 files changed, 247 insertions, 72 deletions
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index e694cd1b52cf..d6fd6c6e4244 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -88,6 +88,16 @@ OPTIONS
88 This can be used to share devices/named pipes/sockets between 88 This can be used to share devices/named pipes/sockets between
89 hosts. This functionality will be expanded in later versions. 89 hosts. This functionality will be expanded in later versions.
90 90
91 access there are three access modes.
92 user = if a user tries to access a file on v9fs
93 filesystem for the first time, v9fs sends an
94 attach command (Tattach) for that user.
95 This is the default mode.
96 <uid> = allows only user with uid=<uid> to access
97 the files on the mounted filesystem
98 any = v9fs does single attach and performs all
99 operations as one user
100
91RESOURCES 101RESOURCES
92========= 102=========
93 103
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 15e05a15b575..b364da70ff28 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * V9FS FID Management 2 * V9FS FID Management
3 * 3 *
4 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
4 * Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com> 5 * Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -34,9 +35,9 @@
34#include "fid.h" 35#include "fid.h"
35 36
36/** 37/**
37 * v9fs_fid_insert - add a fid to a dentry 38 * v9fs_fid_add - add a fid to a dentry
39 * @dentry: dentry that the fid is being added to
38 * @fid: fid to add 40 * @fid: fid to add
39 * @dentry: dentry that it is being added to
40 * 41 *
41 */ 42 */
42 43
@@ -66,52 +67,144 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
66} 67}
67 68
68/** 69/**
69 * v9fs_fid_lookup - return a locked fid from a dentry 70 * v9fs_fid_find - retrieve a fid that belongs to the specified uid
70 * @dentry: dentry to look for fid in 71 * @dentry: dentry to look for fid in
71 * 72 * @uid: return fid that belongs to the specified user
72 * find a fid in the dentry, obtain its semaphore and return a reference to it. 73 * @any: if non-zero, return any fid associated with the dentry
73 * code calling lookup is responsible for releasing lock
74 *
75 * TODO: only match fids that have the same uid as current user
76 * 74 *
77 */ 75 */
78 76
79struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) 77static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any)
80{ 78{
81 struct v9fs_dentry *dent; 79 struct v9fs_dentry *dent;
82 struct p9_fid *fid; 80 struct p9_fid *fid, *ret;
83 81
84 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 82 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n",
85 dent = dentry->d_fsdata; 83 dentry->d_iname, dentry, uid, any);
86 if (dent) 84 dent = (struct v9fs_dentry *) dentry->d_fsdata;
87 fid = list_entry(dent->fidlist.next, struct p9_fid, dlist); 85 ret = NULL;
88 else 86 if (dent) {
89 fid = ERR_PTR(-EBADF); 87 spin_lock(&dent->lock);
88 list_for_each_entry(fid, &dent->fidlist, dlist) {
89 if (any || fid->uid == uid) {
90 ret = fid;
91 break;
92 }
93 }
94 spin_unlock(&dent->lock);
95 }
90 96
91 P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid); 97 return ret;
92 return fid;
93} 98}
94 99
95/** 100/**
96 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and 101 * v9fs_fid_lookup - lookup for a fid, try to walk if not found
97 * release it
98 * @dentry: dentry to look for fid in 102 * @dentry: dentry to look for fid in
99 * 103 *
100 * find a fid in the dentry and then clone to a new private fid 104 * Look for a fid in the specified dentry for the current user.
101 * 105 * If no fid is found, try to create one walking from a fid from the parent
102 * TODO: only match fids that have the same uid as current user 106 * dentry (if it has one), or the root dentry. If the user haven't accessed
103 * 107 * the fs yet, attach now and walk from the root.
104 */ 108 */
105 109
106struct p9_fid *v9fs_fid_clone(struct dentry *dentry) 110struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
107{ 111{
108 struct p9_fid *ofid, *fid; 112 int i, n, l, clone, any, access;
113 u32 uid;
114 struct p9_fid *fid;
115 struct dentry *d, *ds;
116 struct v9fs_session_info *v9ses;
117 char **wnames, *uname;
118
119 v9ses = v9fs_inode2v9ses(dentry->d_inode);
120 access = v9ses->flags & V9FS_ACCESS_MASK;
121 switch (access) {
122 case V9FS_ACCESS_SINGLE:
123 case V9FS_ACCESS_USER:
124 uid = current->fsuid;
125 any = 0;
126 break;
127
128 case V9FS_ACCESS_ANY:
129 uid = v9ses->uid;
130 any = 1;
131 break;
132
133 default:
134 uid = ~0;
135 any = 0;
136 break;
137 }
109 138
110 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 139 fid = v9fs_fid_find(dentry, uid, any);
111 ofid = v9fs_fid_lookup(dentry); 140 if (fid)
112 if (IS_ERR(ofid)) 141 return fid;
113 return ofid; 142
143 ds = dentry->d_parent;
144 fid = v9fs_fid_find(ds, uid, any);
145 if (!fid) { /* walk from the root */
146 n = 0;
147 for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)
148 n++;
149
150 fid = v9fs_fid_find(ds, uid, any);
151 if (!fid) { /* the user is not attached to the fs yet */
152 if (access == V9FS_ACCESS_SINGLE)
153 return ERR_PTR(-EPERM);
154
155 if (v9fs_extended(v9ses))
156 uname = NULL;
157 else
158 uname = v9ses->uname;
159
160 fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
161 v9ses->aname);
162
163 if (IS_ERR(fid))
164 return fid;
165
166 v9fs_fid_add(ds, fid);
167 }
168 } else /* walk from the parent */
169 n = 1;
170
171 if (ds == dentry)
172 return fid;
173
174 wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);
175 if (!wnames)
176 return ERR_PTR(-ENOMEM);
177
178 for (d = dentry, i = n; i >= 0; i--, d = d->d_parent)
179 wnames[i] = (char *) d->d_name.name;
180
181 clone = 1;
182 i = 0;
183 while (i < n) {
184 l = min(n - i, P9_MAXWELEM);
185 fid = p9_client_walk(fid, l, &wnames[i], clone);
186 if (!fid) {
187 kfree(wnames);
188 return fid;
189 }
190
191 i += l;
192 clone = 0;
193 }
114 194
115 fid = p9_client_walk(ofid, 0, NULL, 1); 195 kfree(wnames);
196 v9fs_fid_add(dentry, fid);
116 return fid; 197 return fid;
117} 198}
199
200struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
201{
202 struct p9_fid *fid, *ret;
203
204 fid = v9fs_fid_lookup(dentry);
205 if (IS_ERR(fid))
206 return fid;
207
208 ret = p9_client_walk(fid, 0, NULL, 1);
209 return ret;
210}
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 68f82be3bf37..89ee0bace41d 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -91,6 +91,8 @@ enum {
91 Opt_legacy, Opt_nodevmap, 91 Opt_legacy, Opt_nodevmap,
92 /* Cache options */ 92 /* Cache options */
93 Opt_cache_loose, 93 Opt_cache_loose,
94 /* Access options */
95 Opt_access,
94 /* Error token */ 96 /* Error token */
95 Opt_err 97 Opt_err
96}; 98};
@@ -108,6 +110,7 @@ static match_table_t tokens = {
108 {Opt_nodevmap, "nodevmap"}, 110 {Opt_nodevmap, "nodevmap"},
109 {Opt_cache_loose, "cache=loose"}, 111 {Opt_cache_loose, "cache=loose"},
110 {Opt_cache_loose, "loose"}, 112 {Opt_cache_loose, "loose"},
113 {Opt_access, "access=%s"},
111 {Opt_err, NULL} 114 {Opt_err, NULL}
112}; 115};
113 116
@@ -125,10 +128,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses)
125 char *p; 128 char *p;
126 int option; 129 int option;
127 int ret; 130 int ret;
131 char *s, *e;
128 132
129 /* setup defaults */ 133 /* setup defaults */
130 v9ses->maxdata = 8192; 134 v9ses->maxdata = 8192;
131 v9ses->flags = V9FS_EXTENDED;
132 v9ses->afid = ~0; 135 v9ses->afid = ~0;
133 v9ses->debug = 0; 136 v9ses->debug = 0;
134 v9ses->cache = 0; 137 v9ses->cache = 0;
@@ -172,10 +175,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses)
172 v9ses->trans = v9fs_match_trans(&args[0]); 175 v9ses->trans = v9fs_match_trans(&args[0]);
173 break; 176 break;
174 case Opt_uname: 177 case Opt_uname:
175 match_strcpy(v9ses->name, &args[0]); 178 match_strcpy(v9ses->uname, &args[0]);
176 break; 179 break;
177 case Opt_remotename: 180 case Opt_remotename:
178 match_strcpy(v9ses->remotename, &args[0]); 181 match_strcpy(v9ses->aname, &args[0]);
179 break; 182 break;
180 case Opt_legacy: 183 case Opt_legacy:
181 v9ses->flags &= ~V9FS_EXTENDED; 184 v9ses->flags &= ~V9FS_EXTENDED;
@@ -186,6 +189,22 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses)
186 case Opt_cache_loose: 189 case Opt_cache_loose:
187 v9ses->cache = CACHE_LOOSE; 190 v9ses->cache = CACHE_LOOSE;
188 break; 191 break;
192
193 case Opt_access:
194 s = match_strdup(&args[0]);
195 v9ses->flags &= ~V9FS_ACCESS_MASK;
196 if (strcmp(s, "user") == 0)
197 v9ses->flags |= V9FS_ACCESS_USER;
198 else if (strcmp(s, "any") == 0)
199 v9ses->flags |= V9FS_ACCESS_ANY;
200 else {
201 v9ses->flags |= V9FS_ACCESS_SINGLE;
202 v9ses->uid = simple_strtol(s, &e, 10);
203 if (*e != '\0')
204 v9ses->uid = ~0;
205 }
206 break;
207
189 default: 208 default:
190 continue; 209 continue;
191 } 210 }
@@ -207,21 +226,22 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
207 struct p9_trans *trans = NULL; 226 struct p9_trans *trans = NULL;
208 struct p9_fid *fid; 227 struct p9_fid *fid;
209 228
210 v9ses->name = __getname(); 229 v9ses->uname = __getname();
211 if (!v9ses->name) 230 if (!v9ses->uname)
212 return ERR_PTR(-ENOMEM); 231 return ERR_PTR(-ENOMEM);
213 232
214 v9ses->remotename = __getname(); 233 v9ses->aname = __getname();
215 if (!v9ses->remotename) { 234 if (!v9ses->aname) {
216 __putname(v9ses->name); 235 __putname(v9ses->uname);
217 return ERR_PTR(-ENOMEM); 236 return ERR_PTR(-ENOMEM);
218 } 237 }
219 238
220 strcpy(v9ses->name, V9FS_DEFUSER); 239 v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
221 strcpy(v9ses->remotename, V9FS_DEFANAME); 240 strcpy(v9ses->uname, V9FS_DEFUSER);
241 strcpy(v9ses->aname, V9FS_DEFANAME);
242 v9ses->uid = ~0;
222 v9ses->dfltuid = V9FS_DEFUID; 243 v9ses->dfltuid = V9FS_DEFUID;
223 v9ses->dfltgid = V9FS_DEFGID; 244 v9ses->dfltgid = V9FS_DEFGID;
224
225 v9ses->options = kstrdup(data, GFP_KERNEL); 245 v9ses->options = kstrdup(data, GFP_KERNEL);
226 v9fs_parse_options(v9ses); 246 v9fs_parse_options(v9ses);
227 247
@@ -255,8 +275,20 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
255 goto error; 275 goto error;
256 } 276 }
257 277
258 fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name, 278 if (!v9ses->clnt->dotu)
259 v9ses->remotename); 279 v9ses->flags &= ~V9FS_EXTENDED;
280
281 /* for legacy mode, fall back to V9FS_ACCESS_ANY */
282 if (!v9fs_extended(v9ses) &&
283 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
284
285 v9ses->flags &= ~V9FS_ACCESS_MASK;
286 v9ses->flags |= V9FS_ACCESS_ANY;
287 v9ses->uid = ~0;
288 }
289
290 fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
291 v9ses->aname);
260 if (IS_ERR(fid)) { 292 if (IS_ERR(fid)) {
261 retval = PTR_ERR(fid); 293 retval = PTR_ERR(fid);
262 fid = NULL; 294 fid = NULL;
@@ -264,6 +296,11 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
264 goto error; 296 goto error;
265 } 297 }
266 298
299 if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
300 fid->uid = v9ses->uid;
301 else
302 fid->uid = ~0;
303
267 return fid; 304 return fid;
268 305
269error: 306error:
@@ -284,8 +321,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
284 v9ses->clnt = NULL; 321 v9ses->clnt = NULL;
285 } 322 }
286 323
287 __putname(v9ses->name); 324 __putname(v9ses->uname);
288 __putname(v9ses->remotename); 325 __putname(v9ses->aname);
289 kfree(v9ses->options); 326 kfree(v9ses->options);
290} 327}
291 328
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 8e0999b3d0cc..db4b4193f2e2 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -36,10 +36,11 @@ struct v9fs_session_info {
36 unsigned int cache; /* cache mode */ 36 unsigned int cache; /* cache mode */
37 37
38 char *options; /* copy of mount options */ 38 char *options; /* copy of mount options */
39 char *name; /* user name to mount as */ 39 char *uname; /* user name to mount as */
40 char *remotename; /* name of remote hierarchy being mounted */ 40 char *aname; /* name of remote hierarchy being mounted */
41 unsigned int dfltuid; /* default uid/muid for legacy support */ 41 unsigned int dfltuid; /* default uid/muid for legacy support */
42 unsigned int dfltgid; /* default gid for legacy support */ 42 unsigned int dfltgid; /* default gid for legacy support */
43 u32 uid; /* if ACCESS_SINGLE, the uid that has access */
43 struct p9_trans_module *trans; /* 9p transport */ 44 struct p9_trans_module *trans; /* 9p transport */
44 struct p9_client *clnt; /* 9p client */ 45 struct p9_client *clnt; /* 9p client */
45 struct dentry *debugfs_dir; 46 struct dentry *debugfs_dir;
@@ -47,7 +48,11 @@ struct v9fs_session_info {
47 48
48/* session flags */ 49/* session flags */
49enum { 50enum {
50 V9FS_EXTENDED, 51 V9FS_EXTENDED = 0x01, /* 9P2000.u */
52 V9FS_ACCESS_MASK = 0x06, /* access mask */
53 V9FS_ACCESS_SINGLE = 0x02, /* only one user can access the files */
54 V9FS_ACCESS_USER = 0x04, /* attache per user */
55 V9FS_ACCESS_ANY = 0x06, /* use the same attach for all users */
51}; 56};
52 57
53/* possible values of ->cache */ 58/* possible values of ->cache */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index f08a35d2973a..175b4d9bf3f8 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -364,7 +364,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
364 file_inode = file->d_inode; 364 file_inode = file->d_inode;
365 v9ses = v9fs_inode2v9ses(file_inode); 365 v9ses = v9fs_inode2v9ses(file_inode);
366 v9fid = v9fs_fid_clone(file); 366 v9fid = v9fs_fid_clone(file);
367 if(IS_ERR(v9fid)) 367 if (IS_ERR(v9fid))
368 return PTR_ERR(v9fid); 368 return PTR_ERR(v9fid);
369 369
370 return p9_client_remove(v9fid); 370 return p9_client_remove(v9fid);
@@ -398,7 +398,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
398 fid = NULL; 398 fid = NULL;
399 name = (char *) dentry->d_name.name; 399 name = (char *) dentry->d_name.name;
400 dfid = v9fs_fid_clone(dentry->d_parent); 400 dfid = v9fs_fid_clone(dentry->d_parent);
401 if(IS_ERR(dfid)) { 401 if (IS_ERR(dfid)) {
402 err = PTR_ERR(dfid); 402 err = PTR_ERR(dfid);
403 dfid = NULL; 403 dfid = NULL;
404 goto error; 404 goto error;
@@ -432,7 +432,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
432 goto error; 432 goto error;
433 } 433 }
434 434
435 if(v9ses->cache) 435 if (v9ses->cache)
436 dentry->d_op = &v9fs_cached_dentry_operations; 436 dentry->d_op = &v9fs_cached_dentry_operations;
437 else 437 else
438 dentry->d_op = &v9fs_dentry_operations; 438 dentry->d_op = &v9fs_dentry_operations;
@@ -593,7 +593,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
593 if (result < 0) 593 if (result < 0)
594 goto error; 594 goto error;
595 595
596 if((fid->qid.version)&&(v9ses->cache)) 596 if ((fid->qid.version) && (v9ses->cache))
597 dentry->d_op = &v9fs_cached_dentry_operations; 597 dentry->d_op = &v9fs_cached_dentry_operations;
598 else 598 else
599 dentry->d_op = &v9fs_dentry_operations; 599 dentry->d_op = &v9fs_dentry_operations;
@@ -658,17 +658,17 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
658 old_inode = old_dentry->d_inode; 658 old_inode = old_dentry->d_inode;
659 v9ses = v9fs_inode2v9ses(old_inode); 659 v9ses = v9fs_inode2v9ses(old_inode);
660 oldfid = v9fs_fid_lookup(old_dentry); 660 oldfid = v9fs_fid_lookup(old_dentry);
661 if(IS_ERR(oldfid)) 661 if (IS_ERR(oldfid))
662 return PTR_ERR(oldfid); 662 return PTR_ERR(oldfid);
663 663
664 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 664 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
665 if(IS_ERR(olddirfid)) { 665 if (IS_ERR(olddirfid)) {
666 retval = PTR_ERR(olddirfid); 666 retval = PTR_ERR(olddirfid);
667 goto done; 667 goto done;
668 } 668 }
669 669
670 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 670 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
671 if(IS_ERR(newdirfid)) { 671 if (IS_ERR(newdirfid)) {
672 retval = PTR_ERR(newdirfid); 672 retval = PTR_ERR(newdirfid);
673 goto clunk_olddir; 673 goto clunk_olddir;
674 } 674 }
@@ -682,7 +682,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
682 } 682 }
683 683
684 v9fs_blank_wstat(&wstat); 684 v9fs_blank_wstat(&wstat);
685 wstat.muid = v9ses->name; 685 wstat.muid = v9ses->uname;
686 wstat.name = (char *) new_dentry->d_name.name; 686 wstat.name = (char *) new_dentry->d_name.name;
687 retval = p9_client_wstat(oldfid, &wstat); 687 retval = p9_client_wstat(oldfid, &wstat);
688 688
@@ -887,7 +887,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
887 retval = -EPERM; 887 retval = -EPERM;
888 v9ses = v9fs_inode2v9ses(dentry->d_inode); 888 v9ses = v9fs_inode2v9ses(dentry->d_inode);
889 fid = v9fs_fid_lookup(dentry); 889 fid = v9fs_fid_lookup(dentry);
890 if(IS_ERR(fid)) 890 if (IS_ERR(fid))
891 return PTR_ERR(fid); 891 return PTR_ERR(fid);
892 892
893 if (!v9fs_extended(v9ses)) 893 if (!v9fs_extended(v9ses))
@@ -1070,7 +1070,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1070 old_dentry->d_name.name); 1070 old_dentry->d_name.name);
1071 1071
1072 oldfid = v9fs_fid_clone(old_dentry); 1072 oldfid = v9fs_fid_clone(old_dentry);
1073 if(IS_ERR(oldfid)) 1073 if (IS_ERR(oldfid))
1074 return PTR_ERR(oldfid); 1074 return PTR_ERR(oldfid);
1075 1075
1076 name = __getname(); 1076 name = __getname();
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 7726ff41c3e6..7a448a30e39b 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -216,6 +216,7 @@ struct p9_tauth {
216 u32 afid; 216 u32 afid;
217 struct p9_str uname; 217 struct p9_str uname;
218 struct p9_str aname; 218 struct p9_str aname;
219 u32 n_uname; /* 9P2000.u extensions */
219}; 220};
220 221
221struct p9_rauth { 222struct p9_rauth {
@@ -239,6 +240,7 @@ struct p9_tattach {
239 u32 afid; 240 u32 afid;
240 struct p9_str uname; 241 struct p9_str uname;
241 struct p9_str aname; 242 struct p9_str aname;
243 u32 n_uname; /* 9P2000.u extensions */
242}; 244};
243 245
244struct p9_rattach { 246struct p9_rattach {
@@ -382,8 +384,9 @@ int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu);
382void p9_set_tag(struct p9_fcall *fc, u16 tag); 384void p9_set_tag(struct p9_fcall *fc, u16 tag);
383struct p9_fcall *p9_create_tversion(u32 msize, char *version); 385struct p9_fcall *p9_create_tversion(u32 msize, char *version);
384struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname, 386struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname,
385 char *aname); 387 char *aname, u32 n_uname, int dotu);
386struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname); 388struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
389 u32 n_uname, int dotu);
387struct p9_fcall *p9_create_tflush(u16 oldtag); 390struct p9_fcall *p9_create_tflush(u16 oldtag);
388struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, 391struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
389 char **wnames); 392 char **wnames);
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 0adafdb273f0..9b9221a21392 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -57,8 +57,9 @@ struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
57void p9_client_destroy(struct p9_client *clnt); 57void p9_client_destroy(struct p9_client *clnt);
58void p9_client_disconnect(struct p9_client *clnt); 58void p9_client_disconnect(struct p9_client *clnt);
59struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 59struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
60 char *uname, char *aname); 60 char *uname, u32 n_uname, char *aname);
61struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname); 61struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
62 u32 n_uname, char *aname);
62struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, 63struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
63 int clone); 64 int clone);
64int p9_client_open(struct p9_fid *fid, int mode); 65int p9_client_open(struct p9_fid *fid, int mode);
diff --git a/net/9p/client.c b/net/9p/client.c
index e1610125a882..d83cc1247f1e 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -146,7 +146,7 @@ void p9_client_disconnect(struct p9_client *clnt)
146EXPORT_SYMBOL(p9_client_disconnect); 146EXPORT_SYMBOL(p9_client_disconnect);
147 147
148struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 148struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
149 char *uname, char *aname) 149 char *uname, u32 n_uname, char *aname)
150{ 150{
151 int err; 151 int err;
152 struct p9_fcall *tc, *rc; 152 struct p9_fcall *tc, *rc;
@@ -165,7 +165,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
165 goto error; 165 goto error;
166 } 166 }
167 167
168 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname); 168 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname,
169 n_uname, clnt->dotu);
169 if (IS_ERR(tc)) { 170 if (IS_ERR(tc)) {
170 err = PTR_ERR(tc); 171 err = PTR_ERR(tc);
171 tc = NULL; 172 tc = NULL;
@@ -190,7 +191,8 @@ error:
190} 191}
191EXPORT_SYMBOL(p9_client_attach); 192EXPORT_SYMBOL(p9_client_attach);
192 193
193struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname) 194struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
195 u32 n_uname, char *aname)
194{ 196{
195 int err; 197 int err;
196 struct p9_fcall *tc, *rc; 198 struct p9_fcall *tc, *rc;
@@ -209,7 +211,7 @@ struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
209 goto error; 211 goto error;
210 } 212 }
211 213
212 tc = p9_create_tauth(fid->fid, uname, aname); 214 tc = p9_create_tauth(fid->fid, uname, aname, n_uname, clnt->dotu);
213 if (IS_ERR(tc)) { 215 if (IS_ERR(tc)) {
214 err = PTR_ERR(tc); 216 err = PTR_ERR(tc);
215 tc = NULL; 217 tc = NULL;
diff --git a/net/9p/conv.c b/net/9p/conv.c
index d979d958ea19..aa2aa9884f95 100644
--- a/net/9p/conv.c
+++ b/net/9p/conv.c
@@ -547,7 +547,8 @@ error:
547} 547}
548EXPORT_SYMBOL(p9_create_tversion); 548EXPORT_SYMBOL(p9_create_tversion);
549 549
550struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname) 550struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
551 u32 n_uname, int dotu)
551{ 552{
552 int size; 553 int size;
553 struct p9_fcall *fc; 554 struct p9_fcall *fc;
@@ -555,7 +556,16 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
555 struct cbuf *bufp = &buffer; 556 struct cbuf *bufp = &buffer;
556 557
557 /* afid[4] uname[s] aname[s] */ 558 /* afid[4] uname[s] aname[s] */
558 size = 4 + 2 + strlen(uname) + 2 + strlen(aname); 559 size = 4 + 2 + 2;
560 if (uname)
561 size += strlen(uname);
562
563 if (aname)
564 size += strlen(aname);
565
566 if (dotu)
567 size += 4; /* n_uname */
568
559 fc = p9_create_common(bufp, size, P9_TAUTH); 569 fc = p9_create_common(bufp, size, P9_TAUTH);
560 if (IS_ERR(fc)) 570 if (IS_ERR(fc))
561 goto error; 571 goto error;
@@ -563,6 +573,8 @@ struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
563 p9_put_int32(bufp, afid, &fc->params.tauth.afid); 573 p9_put_int32(bufp, afid, &fc->params.tauth.afid);
564 p9_put_str(bufp, uname, &fc->params.tauth.uname); 574 p9_put_str(bufp, uname, &fc->params.tauth.uname);
565 p9_put_str(bufp, aname, &fc->params.tauth.aname); 575 p9_put_str(bufp, aname, &fc->params.tauth.aname);
576 if (dotu)
577 p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname);
566 578
567 if (buf_check_overflow(bufp)) { 579 if (buf_check_overflow(bufp)) {
568 kfree(fc); 580 kfree(fc);
@@ -574,7 +586,8 @@ error:
574EXPORT_SYMBOL(p9_create_tauth); 586EXPORT_SYMBOL(p9_create_tauth);
575 587
576struct p9_fcall * 588struct p9_fcall *
577p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname) 589p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname,
590 u32 n_uname, int dotu)
578{ 591{
579 int size; 592 int size;
580 struct p9_fcall *fc; 593 struct p9_fcall *fc;
@@ -582,7 +595,16 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
582 struct cbuf *bufp = &buffer; 595 struct cbuf *bufp = &buffer;
583 596
584 /* fid[4] afid[4] uname[s] aname[s] */ 597 /* fid[4] afid[4] uname[s] aname[s] */
585 size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); 598 size = 4 + 4 + 2 + 2;
599 if (uname)
600 size += strlen(uname);
601
602 if (aname)
603 size += strlen(aname);
604
605 if (dotu)
606 size += 4; /* n_uname */
607
586 fc = p9_create_common(bufp, size, P9_TATTACH); 608 fc = p9_create_common(bufp, size, P9_TATTACH);
587 if (IS_ERR(fc)) 609 if (IS_ERR(fc))
588 goto error; 610 goto error;
@@ -591,6 +613,8 @@ p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
591 p9_put_int32(bufp, afid, &fc->params.tattach.afid); 613 p9_put_int32(bufp, afid, &fc->params.tattach.afid);
592 p9_put_str(bufp, uname, &fc->params.tattach.uname); 614 p9_put_str(bufp, uname, &fc->params.tattach.uname);
593 p9_put_str(bufp, aname, &fc->params.tattach.aname); 615 p9_put_str(bufp, aname, &fc->params.tattach.aname);
616 if (dotu)
617 p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname);
594 618
595error: 619error:
596 return fc; 620 return fc;