aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/9p/9p.h375
-rw-r--r--fs/9p/Makefile6
-rw-r--r--fs/9p/conv.h50
-rw-r--r--fs/9p/debug.h77
-rw-r--r--fs/9p/error.c93
-rw-r--r--fs/9p/fcall.c427
-rw-r--r--fs/9p/fid.c168
-rw-r--r--fs/9p/fid.h43
-rw-r--r--fs/9p/trans_fd.c308
-rw-r--r--fs/9p/v9fs.c293
-rw-r--r--fs/9p/v9fs.h32
-rw-r--r--fs/9p/v9fs_vfs.h6
-rw-r--r--fs/9p/vfs_addr.c57
-rw-r--r--fs/9p/vfs_dentry.c37
-rw-r--r--fs/9p/vfs_dir.c155
-rw-r--r--fs/9p/vfs_file.c166
-rw-r--r--fs/9p/vfs_inode.c754
-rw-r--r--fs/9p/vfs_super.c93
-rw-r--r--fs/Kconfig2
-rw-r--r--include/net/9p/9p.h417
-rw-r--r--include/net/9p/client.h80
-rw-r--r--include/net/9p/conn.h (renamed from fs/9p/mux.h)42
-rw-r--r--include/net/9p/transport.h (renamed from fs/9p/transport.h)28
-rw-r--r--net/9p/Kconfig21
-rw-r--r--net/9p/Makefile13
-rw-r--r--net/9p/client.c965
-rw-r--r--net/9p/conv.c (renamed from fs/9p/conv.c)424
-rw-r--r--net/9p/error.c (renamed from fs/9p/error.h)79
-rw-r--r--net/9p/fcprint.c (renamed from fs/9p/fcprint.c)187
-rw-r--r--net/9p/mod.c85
-rw-r--r--net/9p/mux.c (renamed from fs/9p/mux.c)515
-rw-r--r--net/9p/sysctl.c86
-rw-r--r--net/9p/trans_fd.c363
-rw-r--r--net/9p/util.c125
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
36 files changed, 3444 insertions, 3130 deletions
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
deleted file mode 100644
index 94e2f92ab2e8..000000000000
--- a/fs/9p/9p.h
+++ /dev/null
@@ -1,375 +0,0 @@
1/*
2 * linux/fs/9p/9p.h
3 *
4 * 9P protocol definitions.
5 *
6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27/* Message Types */
28enum {
29 TVERSION = 100,
30 RVERSION,
31 TAUTH = 102,
32 RAUTH,
33 TATTACH = 104,
34 RATTACH,
35 TERROR = 106,
36 RERROR,
37 TFLUSH = 108,
38 RFLUSH,
39 TWALK = 110,
40 RWALK,
41 TOPEN = 112,
42 ROPEN,
43 TCREATE = 114,
44 RCREATE,
45 TREAD = 116,
46 RREAD,
47 TWRITE = 118,
48 RWRITE,
49 TCLUNK = 120,
50 RCLUNK,
51 TREMOVE = 122,
52 RREMOVE,
53 TSTAT = 124,
54 RSTAT,
55 TWSTAT = 126,
56 RWSTAT,
57};
58
59/* modes */
60enum {
61 V9FS_OREAD = 0x00,
62 V9FS_OWRITE = 0x01,
63 V9FS_ORDWR = 0x02,
64 V9FS_OEXEC = 0x03,
65 V9FS_OEXCL = 0x04,
66 V9FS_OTRUNC = 0x10,
67 V9FS_OREXEC = 0x20,
68 V9FS_ORCLOSE = 0x40,
69 V9FS_OAPPEND = 0x80,
70};
71
72/* permissions */
73enum {
74 V9FS_DMDIR = 0x80000000,
75 V9FS_DMAPPEND = 0x40000000,
76 V9FS_DMEXCL = 0x20000000,
77 V9FS_DMMOUNT = 0x10000000,
78 V9FS_DMAUTH = 0x08000000,
79 V9FS_DMTMP = 0x04000000,
80 V9FS_DMSYMLINK = 0x02000000,
81 V9FS_DMLINK = 0x01000000,
82 /* 9P2000.u extensions */
83 V9FS_DMDEVICE = 0x00800000,
84 V9FS_DMNAMEDPIPE = 0x00200000,
85 V9FS_DMSOCKET = 0x00100000,
86 V9FS_DMSETUID = 0x00080000,
87 V9FS_DMSETGID = 0x00040000,
88};
89
90/* qid.types */
91enum {
92 V9FS_QTDIR = 0x80,
93 V9FS_QTAPPEND = 0x40,
94 V9FS_QTEXCL = 0x20,
95 V9FS_QTMOUNT = 0x10,
96 V9FS_QTAUTH = 0x08,
97 V9FS_QTTMP = 0x04,
98 V9FS_QTSYMLINK = 0x02,
99 V9FS_QTLINK = 0x01,
100 V9FS_QTFILE = 0x00,
101};
102
103#define V9FS_NOTAG (u16)(~0)
104#define V9FS_NOFID (u32)(~0)
105#define V9FS_MAXWELEM 16
106
107/* ample room for Twrite/Rread header (iounit) */
108#define V9FS_IOHDRSZ 24
109
110struct v9fs_str {
111 u16 len;
112 char *str;
113};
114
115/* qids are the unique ID for a file (like an inode */
116struct v9fs_qid {
117 u8 type;
118 u32 version;
119 u64 path;
120};
121
122/* Plan 9 file metadata (stat) structure */
123struct v9fs_stat {
124 u16 size;
125 u16 type;
126 u32 dev;
127 struct v9fs_qid qid;
128 u32 mode;
129 u32 atime;
130 u32 mtime;
131 u64 length;
132 struct v9fs_str name;
133 struct v9fs_str uid;
134 struct v9fs_str gid;
135 struct v9fs_str muid;
136 struct v9fs_str extension; /* 9p2000.u extensions */
137 u32 n_uid; /* 9p2000.u extensions */
138 u32 n_gid; /* 9p2000.u extensions */
139 u32 n_muid; /* 9p2000.u extensions */
140};
141
142/* file metadata (stat) structure used to create Twstat message
143 The is similar to v9fs_stat, but the strings don't point to
144 the same memory block and should be freed separately
145*/
146struct v9fs_wstat {
147 u16 size;
148 u16 type;
149 u32 dev;
150 struct v9fs_qid qid;
151 u32 mode;
152 u32 atime;
153 u32 mtime;
154 u64 length;
155 char *name;
156 char *uid;
157 char *gid;
158 char *muid;
159 char *extension; /* 9p2000.u extensions */
160 u32 n_uid; /* 9p2000.u extensions */
161 u32 n_gid; /* 9p2000.u extensions */
162 u32 n_muid; /* 9p2000.u extensions */
163};
164
165/* Structures for Protocol Operations */
166
167struct Tversion {
168 u32 msize;
169 struct v9fs_str version;
170};
171
172struct Rversion {
173 u32 msize;
174 struct v9fs_str version;
175};
176
177struct Tauth {
178 u32 afid;
179 struct v9fs_str uname;
180 struct v9fs_str aname;
181};
182
183struct Rauth {
184 struct v9fs_qid qid;
185};
186
187struct Rerror {
188 struct v9fs_str error;
189 u32 errno; /* 9p2000.u extension */
190};
191
192struct Tflush {
193 u16 oldtag;
194};
195
196struct Rflush {
197};
198
199struct Tattach {
200 u32 fid;
201 u32 afid;
202 struct v9fs_str uname;
203 struct v9fs_str aname;
204};
205
206struct Rattach {
207 struct v9fs_qid qid;
208};
209
210struct Twalk {
211 u32 fid;
212 u32 newfid;
213 u16 nwname;
214 struct v9fs_str wnames[16];
215};
216
217struct Rwalk {
218 u16 nwqid;
219 struct v9fs_qid wqids[16];
220};
221
222struct Topen {
223 u32 fid;
224 u8 mode;
225};
226
227struct Ropen {
228 struct v9fs_qid qid;
229 u32 iounit;
230};
231
232struct Tcreate {
233 u32 fid;
234 struct v9fs_str name;
235 u32 perm;
236 u8 mode;
237 struct v9fs_str extension;
238};
239
240struct Rcreate {
241 struct v9fs_qid qid;
242 u32 iounit;
243};
244
245struct Tread {
246 u32 fid;
247 u64 offset;
248 u32 count;
249};
250
251struct Rread {
252 u32 count;
253 u8 *data;
254};
255
256struct Twrite {
257 u32 fid;
258 u64 offset;
259 u32 count;
260 u8 *data;
261};
262
263struct Rwrite {
264 u32 count;
265};
266
267struct Tclunk {
268 u32 fid;
269};
270
271struct Rclunk {
272};
273
274struct Tremove {
275 u32 fid;
276};
277
278struct Rremove {
279};
280
281struct Tstat {
282 u32 fid;
283};
284
285struct Rstat {
286 struct v9fs_stat stat;
287};
288
289struct Twstat {
290 u32 fid;
291 struct v9fs_stat stat;
292};
293
294struct Rwstat {
295};
296
297/*
298 * fcall is the primary packet structure
299 *
300 */
301
302struct v9fs_fcall {
303 u32 size;
304 u8 id;
305 u16 tag;
306 void *sdata;
307
308 union {
309 struct Tversion tversion;
310 struct Rversion rversion;
311 struct Tauth tauth;
312 struct Rauth rauth;
313 struct Rerror rerror;
314 struct Tflush tflush;
315 struct Rflush rflush;
316 struct Tattach tattach;
317 struct Rattach rattach;
318 struct Twalk twalk;
319 struct Rwalk rwalk;
320 struct Topen topen;
321 struct Ropen ropen;
322 struct Tcreate tcreate;
323 struct Rcreate rcreate;
324 struct Tread tread;
325 struct Rread rread;
326 struct Twrite twrite;
327 struct Rwrite rwrite;
328 struct Tclunk tclunk;
329 struct Rclunk rclunk;
330 struct Tremove tremove;
331 struct Rremove rremove;
332 struct Tstat tstat;
333 struct Rstat rstat;
334 struct Twstat twstat;
335 struct Rwstat rwstat;
336 } params;
337};
338
339#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \
340 fcall?fcall->params.rerror.error.len:0, \
341 fcall?fcall->params.rerror.error.str:"");
342
343int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
344 char *version, struct v9fs_fcall **rcall);
345
346int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
347 u32 fid, u32 afid, struct v9fs_fcall **rcall);
348
349int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid);
350
351int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
352 struct v9fs_fcall **rcall);
353
354int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
355 struct v9fs_wstat *wstat, struct v9fs_fcall **rcall);
356
357int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
358 char *name, struct v9fs_fcall **rcall);
359
360int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
361 struct v9fs_fcall **rcall);
362
363int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
364 struct v9fs_fcall **rcall);
365
366int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
367 u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall);
368
369int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
370 u64 offset, u32 count, struct v9fs_fcall **rcall);
371
372int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
373 u32 count, const char __user * data,
374 struct v9fs_fcall **rcall);
375int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 87897f84dfb6..bc7f0d1551e6 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,18 +1,12 @@
1obj-$(CONFIG_9P_FS) := 9p.o 1obj-$(CONFIG_9P_FS) := 9p.o
2 2
39p-objs := \ 39p-objs := \
4 trans_fd.o \
5 mux.o \
6 fcall.o \
7 conv.o \
8 vfs_super.o \ 4 vfs_super.o \
9 vfs_inode.o \ 5 vfs_inode.o \
10 vfs_addr.o \ 6 vfs_addr.o \
11 vfs_file.o \ 7 vfs_file.o \
12 vfs_dir.o \ 8 vfs_dir.o \
13 vfs_dentry.o \ 9 vfs_dentry.o \
14 error.o \
15 v9fs.o \ 10 v9fs.o \
16 fid.o \ 11 fid.o \
17 fcprint.o
18 12
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
deleted file mode 100644
index dd5b6b1b610f..000000000000
--- a/fs/9p/conv.h
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * linux/fs/9p/conv.h
3 *
4 * 9P protocol conversion definitions.
5 *
6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
28 int extended);
29int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
30 int extended);
31
32void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag);
33
34struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version);
35struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname,
36 char *aname);
37struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
38struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
39 char **wnames);
40struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
41struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
42 char *extension, int extended);
43struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
44struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
45 const char __user *data);
46struct v9fs_fcall *v9fs_create_tclunk(u32 fid);
47struct v9fs_fcall *v9fs_create_tremove(u32 fid);
48struct v9fs_fcall *v9fs_create_tstat(u32 fid);
49struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
50 int extended);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
deleted file mode 100644
index 4228c0bb3c32..000000000000
--- a/fs/9p/debug.h
+++ /dev/null
@@ -1,77 +0,0 @@
1/*
2 * linux/fs/9p/debug.h - V9FS Debug Definitions
3 *
4 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
5 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to:
18 * Free Software Foundation
19 * 51 Franklin Street, Fifth Floor
20 * Boston, MA 02111-1301 USA
21 *
22 */
23
24#define DEBUG_ERROR (1<<0)
25#define DEBUG_CURRENT (1<<1)
26#define DEBUG_9P (1<<2)
27#define DEBUG_VFS (1<<3)
28#define DEBUG_CONV (1<<4)
29#define DEBUG_MUX (1<<5)
30#define DEBUG_TRANS (1<<6)
31#define DEBUG_SLABS (1<<7)
32#define DEBUG_FCALL (1<<8)
33
34#define DEBUG_DUMP_PKT 0
35
36extern int v9fs_debug_level;
37
38#define dprintk(level, format, arg...) \
39do { \
40 if((v9fs_debug_level & level)==level) \
41 printk(KERN_NOTICE "-- %s (%d): " \
42 format , __FUNCTION__, current->pid , ## arg); \
43} while(0)
44
45#define eprintk(level, format, arg...) \
46do { \
47 printk(level "v9fs: %s (%d): " \
48 format , __FUNCTION__, current->pid , ## arg); \
49} while(0)
50
51#if DEBUG_DUMP_PKT
52static inline void dump_data(const unsigned char *data, unsigned int datalen)
53{
54 int i, n;
55 char buf[5*8];
56
57 n = 0;
58 i = 0;
59 while (i < datalen) {
60 n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]);
61 if (i%4 == 0)
62 n += snprintf(buf+n, sizeof(buf)-n, " ");
63
64 if (i%16 == 0) {
65 dprintk(DEBUG_ERROR, "%s\n", buf);
66 n = 0;
67 }
68 }
69
70 dprintk(DEBUG_ERROR, "%s\n", buf);
71}
72#else /* DEBUG_DUMP_PKT */
73static inline void dump_data(const unsigned char *data, unsigned int datalen)
74{
75
76}
77#endif /* DEBUG_DUMP_PKT */
diff --git a/fs/9p/error.c b/fs/9p/error.c
deleted file mode 100644
index 0d7fa4e08812..000000000000
--- a/fs/9p/error.c
+++ /dev/null
@@ -1,93 +0,0 @@
1/*
2 * linux/fs/9p/error.c
3 *
4 * Error string handling
5 *
6 * Plan 9 uses error strings, Unix uses error numbers. These functions
7 * try to help manage that and provide for dynamically adding error
8 * mappings.
9 *
10 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
11 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2
15 * as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to:
24 * Free Software Foundation
25 * 51 Franklin Street, Fifth Floor
26 * Boston, MA 02111-1301 USA
27 *
28 */
29
30#include <linux/module.h>
31
32#include <linux/list.h>
33#include <linux/jhash.h>
34
35#include "debug.h"
36#include "error.h"
37
38/**
39 * v9fs_error_init - preload
40 * @errstr: error string
41 *
42 */
43
44int v9fs_error_init(void)
45{
46 struct errormap *c;
47 int bucket;
48
49 /* initialize hash table */
50 for (bucket = 0; bucket < ERRHASHSZ; bucket++)
51 INIT_HLIST_HEAD(&hash_errmap[bucket]);
52
53 /* load initial error map into hash table */
54 for (c = errmap; c->name != NULL; c++) {
55 c->namelen = strlen(c->name);
56 bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
57 INIT_HLIST_NODE(&c->list);
58 hlist_add_head(&c->list, &hash_errmap[bucket]);
59 }
60
61 return 1;
62}
63
64/**
65 * errstr2errno - convert error string to error number
66 * @errstr: error string
67 *
68 */
69
70int v9fs_errstr2errno(char *errstr, int len)
71{
72 int errno = 0;
73 struct hlist_node *p = NULL;
74 struct errormap *c = NULL;
75 int bucket = jhash(errstr, len, 0) % ERRHASHSZ;
76
77 hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
78 if (c->namelen==len && !memcmp(c->name, errstr, len)) {
79 errno = c->val;
80 break;
81 }
82 }
83
84 if (errno == 0) {
85 /* TODO: if error isn't found, add it dynamically */
86 errstr[len] = 0;
87 printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
88 errstr);
89 errno = 1;
90 }
91
92 return -errno;
93}
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
deleted file mode 100644
index dc336a67592f..000000000000
--- a/fs/9p/fcall.c
+++ /dev/null
@@ -1,427 +0,0 @@
1/*
2 * linux/fs/9p/fcall.c
3 *
4 * This file contains functions to perform synchronous 9P calls
5 *
6 * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27#include <linux/module.h>
28#include <linux/errno.h>
29#include <linux/fs.h>
30#include <linux/sched.h>
31#include <linux/idr.h>
32
33#include "debug.h"
34#include "v9fs.h"
35#include "9p.h"
36#include "conv.h"
37#include "mux.h"
38
39/**
40 * v9fs_t_version - negotiate protocol parameters with sever
41 * @v9ses: 9P2000 session information
42 * @msize: requested max size packet
43 * @version: requested version.extension string
44 * @fcall: pointer to response fcall pointer
45 *
46 */
47
48int
49v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
50 char *version, struct v9fs_fcall **rcp)
51{
52 int ret;
53 struct v9fs_fcall *tc;
54
55 dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
56 tc = v9fs_create_tversion(msize, version);
57
58 if (!IS_ERR(tc)) {
59 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
60 kfree(tc);
61 } else
62 ret = PTR_ERR(tc);
63
64 return ret;
65}
66
67/**
68 * v9fs_t_attach - mount the server
69 * @v9ses: 9P2000 session information
70 * @uname: user name doing the attach
71 * @aname: remote name being attached to
72 * @fid: mount fid to attatch to root node
73 * @afid: authentication fid (in this case result key)
74 * @fcall: pointer to response fcall pointer
75 *
76 */
77
78int
79v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
80 u32 fid, u32 afid, struct v9fs_fcall **rcp)
81{
82 int ret;
83 struct v9fs_fcall* tc;
84
85 dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
86 aname, fid, afid);
87
88 tc = v9fs_create_tattach(fid, afid, uname, aname);
89 if (!IS_ERR(tc)) {
90 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
91 kfree(tc);
92 } else
93 ret = PTR_ERR(tc);
94
95 return ret;
96}
97
98static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
99 struct v9fs_fcall *rc, int err)
100{
101 int fid, id;
102 struct v9fs_session_info *v9ses;
103
104 id = 0;
105 fid = tc->params.tclunk.fid;
106 if (rc)
107 id = rc->id;
108
109 kfree(tc);
110 kfree(rc);
111 if (id == RCLUNK) {
112 v9ses = a;
113 v9fs_put_idpool(fid, &v9ses->fidpool);
114 }
115}
116
117/**
118 * v9fs_t_clunk - release a fid (finish a transaction)
119 * @v9ses: 9P2000 session information
120 * @fid: fid to release
121 * @fcall: pointer to response fcall pointer
122 *
123 */
124
125int
126v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
127{
128 int ret;
129 struct v9fs_fcall *tc, *rc;
130
131 dprintk(DEBUG_9P, "fid %d\n", fid);
132
133 rc = NULL;
134 tc = v9fs_create_tclunk(fid);
135 if (!IS_ERR(tc))
136 ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
137 else
138 ret = PTR_ERR(tc);
139
140 if (ret)
141 dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);
142
143 v9fs_t_clunk_cb(v9ses, tc, rc, ret);
144 return ret;
145}
146
147#if 0
148/**
149 * v9fs_v9fs_t_flush - flush a pending transaction
150 * @v9ses: 9P2000 session information
151 * @tag: tag to release
152 *
153 */
154int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
155{
156 int ret;
157 struct v9fs_fcall *tc;
158
159 dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
160
161 tc = v9fs_create_tflush(oldtag);
162 if (!IS_ERR(tc)) {
163 ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
164 kfree(tc);
165 } else
166 ret = PTR_ERR(tc);
167
168 return ret;
169}
170#endif
171
172/**
173 * v9fs_t_stat - read a file's meta-data
174 * @v9ses: 9P2000 session information
175 * @fid: fid pointing to file or directory to get info about
176 * @fcall: pointer to response fcall
177 *
178 */
179
180int
181v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
182{
183 int ret;
184 struct v9fs_fcall *tc;
185
186 dprintk(DEBUG_9P, "fid %d\n", fid);
187
188 ret = -ENOMEM;
189 tc = v9fs_create_tstat(fid);
190 if (!IS_ERR(tc)) {
191 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
192 kfree(tc);
193 } else
194 ret = PTR_ERR(tc);
195
196 return ret;
197}
198
199/**
200 * v9fs_t_wstat - write a file's meta-data
201 * @v9ses: 9P2000 session information
202 * @fid: fid pointing to file or directory to write info about
203 * @stat: metadata
204 * @fcall: pointer to response fcall
205 *
206 */
207
208int
209v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
210 struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
211{
212 int ret;
213 struct v9fs_fcall *tc;
214
215 dprintk(DEBUG_9P, "fid %d\n", fid);
216
217 tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
218 if (!IS_ERR(tc)) {
219 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
220 kfree(tc);
221 } else
222 ret = PTR_ERR(tc);
223
224 return ret;
225}
226
227/**
228 * v9fs_t_walk - walk a fid to a new file or directory
229 * @v9ses: 9P2000 session information
230 * @fid: fid to walk
231 * @newfid: new fid (for clone operations)
232 * @name: path to walk fid to
233 * @fcall: pointer to response fcall
234 *
235 */
236
237/* TODO: support multiple walk */
238
239int
240v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
241 char *name, struct v9fs_fcall **rcp)
242{
243 int ret;
244 struct v9fs_fcall *tc;
245 int nwname;
246
247 dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
248
249 if (name)
250 nwname = 1;
251 else
252 nwname = 0;
253
254 tc = v9fs_create_twalk(fid, newfid, nwname, &name);
255 if (!IS_ERR(tc)) {
256 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
257 kfree(tc);
258 } else
259 ret = PTR_ERR(tc);
260
261 return ret;
262}
263
264/**
265 * v9fs_t_open - open a file
266 *
267 * @v9ses - 9P2000 session information
268 * @fid - fid to open
269 * @mode - mode to open file (R, RW, etc)
270 * @fcall - pointer to response fcall
271 *
272 */
273
274int
275v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
276 struct v9fs_fcall **rcp)
277{
278 int ret;
279 struct v9fs_fcall *tc;
280
281 dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
282
283 tc = v9fs_create_topen(fid, mode);
284 if (!IS_ERR(tc)) {
285 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
286 kfree(tc);
287 } else
288 ret = PTR_ERR(tc);
289
290 return ret;
291}
292
293/**
294 * v9fs_t_remove - remove a file or directory
295 * @v9ses: 9P2000 session information
296 * @fid: fid to remove
297 * @fcall: pointer to response fcall
298 *
299 */
300
301int
302v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
303 struct v9fs_fcall **rcp)
304{
305 int ret;
306 struct v9fs_fcall *tc;
307
308 dprintk(DEBUG_9P, "fid %d\n", fid);
309
310 tc = v9fs_create_tremove(fid);
311 if (!IS_ERR(tc)) {
312 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
313 kfree(tc);
314 } else
315 ret = PTR_ERR(tc);
316
317 return ret;
318}
319
320/**
321 * v9fs_t_create - create a file or directory
322 * @v9ses: 9P2000 session information
323 * @fid: fid to create
324 * @name: name of the file or directory to create
325 * @perm: permissions to create with
326 * @mode: mode to open file (R, RW, etc)
327 * @fcall: pointer to response fcall
328 *
329 */
330
331int
332v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm,
333 u8 mode, char *extension, struct v9fs_fcall **rcp)
334{
335 int ret;
336 struct v9fs_fcall *tc;
337
338 dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
339 fid, name, perm, mode);
340
341 tc = v9fs_create_tcreate(fid, name, perm, mode, extension,
342 v9ses->extended);
343
344 if (!IS_ERR(tc)) {
345 ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
346 kfree(tc);
347 } else
348 ret = PTR_ERR(tc);
349
350 return ret;
351}
352
353/**
354 * v9fs_t_read - read data
355 * @v9ses: 9P2000 session information
356 * @fid: fid to read from
357 * @offset: offset to start read at
358 * @count: how many bytes to read
359 * @fcall: pointer to response fcall (with data)
360 *
361 */
362
363int
364v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
365 u32 count, struct v9fs_fcall **rcp)
366{
367 int ret;
368 struct v9fs_fcall *tc, *rc;
369
370 dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
371 (long long unsigned) offset, count);
372
373 tc = v9fs_create_tread(fid, offset, count);
374 if (!IS_ERR(tc)) {
375 ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
376 if (!ret)
377 ret = rc->params.rread.count;
378 if (rcp)
379 *rcp = rc;
380 else
381 kfree(rc);
382
383 kfree(tc);
384 } else
385 ret = PTR_ERR(tc);
386
387 return ret;
388}
389
390/**
391 * v9fs_t_write - write data
392 * @v9ses: 9P2000 session information
393 * @fid: fid to write to
394 * @offset: offset to start write at
395 * @count: how many bytes to write
396 * @fcall: pointer to response fcall
397 *
398 */
399
400int
401v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
402 const char __user *data, struct v9fs_fcall **rcp)
403{
404 int ret;
405 struct v9fs_fcall *tc, *rc;
406
407 dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
408 (long long unsigned) offset, count);
409
410 tc = v9fs_create_twrite(fid, offset, count, data);
411 if (!IS_ERR(tc)) {
412 ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
413
414 if (!ret)
415 ret = rc->params.rwrite.count;
416 if (rcp)
417 *rcp = rc;
418 else
419 kfree(rc);
420
421 kfree(tc);
422 } else
423 ret = PTR_ERR(tc);
424
425 return ret;
426}
427
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 90419715c7e9..08fa320b7e6d 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -26,10 +26,10 @@
26#include <linux/sched.h> 26#include <linux/sched.h>
27#include <linux/idr.h> 27#include <linux/idr.h>
28#include <asm/semaphore.h> 28#include <asm/semaphore.h>
29#include <net/9p/9p.h>
30#include <net/9p/client.h>
29 31
30#include "debug.h"
31#include "v9fs.h" 32#include "v9fs.h"
32#include "9p.h"
33#include "v9fs_vfs.h" 33#include "v9fs_vfs.h"
34#include "fid.h" 34#include "fid.h"
35 35
@@ -40,67 +40,29 @@
40 * 40 *
41 */ 41 */
42 42
43int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) 43int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
44{ 44{
45 struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; 45 struct v9fs_dentry *dent;
46 dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
47 dentry->d_iname, dentry);
48 if (dentry->d_fsdata == NULL) {
49 dentry->d_fsdata =
50 kmalloc(sizeof(struct list_head), GFP_KERNEL);
51 if (dentry->d_fsdata == NULL) {
52 dprintk(DEBUG_ERROR, "Out of memory\n");
53 return -ENOMEM;
54 }
55 fid_list = (struct list_head *)dentry->d_fsdata;
56 INIT_LIST_HEAD(fid_list); /* Initialize list head */
57 }
58 46
59 fid->uid = current->uid; 47 P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
60 list_add(&fid->list, fid_list); 48 fid->fid, dentry->d_iname);
61 return 0;
62}
63 49
64/** 50 dent = dentry->d_fsdata;
65 * v9fs_fid_create - allocate a FID structure 51 if (!dent) {
66 * @dentry - dentry to link newly created fid to 52 dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
67 * 53 if (!dent)
68 */ 54 return -ENOMEM;
69
70struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
71{
72 struct v9fs_fid *new;
73 55
74 dprintk(DEBUG_9P, "fid create fid %d\n", fid); 56 spin_lock_init(&dent->lock);
75 new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); 57 INIT_LIST_HEAD(&dent->fidlist);
76 if (new == NULL) { 58 dentry->d_fsdata = dent;
77 dprintk(DEBUG_ERROR, "Out of Memory\n");
78 return ERR_PTR(-ENOMEM);
79 } 59 }
80 60
81 new->fid = fid; 61 spin_lock(&dent->lock);
82 new->v9ses = v9ses; 62 list_add(&fid->dlist, &dent->fidlist);
83 new->fidopen = 0; 63 spin_unlock(&dent->lock);
84 new->fidclunked = 0;
85 new->iounit = 0;
86 new->rdir_pos = 0;
87 new->rdir_fcall = NULL;
88 init_MUTEX(&new->lock);
89 INIT_LIST_HEAD(&new->list);
90
91 return new;
92}
93
94/**
95 * v9fs_fid_destroy - deallocate a FID structure
96 * @fid: fid to destroy
97 *
98 */
99 64
100void v9fs_fid_destroy(struct v9fs_fid *fid) 65 return 0;
101{
102 list_del(&fid->list);
103 kfree(fid);
104} 66}
105 67
106/** 68/**
@@ -114,30 +76,42 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
114 * 76 *
115 */ 77 */
116 78
117struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) 79struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
118{ 80{
119 struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; 81 struct v9fs_dentry *dent;
120 struct v9fs_fid *return_fid = NULL; 82 struct p9_fid *fid;
121 83
122 dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); 84 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
123 85 dent = dentry->d_fsdata;
124 if (fid_list) 86 if (dent)
125 return_fid = list_entry(fid_list->next, struct v9fs_fid, list); 87 fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);
88 else
89 fid = ERR_PTR(-EBADF);
90
91 P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
92 return fid;
93}
126 94
127 if (!return_fid) { 95struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry)
128 dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); 96{
129 return_fid = ERR_PTR(-EBADF); 97 struct p9_fid *fid;
98 struct v9fs_dentry *dent;
99
100 dent = dentry->d_fsdata;
101 fid = v9fs_fid_lookup(dentry);
102 if (!IS_ERR(fid)) {
103 spin_lock(&dent->lock);
104 list_del(&fid->dlist);
105 spin_unlock(&dent->lock);
130 } 106 }
131 107
132 if(down_interruptible(&return_fid->lock)) 108 return fid;
133 return ERR_PTR(-EINTR);
134
135 return return_fid;
136} 109}
137 110
111
138/** 112/**
139 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and 113 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
140 * release it 114 * release it
141 * @dentry: dentry to look for fid in 115 * @dentry: dentry to look for fid in
142 * 116 *
143 * find a fid in the dentry and then clone to a new private fid 117 * find a fid in the dentry and then clone to a new private fid
@@ -146,49 +120,15 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
146 * 120 *
147 */ 121 */
148 122
149struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry) 123struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
150{ 124{
151 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 125 struct p9_fid *ofid, *fid;
152 struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
153 struct v9fs_fcall *fcall = NULL;
154 int fid, err;
155
156 base_fid = v9fs_fid_lookup(dentry);
157
158 if(IS_ERR(base_fid))
159 return base_fid;
160
161 if(base_fid) { /* clone fid */
162 fid = v9fs_get_idpool(&v9ses->fidpool);
163 if (fid < 0) {
164 eprintk(KERN_WARNING, "newfid fails!\n");
165 new_fid = ERR_PTR(-ENOSPC);
166 goto Release_Fid;
167 }
168
169 err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
170 if (err < 0) {
171 dprintk(DEBUG_ERROR, "clone walk didn't work\n");
172 v9fs_put_idpool(fid, &v9ses->fidpool);
173 new_fid = ERR_PTR(err);
174 goto Free_Fcall;
175 }
176 new_fid = v9fs_fid_create(v9ses, fid);
177 if (new_fid == NULL) {
178 dprintk(DEBUG_ERROR, "out of memory\n");
179 new_fid = ERR_PTR(-ENOMEM);
180 }
181Free_Fcall:
182 kfree(fcall);
183 }
184 126
185Release_Fid: 127 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
186 up(&base_fid->lock); 128 ofid = v9fs_fid_lookup(dentry);
187 return new_fid; 129 if (IS_ERR(ofid))
188} 130 return ofid;
189 131
190void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid) 132 fid = p9_client_walk(ofid, 0, NULL, 1);
191{ 133 return fid;
192 v9fs_t_clunk(v9ses, fid->fid);
193 v9fs_fid_destroy(fid);
194} 134}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 48fc170c26c8..47a0ba742872 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -22,41 +22,12 @@
22 22
23#include <linux/list.h> 23#include <linux/list.h>
24 24
25#define FID_OP 0 25struct v9fs_dentry {
26#define FID_WALK 1 26 spinlock_t lock; /* protect fidlist */
27#define FID_CREATE 2 27 struct list_head fidlist;
28
29struct v9fs_fid {
30 struct list_head list; /* list of fids associated with a dentry */
31 struct list_head active; /* XXX - debug */
32
33 struct semaphore lock;
34
35 u32 fid;
36 unsigned char fidopen; /* set when fid is opened */
37 unsigned char fidclunked; /* set when fid has already been clunked */
38
39 struct v9fs_qid qid;
40 u32 iounit;
41
42 /* readdir stuff */
43 int rdir_fpos;
44 loff_t rdir_pos;
45 struct v9fs_fcall *rdir_fcall;
46
47 /* management stuff */
48 uid_t uid; /* user associated with this fid */
49
50 /* private data */
51 struct file *filp; /* backpointer to File struct for open files */
52 struct v9fs_session_info *v9ses; /* session info for this FID */
53}; 28};
54 29
55struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); 30struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
56struct v9fs_fid *v9fs_fid_get_created(struct dentry *); 31struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry);
57void v9fs_fid_destroy(struct v9fs_fid *fid); 32struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
58struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); 33int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
59int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry);
60struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry);
61void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid);
62
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
deleted file mode 100644
index 34d43355beb7..000000000000
--- a/fs/9p/trans_fd.c
+++ /dev/null
@@ -1,308 +0,0 @@
1/*
2 * linux/fs/9p/trans_fd.c
3 *
4 * Fd transport layer. Includes deprecated socket layer.
5 *
6 * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
7 * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
8 * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
9 * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to:
22 * Free Software Foundation
23 * 51 Franklin Street, Fifth Floor
24 * Boston, MA 02111-1301 USA
25 *
26 */
27
28#include <linux/in.h>
29#include <linux/module.h>
30#include <linux/net.h>
31#include <linux/ipv6.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
34#include <linux/un.h>
35#include <asm/uaccess.h>
36#include <linux/inet.h>
37#include <linux/idr.h>
38#include <linux/file.h>
39
40#include "debug.h"
41#include "v9fs.h"
42#include "transport.h"
43
44#define V9FS_PORT 564
45
46struct v9fs_trans_fd {
47 struct file *rd;
48 struct file *wr;
49};
50
51/**
52 * v9fs_fd_read- read from a fd
53 * @v9ses: session information
54 * @v: buffer to receive data into
55 * @len: size of receive buffer
56 *
57 */
58static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len)
59{
60 int ret;
61 struct v9fs_trans_fd *ts;
62
63 if (!trans || trans->status == Disconnected || !(ts = trans->priv))
64 return -EREMOTEIO;
65
66 if (!(ts->rd->f_flags & O_NONBLOCK))
67 dprintk(DEBUG_ERROR, "blocking read ...\n");
68
69 ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
70 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
71 trans->status = Disconnected;
72 return ret;
73}
74
75/**
76 * v9fs_fd_write - write to a socket
77 * @v9ses: session information
78 * @v: buffer to send data from
79 * @len: size of send buffer
80 *
81 */
82static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len)
83{
84 int ret;
85 mm_segment_t oldfs;
86 struct v9fs_trans_fd *ts;
87
88 if (!trans || trans->status == Disconnected || !(ts = trans->priv))
89 return -EREMOTEIO;
90
91 if (!(ts->wr->f_flags & O_NONBLOCK))
92 dprintk(DEBUG_ERROR, "blocking write ...\n");
93
94 oldfs = get_fs();
95 set_fs(get_ds());
96 /* The cast to a user pointer is valid due to the set_fs() */
97 ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
98 set_fs(oldfs);
99
100 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
101 trans->status = Disconnected;
102 return ret;
103}
104
105static unsigned int
106v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
107{
108 int ret, n;
109 struct v9fs_trans_fd *ts;
110 mm_segment_t oldfs;
111
112 if (!trans || trans->status != Connected || !(ts = trans->priv))
113 return -EREMOTEIO;
114
115 if (!ts->rd->f_op || !ts->rd->f_op->poll)
116 return -EIO;
117
118 if (!ts->wr->f_op || !ts->wr->f_op->poll)
119 return -EIO;
120
121 oldfs = get_fs();
122 set_fs(get_ds());
123
124 ret = ts->rd->f_op->poll(ts->rd, pt);
125 if (ret < 0)
126 goto end;
127
128 if (ts->rd != ts->wr) {
129 n = ts->wr->f_op->poll(ts->wr, pt);
130 if (n < 0) {
131 ret = n;
132 goto end;
133 }
134 ret = (ret & ~POLLOUT) | (n & ~POLLIN);
135 }
136
137 end:
138 set_fs(oldfs);
139 return ret;
140}
141
142static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd)
143{
144 struct v9fs_transport *trans = v9ses->transport;
145 struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd),
146 GFP_KERNEL);
147 if (!ts)
148 return -ENOMEM;
149
150 ts->rd = fget(rfd);
151 ts->wr = fget(wfd);
152 if (!ts->rd || !ts->wr) {
153 if (ts->rd)
154 fput(ts->rd);
155 if (ts->wr)
156 fput(ts->wr);
157 kfree(ts);
158 return -EIO;
159 }
160
161 trans->priv = ts;
162 trans->status = Connected;
163
164 return 0;
165}
166
167static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr,
168 char *data)
169{
170 if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) {
171 printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
172 return -ENOPROTOOPT;
173 }
174
175 return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno);
176}
177
178static int v9fs_socket_open(struct v9fs_session_info *v9ses,
179 struct socket *csocket)
180{
181 int fd, ret;
182
183 csocket->sk->sk_allocation = GFP_NOIO;
184 if ((fd = sock_map_fd(csocket)) < 0) {
185 eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n");
186 ret = fd;
187 release_csocket:
188 sock_release(csocket);
189 return ret;
190 }
191
192 if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) {
193 sockfd_put(csocket);
194 eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n");
195 goto release_csocket;
196 }
197
198 ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |=
199 O_NONBLOCK;
200 return 0;
201}
202
203static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr,
204 char *data)
205{
206 int ret;
207 struct socket *csocket = NULL;
208 struct sockaddr_in sin_server;
209
210 sin_server.sin_family = AF_INET;
211 sin_server.sin_addr.s_addr = in_aton(addr);
212 sin_server.sin_port = htons(v9ses->port);
213 sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
214
215 if (!csocket) {
216 eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n");
217 return -1;
218 }
219
220 ret = csocket->ops->connect(csocket,
221 (struct sockaddr *)&sin_server,
222 sizeof(struct sockaddr_in), 0);
223 if (ret < 0) {
224 eprintk(KERN_ERR,
225 "v9fs_trans_tcp: problem connecting socket to %s\n",
226 addr);
227 return ret;
228 }
229
230 return v9fs_socket_open(v9ses, csocket);
231}
232
233static int
234v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
235{
236 int ret;
237 struct socket *csocket;
238 struct sockaddr_un sun_server;
239
240 if (strlen(addr) > UNIX_PATH_MAX) {
241 eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
242 addr);
243 return -ENAMETOOLONG;
244 }
245
246 sun_server.sun_family = PF_UNIX;
247 strcpy(sun_server.sun_path, addr);
248 sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
249 ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
250 sizeof(struct sockaddr_un) - 1, 0);
251 if (ret < 0) {
252 eprintk(KERN_ERR,
253 "v9fs_trans_unix: problem connecting socket: %s: %d\n",
254 addr, ret);
255 return ret;
256 }
257
258 return v9fs_socket_open(v9ses, csocket);
259}
260
261/**
262 * v9fs_sock_close - shutdown socket
263 * @trans: private socket structure
264 *
265 */
266static void v9fs_fd_close(struct v9fs_transport *trans)
267{
268 struct v9fs_trans_fd *ts;
269
270 if (!trans)
271 return;
272
273 ts = xchg(&trans->priv, NULL);
274
275 if (!ts)
276 return;
277
278 trans->status = Disconnected;
279 if (ts->rd)
280 fput(ts->rd);
281 if (ts->wr)
282 fput(ts->wr);
283 kfree(ts);
284}
285
286struct v9fs_transport v9fs_trans_fd = {
287 .init = v9fs_fd_init,
288 .write = v9fs_fd_write,
289 .read = v9fs_fd_read,
290 .close = v9fs_fd_close,
291 .poll = v9fs_fd_poll,
292};
293
294struct v9fs_transport v9fs_trans_tcp = {
295 .init = v9fs_tcp_init,
296 .write = v9fs_fd_write,
297 .read = v9fs_fd_read,
298 .close = v9fs_fd_close,
299 .poll = v9fs_fd_poll,
300};
301
302struct v9fs_transport v9fs_trans_unix = {
303 .init = v9fs_unix_init,
304 .write = v9fs_fd_write,
305 .read = v9fs_fd_read,
306 .close = v9fs_fd_close,
307 .poll = v9fs_fd_poll,
308};
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 6ad6f192b6e4..45c35986d49f 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -29,16 +29,12 @@
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 32#include <net/9p/9p.h>
33#include "debug.h" 33#include <net/9p/transport.h>
34#include <net/9p/conn.h>
35#include <net/9p/client.h>
34#include "v9fs.h" 36#include "v9fs.h"
35#include "9p.h"
36#include "v9fs_vfs.h" 37#include "v9fs_vfs.h"
37#include "transport.h"
38#include "mux.h"
39
40/* TODO: sysfs or debugfs interface */
41int v9fs_debug_level = 0; /* feature-rific global debug level */
42 38
43/* 39/*
44 * Option Parsing (code inspired by NFS code) 40 * Option Parsing (code inspired by NFS code)
@@ -47,12 +43,12 @@ int v9fs_debug_level = 0; /* feature-rific global debug level */
47 43
48enum { 44enum {
49 /* Options that take integer arguments */ 45 /* Options that take integer arguments */
50 Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug, 46 Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
51 Opt_rfdno, Opt_wfdno, 47 Opt_rfdno, Opt_wfdno,
52 /* String options */ 48 /* String options */
53 Opt_uname, Opt_remotename, 49 Opt_uname, Opt_remotename,
54 /* Options that take no arguments */ 50 /* Options that take no arguments */
55 Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, 51 Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci,
56 /* Cache options */ 52 /* Cache options */
57 Opt_cache_loose, 53 Opt_cache_loose,
58 /* Error token */ 54 /* Error token */
@@ -60,6 +56,7 @@ enum {
60}; 56};
61 57
62static match_table_t tokens = { 58static match_table_t tokens = {
59 {Opt_debug, "debug=%x"},
63 {Opt_port, "port=%u"}, 60 {Opt_port, "port=%u"},
64 {Opt_msize, "msize=%u"}, 61 {Opt_msize, "msize=%u"},
65 {Opt_uid, "uid=%u"}, 62 {Opt_uid, "uid=%u"},
@@ -67,12 +64,14 @@ static match_table_t tokens = {
67 {Opt_afid, "afid=%u"}, 64 {Opt_afid, "afid=%u"},
68 {Opt_rfdno, "rfdno=%u"}, 65 {Opt_rfdno, "rfdno=%u"},
69 {Opt_wfdno, "wfdno=%u"}, 66 {Opt_wfdno, "wfdno=%u"},
70 {Opt_debug, "debug=%x"},
71 {Opt_uname, "uname=%s"}, 67 {Opt_uname, "uname=%s"},
72 {Opt_remotename, "aname=%s"}, 68 {Opt_remotename, "aname=%s"},
73 {Opt_unix, "proto=unix"}, 69 {Opt_unix, "proto=unix"},
74 {Opt_tcp, "proto=tcp"}, 70 {Opt_tcp, "proto=tcp"},
75 {Opt_fd, "proto=fd"}, 71 {Opt_fd, "proto=fd"},
72#ifdef CONFIG_PCI_9P
73 {Opt_pci, "proto=pci"},
74#endif
76 {Opt_tcp, "tcp"}, 75 {Opt_tcp, "tcp"},
77 {Opt_unix, "unix"}, 76 {Opt_unix, "unix"},
78 {Opt_fd, "fd"}, 77 {Opt_fd, "fd"},
@@ -83,6 +82,8 @@ static match_table_t tokens = {
83 {Opt_err, NULL} 82 {Opt_err, NULL}
84}; 83};
85 84
85extern struct p9_transport *p9pci_trans_create(void);
86
86/* 87/*
87 * Parse option string. 88 * Parse option string.
88 */ 89 */
@@ -122,12 +123,16 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
122 token = match_token(p, tokens, args); 123 token = match_token(p, tokens, args);
123 if (token < Opt_uname) { 124 if (token < Opt_uname) {
124 if ((ret = match_int(&args[0], &option)) < 0) { 125 if ((ret = match_int(&args[0], &option)) < 0) {
125 dprintk(DEBUG_ERROR, 126 P9_DPRINTK(P9_DEBUG_ERROR,
126 "integer field, but no integer?\n"); 127 "integer field, but no integer?\n");
127 continue; 128 continue;
128 } 129 }
129 } 130 }
130 switch (token) { 131 switch (token) {
132 case Opt_debug:
133 v9ses->debug = option;
134 p9_debug_level = option;
135 break;
131 case Opt_port: 136 case Opt_port:
132 v9ses->port = option; 137 v9ses->port = option;
133 break; 138 break;
@@ -149,15 +154,15 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
149 case Opt_wfdno: 154 case Opt_wfdno:
150 v9ses->wfdno = option; 155 v9ses->wfdno = option;
151 break; 156 break;
152 case Opt_debug:
153 v9ses->debug = option;
154 break;
155 case Opt_tcp: 157 case Opt_tcp:
156 v9ses->proto = PROTO_TCP; 158 v9ses->proto = PROTO_TCP;
157 break; 159 break;
158 case Opt_unix: 160 case Opt_unix:
159 v9ses->proto = PROTO_UNIX; 161 v9ses->proto = PROTO_UNIX;
160 break; 162 break;
163 case Opt_pci:
164 v9ses->proto = PROTO_PCI;
165 break;
161 case Opt_fd: 166 case Opt_fd:
162 v9ses->proto = PROTO_FD; 167 v9ses->proto = PROTO_FD;
163 break; 168 break;
@@ -183,82 +188,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
183} 188}
184 189
185/** 190/**
186 * v9fs_inode2v9ses - safely extract v9fs session info from super block
187 * @inode: inode to extract information from
188 *
189 * Paranoid function to extract v9ses information from superblock,
190 * if anything is missing it will report an error.
191 *
192 */
193
194struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
195{
196 return (inode->i_sb->s_fs_info);
197}
198
199/**
200 * v9fs_get_idpool - allocate numeric id from pool
201 * @p - pool to allocate from
202 *
203 * XXX - This seems to be an awful generic function, should it be in idr.c with
204 * the lock included in struct idr?
205 */
206
207int v9fs_get_idpool(struct v9fs_idpool *p)
208{
209 int i = 0;
210 int error;
211
212retry:
213 if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
214 return 0;
215
216 if (down_interruptible(&p->lock) == -EINTR) {
217 eprintk(KERN_WARNING, "Interrupted while locking\n");
218 return -1;
219 }
220
221 /* no need to store exactly p, we just need something non-null */
222 error = idr_get_new(&p->pool, p, &i);
223 up(&p->lock);
224
225 if (error == -EAGAIN)
226 goto retry;
227 else if (error)
228 return -1;
229
230 return i;
231}
232
233/**
234 * v9fs_put_idpool - release numeric id from pool
235 * @p - pool to allocate from
236 *
237 * XXX - This seems to be an awful generic function, should it be in idr.c with
238 * the lock included in struct idr?
239 */
240
241void v9fs_put_idpool(int id, struct v9fs_idpool *p)
242{
243 if (down_interruptible(&p->lock) == -EINTR) {
244 eprintk(KERN_WARNING, "Interrupted while locking\n");
245 return;
246 }
247 idr_remove(&p->pool, id);
248 up(&p->lock);
249}
250
251/**
252 * v9fs_check_idpool - check if the specified id is available
253 * @id - id to check
254 * @p - pool
255 */
256int v9fs_check_idpool(int id, struct v9fs_idpool *p)
257{
258 return idr_find(&p->pool, id) != NULL;
259}
260
261/**
262 * v9fs_session_init - initialize session 191 * v9fs_session_init - initialize session
263 * @v9ses: session information structure 192 * @v9ses: session information structure
264 * @dev_name: device being mounted 193 * @dev_name: device being mounted
@@ -266,25 +195,21 @@ int v9fs_check_idpool(int id, struct v9fs_idpool *p)
266 * 195 *
267 */ 196 */
268 197
269int 198struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
270v9fs_session_init(struct v9fs_session_info *v9ses,
271 const char *dev_name, char *data) 199 const char *dev_name, char *data)
272{ 200{
273 struct v9fs_fcall *fcall = NULL;
274 struct v9fs_transport *trans_proto;
275 int n = 0;
276 int newfid = -1;
277 int retval = -EINVAL; 201 int retval = -EINVAL;
278 struct v9fs_str *version; 202 struct p9_transport *trans;
203 struct p9_fid *fid;
279 204
280 v9ses->name = __getname(); 205 v9ses->name = __getname();
281 if (!v9ses->name) 206 if (!v9ses->name)
282 return -ENOMEM; 207 return ERR_PTR(-ENOMEM);
283 208
284 v9ses->remotename = __getname(); 209 v9ses->remotename = __getname();
285 if (!v9ses->remotename) { 210 if (!v9ses->remotename) {
286 __putname(v9ses->name); 211 __putname(v9ses->name);
287 return -ENOMEM; 212 return ERR_PTR(-ENOMEM);
288 } 213 }
289 214
290 strcpy(v9ses->name, V9FS_DEFUSER); 215 strcpy(v9ses->name, V9FS_DEFUSER);
@@ -292,130 +217,60 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
292 217
293 v9fs_parse_options(data, v9ses); 218 v9fs_parse_options(data, v9ses);
294 219
295 /* set global debug level */
296 v9fs_debug_level = v9ses->debug;
297
298 /* id pools that are session-dependent: fids and tags */
299 idr_init(&v9ses->fidpool.pool);
300 init_MUTEX(&v9ses->fidpool.lock);
301
302 switch (v9ses->proto) { 220 switch (v9ses->proto) {
303 case PROTO_TCP: 221 case PROTO_TCP:
304 trans_proto = &v9fs_trans_tcp; 222 trans = p9_trans_create_tcp(dev_name, v9ses->port);
305 break; 223 break;
306 case PROTO_UNIX: 224 case PROTO_UNIX:
307 trans_proto = &v9fs_trans_unix; 225 trans = p9_trans_create_unix(dev_name);
308 *v9ses->remotename = 0; 226 *v9ses->remotename = 0;
309 break; 227 break;
310 case PROTO_FD: 228 case PROTO_FD:
311 trans_proto = &v9fs_trans_fd; 229 trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
312 *v9ses->remotename = 0; 230 *v9ses->remotename = 0;
313 break; 231 break;
232#ifdef CONFIG_PCI_9P
233 case PROTO_PCI:
234 trans = p9pci_trans_create();
235 *v9ses->remotename = 0;
236 break;
237#endif
314 default: 238 default:
315 printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto); 239 printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
316 retval = -ENOPROTOOPT; 240 retval = -ENOPROTOOPT;
317 goto SessCleanUp; 241 goto error;
318 }; 242 };
319 243
320 v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); 244 if (IS_ERR(trans)) {
321 if (!v9ses->transport) { 245 retval = PTR_ERR(trans);
322 retval = -ENOMEM; 246 trans = NULL;
323 goto SessCleanUp; 247 goto error;
324 } 248 }
325 249
326 memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); 250 v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
251 v9ses->extended);
327 252
328 if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { 253 if (IS_ERR(v9ses->clnt)) {
329 eprintk(KERN_ERR, "problem initializing transport\n"); 254 retval = PTR_ERR(v9ses->clnt);
330 goto SessCleanUp; 255 v9ses->clnt = NULL;
256 P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
257 goto error;
331 } 258 }
332 259
333 v9ses->inprogress = 0; 260 fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name,
334 v9ses->shutdown = 0; 261 v9ses->remotename);
335 v9ses->session_hung = 0; 262 if (IS_ERR(fid)) {
336 263 retval = PTR_ERR(fid);
337 v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ, 264 fid = NULL;
338 &v9ses->extended); 265 P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
339 266 goto error;
340 if (IS_ERR(v9ses->mux)) {
341 retval = PTR_ERR(v9ses->mux);
342 v9ses->mux = NULL;
343 dprintk(DEBUG_ERROR, "problem initializing mux\n");
344 goto SessCleanUp;
345 } 267 }
346 268
347 if (v9ses->afid == ~0) { 269 return fid;
348 if (v9ses->extended)
349 retval =
350 v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
351 &fcall);
352 else
353 retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
354 &fcall);
355
356 if (retval < 0) {
357 dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
358 goto FreeFcall;
359 }
360
361 version = &fcall->params.rversion.version;
362 if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
363 dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
364 v9ses->extended = 1;
365 } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
366 dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
367 v9ses->extended = 0;
368 } else {
369 retval = -EREMOTEIO;
370 goto FreeFcall;
371 }
372 270
373 n = fcall->params.rversion.msize; 271error:
374 kfree(fcall);
375
376 if (n < v9ses->maxdata)
377 v9ses->maxdata = n;
378 }
379
380 newfid = v9fs_get_idpool(&v9ses->fidpool);
381 if (newfid < 0) {
382 eprintk(KERN_WARNING, "couldn't allocate FID\n");
383 retval = -ENOMEM;
384 goto SessCleanUp;
385 }
386 /* it is a little bit ugly, but we have to prevent newfid */
387 /* being the same as afid, so if it is, get a new fid */
388 if (v9ses->afid != ~0 && newfid == v9ses->afid) {
389 newfid = v9fs_get_idpool(&v9ses->fidpool);
390 if (newfid < 0) {
391 eprintk(KERN_WARNING, "couldn't allocate FID\n");
392 retval = -ENOMEM;
393 goto SessCleanUp;
394 }
395 }
396
397 if ((retval =
398 v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
399 v9ses->afid, NULL))
400 < 0) {
401 dprintk(DEBUG_ERROR, "cannot attach\n");
402 goto SessCleanUp;
403 }
404
405 if (v9ses->afid != ~0) {
406 dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
407 if (v9fs_t_clunk(v9ses, v9ses->afid))
408 dprintk(DEBUG_ERROR, "clunk failed\n");
409 }
410
411 return newfid;
412
413 FreeFcall:
414 kfree(fcall);
415
416 SessCleanUp:
417 v9fs_session_close(v9ses); 272 v9fs_session_close(v9ses);
418 return retval; 273 return ERR_PTR(retval);
419} 274}
420 275
421/** 276/**
@@ -426,15 +281,9 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
426 281
427void v9fs_session_close(struct v9fs_session_info *v9ses) 282void v9fs_session_close(struct v9fs_session_info *v9ses)
428{ 283{
429 if (v9ses->mux) { 284 if (v9ses->clnt) {
430 v9fs_mux_destroy(v9ses->mux); 285 p9_client_destroy(v9ses->clnt);
431 v9ses->mux = NULL; 286 v9ses->clnt = NULL;
432 }
433
434 if (v9ses->transport) {
435 v9ses->transport->close(v9ses->transport);
436 kfree(v9ses->transport);
437 v9ses->transport = NULL;
438 } 287 }
439 288
440 __putname(v9ses->name); 289 __putname(v9ses->name);
@@ -446,9 +295,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
446 * and cancel all pending requests. 295 * and cancel all pending requests.
447 */ 296 */
448void v9fs_session_cancel(struct v9fs_session_info *v9ses) { 297void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
449 dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses); 298 P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
450 v9ses->transport->status = Disconnected; 299 p9_client_disconnect(v9ses->clnt);
451 v9fs_mux_cancel(v9ses->mux, -EIO);
452} 300}
453 301
454extern int v9fs_error_init(void); 302extern int v9fs_error_init(void);
@@ -460,24 +308,9 @@ extern int v9fs_error_init(void);
460 308
461static int __init init_v9fs(void) 309static int __init init_v9fs(void)
462{ 310{
463 int ret;
464
465 v9fs_error_init();
466
467 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); 311 printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
468 312
469 ret = v9fs_mux_global_init(); 313 return register_filesystem(&v9fs_fs_type);
470 if (ret) {
471 printk(KERN_WARNING "v9fs: starting mux failed\n");
472 return ret;
473 }
474 ret = register_filesystem(&v9fs_fs_type);
475 if (ret) {
476 printk(KERN_WARNING "v9fs: registering file system failed\n");
477 v9fs_mux_global_exit();
478 }
479
480 return ret;
481} 314}
482 315
483/** 316/**
@@ -487,13 +320,13 @@ static int __init init_v9fs(void)
487 320
488static void __exit exit_v9fs(void) 321static void __exit exit_v9fs(void)
489{ 322{
490 v9fs_mux_global_exit();
491 unregister_filesystem(&v9fs_fs_type); 323 unregister_filesystem(&v9fs_fs_type);
492} 324}
493 325
494module_init(init_v9fs) 326module_init(init_v9fs)
495module_exit(exit_v9fs) 327module_exit(exit_v9fs)
496 328
329MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
497MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); 330MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
498MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>"); 331MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
499MODULE_LICENSE("GPL"); 332MODULE_LICENSE("GPL");
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 820bf5ca35d8..abc4b1668ace 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -22,16 +22,6 @@
22 */ 22 */
23 23
24/* 24/*
25 * Idpool structure provides lock and id management
26 *
27 */
28
29struct v9fs_idpool {
30 struct semaphore lock;
31 struct idr pool;
32};
33
34/*
35 * Session structure provides information for an opened session 25 * Session structure provides information for an opened session
36 * 26 *
37 */ 27 */
@@ -54,15 +44,7 @@ struct v9fs_session_info {
54 unsigned int uid; /* default uid/muid for legacy support */ 44 unsigned int uid; /* default uid/muid for legacy support */
55 unsigned int gid; /* default gid for legacy support */ 45 unsigned int gid; /* default gid for legacy support */
56 46
57 /* book keeping */ 47 struct p9_client *clnt; /* 9p client */
58 struct v9fs_idpool fidpool; /* The FID pool for file descriptors */
59
60 struct v9fs_transport *transport;
61 struct v9fs_mux_data *mux;
62
63 int inprogress; /* session in progress => true */
64 int shutdown; /* session shutting down. no more attaches. */
65 unsigned char session_hung;
66 struct dentry *debugfs_dir; 48 struct dentry *debugfs_dir;
67}; 49};
68 50
@@ -71,6 +53,7 @@ enum {
71 PROTO_TCP, 53 PROTO_TCP,
72 PROTO_UNIX, 54 PROTO_UNIX,
73 PROTO_FD, 55 PROTO_FD,
56 PROTO_PCI,
74}; 57};
75 58
76/* possible values of ->cache */ 59/* possible values of ->cache */
@@ -82,12 +65,9 @@ enum {
82 65
83extern struct dentry *v9fs_debugfs_root; 66extern struct dentry *v9fs_debugfs_root;
84 67
85int v9fs_session_init(struct v9fs_session_info *, const char *, char *); 68struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
86struct v9fs_session_info *v9fs_inode2v9ses(struct inode *); 69 char *);
87void v9fs_session_close(struct v9fs_session_info *v9ses); 70void v9fs_session_close(struct v9fs_session_info *v9ses);
88int v9fs_get_idpool(struct v9fs_idpool *p);
89void v9fs_put_idpool(int id, struct v9fs_idpool *p);
90int v9fs_check_idpool(int id, struct v9fs_idpool *p);
91void v9fs_session_cancel(struct v9fs_session_info *v9ses); 71void v9fs_session_cancel(struct v9fs_session_info *v9ses);
92 72
93#define V9FS_MAGIC 0x01021997 73#define V9FS_MAGIC 0x01021997
@@ -97,3 +77,7 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
97#define V9FS_DEFUSER "nobody" 77#define V9FS_DEFUSER "nobody"
98#define V9FS_DEFANAME "" 78#define V9FS_DEFANAME ""
99 79
80static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
81{
82 return (inode->i_sb->s_fs_info);
83}
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 6a82d39dc498..fd01d90cada5 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -45,10 +45,10 @@ extern struct dentry_operations v9fs_dentry_operations;
45extern struct dentry_operations v9fs_cached_dentry_operations; 45extern struct dentry_operations v9fs_cached_dentry_operations;
46 46
47struct inode *v9fs_get_inode(struct super_block *sb, int mode); 47struct inode *v9fs_get_inode(struct super_block *sb, int mode);
48ino_t v9fs_qid2ino(struct v9fs_qid *qid); 48ino_t v9fs_qid2ino(struct p9_qid *qid);
49void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *); 49void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *);
50int v9fs_dir_release(struct inode *inode, struct file *filp); 50int v9fs_dir_release(struct inode *inode, struct file *filp);
51int v9fs_file_open(struct inode *inode, struct file *file); 51int v9fs_file_open(struct inode *inode, struct file *file);
52void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); 52void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat);
53void v9fs_dentry_release(struct dentry *); 53void v9fs_dentry_release(struct dentry *);
54int v9fs_uflags2omode(int uflags); 54int v9fs_uflags2omode(int uflags);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 9ac4ffe9ac7d..6248f0e727a3 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -33,10 +33,10 @@
33#include <linux/pagemap.h> 33#include <linux/pagemap.h>
34#include <linux/idr.h> 34#include <linux/idr.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <net/9p/9p.h>
37#include <net/9p/client.h>
36 38
37#include "debug.h"
38#include "v9fs.h" 39#include "v9fs.h"
39#include "9p.h"
40#include "v9fs_vfs.h" 40#include "v9fs_vfs.h"
41#include "fid.h" 41#include "fid.h"
42 42
@@ -50,55 +50,26 @@
50 50
51static int v9fs_vfs_readpage(struct file *filp, struct page *page) 51static int v9fs_vfs_readpage(struct file *filp, struct page *page)
52{ 52{
53 char *buffer = NULL; 53 int retval;
54 int retval = -EIO; 54 loff_t offset;
55 loff_t offset = page_offset(page); 55 char *buffer;
56 int count = PAGE_CACHE_SIZE; 56 struct p9_fid *fid;
57 struct inode *inode = filp->f_path.dentry->d_inode;
58 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
59 int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
60 struct v9fs_fid *v9f = filp->private_data;
61 struct v9fs_fcall *fcall = NULL;
62 int fid = v9f->fid;
63 int total = 0;
64 int result = 0;
65
66 dprintk(DEBUG_VFS, "\n");
67 57
58 P9_DPRINTK(P9_DEBUG_VFS, "\n");
59 fid = filp->private_data;
68 buffer = kmap(page); 60 buffer = kmap(page);
69 do { 61 offset = page_offset(page);
70 if (count < rsize)
71 rsize = count;
72
73 result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
74
75 if (result < 0) {
76 printk(KERN_ERR "v9fs_t_read returned %d\n",
77 result);
78
79 kfree(fcall);
80 goto UnmapAndUnlock;
81 } else
82 offset += result;
83
84 memcpy(buffer, fcall->params.rread.data, result);
85
86 count -= result;
87 buffer += result;
88 total += result;
89
90 kfree(fcall);
91 62
92 if (result < rsize) 63 retval = p9_client_readn(fid, buffer, offset, PAGE_CACHE_SIZE);
93 break; 64 if (retval < 0)
94 } while (count); 65 goto done;
95 66
96 memset(buffer, 0, count); 67 memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
97 flush_dcache_page(page); 68 flush_dcache_page(page);
98 SetPageUptodate(page); 69 SetPageUptodate(page);
99 retval = 0; 70 retval = 0;
100 71
101UnmapAndUnlock: 72done:
102 kunmap(page); 73 kunmap(page);
103 unlock_page(page); 74 unlock_page(page);
104 return retval; 75 return retval;
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index d93960429c09..f9534f18df0a 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -34,10 +34,10 @@
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 <net/9p/9p.h>
38#include <net/9p/client.h>
37 39
38#include "debug.h"
39#include "v9fs.h" 40#include "v9fs.h"
40#include "9p.h"
41#include "v9fs_vfs.h" 41#include "v9fs_vfs.h"
42#include "fid.h" 42#include "fid.h"
43 43
@@ -52,7 +52,7 @@
52 52
53static int v9fs_dentry_delete(struct dentry *dentry) 53static int v9fs_dentry_delete(struct dentry *dentry)
54{ 54{
55 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 55 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
56 56
57 return 1; 57 return 1;
58} 58}
@@ -69,7 +69,7 @@ static int v9fs_dentry_delete(struct dentry *dentry)
69static int v9fs_cached_dentry_delete(struct dentry *dentry) 69static int v9fs_cached_dentry_delete(struct dentry *dentry)
70{ 70{
71 struct inode *inode = dentry->d_inode; 71 struct inode *inode = dentry->d_inode;
72 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 72 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
73 73
74 if(!inode) 74 if(!inode)
75 return 1; 75 return 1;
@@ -85,26 +85,19 @@ static int v9fs_cached_dentry_delete(struct dentry *dentry)
85 85
86void v9fs_dentry_release(struct dentry *dentry) 86void v9fs_dentry_release(struct dentry *dentry)
87{ 87{
88 int err; 88 struct v9fs_dentry *dent;
89 89 struct p9_fid *temp, *current_fid;
90 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 90
91 91 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
92 if (dentry->d_fsdata != NULL) { 92 dent = dentry->d_fsdata;
93 struct list_head *fid_list = dentry->d_fsdata; 93 if (dent) {
94 struct v9fs_fid *temp = NULL; 94 list_for_each_entry_safe(current_fid, temp, &dent->fidlist,
95 struct v9fs_fid *current_fid = NULL; 95 dlist) {
96 96 p9_client_clunk(current_fid);
97 list_for_each_entry_safe(current_fid, temp, fid_list, list) {
98 err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid);
99
100 if (err < 0)
101 dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n",
102 err, dentry->d_iname);
103
104 v9fs_fid_destroy(current_fid);
105 } 97 }
106 98
107 kfree(dentry->d_fsdata); /* free the list_head */ 99 kfree(dent);
100 dentry->d_fsdata = NULL;
108 } 101 }
109} 102}
110 103
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 1dd86ee90bc5..0924d4477da3 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -32,11 +32,10 @@
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 <net/9p/9p.h>
36#include <net/9p/client.h>
35 37
36#include "debug.h"
37#include "v9fs.h" 38#include "v9fs.h"
38#include "9p.h"
39#include "conv.h"
40#include "v9fs_vfs.h" 39#include "v9fs_vfs.h"
41#include "fid.h" 40#include "fid.h"
42 41
@@ -46,14 +45,14 @@
46 * 45 *
47 */ 46 */
48 47
49static inline int dt_type(struct v9fs_stat *mistat) 48static inline int dt_type(struct p9_stat *mistat)
50{ 49{
51 unsigned long perm = mistat->mode; 50 unsigned long perm = mistat->mode;
52 int rettype = DT_REG; 51 int rettype = DT_REG;
53 52
54 if (perm & V9FS_DMDIR) 53 if (perm & P9_DMDIR)
55 rettype = DT_DIR; 54 rettype = DT_DIR;
56 if (perm & V9FS_DMSYMLINK) 55 if (perm & P9_DMSYMLINK)
57 rettype = DT_LNK; 56 rettype = DT_LNK;
58 57
59 return rettype; 58 return rettype;
@@ -69,106 +68,36 @@ static inline int dt_type(struct v9fs_stat *mistat)
69 68
70static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 69static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
71{ 70{
72 struct v9fs_fcall *fcall = NULL; 71 int over;
73 struct inode *inode = filp->f_path.dentry->d_inode; 72 struct p9_fid *fid;
74 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 73 struct v9fs_session_info *v9ses;
75 struct v9fs_fid *file = filp->private_data; 74 struct inode *inode;
76 unsigned int i, n, s; 75 struct p9_stat *st;
77 int fid = -1; 76
78 int ret = 0; 77 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
79 struct v9fs_stat stat; 78 inode = filp->f_path.dentry->d_inode;
80 int over = 0; 79 v9ses = v9fs_inode2v9ses(inode);
81 80 fid = filp->private_data;
82 dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 81 while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) {
83 82 if (IS_ERR(st))
84 fid = file->fid; 83 return PTR_ERR(st);
85 84
86 if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) { 85 over = filldir(dirent, st->name.str, st->name.len, filp->f_pos,
87 kfree(file->rdir_fcall); 86 v9fs_qid2ino(&st->qid), dt_type(st));
88 file->rdir_fcall = NULL; 87
89 } 88 if (over)
90
91 if (file->rdir_fcall) {
92 n = file->rdir_fcall->params.rread.count;
93 i = file->rdir_fpos;
94 while (i < n) {
95 s = v9fs_deserialize_stat(
96 file->rdir_fcall->params.rread.data + i,
97 n - i, &stat, v9ses->extended);
98
99 if (s == 0) {
100 dprintk(DEBUG_ERROR,
101 "error while deserializing stat\n");
102 ret = -EIO;
103 goto FreeStructs;
104 }
105
106 over = filldir(dirent, stat.name.str, stat.name.len,
107 filp->f_pos, v9fs_qid2ino(&stat.qid),
108 dt_type(&stat));
109
110 if (over) {
111 file->rdir_fpos = i;
112 file->rdir_pos = filp->f_pos;
113 break;
114 }
115
116 i += s;
117 filp->f_pos += s;
118 }
119
120 if (!over) {
121 kfree(file->rdir_fcall);
122 file->rdir_fcall = NULL;
123 }
124 }
125
126 while (!over) {
127 ret = v9fs_t_read(v9ses, fid, filp->f_pos,
128 v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
129 if (ret < 0) {
130 dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
131 ret, fcall);
132 goto FreeStructs;
133 } else if (ret == 0)
134 break; 89 break;
135 90
136 n = ret; 91 filp->f_pos += st->size;
137 i = 0; 92 kfree(st);
138 while (i < n) { 93 st = NULL;
139 s = v9fs_deserialize_stat(fcall->params.rread.data + i,
140 n - i, &stat, v9ses->extended);
141
142 if (s == 0) {
143 dprintk(DEBUG_ERROR,
144 "error while deserializing stat\n");
145 return -EIO;
146 }
147
148 over = filldir(dirent, stat.name.str, stat.name.len,
149 filp->f_pos, v9fs_qid2ino(&stat.qid),
150 dt_type(&stat));
151
152 if (over) {
153 file->rdir_fcall = fcall;
154 file->rdir_fpos = i;
155 file->rdir_pos = filp->f_pos;
156 fcall = NULL;
157 break;
158 }
159
160 i += s;
161 filp->f_pos += s;
162 }
163
164 kfree(fcall);
165 } 94 }
166 95
167 FreeStructs: 96 kfree(st);
168 kfree(fcall); 97 return 0;
169 return ret;
170} 98}
171 99
100
172/** 101/**
173 * v9fs_dir_release - close a directory 102 * v9fs_dir_release - close a directory
174 * @inode: inode of the directory 103 * @inode: inode of the directory
@@ -178,29 +107,13 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
178 107
179int v9fs_dir_release(struct inode *inode, struct file *filp) 108int v9fs_dir_release(struct inode *inode, struct file *filp)
180{ 109{
181 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 110 struct p9_fid *fid;
182 struct v9fs_fid *fid = filp->private_data;
183 int fidnum = -1;
184
185 dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp,
186 fid->fid);
187 fidnum = fid->fid;
188 111
112 fid = filp->private_data;
113 P9_DPRINTK(P9_DEBUG_VFS,
114 "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid);
189 filemap_write_and_wait(inode->i_mapping); 115 filemap_write_and_wait(inode->i_mapping);
190 116 p9_client_clunk(fid);
191 if (fidnum >= 0) {
192 dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
193 fid->fid);
194
195 if (v9fs_t_clunk(v9ses, fidnum))
196 dprintk(DEBUG_ERROR, "clunk failed\n");
197
198 kfree(fid->rdir_fcall);
199 kfree(fid);
200
201 filp->private_data = NULL;
202 }
203
204 return 0; 117 return 0;
205} 118}
206 119
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6e7678e4852f..2a40c2946d0a 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -34,10 +34,10 @@
34#include <linux/list.h> 34#include <linux/list.h>
35#include <asm/uaccess.h> 35#include <asm/uaccess.h>
36#include <linux/idr.h> 36#include <linux/idr.h>
37#include <net/9p/9p.h>
38#include <net/9p/client.h>
37 39
38#include "debug.h"
39#include "v9fs.h" 40#include "v9fs.h"
40#include "9p.h"
41#include "v9fs_vfs.h" 41#include "v9fs_vfs.h"
42#include "fid.h" 42#include "fid.h"
43 43
@@ -52,48 +52,40 @@ static const struct file_operations v9fs_cached_file_operations;
52 52
53int v9fs_file_open(struct inode *inode, struct file *file) 53int v9fs_file_open(struct inode *inode, struct file *file)
54{ 54{
55 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
56 struct v9fs_fid *vfid;
57 struct v9fs_fcall *fcall = NULL;
58 int omode;
59 int err; 55 int err;
56 struct v9fs_session_info *v9ses;
57 struct p9_fid *fid;
58 int omode;
60 59
61 dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); 60 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file);
62 61 v9ses = v9fs_inode2v9ses(inode);
63 vfid = v9fs_fid_clone(file->f_path.dentry);
64 if (IS_ERR(vfid))
65 return PTR_ERR(vfid);
66
67 omode = v9fs_uflags2omode(file->f_flags); 62 omode = v9fs_uflags2omode(file->f_flags);
68 err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall); 63 fid = file->private_data;
69 if (err < 0) { 64 if (!fid) {
70 PRINT_FCALL_ERROR("open failed", fcall); 65 fid = v9fs_fid_clone(file->f_path.dentry);
71 goto Clunk_Fid; 66 if (IS_ERR(fid))
67 return PTR_ERR(fid);
68
69 err = p9_client_open(fid, omode);
70 if (err < 0) {
71 p9_client_clunk(fid);
72 return err;
73 }
74 if (omode & P9_OTRUNC) {
75 inode->i_size = 0;
76 inode->i_blocks = 0;
77 }
72 } 78 }
73 79
74 file->private_data = vfid; 80 file->private_data = fid;
75 vfid->fidopen = 1; 81 if ((fid->qid.version) && (v9ses->cache)) {
76 vfid->fidclunked = 0; 82 P9_DPRINTK(P9_DEBUG_VFS, "cached");
77 vfid->iounit = fcall->params.ropen.iounit;
78 vfid->rdir_pos = 0;
79 vfid->rdir_fcall = NULL;
80 vfid->filp = file;
81 kfree(fcall);
82
83 if((vfid->qid.version) && (v9ses->cache)) {
84 dprintk(DEBUG_VFS, "cached");
85 /* enable cached file options */ 83 /* enable cached file options */
86 if(file->f_op == &v9fs_file_operations) 84 if(file->f_op == &v9fs_file_operations)
87 file->f_op = &v9fs_cached_file_operations; 85 file->f_op = &v9fs_cached_file_operations;
88 } 86 }
89 87
90 return 0; 88 return 0;
91
92Clunk_Fid:
93 v9fs_fid_clunk(v9ses, vfid);
94 kfree(fcall);
95
96 return err;
97} 89}
98 90
99/** 91/**
@@ -110,7 +102,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
110 int res = 0; 102 int res = 0;
111 struct inode *inode = filp->f_path.dentry->d_inode; 103 struct inode *inode = filp->f_path.dentry->d_inode;
112 104
113 dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 105 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
114 106
115 /* No mandatory locks */ 107 /* No mandatory locks */
116 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 108 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
@@ -136,55 +128,16 @@ static ssize_t
136v9fs_file_read(struct file *filp, char __user * data, size_t count, 128v9fs_file_read(struct file *filp, char __user * data, size_t count,
137 loff_t * offset) 129 loff_t * offset)
138{ 130{
139 struct inode *inode = filp->f_path.dentry->d_inode; 131 int ret;
140 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 132 struct p9_fid *fid;
141 struct v9fs_fid *v9f = filp->private_data;
142 struct v9fs_fcall *fcall = NULL;
143 int fid = v9f->fid;
144 int rsize = 0;
145 int result = 0;
146 int total = 0;
147 int n;
148
149 dprintk(DEBUG_VFS, "\n");
150
151 rsize = v9ses->maxdata - V9FS_IOHDRSZ;
152 if (v9f->iounit != 0 && rsize > v9f->iounit)
153 rsize = v9f->iounit;
154
155 do {
156 if (count < rsize)
157 rsize = count;
158 133
159 result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall); 134 P9_DPRINTK(P9_DEBUG_VFS, "\n");
135 fid = filp->private_data;
136 ret = p9_client_uread(fid, data, *offset, count);
137 if (ret > 0)
138 *offset += ret;
160 139
161 if (result < 0) { 140 return ret;
162 printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n",
163 result);
164
165 kfree(fcall);
166 return total;
167 } else
168 *offset += result;
169
170 n = copy_to_user(data, fcall->params.rread.data, result);
171 if (n) {
172 dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n);
173 kfree(fcall);
174 return -EFAULT;
175 }
176
177 count -= result;
178 data += result;
179 total += result;
180
181 kfree(fcall);
182
183 if (result < rsize)
184 break;
185 } while (count);
186
187 return total;
188} 141}
189 142
190/** 143/**
@@ -200,50 +153,25 @@ static ssize_t
200v9fs_file_write(struct file *filp, const char __user * data, 153v9fs_file_write(struct file *filp, const char __user * data,
201 size_t count, loff_t * offset) 154 size_t count, loff_t * offset)
202{ 155{
156 int ret;
157 struct p9_fid *fid;
203 struct inode *inode = filp->f_path.dentry->d_inode; 158 struct inode *inode = filp->f_path.dentry->d_inode;
204 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
205 struct v9fs_fid *v9fid = filp->private_data;
206 struct v9fs_fcall *fcall;
207 int fid = v9fid->fid;
208 int result = -EIO;
209 int rsize = 0;
210 int total = 0;
211
212 dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
213 (int)*offset);
214 rsize = v9ses->maxdata - V9FS_IOHDRSZ;
215 if (v9fid->iounit != 0 && rsize > v9fid->iounit)
216 rsize = v9fid->iounit;
217
218 do {
219 if (count < rsize)
220 rsize = count;
221 159
222 result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall); 160 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
223 if (result < 0) { 161 (int)count, (int)*offset);
224 PRINT_FCALL_ERROR("error while writing", fcall);
225 kfree(fcall);
226 return result;
227 } else
228 *offset += result;
229 162
230 kfree(fcall); 163 fid = filp->private_data;
231 fcall = NULL; 164 ret = p9_client_uwrite(fid, data, *offset, count);
165 if (ret > 0)
166 *offset += ret;
232 167
233 if (result != rsize) { 168 if (*offset > inode->i_size) {
234 eprintk(KERN_ERR, 169 inode->i_size = *offset;
235 "short write: v9fs_t_write returned %d\n", 170 inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
236 result); 171 }
237 break;
238 }
239
240 count -= result;
241 data += result;
242 total += result;
243 } while (count);
244 172
245 invalidate_inode_pages2(inode->i_mapping); 173 invalidate_inode_pages2(inode->i_mapping);
246 return total; 174 return ret;
247} 175}
248 176
249static const struct file_operations v9fs_cached_file_operations = { 177static const struct file_operations v9fs_cached_file_operations = {
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index c76cd8fa3f6c..e5c45eed58a9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -34,10 +34,10 @@
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 <net/9p/9p.h>
38#include <net/9p/client.h>
37 39
38#include "debug.h"
39#include "v9fs.h" 40#include "v9fs.h"
40#include "9p.h"
41#include "v9fs_vfs.h" 41#include "v9fs_vfs.h"
42#include "fid.h" 42#include "fid.h"
43 43
@@ -58,27 +58,27 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
58 int res; 58 int res;
59 res = mode & 0777; 59 res = mode & 0777;
60 if (S_ISDIR(mode)) 60 if (S_ISDIR(mode))
61 res |= V9FS_DMDIR; 61 res |= P9_DMDIR;
62 if (v9ses->extended) { 62 if (v9ses->extended) {
63 if (S_ISLNK(mode)) 63 if (S_ISLNK(mode))
64 res |= V9FS_DMSYMLINK; 64 res |= P9_DMSYMLINK;
65 if (v9ses->nodev == 0) { 65 if (v9ses->nodev == 0) {
66 if (S_ISSOCK(mode)) 66 if (S_ISSOCK(mode))
67 res |= V9FS_DMSOCKET; 67 res |= P9_DMSOCKET;
68 if (S_ISFIFO(mode)) 68 if (S_ISFIFO(mode))
69 res |= V9FS_DMNAMEDPIPE; 69 res |= P9_DMNAMEDPIPE;
70 if (S_ISBLK(mode)) 70 if (S_ISBLK(mode))
71 res |= V9FS_DMDEVICE; 71 res |= P9_DMDEVICE;
72 if (S_ISCHR(mode)) 72 if (S_ISCHR(mode))
73 res |= V9FS_DMDEVICE; 73 res |= P9_DMDEVICE;
74 } 74 }
75 75
76 if ((mode & S_ISUID) == S_ISUID) 76 if ((mode & S_ISUID) == S_ISUID)
77 res |= V9FS_DMSETUID; 77 res |= P9_DMSETUID;
78 if ((mode & S_ISGID) == S_ISGID) 78 if ((mode & S_ISGID) == S_ISGID)
79 res |= V9FS_DMSETGID; 79 res |= P9_DMSETGID;
80 if ((mode & V9FS_DMLINK)) 80 if ((mode & P9_DMLINK))
81 res |= V9FS_DMLINK; 81 res |= P9_DMLINK;
82 } 82 }
83 83
84 return res; 84 return res;
@@ -97,27 +97,27 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
97 97
98 res = mode & 0777; 98 res = mode & 0777;
99 99
100 if ((mode & V9FS_DMDIR) == V9FS_DMDIR) 100 if ((mode & P9_DMDIR) == P9_DMDIR)
101 res |= S_IFDIR; 101 res |= S_IFDIR;
102 else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended)) 102 else if ((mode & P9_DMSYMLINK) && (v9ses->extended))
103 res |= S_IFLNK; 103 res |= S_IFLNK;
104 else if ((mode & V9FS_DMSOCKET) && (v9ses->extended) 104 else if ((mode & P9_DMSOCKET) && (v9ses->extended)
105 && (v9ses->nodev == 0)) 105 && (v9ses->nodev == 0))
106 res |= S_IFSOCK; 106 res |= S_IFSOCK;
107 else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended) 107 else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended)
108 && (v9ses->nodev == 0)) 108 && (v9ses->nodev == 0))
109 res |= S_IFIFO; 109 res |= S_IFIFO;
110 else if ((mode & V9FS_DMDEVICE) && (v9ses->extended) 110 else if ((mode & P9_DMDEVICE) && (v9ses->extended)
111 && (v9ses->nodev == 0)) 111 && (v9ses->nodev == 0))
112 res |= S_IFBLK; 112 res |= S_IFBLK;
113 else 113 else
114 res |= S_IFREG; 114 res |= S_IFREG;
115 115
116 if (v9ses->extended) { 116 if (v9ses->extended) {
117 if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID) 117 if ((mode & P9_DMSETUID) == P9_DMSETUID)
118 res |= S_ISUID; 118 res |= S_ISUID;
119 119
120 if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID) 120 if ((mode & P9_DMSETGID) == P9_DMSETGID)
121 res |= S_ISGID; 121 res |= S_ISGID;
122 } 122 }
123 123
@@ -132,26 +132,26 @@ int v9fs_uflags2omode(int uflags)
132 switch (uflags&3) { 132 switch (uflags&3) {
133 default: 133 default:
134 case O_RDONLY: 134 case O_RDONLY:
135 ret = V9FS_OREAD; 135 ret = P9_OREAD;
136 break; 136 break;
137 137
138 case O_WRONLY: 138 case O_WRONLY:
139 ret = V9FS_OWRITE; 139 ret = P9_OWRITE;
140 break; 140 break;
141 141
142 case O_RDWR: 142 case O_RDWR:
143 ret = V9FS_ORDWR; 143 ret = P9_ORDWR;
144 break; 144 break;
145 } 145 }
146 146
147 if (uflags & O_EXCL) 147 if (uflags & O_EXCL)
148 ret |= V9FS_OEXCL; 148 ret |= P9_OEXCL;
149 149
150 if (uflags & O_TRUNC) 150 if (uflags & O_TRUNC)
151 ret |= V9FS_OTRUNC; 151 ret |= P9_OTRUNC;
152 152
153 if (uflags & O_APPEND) 153 if (uflags & O_APPEND)
154 ret |= V9FS_OAPPEND; 154 ret |= P9_OAPPEND;
155 155
156 return ret; 156 return ret;
157} 157}
@@ -164,7 +164,7 @@ int v9fs_uflags2omode(int uflags)
164 */ 164 */
165 165
166static void 166static void
167v9fs_blank_wstat(struct v9fs_wstat *wstat) 167v9fs_blank_wstat(struct p9_wstat *wstat)
168{ 168{
169 wstat->type = ~0; 169 wstat->type = ~0;
170 wstat->dev = ~0; 170 wstat->dev = ~0;
@@ -197,7 +197,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
197 struct inode *inode; 197 struct inode *inode;
198 struct v9fs_session_info *v9ses = sb->s_fs_info; 198 struct v9fs_session_info *v9ses = sb->s_fs_info;
199 199
200 dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 200 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
201 201
202 inode = new_inode(sb); 202 inode = new_inode(sb);
203 if (inode) { 203 if (inode) {
@@ -215,7 +215,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
215 case S_IFCHR: 215 case S_IFCHR:
216 case S_IFSOCK: 216 case S_IFSOCK:
217 if(!v9ses->extended) { 217 if(!v9ses->extended) {
218 dprintk(DEBUG_ERROR, "special files without extended mode\n"); 218 P9_DPRINTK(P9_DEBUG_ERROR,
219 "special files without extended mode\n");
219 return ERR_PTR(-EINVAL); 220 return ERR_PTR(-EINVAL);
220 } 221 }
221 init_special_inode(inode, inode->i_mode, 222 init_special_inode(inode, inode->i_mode,
@@ -227,7 +228,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
227 break; 228 break;
228 case S_IFLNK: 229 case S_IFLNK:
229 if(!v9ses->extended) { 230 if(!v9ses->extended) {
230 dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n"); 231 P9_DPRINTK(P9_DEBUG_ERROR,
232 "extended modes used w/o 9P2000.u\n");
231 return ERR_PTR(-EINVAL); 233 return ERR_PTR(-EINVAL);
232 } 234 }
233 inode->i_op = &v9fs_symlink_inode_operations; 235 inode->i_op = &v9fs_symlink_inode_operations;
@@ -241,71 +243,19 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
241 inode->i_fop = &v9fs_dir_operations; 243 inode->i_fop = &v9fs_dir_operations;
242 break; 244 break;
243 default: 245 default:
244 dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", 246 P9_DPRINTK(P9_DEBUG_ERROR,
247 "BAD mode 0x%x S_IFMT 0x%x\n",
245 mode, mode & S_IFMT); 248 mode, mode & S_IFMT);
246 return ERR_PTR(-EINVAL); 249 return ERR_PTR(-EINVAL);
247 } 250 }
248 } else { 251 } else {
249 eprintk(KERN_WARNING, "Problem allocating inode\n"); 252 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
250 return ERR_PTR(-ENOMEM); 253 return ERR_PTR(-ENOMEM);
251 } 254 }
252 return inode; 255 return inode;
253} 256}
254 257
255static int 258/*
256v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
257 u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
258{
259 int fid;
260 int err;
261 struct v9fs_fcall *fcall;
262
263 fid = v9fs_get_idpool(&v9ses->fidpool);
264 if (fid < 0) {
265 eprintk(KERN_WARNING, "no free fids available\n");
266 return -ENOSPC;
267 }
268
269 err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
270 if (err < 0) {
271 PRINT_FCALL_ERROR("clone error", fcall);
272 if (fcall && fcall->id == RWALK)
273 goto clunk_fid;
274 else
275 goto put_fid;
276 }
277 kfree(fcall);
278
279 err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
280 if (err < 0) {
281 PRINT_FCALL_ERROR("create fails", fcall);
282 goto clunk_fid;
283 }
284
285 if (iounit)
286 *iounit = fcall->params.rcreate.iounit;
287
288 if (qid)
289 *qid = fcall->params.rcreate.qid;
290
291 if (fidp)
292 *fidp = fid;
293
294 kfree(fcall);
295 return 0;
296
297clunk_fid:
298 v9fs_t_clunk(v9ses, fid);
299 fid = V9FS_NOFID;
300
301put_fid:
302 if (fid != V9FS_NOFID)
303 v9fs_put_idpool(fid, &v9ses->fidpool);
304
305 kfree(fcall);
306 return err;
307}
308
309static struct v9fs_fid* 259static struct v9fs_fid*
310v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) 260v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
311{ 261{
@@ -355,23 +305,25 @@ error:
355 kfree(fcall); 305 kfree(fcall);
356 return ERR_PTR(err); 306 return ERR_PTR(err);
357} 307}
308*/
358 309
359static struct inode * 310static struct inode *
360v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, 311v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
361 struct super_block *sb) 312 struct super_block *sb)
362{ 313{
363 int err, umode; 314 int err, umode;
364 struct inode *ret; 315 struct inode *ret;
365 struct v9fs_fcall *fcall; 316 struct p9_stat *st;
366 317
367 ret = NULL; 318 ret = NULL;
368 err = v9fs_t_stat(v9ses, fid, &fcall); 319 st = p9_client_stat(fid);
369 if (err) { 320 if (IS_ERR(st)) {
370 PRINT_FCALL_ERROR("stat error", fcall); 321 err = PTR_ERR(st);
322 st = NULL;
371 goto error; 323 goto error;
372 } 324 }
373 325
374 umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); 326 umode = p9mode2unixmode(v9ses, st->mode);
375 ret = v9fs_get_inode(sb, umode); 327 ret = v9fs_get_inode(sb, umode);
376 if (IS_ERR(ret)) { 328 if (IS_ERR(ret)) {
377 err = PTR_ERR(ret); 329 err = PTR_ERR(ret);
@@ -379,12 +331,13 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
379 goto error; 331 goto error;
380 } 332 }
381 333
382 v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); 334 v9fs_stat2inode(st, ret, sb);
383 kfree(fcall); 335 ret->i_ino = v9fs_qid2ino(&st->qid);
336 kfree(st);
384 return ret; 337 return ret;
385 338
386error: 339error:
387 kfree(fcall); 340 kfree(st);
388 if (ret) 341 if (ret)
389 iput(ret); 342 iput(ret);
390 343
@@ -401,43 +354,20 @@ error:
401 354
402static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 355static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
403{ 356{
404 struct v9fs_fcall *fcall = NULL; 357 struct inode *file_inode;
405 struct super_block *sb = NULL; 358 struct v9fs_session_info *v9ses;
406 struct v9fs_session_info *v9ses = NULL; 359 struct p9_fid *v9fid;
407 struct v9fs_fid *v9fid = NULL;
408 struct inode *file_inode = NULL;
409 int fid = -1;
410 int result = 0;
411 360
412 dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, 361 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
413 rmdir); 362 rmdir);
414 363
415 file_inode = file->d_inode; 364 file_inode = file->d_inode;
416 sb = file_inode->i_sb;
417 v9ses = v9fs_inode2v9ses(file_inode); 365 v9ses = v9fs_inode2v9ses(file_inode);
418 v9fid = v9fs_fid_clone(file); 366 v9fid = v9fs_fid_clone(file);
419 if(IS_ERR(v9fid)) 367 if(IS_ERR(v9fid))
420 return PTR_ERR(v9fid); 368 return PTR_ERR(v9fid);
421 369
422 fid = v9fid->fid; 370 return p9_client_remove(v9fid);
423 if (fid < 0) {
424 dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n",
425 file_inode->i_ino);
426 return -EBADF;
427 }
428
429 result = v9fs_t_remove(v9ses, fid, &fcall);
430 if (result < 0) {
431 PRINT_FCALL_ERROR("remove fails", fcall);
432 goto Error;
433 }
434
435 v9fs_put_idpool(fid, &v9ses->fidpool);
436 v9fs_fid_destroy(v9fid);
437
438Error:
439 kfree(fcall);
440 return result;
441} 371}
442 372
443static int 373static int
@@ -446,61 +376,59 @@ v9fs_open_created(struct inode *inode, struct file *file)
446 return 0; 376 return 0;
447} 377}
448 378
379
449/** 380/**
450 * v9fs_vfs_create - VFS hook to create files 381 * v9fs_create - Create a file
451 * @inode: directory inode that is being deleted 382 * @dentry: dentry that is being created
452 * @dentry: dentry that is being deleted 383 * @perm: create permissions
453 * @mode: create permissions 384 * @mode: open mode
454 * @nd: path information
455 * 385 *
456 */ 386 */
457 387static struct p9_fid *
458static int 388v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
459v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, 389 struct dentry *dentry, char *extension, u32 perm, u8 mode)
460 struct nameidata *nd)
461{ 390{
462 int err; 391 int err;
463 u32 fid, perm, iounit; 392 char *name;
464 int flags; 393 struct p9_fid *dfid, *ofid, *fid;
465 struct v9fs_session_info *v9ses;
466 struct v9fs_fid *dfid, *vfid, *ffid;
467 struct inode *inode; 394 struct inode *inode;
468 struct v9fs_qid qid;
469 struct file *filp;
470 395
471 inode = NULL; 396 err = 0;
472 vfid = NULL; 397 ofid = NULL;
473 v9ses = v9fs_inode2v9ses(dir); 398 fid = NULL;
399 name = (char *) dentry->d_name.name;
474 dfid = v9fs_fid_clone(dentry->d_parent); 400 dfid = v9fs_fid_clone(dentry->d_parent);
475 if(IS_ERR(dfid)) { 401 if(IS_ERR(dfid)) {
476 err = PTR_ERR(dfid); 402 err = PTR_ERR(dfid);
403 dfid = NULL;
477 goto error; 404 goto error;
478 } 405 }
479 406
480 perm = unixmode2p9mode(v9ses, mode); 407 /* clone a fid to use for creation */
481 if (nd && nd->flags & LOOKUP_OPEN) 408 ofid = p9_client_walk(dfid, 0, NULL, 1);
482 flags = nd->intent.open.flags - 1; 409 if (IS_ERR(ofid)) {
483 else 410 err = PTR_ERR(ofid);
484 flags = O_RDWR; 411 ofid = NULL;
485 412 goto error;
486 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 413 }
487 perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
488 414
489 if (err) 415 err = p9_client_fcreate(ofid, name, perm, mode, extension);
490 goto clunk_dfid; 416 if (err < 0)
417 goto error;
491 418
492 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); 419 /* now walk from the parent so we can get unopened fid */
493 v9fs_fid_clunk(v9ses, dfid); 420 fid = p9_client_walk(dfid, 1, &name, 0);
494 if (IS_ERR(vfid)) { 421 if (IS_ERR(fid)) {
495 err = PTR_ERR(vfid); 422 err = PTR_ERR(fid);
496 vfid = NULL; 423 fid = NULL;
497 goto error; 424 goto error;
498 } 425 } else
426 dfid = NULL;
499 427
500 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); 428 /* instantiate inode and assign the unopened fid to the dentry */
429 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
501 if (IS_ERR(inode)) { 430 if (IS_ERR(inode)) {
502 err = PTR_ERR(inode); 431 err = PTR_ERR(inode);
503 inode = NULL;
504 goto error; 432 goto error;
505 } 433 }
506 434
@@ -508,35 +436,78 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
508 dentry->d_op = &v9fs_cached_dentry_operations; 436 dentry->d_op = &v9fs_cached_dentry_operations;
509 else 437 else
510 dentry->d_op = &v9fs_dentry_operations; 438 dentry->d_op = &v9fs_dentry_operations;
439
511 d_instantiate(dentry, inode); 440 d_instantiate(dentry, inode);
441 v9fs_fid_add(dentry, fid);
442 return ofid;
512 443
513 if (nd && nd->flags & LOOKUP_OPEN) { 444error:
514 ffid = v9fs_fid_create(v9ses, fid); 445 if (dfid)
515 if (!ffid) 446 p9_client_clunk(dfid);
516 return -ENOMEM; 447
448 if (ofid)
449 p9_client_clunk(ofid);
450
451 if (fid)
452 p9_client_clunk(fid);
453
454 return ERR_PTR(err);
455}
456
457/**
458 * v9fs_vfs_create - VFS hook to create files
459 * @inode: directory inode that is being created
460 * @dentry: dentry that is being deleted
461 * @mode: create permissions
462 * @nd: path information
463 *
464 */
517 465
466static int
467v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
468 struct nameidata *nd)
469{
470 int err;
471 u32 perm;
472 int flags;
473 struct v9fs_session_info *v9ses;
474 struct p9_fid *fid;
475 struct file *filp;
476
477 err = 0;
478 fid = NULL;
479 v9ses = v9fs_inode2v9ses(dir);
480 perm = unixmode2p9mode(v9ses, mode);
481 if (nd && nd->flags & LOOKUP_OPEN)
482 flags = nd->intent.open.flags - 1;
483 else
484 flags = O_RDWR;
485
486 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
487 v9fs_uflags2omode(flags));
488 if (IS_ERR(fid)) {
489 err = PTR_ERR(fid);
490 fid = NULL;
491 goto error;
492 }
493
494 /* if we are opening a file, assign the open fid to the file */
495 if (nd && nd->flags & LOOKUP_OPEN) {
518 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 496 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
519 if (IS_ERR(filp)) { 497 if (IS_ERR(filp)) {
520 v9fs_fid_destroy(ffid); 498 err = PTR_ERR(filp);
521 return PTR_ERR(filp); 499 goto error;
522 } 500 }
523 501
524 ffid->rdir_pos = 0; 502 filp->private_data = fid;
525 ffid->rdir_fcall = NULL; 503 } else
526 ffid->fidopen = 1; 504 p9_client_clunk(fid);
527 ffid->iounit = iounit;
528 ffid->filp = filp;
529 filp->private_data = ffid;
530 }
531 505
532 return 0; 506 return 0;
533 507
534clunk_dfid:
535 v9fs_fid_clunk(v9ses, dfid);
536
537error: 508error:
538 if (vfid) 509 if (fid)
539 v9fs_fid_destroy(vfid); 510 p9_client_clunk(fid);
540 511
541 return err; 512 return err;
542} 513}
@@ -552,57 +523,23 @@ error:
552static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 523static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
553{ 524{
554 int err; 525 int err;
555 u32 fid, perm; 526 u32 perm;
556 struct v9fs_session_info *v9ses; 527 struct v9fs_session_info *v9ses;
557 struct v9fs_fid *dfid, *vfid; 528 struct p9_fid *fid;
558 struct inode *inode;
559 529
560 inode = NULL; 530 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
561 vfid = NULL; 531 err = 0;
562 v9ses = v9fs_inode2v9ses(dir); 532 v9ses = v9fs_inode2v9ses(dir);
563 dfid = v9fs_fid_clone(dentry->d_parent);
564 if(IS_ERR(dfid)) {
565 err = PTR_ERR(dfid);
566 goto error;
567 }
568
569 perm = unixmode2p9mode(v9ses, mode | S_IFDIR); 533 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
570 534 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
571 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 535 if (IS_ERR(fid)) {
572 perm, V9FS_OREAD, NULL, &fid, NULL, NULL); 536 err = PTR_ERR(fid);
573 537 fid = NULL;
574 if (err) {
575 dprintk(DEBUG_ERROR, "create error %d\n", err);
576 goto clean_up_dfid;
577 } 538 }
578 539
579 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); 540 if (fid)
580 if (IS_ERR(vfid)) { 541 p9_client_clunk(fid);
581 err = PTR_ERR(vfid);
582 vfid = NULL;
583 goto clean_up_dfid;
584 }
585 542
586 v9fs_fid_clunk(v9ses, dfid);
587 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
588 if (IS_ERR(inode)) {
589 err = PTR_ERR(inode);
590 inode = NULL;
591 v9fs_fid_destroy(vfid);
592 goto error;
593 }
594
595 if(v9ses->cache)
596 dentry->d_op = &v9fs_cached_dentry_operations;
597 else
598 dentry->d_op = &v9fs_dentry_operations;
599 d_instantiate(dentry, inode);
600 return 0;
601
602clean_up_dfid:
603 v9fs_fid_clunk(v9ses, dfid);
604
605error:
606 return err; 543 return err;
607} 544}
608 545
@@ -619,104 +556,54 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
619{ 556{
620 struct super_block *sb; 557 struct super_block *sb;
621 struct v9fs_session_info *v9ses; 558 struct v9fs_session_info *v9ses;
622 struct v9fs_fid *dirfid; 559 struct p9_fid *dfid, *fid;
623 struct v9fs_fid *fid;
624 struct inode *inode; 560 struct inode *inode;
625 struct v9fs_fcall *fcall = NULL; 561 char *name;
626 int dirfidnum = -1;
627 int newfid = -1;
628 int result = 0; 562 int result = 0;
629 563
630 dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 564 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
631 dir, dentry->d_name.name, dentry, nameidata); 565 dir, dentry->d_name.name, dentry, nameidata);
632 566
633 sb = dir->i_sb; 567 sb = dir->i_sb;
634 v9ses = v9fs_inode2v9ses(dir); 568 v9ses = v9fs_inode2v9ses(dir);
635 dirfid = v9fs_fid_lookup(dentry->d_parent); 569 dfid = v9fs_fid_lookup(dentry->d_parent);
636 570 if (IS_ERR(dfid))
637 if(IS_ERR(dirfid)) 571 return ERR_PTR(PTR_ERR(dfid));
638 return ERR_PTR(PTR_ERR(dirfid)); 572
639 573 name = (char *) dentry->d_name.name;
640 dirfidnum = dirfid->fid; 574 fid = p9_client_walk(dfid, 1, &name, 1);
641 575 if (IS_ERR(fid)) {
642 newfid = v9fs_get_idpool(&v9ses->fidpool); 576 result = PTR_ERR(fid);
643 if (newfid < 0) {
644 eprintk(KERN_WARNING, "newfid fails!\n");
645 result = -ENOSPC;
646 goto Release_Dirfid;
647 }
648
649 result = v9fs_t_walk(v9ses, dirfidnum, newfid,
650 (char *)dentry->d_name.name, &fcall);
651
652 up(&dirfid->lock);
653
654 if (result < 0) {
655 if (fcall && fcall->id == RWALK)
656 v9fs_t_clunk(v9ses, newfid);
657 else
658 v9fs_put_idpool(newfid, &v9ses->fidpool);
659
660 if (result == -ENOENT) { 577 if (result == -ENOENT) {
661 d_add(dentry, NULL); 578 d_add(dentry, NULL);
662 dprintk(DEBUG_VFS,
663 "Return negative dentry %p count %d\n",
664 dentry, atomic_read(&dentry->d_count));
665 kfree(fcall);
666 return NULL; 579 return NULL;
667 } 580 }
668 dprintk(DEBUG_ERROR, "walk error:%d\n", result);
669 goto FreeFcall;
670 }
671 kfree(fcall);
672
673 result = v9fs_t_stat(v9ses, newfid, &fcall);
674 if (result < 0) {
675 dprintk(DEBUG_ERROR, "stat error\n");
676 goto FreeFcall;
677 }
678
679 inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
680 fcall->params.rstat.stat.mode));
681 581
682 if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { 582 return ERR_PTR(result);
683 eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
684 PTR_ERR(inode));
685
686 result = -ENOSPC;
687 goto FreeFcall;
688 } 583 }
689 584
690 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); 585 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
691 586 if (IS_ERR(inode)) {
692 fid = v9fs_fid_create(v9ses, newfid); 587 result = PTR_ERR(inode);
693 if (fid == NULL) { 588 inode = NULL;
694 dprintk(DEBUG_ERROR, "couldn't insert\n"); 589 goto error;
695 result = -ENOMEM;
696 goto FreeFcall;
697 } 590 }
698 591
699 result = v9fs_fid_insert(fid, dentry); 592 result = v9fs_fid_add(dentry, fid);
700 if (result < 0) 593 if (result < 0)
701 goto FreeFcall; 594 goto error;
702 595
703 fid->qid = fcall->params.rstat.stat.qid;
704 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
705 if((fid->qid.version)&&(v9ses->cache)) 596 if((fid->qid.version)&&(v9ses->cache))
706 dentry->d_op = &v9fs_cached_dentry_operations; 597 dentry->d_op = &v9fs_cached_dentry_operations;
707 else 598 else
708 dentry->d_op = &v9fs_dentry_operations; 599 dentry->d_op = &v9fs_dentry_operations;
709 600
710 d_add(dentry, inode); 601 d_add(dentry, inode);
711 kfree(fcall);
712
713 return NULL; 602 return NULL;
714 603
715Release_Dirfid: 604error:
716 up(&dirfid->lock); 605 if (fid)
717 606 p9_client_clunk(fid);
718FreeFcall:
719 kfree(fcall);
720 607
721 return ERR_PTR(result); 608 return ERR_PTR(result);
722} 609}
@@ -758,73 +645,54 @@ static int
758v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 645v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
759 struct inode *new_dir, struct dentry *new_dentry) 646 struct inode *new_dir, struct dentry *new_dentry)
760{ 647{
761 struct inode *old_inode = old_dentry->d_inode; 648 struct inode *old_inode;
762 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); 649 struct v9fs_session_info *v9ses;
763 struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); 650 struct p9_fid *oldfid;
764 struct v9fs_fid *olddirfid; 651 struct p9_fid *olddirfid;
765 struct v9fs_fid *newdirfid; 652 struct p9_fid *newdirfid;
766 struct v9fs_wstat wstat; 653 struct p9_wstat wstat;
767 struct v9fs_fcall *fcall = NULL; 654 int retval;
768 int fid = -1;
769 int olddirfidnum = -1;
770 int newdirfidnum = -1;
771 int retval = 0;
772
773 dprintk(DEBUG_VFS, "\n");
774 655
656 P9_DPRINTK(P9_DEBUG_VFS, "\n");
657 retval = 0;
658 old_inode = old_dentry->d_inode;
659 v9ses = v9fs_inode2v9ses(old_inode);
660 oldfid = v9fs_fid_lookup(old_dentry);
775 if(IS_ERR(oldfid)) 661 if(IS_ERR(oldfid))
776 return PTR_ERR(oldfid); 662 return PTR_ERR(oldfid);
777 663
778 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 664 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
779 if(IS_ERR(olddirfid)) { 665 if(IS_ERR(olddirfid)) {
780 retval = PTR_ERR(olddirfid); 666 retval = PTR_ERR(olddirfid);
781 goto Release_lock; 667 goto done;
782 } 668 }
783 669
784 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 670 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
785 if(IS_ERR(newdirfid)) { 671 if(IS_ERR(newdirfid)) {
786 retval = PTR_ERR(newdirfid); 672 retval = PTR_ERR(newdirfid);
787 goto Clunk_olddir; 673 goto clunk_olddir;
788 } 674 }
789 675
790 /* 9P can only handle file rename in the same directory */ 676 /* 9P can only handle file rename in the same directory */
791 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { 677 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
792 dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); 678 P9_DPRINTK(P9_DEBUG_ERROR,
679 "old dir and new dir are different\n");
793 retval = -EXDEV; 680 retval = -EXDEV;
794 goto Clunk_newdir; 681 goto clunk_newdir;
795 }
796
797 fid = oldfid->fid;
798 olddirfidnum = olddirfid->fid;
799 newdirfidnum = newdirfid->fid;
800
801 if (fid < 0) {
802 dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
803 old_inode->i_ino);
804 retval = -EBADF;
805 goto Clunk_newdir;
806 } 682 }
807 683
808 v9fs_blank_wstat(&wstat); 684 v9fs_blank_wstat(&wstat);
809 wstat.muid = v9ses->name; 685 wstat.muid = v9ses->name;
810 wstat.name = (char *) new_dentry->d_name.name; 686 wstat.name = (char *) new_dentry->d_name.name;
687 retval = p9_client_wstat(oldfid, &wstat);
811 688
812 retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); 689clunk_newdir:
690 p9_client_clunk(olddirfid);
813 691
814 if (retval < 0) 692clunk_olddir:
815 PRINT_FCALL_ERROR("wstat error", fcall); 693 p9_client_clunk(newdirfid);
816
817 kfree(fcall);
818
819Clunk_newdir:
820 v9fs_fid_clunk(v9ses, newdirfid);
821
822Clunk_olddir:
823 v9fs_fid_clunk(v9ses, olddirfid);
824
825Release_lock:
826 up(&oldfid->lock);
827 694
695done:
828 return retval; 696 return retval;
829} 697}
830 698
@@ -840,28 +708,30 @@ static int
840v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 708v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
841 struct kstat *stat) 709 struct kstat *stat)
842{ 710{
843 struct v9fs_fcall *fcall = NULL; 711 int err;
844 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 712 struct v9fs_session_info *v9ses;
845 struct v9fs_fid *fid = v9fs_fid_clone(dentry); 713 struct p9_fid *fid;
846 int err = -EPERM; 714 struct p9_stat *st;
847 715
848 dprintk(DEBUG_VFS, "dentry: %p\n", dentry); 716 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
849 if(IS_ERR(fid)) 717 err = -EPERM;
718 v9ses = v9fs_inode2v9ses(dentry->d_inode);
719 if (v9ses->cache == CACHE_LOOSE)
720 return simple_getattr(mnt, dentry, stat);
721
722 fid = v9fs_fid_lookup(dentry);
723 if (IS_ERR(fid))
850 return PTR_ERR(fid); 724 return PTR_ERR(fid);
851 725
852 err = v9fs_t_stat(v9ses, fid->fid, &fcall); 726 st = p9_client_stat(fid);
727 if (IS_ERR(st))
728 return PTR_ERR(st);
853 729
854 if (err < 0) 730 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
855 dprintk(DEBUG_ERROR, "stat error\n");
856 else {
857 v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
858 dentry->d_inode->i_sb);
859 generic_fillattr(dentry->d_inode, stat); 731 generic_fillattr(dentry->d_inode, stat);
860 }
861 732
862 kfree(fcall); 733 kfree(st);
863 v9fs_fid_clunk(v9ses, fid); 734 return 0;
864 return err;
865} 735}
866 736
867/** 737/**
@@ -873,13 +743,15 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
873 743
874static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 744static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
875{ 745{
876 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 746 int retval;
877 struct v9fs_fid *fid = v9fs_fid_clone(dentry); 747 struct v9fs_session_info *v9ses;
878 struct v9fs_fcall *fcall = NULL; 748 struct p9_fid *fid;
879 struct v9fs_wstat wstat; 749 struct p9_wstat wstat;
880 int res = -EPERM;
881 750
882 dprintk(DEBUG_VFS, "\n"); 751 P9_DPRINTK(P9_DEBUG_VFS, "\n");
752 retval = -EPERM;
753 v9ses = v9fs_inode2v9ses(dentry->d_inode);
754 fid = v9fs_fid_lookup(dentry);
883 if(IS_ERR(fid)) 755 if(IS_ERR(fid))
884 return PTR_ERR(fid); 756 return PTR_ERR(fid);
885 757
@@ -904,17 +776,11 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
904 wstat.n_gid = iattr->ia_gid; 776 wstat.n_gid = iattr->ia_gid;
905 } 777 }
906 778
907 res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); 779 retval = p9_client_wstat(fid, &wstat);
780 if (retval >= 0)
781 retval = inode_setattr(dentry->d_inode, iattr);
908 782
909 if (res < 0) 783 return retval;
910 PRINT_FCALL_ERROR("wstat error", fcall);
911
912 kfree(fcall);
913 if (res >= 0)
914 res = inode_setattr(dentry->d_inode, iattr);
915
916 v9fs_fid_clunk(v9ses, fid);
917 return res;
918} 784}
919 785
920/** 786/**
@@ -926,7 +792,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
926 */ 792 */
927 793
928void 794void
929v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, 795v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
930 struct super_block *sb) 796 struct super_block *sb)
931{ 797{
932 int n; 798 int n;
@@ -967,8 +833,9 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
967 case 'b': 833 case 'b':
968 break; 834 break;
969 default: 835 default:
970 dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n", 836 P9_DPRINTK(P9_DEBUG_ERROR,
971 type, stat->extension.len, stat->extension.str); 837 "Unknown special type %c (%.*s)\n", type,
838 stat->extension.len, stat->extension.str);
972 }; 839 };
973 inode->i_rdev = MKDEV(major, minor); 840 inode->i_rdev = MKDEV(major, minor);
974 } else 841 } else
@@ -976,8 +843,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
976 843
977 inode->i_size = stat->length; 844 inode->i_size = stat->length;
978 845
979 inode->i_blocks = 846 /* not real number of blocks, but 512 byte ones ... */
980 (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 847 inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
981} 848}
982 849
983/** 850/**
@@ -987,7 +854,7 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
987 * BUG: potential for inode number collisions? 854 * BUG: potential for inode number collisions?
988 */ 855 */
989 856
990ino_t v9fs_qid2ino(struct v9fs_qid *qid) 857ino_t v9fs_qid2ino(struct p9_qid *qid)
991{ 858{
992 u64 path = qid->path + 2; 859 u64 path = qid->path + 2;
993 ino_t i = 0; 860 ino_t i = 0;
@@ -1010,56 +877,46 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid)
1010 877
1011static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 878static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1012{ 879{
1013 int retval = -EPERM; 880 int retval;
1014 881
1015 struct v9fs_fcall *fcall = NULL; 882 struct v9fs_session_info *v9ses;
1016 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 883 struct p9_fid *fid;
1017 struct v9fs_fid *fid = v9fs_fid_clone(dentry); 884 struct p9_stat *st;
1018 885
886 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
887 retval = -EPERM;
888 v9ses = v9fs_inode2v9ses(dentry->d_inode);
889 fid = v9fs_fid_lookup(dentry);
1019 if(IS_ERR(fid)) 890 if(IS_ERR(fid))
1020 return PTR_ERR(fid); 891 return PTR_ERR(fid);
1021 892
1022 if (!v9ses->extended) { 893 if (!v9ses->extended)
1023 retval = -EBADF; 894 return -EBADF;
1024 dprintk(DEBUG_ERROR, "not extended\n");
1025 goto ClunkFid;
1026 }
1027
1028 dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
1029 retval = v9fs_t_stat(v9ses, fid->fid, &fcall);
1030
1031 if (retval < 0) {
1032 dprintk(DEBUG_ERROR, "stat error\n");
1033 goto FreeFcall;
1034 }
1035 895
1036 if (!fcall) { 896 st = p9_client_stat(fid);
1037 retval = -EIO; 897 if (IS_ERR(st))
1038 goto ClunkFid; 898 return PTR_ERR(st);
1039 }
1040 899
1041 if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { 900 if (!(st->mode & P9_DMSYMLINK)) {
1042 retval = -EINVAL; 901 retval = -EINVAL;
1043 goto FreeFcall; 902 goto done;
1044 } 903 }
1045 904
1046 /* copy extension buffer into buffer */ 905 /* copy extension buffer into buffer */
1047 if (fcall->params.rstat.stat.extension.len < buflen) 906 if (st->extension.len < buflen)
1048 buflen = fcall->params.rstat.stat.extension.len + 1; 907 buflen = st->extension.len + 1;
1049 908
1050 memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); 909 memmove(buffer, st->extension.str, buflen - 1);
1051 buffer[buflen-1] = 0; 910 buffer[buflen-1] = 0;
1052 911
1053 dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len, 912 P9_DPRINTK(P9_DEBUG_VFS,
1054 fcall->params.rstat.stat.extension.str, buffer); 913 "%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len,
1055 retval = buflen; 914 st->extension.str, buffer);
1056 915
1057FreeFcall: 916 retval = buflen;
1058 kfree(fcall);
1059
1060ClunkFid:
1061 v9fs_fid_clunk(v9ses, fid);
1062 917
918done:
919 kfree(st);
1063 return retval; 920 return retval;
1064} 921}
1065 922
@@ -1084,14 +941,14 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
1084 if (buflen > PATH_MAX) 941 if (buflen > PATH_MAX)
1085 buflen = PATH_MAX; 942 buflen = PATH_MAX;
1086 943
1087 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 944 P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
1088 945
1089 retval = v9fs_readlink(dentry, link, buflen); 946 retval = v9fs_readlink(dentry, link, buflen);
1090 947
1091 if (retval > 0) { 948 if (retval > 0) {
1092 if ((ret = copy_to_user(buffer, link, retval)) != 0) { 949 if ((ret = copy_to_user(buffer, link, retval)) != 0) {
1093 dprintk(DEBUG_ERROR, "problem copying to user: %d\n", 950 P9_DPRINTK(P9_DEBUG_ERROR,
1094 ret); 951 "problem copying to user: %d\n", ret);
1095 retval = ret; 952 retval = ret;
1096 } 953 }
1097 } 954 }
@@ -1112,7 +969,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1112 int len = 0; 969 int len = 0;
1113 char *link = __getname(); 970 char *link = __getname();
1114 971
1115 dprintk(DEBUG_VFS, "%s n", dentry->d_name.name); 972 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
1116 973
1117 if (!link) 974 if (!link)
1118 link = ERR_PTR(-ENOMEM); 975 link = ERR_PTR(-ENOMEM);
@@ -1141,7 +998,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
1141{ 998{
1142 char *s = nd_get_link(nd); 999 char *s = nd_get_link(nd);
1143 1000
1144 dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); 1001 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
1145 if (!IS_ERR(s)) 1002 if (!IS_ERR(s))
1146 __putname(s); 1003 __putname(s);
1147} 1004}
@@ -1149,66 +1006,24 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
1149static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1006static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1150 int mode, const char *extension) 1007 int mode, const char *extension)
1151{ 1008{
1152 int err; 1009 u32 perm;
1153 u32 fid, perm;
1154 struct v9fs_session_info *v9ses; 1010 struct v9fs_session_info *v9ses;
1155 struct v9fs_fid *dfid, *vfid = NULL; 1011 struct p9_fid *fid;
1156 struct inode *inode = NULL;
1157 1012
1158 v9ses = v9fs_inode2v9ses(dir); 1013 v9ses = v9fs_inode2v9ses(dir);
1159 if (!v9ses->extended) { 1014 if (!v9ses->extended) {
1160 dprintk(DEBUG_ERROR, "not extended\n"); 1015 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
1161 return -EPERM; 1016 return -EPERM;
1162 } 1017 }
1163 1018
1164 dfid = v9fs_fid_clone(dentry->d_parent);
1165 if(IS_ERR(dfid)) {
1166 err = PTR_ERR(dfid);
1167 goto error;
1168 }
1169
1170 perm = unixmode2p9mode(v9ses, mode); 1019 perm = unixmode2p9mode(v9ses, mode);
1020 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1021 P9_OREAD);
1022 if (IS_ERR(fid))
1023 return PTR_ERR(fid);
1171 1024
1172 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, 1025 p9_client_clunk(fid);
1173 perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
1174
1175 if (err)
1176 goto clunk_dfid;
1177
1178 err = v9fs_t_clunk(v9ses, fid);
1179 if (err)
1180 goto clunk_dfid;
1181
1182 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
1183 if (IS_ERR(vfid)) {
1184 err = PTR_ERR(vfid);
1185 vfid = NULL;
1186 goto clunk_dfid;
1187 }
1188
1189 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
1190 if (IS_ERR(inode)) {
1191 err = PTR_ERR(inode);
1192 inode = NULL;
1193 goto free_vfid;
1194 }
1195
1196 if(v9ses->cache)
1197 dentry->d_op = &v9fs_cached_dentry_operations;
1198 else
1199 dentry->d_op = &v9fs_dentry_operations;
1200 d_instantiate(dentry, inode);
1201 return 0; 1026 return 0;
1202
1203free_vfid:
1204 v9fs_fid_destroy(vfid);
1205
1206clunk_dfid:
1207 v9fs_fid_clunk(v9ses, dfid);
1208
1209error:
1210 return err;
1211
1212} 1027}
1213 1028
1214/** 1029/**
@@ -1224,8 +1039,8 @@ error:
1224static int 1039static int
1225v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1040v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1226{ 1041{
1227 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1042 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
1228 symname); 1043 dentry->d_name.name, symname);
1229 1044
1230 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); 1045 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1231} 1046}
@@ -1247,11 +1062,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1247 struct dentry *dentry) 1062 struct dentry *dentry)
1248{ 1063{
1249 int retval; 1064 int retval;
1250 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); 1065 struct p9_fid *oldfid;
1251 struct v9fs_fid *oldfid;
1252 char *name; 1066 char *name;
1253 1067
1254 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1068 P9_DPRINTK(P9_DEBUG_VFS,
1069 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
1255 old_dentry->d_name.name); 1070 old_dentry->d_name.name);
1256 1071
1257 oldfid = v9fs_fid_clone(old_dentry); 1072 oldfid = v9fs_fid_clone(old_dentry);
@@ -1265,11 +1080,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1265 } 1080 }
1266 1081
1267 sprintf(name, "%d\n", oldfid->fid); 1082 sprintf(name, "%d\n", oldfid->fid);
1268 retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); 1083 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1269 __putname(name); 1084 __putname(name);
1270 1085
1271clunk_fid: 1086clunk_fid:
1272 v9fs_fid_clunk(v9ses, oldfid); 1087 p9_client_clunk(oldfid);
1273 return retval; 1088 return retval;
1274} 1089}
1275 1090
@@ -1288,7 +1103,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1288 int retval; 1103 int retval;
1289 char *name; 1104 char *name;
1290 1105
1291 dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1106 P9_DPRINTK(P9_DEBUG_VFS,
1107 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1292 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1108 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1293 1109
1294 if (!new_valid_dev(rdev)) 1110 if (!new_valid_dev(rdev))
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 7bdf8b326841..ba904371218b 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -37,10 +37,10 @@
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 <net/9p/9p.h>
41#include <net/9p/client.h>
40 42
41#include "debug.h"
42#include "v9fs.h" 43#include "v9fs.h"
43#include "9p.h"
44#include "v9fs_vfs.h" 44#include "v9fs_vfs.h"
45#include "fid.h" 45#include "fid.h"
46 46
@@ -107,41 +107,48 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
107 struct vfsmount *mnt) 107 struct vfsmount *mnt)
108{ 108{
109 struct super_block *sb = NULL; 109 struct super_block *sb = NULL;
110 struct v9fs_fcall *fcall = NULL;
111 struct inode *inode = NULL; 110 struct inode *inode = NULL;
112 struct dentry *root = NULL; 111 struct dentry *root = NULL;
113 struct v9fs_session_info *v9ses = NULL; 112 struct v9fs_session_info *v9ses = NULL;
114 struct v9fs_fid *root_fid = NULL; 113 struct p9_stat *st = NULL;
115 int mode = S_IRWXUGO | S_ISVTX; 114 int mode = S_IRWXUGO | S_ISVTX;
116 uid_t uid = current->fsuid; 115 uid_t uid = current->fsuid;
117 gid_t gid = current->fsgid; 116 gid_t gid = current->fsgid;
118 int stat_result = 0; 117 struct p9_fid *fid;
119 int newfid = 0;
120 int retval = 0; 118 int retval = 0;
121 119
122 dprintk(DEBUG_VFS, " \n"); 120 P9_DPRINTK(P9_DEBUG_VFS, " \n");
123 121
124 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 122 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
125 if (!v9ses) 123 if (!v9ses)
126 return -ENOMEM; 124 return -ENOMEM;
127 125
128 if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { 126 fid = v9fs_session_init(v9ses, dev_name, data);
129 dprintk(DEBUG_ERROR, "problem initiating session\n"); 127 if (IS_ERR(fid)) {
130 retval = newfid; 128 retval = PTR_ERR(fid);
131 goto out_free_session; 129 fid = NULL;
130 kfree(v9ses);
131 v9ses = NULL;
132 goto error;
133 }
134
135 st = p9_client_stat(fid);
136 if (IS_ERR(st)) {
137 retval = PTR_ERR(st);
138 goto error;
132 } 139 }
133 140
134 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 141 sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
135 if (IS_ERR(sb)) { 142 if (IS_ERR(sb)) {
136 retval = PTR_ERR(sb); 143 retval = PTR_ERR(sb);
137 goto out_close_session; 144 goto error;
138 } 145 }
139 v9fs_fill_super(sb, v9ses, flags); 146 v9fs_fill_super(sb, v9ses, flags);
140 147
141 inode = v9fs_get_inode(sb, S_IFDIR | mode); 148 inode = v9fs_get_inode(sb, S_IFDIR | mode);
142 if (IS_ERR(inode)) { 149 if (IS_ERR(inode)) {
143 retval = PTR_ERR(inode); 150 retval = PTR_ERR(inode);
144 goto put_back_sb; 151 goto error;
145 } 152 }
146 153
147 inode->i_uid = uid; 154 inode->i_uid = uid;
@@ -150,54 +157,30 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
150 root = d_alloc_root(inode); 157 root = d_alloc_root(inode);
151 if (!root) { 158 if (!root) {
152 retval = -ENOMEM; 159 retval = -ENOMEM;
153 goto put_back_sb; 160 goto error;
154 } 161 }
155 162
156 sb->s_root = root; 163 sb->s_root = root;
164 root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
165 v9fs_stat2inode(st, root->d_inode, sb);
166 v9fs_fid_add(root, fid);
157 167
158 stat_result = v9fs_t_stat(v9ses, newfid, &fcall); 168 return simple_set_mnt(mnt, sb);
159 if (stat_result < 0) {
160 dprintk(DEBUG_ERROR, "stat error\n");
161 v9fs_t_clunk(v9ses, newfid);
162 } else {
163 /* Setup the Root Inode */
164 root_fid = v9fs_fid_create(v9ses, newfid);
165 if (root_fid == NULL) {
166 retval = -ENOMEM;
167 goto put_back_sb;
168 }
169
170 retval = v9fs_fid_insert(root_fid, root);
171 if (retval < 0) {
172 kfree(fcall);
173 goto put_back_sb;
174 }
175
176 root_fid->qid = fcall->params.rstat.stat.qid;
177 root->d_inode->i_ino =
178 v9fs_qid2ino(&fcall->params.rstat.stat.qid);
179 v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb);
180 }
181 169
182 kfree(fcall); 170error:
171 if (fid)
172 p9_client_clunk(fid);
183 173
184 if (stat_result < 0) { 174 if (v9ses) {
185 retval = stat_result; 175 v9fs_session_close(v9ses);
186 goto put_back_sb; 176 kfree(v9ses);
187 } 177 }
188 178
189 return simple_set_mnt(mnt, sb); 179 if (sb) {
190 180 up_write(&sb->s_umount);
191out_close_session: 181 deactivate_super(sb);
192 v9fs_session_close(v9ses); 182 }
193out_free_session:
194 kfree(v9ses);
195 return retval;
196 183
197put_back_sb:
198 /* deactivate_super calls v9fs_kill_super which will frees the rest */
199 up_write(&sb->s_umount);
200 deactivate_super(sb);
201 return retval; 184 return retval;
202} 185}
203 186
@@ -211,7 +194,7 @@ static void v9fs_kill_super(struct super_block *s)
211{ 194{
212 struct v9fs_session_info *v9ses = s->s_fs_info; 195 struct v9fs_session_info *v9ses = s->s_fs_info;
213 196
214 dprintk(DEBUG_VFS, " %p\n", s); 197 P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
215 198
216 v9fs_dentry_release(s->s_root); /* clunk root */ 199 v9fs_dentry_release(s->s_root); /* clunk root */
217 200
@@ -219,7 +202,7 @@ static void v9fs_kill_super(struct super_block *s)
219 202
220 v9fs_session_close(v9ses); 203 v9fs_session_close(v9ses);
221 kfree(v9ses); 204 kfree(v9ses);
222 dprintk(DEBUG_VFS, "exiting kill_super\n"); 205 P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
223} 206}
224 207
225/** 208/**
@@ -234,7 +217,7 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
234 struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info; 217 struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
235 218
236 if (v9ses->debug != 0) 219 if (v9ses->debug != 0)
237 seq_printf(m, ",debug=%u", v9ses->debug); 220 seq_printf(m, ",debug=%x", v9ses->debug);
238 if (v9ses->port != V9FS_PORT) 221 if (v9ses->port != V9FS_PORT)
239 seq_printf(m, ",port=%u", v9ses->port); 222 seq_printf(m, ",port=%u", v9ses->port);
240 if (v9ses->maxdata != 9000) 223 if (v9ses->maxdata != 9000)
diff --git a/fs/Kconfig b/fs/Kconfig
index 0fa0c1193e81..94b9d861bf9b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -2048,7 +2048,7 @@ config AFS_DEBUG
2048 2048
2049config 9P_FS 2049config 9P_FS
2050 tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" 2050 tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
2051 depends on INET && EXPERIMENTAL 2051 depends on INET && NET_9P && EXPERIMENTAL
2052 help 2052 help
2053 If you say Y here, you will get experimental support for 2053 If you say Y here, you will get experimental support for
2054 Plan 9 resource sharing via the 9P2000 protocol. 2054 Plan 9 resource sharing via the 9P2000 protocol.
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
new file mode 100644
index 000000000000..88884d39f28f
--- /dev/null
+++ b/include/net/9p/9p.h
@@ -0,0 +1,417 @@
1/*
2 * include/net/9p/9p.h
3 *
4 * 9P protocol definitions.
5 *
6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27#ifndef NET_9P_H
28#define NET_9P_H
29
30#ifdef CONFIG_NET_9P_DEBUG
31
32#define P9_DEBUG_ERROR (1<<0)
33#define P9_DEBUG_9P (1<<2)
34#define P9_DEBUG_VFS (1<<3)
35#define P9_DEBUG_CONV (1<<4)
36#define P9_DEBUG_MUX (1<<5)
37#define P9_DEBUG_TRANS (1<<6)
38#define P9_DEBUG_SLABS (1<<7)
39#define P9_DEBUG_FCALL (1<<8)
40
41extern unsigned int p9_debug_level;
42
43#define P9_DPRINTK(level, format, arg...) \
44do { \
45 if ((p9_debug_level & level) == level) \
46 printk(KERN_NOTICE "-- %s (%d): " \
47 format , __FUNCTION__, current->pid , ## arg); \
48} while (0)
49
50#define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR, \
51 "%s: %.*s\n", s, fcall?fcall->params.rerror.error.len:0, \
52 fcall?fcall->params.rerror.error.str:"");
53
54#else
55#define P9_DPRINTK(level, format, arg...) do { } while (0)
56#define PRINT_FCALL_ERROR(s, fcall) do { } while (0)
57#endif
58
59#define P9_EPRINTK(level, format, arg...) \
60do { \
61 printk(level "9p: %s (%d): " \
62 format , __FUNCTION__, current->pid , ## arg); \
63} while (0)
64
65
66/* Message Types */
67enum {
68 P9_TVERSION = 100,
69 P9_RVERSION,
70 P9_TAUTH = 102,
71 P9_RAUTH,
72 P9_TATTACH = 104,
73 P9_RATTACH,
74 P9_TERROR = 106,
75 P9_RERROR,
76 P9_TFLUSH = 108,
77 P9_RFLUSH,
78 P9_TWALK = 110,
79 P9_RWALK,
80 P9_TOPEN = 112,
81 P9_ROPEN,
82 P9_TCREATE = 114,
83 P9_RCREATE,
84 P9_TREAD = 116,
85 P9_RREAD,
86 P9_TWRITE = 118,
87 P9_RWRITE,
88 P9_TCLUNK = 120,
89 P9_RCLUNK,
90 P9_TREMOVE = 122,
91 P9_RREMOVE,
92 P9_TSTAT = 124,
93 P9_RSTAT,
94 P9_TWSTAT = 126,
95 P9_RWSTAT,
96};
97
98/* open modes */
99enum {
100 P9_OREAD = 0x00,
101 P9_OWRITE = 0x01,
102 P9_ORDWR = 0x02,
103 P9_OEXEC = 0x03,
104 P9_OEXCL = 0x04,
105 P9_OTRUNC = 0x10,
106 P9_OREXEC = 0x20,
107 P9_ORCLOSE = 0x40,
108 P9_OAPPEND = 0x80,
109};
110
111/* permissions */
112enum {
113 P9_DMDIR = 0x80000000,
114 P9_DMAPPEND = 0x40000000,
115 P9_DMEXCL = 0x20000000,
116 P9_DMMOUNT = 0x10000000,
117 P9_DMAUTH = 0x08000000,
118 P9_DMTMP = 0x04000000,
119 P9_DMSYMLINK = 0x02000000,
120 P9_DMLINK = 0x01000000,
121 /* 9P2000.u extensions */
122 P9_DMDEVICE = 0x00800000,
123 P9_DMNAMEDPIPE = 0x00200000,
124 P9_DMSOCKET = 0x00100000,
125 P9_DMSETUID = 0x00080000,
126 P9_DMSETGID = 0x00040000,
127};
128
129/* qid.types */
130enum {
131 P9_QTDIR = 0x80,
132 P9_QTAPPEND = 0x40,
133 P9_QTEXCL = 0x20,
134 P9_QTMOUNT = 0x10,
135 P9_QTAUTH = 0x08,
136 P9_QTTMP = 0x04,
137 P9_QTSYMLINK = 0x02,
138 P9_QTLINK = 0x01,
139 P9_QTFILE = 0x00,
140};
141
142#define P9_NOTAG (u16)(~0)
143#define P9_NOFID (u32)(~0)
144#define P9_MAXWELEM 16
145
146/* ample room for Twrite/Rread header */
147#define P9_IOHDRSZ 24
148
149struct p9_str {
150 u16 len;
151 char *str;
152};
153
154/* qids are the unique ID for a file (like an inode */
155struct p9_qid {
156 u8 type;
157 u32 version;
158 u64 path;
159};
160
161/* Plan 9 file metadata (stat) structure */
162struct p9_stat {
163 u16 size;
164 u16 type;
165 u32 dev;
166 struct p9_qid qid;
167 u32 mode;
168 u32 atime;
169 u32 mtime;
170 u64 length;
171 struct p9_str name;
172 struct p9_str uid;
173 struct p9_str gid;
174 struct p9_str muid;
175 struct p9_str extension; /* 9p2000.u extensions */
176 u32 n_uid; /* 9p2000.u extensions */
177 u32 n_gid; /* 9p2000.u extensions */
178 u32 n_muid; /* 9p2000.u extensions */
179};
180
181/* file metadata (stat) structure used to create Twstat message
182 The is similar to p9_stat, but the strings don't point to
183 the same memory block and should be freed separately
184*/
185struct p9_wstat {
186 u16 size;
187 u16 type;
188 u32 dev;
189 struct p9_qid qid;
190 u32 mode;
191 u32 atime;
192 u32 mtime;
193 u64 length;
194 char *name;
195 char *uid;
196 char *gid;
197 char *muid;
198 char *extension; /* 9p2000.u extensions */
199 u32 n_uid; /* 9p2000.u extensions */
200 u32 n_gid; /* 9p2000.u extensions */
201 u32 n_muid; /* 9p2000.u extensions */
202};
203
204/* Structures for Protocol Operations */
205struct p9_tversion {
206 u32 msize;
207 struct p9_str version;
208};
209
210struct p9_rversion {
211 u32 msize;
212 struct p9_str version;
213};
214
215struct p9_tauth {
216 u32 afid;
217 struct p9_str uname;
218 struct p9_str aname;
219};
220
221struct p9_rauth {
222 struct p9_qid qid;
223};
224
225struct p9_rerror {
226 struct p9_str error;
227 u32 errno; /* 9p2000.u extension */
228};
229
230struct p9_tflush {
231 u16 oldtag;
232};
233
234struct p9_rflush {
235};
236
237struct p9_tattach {
238 u32 fid;
239 u32 afid;
240 struct p9_str uname;
241 struct p9_str aname;
242};
243
244struct p9_rattach {
245 struct p9_qid qid;
246};
247
248struct p9_twalk {
249 u32 fid;
250 u32 newfid;
251 u16 nwname;
252 struct p9_str wnames[16];
253};
254
255struct p9_rwalk {
256 u16 nwqid;
257 struct p9_qid wqids[16];
258};
259
260struct p9_topen {
261 u32 fid;
262 u8 mode;
263};
264
265struct p9_ropen {
266 struct p9_qid qid;
267 u32 iounit;
268};
269
270struct p9_tcreate {
271 u32 fid;
272 struct p9_str name;
273 u32 perm;
274 u8 mode;
275 struct p9_str extension;
276};
277
278struct p9_rcreate {
279 struct p9_qid qid;
280 u32 iounit;
281};
282
283struct p9_tread {
284 u32 fid;
285 u64 offset;
286 u32 count;
287};
288
289struct p9_rread {
290 u32 count;
291 u8 *data;
292};
293
294struct p9_twrite {
295 u32 fid;
296 u64 offset;
297 u32 count;
298 u8 *data;
299};
300
301struct p9_rwrite {
302 u32 count;
303};
304
305struct p9_tclunk {
306 u32 fid;
307};
308
309struct p9_rclunk {
310};
311
312struct p9_tremove {
313 u32 fid;
314};
315
316struct p9_rremove {
317};
318
319struct p9_tstat {
320 u32 fid;
321};
322
323struct p9_rstat {
324 struct p9_stat stat;
325};
326
327struct p9_twstat {
328 u32 fid;
329 struct p9_stat stat;
330};
331
332struct p9_rwstat {
333};
334
335/*
336 * fcall is the primary packet structure
337 *
338 */
339
340struct p9_fcall {
341 u32 size;
342 u8 id;
343 u16 tag;
344 void *sdata;
345
346 union {
347 struct p9_tversion tversion;
348 struct p9_rversion rversion;
349 struct p9_tauth tauth;
350 struct p9_rauth rauth;
351 struct p9_rerror rerror;
352 struct p9_tflush tflush;
353 struct p9_rflush rflush;
354 struct p9_tattach tattach;
355 struct p9_rattach rattach;
356 struct p9_twalk twalk;
357 struct p9_rwalk rwalk;
358 struct p9_topen topen;
359 struct p9_ropen ropen;
360 struct p9_tcreate tcreate;
361 struct p9_rcreate rcreate;
362 struct p9_tread tread;
363 struct p9_rread rread;
364 struct p9_twrite twrite;
365 struct p9_rwrite rwrite;
366 struct p9_tclunk tclunk;
367 struct p9_rclunk rclunk;
368 struct p9_tremove tremove;
369 struct p9_rremove rremove;
370 struct p9_tstat tstat;
371 struct p9_rstat rstat;
372 struct p9_twstat twstat;
373 struct p9_rwstat rwstat;
374 } params;
375};
376
377struct p9_idpool;
378
379int p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
380 int dotu);
381int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu);
382void p9_set_tag(struct p9_fcall *fc, u16 tag);
383struct p9_fcall *p9_create_tversion(u32 msize, char *version);
384struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname,
385 char *aname);
386struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname);
387struct p9_fcall *p9_create_tflush(u16 oldtag);
388struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
389 char **wnames);
390struct p9_fcall *p9_create_topen(u32 fid, u8 mode);
391struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
392 char *extension, int dotu);
393struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count);
394struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
395 const char *data);
396struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
397 const char __user *data);
398struct p9_fcall *p9_create_tclunk(u32 fid);
399struct p9_fcall *p9_create_tremove(u32 fid);
400struct p9_fcall *p9_create_tstat(u32 fid);
401struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
402 int dotu);
403
404int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int dotu);
405int p9_errstr2errno(char *errstr, int len);
406
407struct p9_idpool *p9_idpool_create(void);
408void p9_idpool_destroy(struct p9_idpool *);
409int p9_idpool_get(struct p9_idpool *p);
410void p9_idpool_put(int id, struct p9_idpool *p);
411int p9_idpool_check(int id, struct p9_idpool *p);
412
413int p9_error_init(void);
414int p9_errstr2errno(char *, int);
415int __init p9_sysctl_register(void);
416void __exit p9_sysctl_unregister(void);
417#endif /* NET_9P_H */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
new file mode 100644
index 000000000000..d65ed7c69063
--- /dev/null
+++ b/include/net/9p/client.h
@@ -0,0 +1,80 @@
1/*
2 * include/net/9p/client.h
3 *
4 * 9P Client Definitions
5 *
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to:
19 * Free Software Foundation
20 * 51 Franklin Street, Fifth Floor
21 * Boston, MA 02111-1301 USA
22 *
23 */
24
25#ifndef NET_9P_CLIENT_H
26#define NET_9P_CLIENT_H
27
28struct p9_client {
29 spinlock_t lock; /* protect client structure */
30 int msize;
31 unsigned char dotu;
32 struct p9_transport *trans;
33 struct p9_conn *conn;
34
35 struct p9_idpool *fidpool;
36 struct list_head fidlist;
37};
38
39struct p9_fid {
40 struct p9_client *clnt;
41 u32 fid;
42 int mode;
43 struct p9_qid qid;
44 u32 iounit;
45 uid_t uid;
46 void *aux;
47
48 int rdir_fpos;
49 int rdir_pos;
50 struct p9_fcall *rdir_fcall;
51 struct list_head flist;
52 struct list_head dlist; /* list of all fids attached to a dentry */
53};
54
55struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
56 int dotu);
57void p9_client_destroy(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,
60 char *uname, char *aname);
61struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname);
62struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
63 int clone);
64int p9_client_open(struct p9_fid *fid, int mode);
65int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
66 char *extension);
67int p9_client_clunk(struct p9_fid *fid);
68int p9_client_remove(struct p9_fid *fid);
69int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count);
70int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
71int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count);
72int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset,
73 u32 count);
74int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
75 u32 count);
76struct p9_stat *p9_client_stat(struct p9_fid *fid);
77int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
78struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
79
80#endif /* NET_9P_CLIENT_H */
diff --git a/fs/9p/mux.h b/include/net/9p/conn.h
index fb10c50186a1..583b6a2cb3df 100644
--- a/fs/9p/mux.h
+++ b/include/net/9p/conn.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/fs/9p/mux.h 2 * include/net/9p/conn.h
3 * 3 *
4 * Multiplexer Definitions 4 * Connection Definitions
5 * 5 *
6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net> 6 * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
@@ -23,33 +23,35 @@
23 * 23 *
24 */ 24 */
25 25
26struct v9fs_mux_data; 26#ifndef NET_9P_CONN_H
27struct v9fs_req; 27#define NET_9P_CONN_H
28
29#undef P9_NONBLOCK
30
31struct p9_conn;
32struct p9_req;
28 33
29/** 34/**
30 * v9fs_mux_req_callback - callback function that is called when the 35 * p9_mux_req_callback - callback function that is called when the
31 * response of a request is received. The callback is called from 36 * response of a request is received. The callback is called from
32 * a workqueue and shouldn't block. 37 * a workqueue and shouldn't block.
33 * 38 *
39 * @req - request
34 * @a - the pointer that was specified when the request was send to be 40 * @a - the pointer that was specified when the request was send to be
35 * passed to the callback 41 * passed to the callback
36 * @tc - request call
37 * @rc - response call
38 * @err - error code (non-zero if error occured)
39 */ 42 */
40typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a); 43typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
41 44
42int v9fs_mux_global_init(void); 45struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
43void v9fs_mux_global_exit(void); 46 unsigned char *dotu);
47void p9_conn_destroy(struct p9_conn *);
48int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc);
44 49
45struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, 50#ifdef P9_NONBLOCK
46 unsigned char *extended); 51int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
47void v9fs_mux_destroy(struct v9fs_mux_data *); 52 p9_conn_req_callback cb, void *a);
53#endif /* P9_NONBLOCK */
48 54
49int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc); 55void p9_conn_cancel(struct p9_conn *m, int err);
50struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m);
51int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc);
52 56
53void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush); 57#endif /* NET_9P_CONN_H */
54void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
55int v9fs_errstr2errno(char *errstr, int len);
diff --git a/fs/9p/transport.h b/include/net/9p/transport.h
index b38a4b8a41ce..462d42279fb0 100644
--- a/fs/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/fs/9p/transport.h 2 * include/net/9p/transport.h
3 * 3 *
4 * Transport Definition 4 * Transport Definition
5 * 5 *
@@ -23,23 +23,27 @@
23 * 23 *
24 */ 24 */
25 25
26enum v9fs_transport_status { 26#ifndef NET_9P_TRANSPORT_H
27#define NET_9P_TRANSPORT_H
28
29enum p9_transport_status {
27 Connected, 30 Connected,
28 Disconnected, 31 Disconnected,
29 Hung, 32 Hung,
30}; 33};
31 34
32struct v9fs_transport { 35struct p9_transport {
33 enum v9fs_transport_status status; 36 enum p9_transport_status status;
34 void *priv; 37 void *priv;
35 38
36 int (*init) (struct v9fs_session_info *, const char *, char *); 39 int (*write) (struct p9_transport *, void *, int);
37 int (*write) (struct v9fs_transport *, void *, int); 40 int (*read) (struct p9_transport *, void *, int);
38 int (*read) (struct v9fs_transport *, void *, int); 41 void (*close) (struct p9_transport *);
39 void (*close) (struct v9fs_transport *); 42 unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *);
40 unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *);
41}; 43};
42 44
43extern struct v9fs_transport v9fs_trans_tcp; 45struct p9_transport *p9_trans_create_tcp(const char *addr, int port);
44extern struct v9fs_transport v9fs_trans_unix; 46struct p9_transport *p9_trans_create_unix(const char *addr);
45extern struct v9fs_transport v9fs_trans_fd; 47struct p9_transport *p9_trans_create_fd(int rfd, int wfd);
48
49#endif /* NET_9P_TRANSPORT_H */
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
new file mode 100644
index 000000000000..66821cd64a76
--- /dev/null
+++ b/net/9p/Kconfig
@@ -0,0 +1,21 @@
1#
2# 9P protocol configuration
3#
4
5menuconfig NET_9P
6 depends on NET && EXPERIMENTAL
7 tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
8 help
9 If you say Y here, you will get experimental support for
10 Plan 9 resource sharing via the 9P2000 protocol.
11
12 See <http://v9fs.sf.net> for more information.
13
14 If unsure, say N.
15
16config NET_9P_DEBUG
17 bool "Debug information"
18 depends on NET_9P
19 help
20 Say Y if you want the 9P subsistem to log debug information.
21
diff --git a/net/9p/Makefile b/net/9p/Makefile
new file mode 100644
index 000000000000..85b3a7838acf
--- /dev/null
+++ b/net/9p/Makefile
@@ -0,0 +1,13 @@
1obj-$(CONFIG_NET_9P) := 9pnet.o
2
39pnet-objs := \
4 mod.o \
5 trans_fd.o \
6 mux.o \
7 client.o \
8 conv.o \
9 error.o \
10 fcprint.o \
11 util.o \
12
139pnet-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/9p/client.c b/net/9p/client.c
new file mode 100644
index 000000000000..cb170750337c
--- /dev/null
+++ b/net/9p/client.c
@@ -0,0 +1,965 @@
1/*
2 * net/9p/clnt.c
3 *
4 * 9P Client
5 *
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to:
19 * Free Software Foundation
20 * 51 Franklin Street, Fifth Floor
21 * Boston, MA 02111-1301 USA
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/errno.h>
27#include <linux/fs.h>
28#include <linux/idr.h>
29#include <linux/mutex.h>
30#include <linux/sched.h>
31#include <linux/uaccess.h>
32#include <net/9p/9p.h>
33#include <net/9p/transport.h>
34#include <net/9p/conn.h>
35#include <net/9p/client.h>
36
37static struct p9_fid *p9_fid_create(struct p9_client *clnt);
38static void p9_fid_destroy(struct p9_fid *fid);
39static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
40
41struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
42 int dotu)
43{
44 int err, n;
45 struct p9_client *clnt;
46 struct p9_fcall *tc, *rc;
47 struct p9_str *version;
48
49 err = 0;
50 tc = NULL;
51 rc = NULL;
52 clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
53 if (!clnt)
54 return ERR_PTR(-ENOMEM);
55
56 P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
57 clnt, trans, msize, dotu);
58 spin_lock_init(&clnt->lock);
59 clnt->trans = trans;
60 clnt->msize = msize;
61 clnt->dotu = dotu;
62 INIT_LIST_HEAD(&clnt->fidlist);
63 clnt->fidpool = p9_idpool_create();
64 if (!clnt->fidpool) {
65 err = PTR_ERR(clnt->fidpool);
66 clnt->fidpool = NULL;
67 goto error;
68 }
69
70 clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu);
71 if (IS_ERR(clnt->conn)) {
72 err = PTR_ERR(clnt->conn);
73 clnt->conn = NULL;
74 goto error;
75 }
76
77 tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000");
78 if (IS_ERR(tc)) {
79 err = PTR_ERR(tc);
80 tc = NULL;
81 goto error;
82 }
83
84 err = p9_conn_rpc(clnt->conn, tc, &rc);
85 if (err)
86 goto error;
87
88 version = &rc->params.rversion.version;
89 if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
90 clnt->dotu = 1;
91 else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
92 clnt->dotu = 0;
93 else {
94 err = -EREMOTEIO;
95 goto error;
96 }
97
98 n = rc->params.rversion.msize;
99 if (n < clnt->msize)
100 clnt->msize = n;
101
102 kfree(tc);
103 kfree(rc);
104 return clnt;
105
106error:
107 kfree(tc);
108 kfree(rc);
109 p9_client_destroy(clnt);
110 return ERR_PTR(err);
111}
112EXPORT_SYMBOL(p9_client_create);
113
114void p9_client_destroy(struct p9_client *clnt)
115{
116 struct p9_fid *fid, *fidptr;
117
118 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
119 if (clnt->conn) {
120 p9_conn_destroy(clnt->conn);
121 clnt->conn = NULL;
122 }
123
124 if (clnt->trans) {
125 clnt->trans->close(clnt->trans);
126 kfree(clnt->trans);
127 clnt->trans = NULL;
128 }
129
130 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
131 p9_fid_destroy(fid);
132
133 if (clnt->fidpool)
134 p9_idpool_destroy(clnt->fidpool);
135
136 kfree(clnt);
137}
138EXPORT_SYMBOL(p9_client_destroy);
139
140void p9_client_disconnect(struct p9_client *clnt)
141{
142 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
143 clnt->trans->status = Disconnected;
144 p9_conn_cancel(clnt->conn, -EIO);
145}
146EXPORT_SYMBOL(p9_client_disconnect);
147
148struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
149 char *uname, char *aname)
150{
151 int err;
152 struct p9_fcall *tc, *rc;
153 struct p9_fid *fid;
154
155 P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
156 clnt, afid?afid->fid:-1, uname, aname);
157 err = 0;
158 tc = NULL;
159 rc = NULL;
160
161 fid = p9_fid_create(clnt);
162 if (IS_ERR(fid)) {
163 err = PTR_ERR(fid);
164 fid = NULL;
165 goto error;
166 }
167
168 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname);
169 if (IS_ERR(tc)) {
170 err = PTR_ERR(tc);
171 tc = NULL;
172 goto error;
173 }
174
175 err = p9_conn_rpc(clnt->conn, tc, &rc);
176 if (err)
177 goto error;
178
179 memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
180 kfree(tc);
181 kfree(rc);
182 return fid;
183
184error:
185 kfree(tc);
186 kfree(rc);
187 if (fid)
188 p9_fid_destroy(fid);
189 return ERR_PTR(err);
190}
191EXPORT_SYMBOL(p9_client_attach);
192
193struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
194{
195 int err;
196 struct p9_fcall *tc, *rc;
197 struct p9_fid *fid;
198
199 P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
200 aname);
201 err = 0;
202 tc = NULL;
203 rc = NULL;
204
205 fid = p9_fid_create(clnt);
206 if (IS_ERR(fid)) {
207 err = PTR_ERR(fid);
208 fid = NULL;
209 goto error;
210 }
211
212 tc = p9_create_tauth(fid->fid, uname, aname);
213 if (IS_ERR(tc)) {
214 err = PTR_ERR(tc);
215 tc = NULL;
216 goto error;
217 }
218
219 err = p9_conn_rpc(clnt->conn, tc, &rc);
220 if (err)
221 goto error;
222
223 memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
224 kfree(tc);
225 kfree(rc);
226 return fid;
227
228error:
229 kfree(tc);
230 kfree(rc);
231 if (fid)
232 p9_fid_destroy(fid);
233 return ERR_PTR(err);
234}
235EXPORT_SYMBOL(p9_client_auth);
236
237struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
238 int clone)
239{
240 int err;
241 struct p9_fcall *tc, *rc;
242 struct p9_client *clnt;
243 struct p9_fid *fid;
244
245 P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
246 oldfid->fid, nwname, wnames?wnames[0]:NULL);
247 err = 0;
248 tc = NULL;
249 rc = NULL;
250 clnt = oldfid->clnt;
251 if (clone) {
252 fid = p9_fid_create(clnt);
253 if (IS_ERR(fid)) {
254 err = PTR_ERR(fid);
255 fid = NULL;
256 goto error;
257 }
258
259 fid->uid = oldfid->uid;
260 } else
261 fid = oldfid;
262
263 tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
264 if (IS_ERR(tc)) {
265 err = PTR_ERR(tc);
266 tc = NULL;
267 goto error;
268 }
269
270 err = p9_conn_rpc(clnt->conn, tc, &rc);
271 if (err) {
272 if (rc && rc->id == P9_RWALK)
273 goto clunk_fid;
274 else
275 goto error;
276 }
277
278 if (rc->params.rwalk.nwqid != nwname) {
279 err = -ENOENT;
280 goto clunk_fid;
281 }
282
283 if (nwname)
284 memmove(&fid->qid,
285 &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
286 sizeof(struct p9_qid));
287 else
288 fid->qid = oldfid->qid;
289
290 kfree(tc);
291 kfree(rc);
292 return fid;
293
294clunk_fid:
295 kfree(tc);
296 kfree(rc);
297 rc = NULL;
298 tc = p9_create_tclunk(fid->fid);
299 if (IS_ERR(tc)) {
300 err = PTR_ERR(tc);
301 tc = NULL;
302 goto error;
303 }
304
305 p9_conn_rpc(clnt->conn, tc, &rc);
306
307error:
308 kfree(tc);
309 kfree(rc);
310 if (fid && (fid != oldfid))
311 p9_fid_destroy(fid);
312
313 return ERR_PTR(err);
314}
315EXPORT_SYMBOL(p9_client_walk);
316
317int p9_client_open(struct p9_fid *fid, int mode)
318{
319 int err;
320 struct p9_fcall *tc, *rc;
321 struct p9_client *clnt;
322
323 P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
324 err = 0;
325 tc = NULL;
326 rc = NULL;
327 clnt = fid->clnt;
328
329 if (fid->mode != -1)
330 return -EINVAL;
331
332 tc = p9_create_topen(fid->fid, mode);
333 if (IS_ERR(tc)) {
334 err = PTR_ERR(tc);
335 tc = NULL;
336 goto done;
337 }
338
339 err = p9_conn_rpc(clnt->conn, tc, &rc);
340 if (err)
341 goto done;
342
343 fid->mode = mode;
344 fid->iounit = rc->params.ropen.iounit;
345
346done:
347 kfree(tc);
348 kfree(rc);
349 return err;
350}
351EXPORT_SYMBOL(p9_client_open);
352
353int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
354 char *extension)
355{
356 int err;
357 struct p9_fcall *tc, *rc;
358 struct p9_client *clnt;
359
360 P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
361 name, perm, mode);
362 err = 0;
363 tc = NULL;
364 rc = NULL;
365 clnt = fid->clnt;
366
367 if (fid->mode != -1)
368 return -EINVAL;
369
370 tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
371 clnt->dotu);
372 if (IS_ERR(tc)) {
373 err = PTR_ERR(tc);
374 tc = NULL;
375 goto done;
376 }
377
378 err = p9_conn_rpc(clnt->conn, tc, &rc);
379 if (err)
380 goto done;
381
382 fid->mode = mode;
383 fid->iounit = rc->params.ropen.iounit;
384
385done:
386 kfree(tc);
387 kfree(rc);
388 return err;
389}
390EXPORT_SYMBOL(p9_client_fcreate);
391
392int p9_client_clunk(struct p9_fid *fid)
393{
394 int err;
395 struct p9_fcall *tc, *rc;
396 struct p9_client *clnt;
397
398 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
399 err = 0;
400 tc = NULL;
401 rc = NULL;
402 clnt = fid->clnt;
403
404 tc = p9_create_tclunk(fid->fid);
405 if (IS_ERR(tc)) {
406 err = PTR_ERR(tc);
407 tc = NULL;
408 goto done;
409 }
410
411 err = p9_conn_rpc(clnt->conn, tc, &rc);
412 if (err)
413 goto done;
414
415 p9_fid_destroy(fid);
416
417done:
418 kfree(tc);
419 kfree(rc);
420 return err;
421}
422EXPORT_SYMBOL(p9_client_clunk);
423
424int p9_client_remove(struct p9_fid *fid)
425{
426 int err;
427 struct p9_fcall *tc, *rc;
428 struct p9_client *clnt;
429
430 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
431 err = 0;
432 tc = NULL;
433 rc = NULL;
434 clnt = fid->clnt;
435
436 tc = p9_create_tremove(fid->fid);
437 if (IS_ERR(tc)) {
438 err = PTR_ERR(tc);
439 tc = NULL;
440 goto done;
441 }
442
443 err = p9_conn_rpc(clnt->conn, tc, &rc);
444 if (err)
445 goto done;
446
447 p9_fid_destroy(fid);
448
449done:
450 kfree(tc);
451 kfree(rc);
452 return err;
453}
454EXPORT_SYMBOL(p9_client_remove);
455
456int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
457{
458 int err, n, rsize, total;
459 struct p9_fcall *tc, *rc;
460 struct p9_client *clnt;
461
462 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
463 (long long unsigned) offset, count);
464 err = 0;
465 tc = NULL;
466 rc = NULL;
467 clnt = fid->clnt;
468 total = 0;
469
470 rsize = fid->iounit;
471 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
472 rsize = clnt->msize - P9_IOHDRSZ;
473
474 do {
475 if (count < rsize)
476 rsize = count;
477
478 tc = p9_create_tread(fid->fid, offset, rsize);
479 if (IS_ERR(tc)) {
480 err = PTR_ERR(tc);
481 tc = NULL;
482 goto error;
483 }
484
485 err = p9_conn_rpc(clnt->conn, tc, &rc);
486 if (err)
487 goto error;
488
489 n = rc->params.rread.count;
490 if (n > count)
491 n = count;
492
493 memmove(data, rc->params.rread.data, n);
494 count -= n;
495 data += n;
496 offset += n;
497 total += n;
498 kfree(tc);
499 tc = NULL;
500 kfree(rc);
501 rc = NULL;
502 } while (count > 0 && n == rsize);
503
504 return total;
505
506error:
507 kfree(tc);
508 kfree(rc);
509 return err;
510}
511EXPORT_SYMBOL(p9_client_read);
512
513int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
514{
515 int err, n, rsize, total;
516 struct p9_fcall *tc, *rc;
517 struct p9_client *clnt;
518
519 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
520 (long long unsigned) offset, count);
521 err = 0;
522 tc = NULL;
523 rc = NULL;
524 clnt = fid->clnt;
525 total = 0;
526
527 rsize = fid->iounit;
528 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
529 rsize = clnt->msize - P9_IOHDRSZ;
530
531 do {
532 if (count < rsize)
533 rsize = count;
534
535 tc = p9_create_twrite(fid->fid, offset, rsize, data);
536 if (IS_ERR(tc)) {
537 err = PTR_ERR(tc);
538 tc = NULL;
539 goto error;
540 }
541
542 err = p9_conn_rpc(clnt->conn, tc, &rc);
543 if (err)
544 goto error;
545
546 n = rc->params.rread.count;
547 count -= n;
548 data += n;
549 offset += n;
550 total += n;
551 kfree(tc);
552 tc = NULL;
553 kfree(rc);
554 rc = NULL;
555 } while (count > 0);
556
557 return total;
558
559error:
560 kfree(tc);
561 kfree(rc);
562 return err;
563}
564EXPORT_SYMBOL(p9_client_write);
565
566int
567p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
568{
569 int err, n, rsize, total;
570 struct p9_fcall *tc, *rc;
571 struct p9_client *clnt;
572
573 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
574 (long long unsigned) offset, count);
575 err = 0;
576 tc = NULL;
577 rc = NULL;
578 clnt = fid->clnt;
579 total = 0;
580
581 rsize = fid->iounit;
582 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
583 rsize = clnt->msize - P9_IOHDRSZ;
584
585 do {
586 if (count < rsize)
587 rsize = count;
588
589 tc = p9_create_tread(fid->fid, offset, rsize);
590 if (IS_ERR(tc)) {
591 err = PTR_ERR(tc);
592 tc = NULL;
593 goto error;
594 }
595
596 err = p9_conn_rpc(clnt->conn, tc, &rc);
597 if (err)
598 goto error;
599
600 n = rc->params.rread.count;
601 if (n > count)
602 n = count;
603
604 err = copy_to_user(data, rc->params.rread.data, n);
605 if (err) {
606 err = -EFAULT;
607 goto error;
608 }
609
610 count -= n;
611 data += n;
612 offset += n;
613 total += n;
614 kfree(tc);
615 tc = NULL;
616 kfree(rc);
617 rc = NULL;
618 } while (count > 0 && n == rsize);
619
620 return total;
621
622error:
623 kfree(tc);
624 kfree(rc);
625 return err;
626}
627EXPORT_SYMBOL(p9_client_uread);
628
629int
630p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
631 u32 count)
632{
633 int err, n, rsize, total;
634 struct p9_fcall *tc, *rc;
635 struct p9_client *clnt;
636
637 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
638 (long long unsigned) offset, count);
639 err = 0;
640 tc = NULL;
641 rc = NULL;
642 clnt = fid->clnt;
643 total = 0;
644
645 rsize = fid->iounit;
646 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
647 rsize = clnt->msize - P9_IOHDRSZ;
648
649 do {
650 if (count < rsize)
651 rsize = count;
652
653 tc = p9_create_twrite_u(fid->fid, offset, rsize, data);
654 if (IS_ERR(tc)) {
655 err = PTR_ERR(tc);
656 tc = NULL;
657 goto error;
658 }
659
660 err = p9_conn_rpc(clnt->conn, tc, &rc);
661 if (err)
662 goto error;
663
664 n = rc->params.rread.count;
665 count -= n;
666 data += n;
667 offset += n;
668 total += n;
669 kfree(tc);
670 tc = NULL;
671 kfree(rc);
672 rc = NULL;
673 } while (count > 0);
674
675 return total;
676
677error:
678 kfree(tc);
679 kfree(rc);
680 return err;
681}
682EXPORT_SYMBOL(p9_client_uwrite);
683
684int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
685{
686 int n, total;
687
688 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
689 (long long unsigned) offset, count);
690 n = 0;
691 total = 0;
692 while (count) {
693 n = p9_client_read(fid, data, offset, count);
694 if (n <= 0)
695 break;
696
697 data += n;
698 offset += n;
699 count -= n;
700 total += n;
701 }
702
703 if (n < 0)
704 total = n;
705
706 return total;
707}
708EXPORT_SYMBOL(p9_client_readn);
709
710struct p9_stat *p9_client_stat(struct p9_fid *fid)
711{
712 int err;
713 struct p9_fcall *tc, *rc;
714 struct p9_client *clnt;
715 struct p9_stat *ret;
716
717 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
718 err = 0;
719 tc = NULL;
720 rc = NULL;
721 ret = NULL;
722 clnt = fid->clnt;
723
724 tc = p9_create_tstat(fid->fid);
725 if (IS_ERR(tc)) {
726 err = PTR_ERR(tc);
727 tc = NULL;
728 goto error;
729 }
730
731 err = p9_conn_rpc(clnt->conn, tc, &rc);
732 if (err)
733 goto error;
734
735 ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
736 if (IS_ERR(ret)) {
737 err = PTR_ERR(ret);
738 ret = NULL;
739 goto error;
740 }
741
742 kfree(tc);
743 kfree(rc);
744 return ret;
745
746error:
747 kfree(tc);
748 kfree(rc);
749 kfree(ret);
750 return ERR_PTR(err);
751}
752EXPORT_SYMBOL(p9_client_stat);
753
754int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
755{
756 int err;
757 struct p9_fcall *tc, *rc;
758 struct p9_client *clnt;
759
760 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
761 err = 0;
762 tc = NULL;
763 rc = NULL;
764 clnt = fid->clnt;
765
766 tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
767 if (IS_ERR(tc)) {
768 err = PTR_ERR(tc);
769 tc = NULL;
770 goto done;
771 }
772
773 err = p9_conn_rpc(clnt->conn, tc, &rc);
774
775done:
776 kfree(tc);
777 kfree(rc);
778 return err;
779}
780EXPORT_SYMBOL(p9_client_wstat);
781
782struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
783{
784 int err, n, m;
785 struct p9_fcall *tc, *rc;
786 struct p9_client *clnt;
787 struct p9_stat st, *ret;
788
789 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid,
790 (long long unsigned) offset);
791 err = 0;
792 tc = NULL;
793 rc = NULL;
794 ret = NULL;
795 clnt = fid->clnt;
796
797 /* if the offset is below or above the current response, free it */
798 if (offset < fid->rdir_fpos || (fid->rdir_fcall &&
799 offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) {
800 fid->rdir_pos = 0;
801 if (fid->rdir_fcall)
802 fid->rdir_fpos += fid->rdir_fcall->params.rread.count;
803
804 kfree(fid->rdir_fcall);
805 fid->rdir_fcall = NULL;
806 if (offset < fid->rdir_fpos)
807 fid->rdir_fpos = 0;
808 }
809
810 if (!fid->rdir_fcall) {
811 n = fid->iounit;
812 if (!n || n > clnt->msize-P9_IOHDRSZ)
813 n = clnt->msize - P9_IOHDRSZ;
814
815 while (1) {
816 if (fid->rdir_fcall) {
817 fid->rdir_fpos +=
818 fid->rdir_fcall->params.rread.count;
819 kfree(fid->rdir_fcall);
820 fid->rdir_fcall = NULL;
821 }
822
823 tc = p9_create_tread(fid->fid, fid->rdir_fpos, n);
824 if (IS_ERR(tc)) {
825 err = PTR_ERR(tc);
826 tc = NULL;
827 goto error;
828 }
829
830 err = p9_conn_rpc(clnt->conn, tc, &rc);
831 if (err)
832 goto error;
833
834 n = rc->params.rread.count;
835 if (n == 0)
836 goto done;
837
838 fid->rdir_fcall = rc;
839 rc = NULL;
840 if (offset >= fid->rdir_fpos &&
841 offset < fid->rdir_fpos+n)
842 break;
843 }
844
845 fid->rdir_pos = 0;
846 }
847
848 m = offset - fid->rdir_fpos;
849 if (m < 0)
850 goto done;
851
852 n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m,
853 fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu);
854
855 if (!n) {
856 err = -EIO;
857 goto error;
858 }
859
860 fid->rdir_pos += n;
861 st.size = n;
862 ret = p9_clone_stat(&st, clnt->dotu);
863 if (IS_ERR(ret)) {
864 err = PTR_ERR(ret);
865 ret = NULL;
866 goto error;
867 }
868
869done:
870 kfree(tc);
871 kfree(rc);
872 return ret;
873
874error:
875 kfree(tc);
876 kfree(rc);
877 kfree(ret);
878 return ERR_PTR(err);
879}
880EXPORT_SYMBOL(p9_client_dirread);
881
882static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
883{
884 int n;
885 char *p;
886 struct p9_stat *ret;
887
888 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
889 st->muid.len;
890
891 if (dotu)
892 n += st->extension.len;
893
894 ret = kmalloc(n, GFP_KERNEL);
895 if (!ret)
896 return ERR_PTR(-ENOMEM);
897
898 memmove(ret, st, sizeof(struct p9_stat));
899 p = ((char *) ret) + sizeof(struct p9_stat);
900 memmove(p, st->name.str, st->name.len);
901 p += st->name.len;
902 memmove(p, st->uid.str, st->uid.len);
903 p += st->uid.len;
904 memmove(p, st->gid.str, st->gid.len);
905 p += st->gid.len;
906 memmove(p, st->muid.str, st->muid.len);
907 p += st->muid.len;
908
909 if (dotu) {
910 memmove(p, st->extension.str, st->extension.len);
911 p += st->extension.len;
912 }
913
914 return ret;
915}
916
917static struct p9_fid *p9_fid_create(struct p9_client *clnt)
918{
919 int err;
920 struct p9_fid *fid;
921
922 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
923 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
924 if (!fid)
925 return ERR_PTR(-ENOMEM);
926
927 fid->fid = p9_idpool_get(clnt->fidpool);
928 if (fid->fid < 0) {
929 err = -ENOSPC;
930 goto error;
931 }
932
933 memset(&fid->qid, 0, sizeof(struct p9_qid));
934 fid->mode = -1;
935 fid->rdir_fpos = 0;
936 fid->rdir_pos = 0;
937 fid->rdir_fcall = NULL;
938 fid->uid = current->fsuid;
939 fid->clnt = clnt;
940 fid->aux = NULL;
941
942 spin_lock(&clnt->lock);
943 list_add(&fid->flist, &clnt->fidlist);
944 spin_unlock(&clnt->lock);
945
946 return fid;
947
948error:
949 kfree(fid);
950 return ERR_PTR(err);
951}
952
953static void p9_fid_destroy(struct p9_fid *fid)
954{
955 struct p9_client *clnt;
956
957 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
958 clnt = fid->clnt;
959 p9_idpool_put(fid->fid, clnt->fidpool);
960 spin_lock(&clnt->lock);
961 list_del(&fid->flist);
962 spin_unlock(&clnt->lock);
963 kfree(fid->rdir_fcall);
964 kfree(fid);
965}
diff --git a/fs/9p/conv.c b/net/9p/conv.c
index a3ed571eee31..37451178e761 100644
--- a/fs/9p/conv.c
+++ b/net/9p/conv.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/fs/9p/conv.c 2 * net/9p/conv.c
3 * 3 *
4 * 9P protocol conversion functions 4 * 9P protocol conversion functions
5 * 5 *
@@ -29,11 +29,8 @@
29#include <linux/fs.h> 29#include <linux/fs.h>
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/idr.h> 31#include <linux/idr.h>
32#include <asm/uaccess.h> 32#include <linux/uaccess.h>
33#include "debug.h" 33#include <net/9p/9p.h>
34#include "v9fs.h"
35#include "9p.h"
36#include "conv.h"
37 34
38/* 35/*
39 * Buffer to help with string parsing 36 * Buffer to help with string parsing
@@ -59,8 +56,9 @@ static int buf_check_size(struct cbuf *buf, int len)
59{ 56{
60 if (buf->p + len > buf->ep) { 57 if (buf->p + len > buf->ep) {
61 if (buf->p < buf->ep) { 58 if (buf->p < buf->ep) {
62 eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", 59 P9_EPRINTK(KERN_ERR,
63 len, (int)(buf->ep - buf->p)); 60 "buffer overflow: want %d has %d\n", len,
61 (int)(buf->ep - buf->p));
64 dump_stack(); 62 dump_stack();
65 buf->p = buf->ep + 1; 63 buf->p = buf->ep + 1;
66 } 64 }
@@ -183,7 +181,7 @@ static u64 buf_get_int64(struct cbuf *buf)
183 return ret; 181 return ret;
184} 182}
185 183
186static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) 184static void buf_get_str(struct cbuf *buf, struct p9_str *vstr)
187{ 185{
188 vstr->len = buf_get_int16(buf); 186 vstr->len = buf_get_int16(buf);
189 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { 187 if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
@@ -195,7 +193,7 @@ static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
195 } 193 }
196} 194}
197 195
198static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) 196static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid)
199{ 197{
200 qid->type = buf_get_int8(bufp); 198 qid->type = buf_get_int8(bufp);
201 qid->version = buf_get_int32(bufp); 199 qid->version = buf_get_int32(bufp);
@@ -203,18 +201,18 @@ static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
203} 201}
204 202
205/** 203/**
206 * v9fs_size_wstat - calculate the size of a variable length stat struct 204 * p9_size_wstat - calculate the size of a variable length stat struct
207 * @stat: metadata (stat) structure 205 * @stat: metadata (stat) structure
208 * @extended: non-zero if 9P2000.u 206 * @dotu: non-zero if 9P2000.u
209 * 207 *
210 */ 208 */
211 209
212static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) 210static int p9_size_wstat(struct p9_wstat *wstat, int dotu)
213{ 211{
214 int size = 0; 212 int size = 0;
215 213
216 if (wstat == NULL) { 214 if (wstat == NULL) {
217 eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n"); 215 P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");
218 return 0; 216 return 0;
219 } 217 }
220 218
@@ -239,7 +237,7 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
239 if (wstat->muid) 237 if (wstat->muid)
240 size += strlen(wstat->muid); 238 size += strlen(wstat->muid);
241 239
242 if (extended) { 240 if (dotu) {
243 size += 4 + /* n_uid[4] */ 241 size += 4 + /* n_uid[4] */
244 4 + /* n_gid[4] */ 242 4 + /* n_gid[4] */
245 4 + /* n_muid[4] */ 243 4 + /* n_muid[4] */
@@ -255,12 +253,12 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
255 * buf_get_stat - safely decode a recieved metadata (stat) structure 253 * buf_get_stat - safely decode a recieved metadata (stat) structure
256 * @bufp: buffer to deserialize 254 * @bufp: buffer to deserialize
257 * @stat: metadata (stat) structure 255 * @stat: metadata (stat) structure
258 * @extended: non-zero if 9P2000.u 256 * @dotu: non-zero if 9P2000.u
259 * 257 *
260 */ 258 */
261 259
262static void 260static void
263buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) 261buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu)
264{ 262{
265 stat->size = buf_get_int16(bufp); 263 stat->size = buf_get_int16(bufp);
266 stat->type = buf_get_int16(bufp); 264 stat->type = buf_get_int16(bufp);
@@ -277,7 +275,7 @@ buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
277 buf_get_str(bufp, &stat->gid); 275 buf_get_str(bufp, &stat->gid);
278 buf_get_str(bufp, &stat->muid); 276 buf_get_str(bufp, &stat->muid);
279 277
280 if (extended) { 278 if (dotu) {
281 buf_get_str(bufp, &stat->extension); 279 buf_get_str(bufp, &stat->extension);
282 stat->n_uid = buf_get_int32(bufp); 280 stat->n_uid = buf_get_int32(bufp);
283 stat->n_gid = buf_get_int32(bufp); 281 stat->n_gid = buf_get_int32(bufp);
@@ -286,18 +284,18 @@ buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
286} 284}
287 285
288/** 286/**
289 * v9fs_deserialize_stat - decode a received metadata structure 287 * p9_deserialize_stat - decode a received metadata structure
290 * @buf: buffer to deserialize 288 * @buf: buffer to deserialize
291 * @buflen: length of received buffer 289 * @buflen: length of received buffer
292 * @stat: metadata structure to decode into 290 * @stat: metadata structure to decode into
293 * @extended: non-zero if 9P2000.u 291 * @dotu: non-zero if 9P2000.u
294 * 292 *
295 * Note: stat will point to the buf region. 293 * Note: stat will point to the buf region.
296 */ 294 */
297 295
298int 296int
299v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, 297p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
300 int extended) 298 int dotu)
301{ 299{
302 struct cbuf buffer; 300 struct cbuf buffer;
303 struct cbuf *bufp = &buffer; 301 struct cbuf *bufp = &buffer;
@@ -305,13 +303,14 @@ v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
305 303
306 buf_init(bufp, buf, buflen); 304 buf_init(bufp, buf, buflen);
307 p = bufp->p; 305 p = bufp->p;
308 buf_get_stat(bufp, stat, extended); 306 buf_get_stat(bufp, stat, dotu);
309 307
310 if (buf_check_overflow(bufp)) 308 if (buf_check_overflow(bufp))
311 return 0; 309 return 0;
312 else 310 else
313 return bufp->p - p; 311 return bufp->p - p;
314} 312}
313EXPORT_SYMBOL(p9_deserialize_stat);
315 314
316/** 315/**
317 * deserialize_fcall - unmarshal a response 316 * deserialize_fcall - unmarshal a response
@@ -319,13 +318,13 @@ v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
319 * @buflen: length of received buffer 318 * @buflen: length of received buffer
320 * @rcall: fcall structure to populate 319 * @rcall: fcall structure to populate
321 * @rcalllen: length of fcall structure to populate 320 * @rcalllen: length of fcall structure to populate
322 * @extended: non-zero if 9P2000.u 321 * @dotu: non-zero if 9P2000.u
323 * 322 *
324 */ 323 */
325 324
326int 325int
327v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, 326p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall,
328 int extended) 327 int dotu)
329{ 328{
330 329
331 struct cbuf buffer; 330 struct cbuf buffer;
@@ -338,102 +337,104 @@ v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
338 rcall->id = buf_get_int8(bufp); 337 rcall->id = buf_get_int8(bufp);
339 rcall->tag = buf_get_int16(bufp); 338 rcall->tag = buf_get_int16(bufp);
340 339
341 dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id, 340 P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size,
342 rcall->tag); 341 rcall->id, rcall->tag);
343 342
344 switch (rcall->id) { 343 switch (rcall->id) {
345 default: 344 default:
346 eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id); 345 P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id);
347 return -EPROTO; 346 return -EPROTO;
348 case RVERSION: 347 case P9_RVERSION:
349 rcall->params.rversion.msize = buf_get_int32(bufp); 348 rcall->params.rversion.msize = buf_get_int32(bufp);
350 buf_get_str(bufp, &rcall->params.rversion.version); 349 buf_get_str(bufp, &rcall->params.rversion.version);
351 break; 350 break;
352 case RFLUSH: 351 case P9_RFLUSH:
353 break; 352 break;
354 case RATTACH: 353 case P9_RATTACH:
355 rcall->params.rattach.qid.type = buf_get_int8(bufp); 354 rcall->params.rattach.qid.type = buf_get_int8(bufp);
356 rcall->params.rattach.qid.version = buf_get_int32(bufp); 355 rcall->params.rattach.qid.version = buf_get_int32(bufp);
357 rcall->params.rattach.qid.path = buf_get_int64(bufp); 356 rcall->params.rattach.qid.path = buf_get_int64(bufp);
358 break; 357 break;
359 case RWALK: 358 case P9_RWALK:
360 rcall->params.rwalk.nwqid = buf_get_int16(bufp); 359 rcall->params.rwalk.nwqid = buf_get_int16(bufp);
361 if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) { 360 if (rcall->params.rwalk.nwqid > P9_MAXWELEM) {
362 eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n", 361 P9_EPRINTK(KERN_ERR,
363 V9FS_MAXWELEM, rcall->params.rwalk.nwqid); 362 "Rwalk with more than %d qids: %d\n",
363 P9_MAXWELEM, rcall->params.rwalk.nwqid);
364 return -EPROTO; 364 return -EPROTO;
365 } 365 }
366 366
367 for (i = 0; i < rcall->params.rwalk.nwqid; i++) 367 for (i = 0; i < rcall->params.rwalk.nwqid; i++)
368 buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]); 368 buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
369 break; 369 break;
370 case ROPEN: 370 case P9_ROPEN:
371 buf_get_qid(bufp, &rcall->params.ropen.qid); 371 buf_get_qid(bufp, &rcall->params.ropen.qid);
372 rcall->params.ropen.iounit = buf_get_int32(bufp); 372 rcall->params.ropen.iounit = buf_get_int32(bufp);
373 break; 373 break;
374 case RCREATE: 374 case P9_RCREATE:
375 buf_get_qid(bufp, &rcall->params.rcreate.qid); 375 buf_get_qid(bufp, &rcall->params.rcreate.qid);
376 rcall->params.rcreate.iounit = buf_get_int32(bufp); 376 rcall->params.rcreate.iounit = buf_get_int32(bufp);
377 break; 377 break;
378 case RREAD: 378 case P9_RREAD:
379 rcall->params.rread.count = buf_get_int32(bufp); 379 rcall->params.rread.count = buf_get_int32(bufp);
380 rcall->params.rread.data = bufp->p; 380 rcall->params.rread.data = bufp->p;
381 buf_check_size(bufp, rcall->params.rread.count); 381 buf_check_size(bufp, rcall->params.rread.count);
382 break; 382 break;
383 case RWRITE: 383 case P9_RWRITE:
384 rcall->params.rwrite.count = buf_get_int32(bufp); 384 rcall->params.rwrite.count = buf_get_int32(bufp);
385 break; 385 break;
386 case RCLUNK: 386 case P9_RCLUNK:
387 break; 387 break;
388 case RREMOVE: 388 case P9_RREMOVE:
389 break; 389 break;
390 case RSTAT: 390 case P9_RSTAT:
391 buf_get_int16(bufp); 391 buf_get_int16(bufp);
392 buf_get_stat(bufp, &rcall->params.rstat.stat, extended); 392 buf_get_stat(bufp, &rcall->params.rstat.stat, dotu);
393 break; 393 break;
394 case RWSTAT: 394 case P9_RWSTAT:
395 break; 395 break;
396 case RERROR: 396 case P9_RERROR:
397 buf_get_str(bufp, &rcall->params.rerror.error); 397 buf_get_str(bufp, &rcall->params.rerror.error);
398 if (extended) 398 if (dotu)
399 rcall->params.rerror.errno = buf_get_int16(bufp); 399 rcall->params.rerror.errno = buf_get_int16(bufp);
400 break; 400 break;
401 } 401 }
402 402
403 if (buf_check_overflow(bufp)) { 403 if (buf_check_overflow(bufp)) {
404 dprintk(DEBUG_ERROR, "buffer overflow\n"); 404 P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n");
405 return -EIO; 405 return -EIO;
406 } 406 }
407 407
408 return bufp->p - bufp->sp; 408 return bufp->p - bufp->sp;
409} 409}
410EXPORT_SYMBOL(p9_deserialize_fcall);
410 411
411static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p) 412static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p)
412{ 413{
413 *p = val; 414 *p = val;
414 buf_put_int8(bufp, val); 415 buf_put_int8(bufp, val);
415} 416}
416 417
417static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p) 418static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p)
418{ 419{
419 *p = val; 420 *p = val;
420 buf_put_int16(bufp, val); 421 buf_put_int16(bufp, val);
421} 422}
422 423
423static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p) 424static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p)
424{ 425{
425 *p = val; 426 *p = val;
426 buf_put_int32(bufp, val); 427 buf_put_int32(bufp, val);
427} 428}
428 429
429static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) 430static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p)
430{ 431{
431 *p = val; 432 *p = val;
432 buf_put_int64(bufp, val); 433 buf_put_int64(bufp, val);
433} 434}
434 435
435static void 436static void
436v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) 437p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str)
437{ 438{
438 int len; 439 int len;
439 char *s; 440 char *s;
@@ -451,7 +452,16 @@ v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
451} 452}
452 453
453static int 454static int
454v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, 455p9_put_data(struct cbuf *bufp, const char *data, int count,
456 unsigned char **pdata)
457{
458 *pdata = buf_alloc(bufp, count);
459 memmove(*pdata, data, count);
460 return count;
461}
462
463static int
464p9_put_user_data(struct cbuf *bufp, const char __user *data, int count,
455 unsigned char **pdata) 465 unsigned char **pdata)
456{ 466{
457 *pdata = buf_alloc(bufp, count); 467 *pdata = buf_alloc(bufp, count);
@@ -459,162 +469,167 @@ v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
459} 469}
460 470
461static void 471static void
462v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat, 472p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat,
463 struct v9fs_stat *stat, int statsz, int extended) 473 struct p9_stat *stat, int statsz, int dotu)
464{ 474{
465 v9fs_put_int16(bufp, statsz, &stat->size); 475 p9_put_int16(bufp, statsz, &stat->size);
466 v9fs_put_int16(bufp, wstat->type, &stat->type); 476 p9_put_int16(bufp, wstat->type, &stat->type);
467 v9fs_put_int32(bufp, wstat->dev, &stat->dev); 477 p9_put_int32(bufp, wstat->dev, &stat->dev);
468 v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type); 478 p9_put_int8(bufp, wstat->qid.type, &stat->qid.type);
469 v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version); 479 p9_put_int32(bufp, wstat->qid.version, &stat->qid.version);
470 v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path); 480 p9_put_int64(bufp, wstat->qid.path, &stat->qid.path);
471 v9fs_put_int32(bufp, wstat->mode, &stat->mode); 481 p9_put_int32(bufp, wstat->mode, &stat->mode);
472 v9fs_put_int32(bufp, wstat->atime, &stat->atime); 482 p9_put_int32(bufp, wstat->atime, &stat->atime);
473 v9fs_put_int32(bufp, wstat->mtime, &stat->mtime); 483 p9_put_int32(bufp, wstat->mtime, &stat->mtime);
474 v9fs_put_int64(bufp, wstat->length, &stat->length); 484 p9_put_int64(bufp, wstat->length, &stat->length);
475 485
476 v9fs_put_str(bufp, wstat->name, &stat->name); 486 p9_put_str(bufp, wstat->name, &stat->name);
477 v9fs_put_str(bufp, wstat->uid, &stat->uid); 487 p9_put_str(bufp, wstat->uid, &stat->uid);
478 v9fs_put_str(bufp, wstat->gid, &stat->gid); 488 p9_put_str(bufp, wstat->gid, &stat->gid);
479 v9fs_put_str(bufp, wstat->muid, &stat->muid); 489 p9_put_str(bufp, wstat->muid, &stat->muid);
480 490
481 if (extended) { 491 if (dotu) {
482 v9fs_put_str(bufp, wstat->extension, &stat->extension); 492 p9_put_str(bufp, wstat->extension, &stat->extension);
483 v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid); 493 p9_put_int32(bufp, wstat->n_uid, &stat->n_uid);
484 v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid); 494 p9_put_int32(bufp, wstat->n_gid, &stat->n_gid);
485 v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid); 495 p9_put_int32(bufp, wstat->n_muid, &stat->n_muid);
486 } 496 }
487} 497}
488 498
489static struct v9fs_fcall * 499static struct p9_fcall *
490v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) 500p9_create_common(struct cbuf *bufp, u32 size, u8 id)
491{ 501{
492 struct v9fs_fcall *fc; 502 struct p9_fcall *fc;
493 503
494 size += 4 + 1 + 2; /* size[4] id[1] tag[2] */ 504 size += 4 + 1 + 2; /* size[4] id[1] tag[2] */
495 fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL); 505 fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL);
496 if (!fc) 506 if (!fc)
497 return ERR_PTR(-ENOMEM); 507 return ERR_PTR(-ENOMEM);
498 508
499 fc->sdata = (char *)fc + sizeof(*fc); 509 fc->sdata = (char *)fc + sizeof(*fc);
500 510
501 buf_init(bufp, (char *)fc->sdata, size); 511 buf_init(bufp, (char *)fc->sdata, size);
502 v9fs_put_int32(bufp, size, &fc->size); 512 p9_put_int32(bufp, size, &fc->size);
503 v9fs_put_int8(bufp, id, &fc->id); 513 p9_put_int8(bufp, id, &fc->id);
504 v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag); 514 p9_put_int16(bufp, P9_NOTAG, &fc->tag);
505 515
506 return fc; 516 return fc;
507} 517}
508 518
509void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) 519void p9_set_tag(struct p9_fcall *fc, u16 tag)
510{ 520{
511 fc->tag = tag; 521 fc->tag = tag;
512 *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); 522 *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
513} 523}
524EXPORT_SYMBOL(p9_set_tag);
514 525
515struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version) 526struct p9_fcall *p9_create_tversion(u32 msize, char *version)
516{ 527{
517 int size; 528 int size;
518 struct v9fs_fcall *fc; 529 struct p9_fcall *fc;
519 struct cbuf buffer; 530 struct cbuf buffer;
520 struct cbuf *bufp = &buffer; 531 struct cbuf *bufp = &buffer;
521 532
522 size = 4 + 2 + strlen(version); /* msize[4] version[s] */ 533 size = 4 + 2 + strlen(version); /* msize[4] version[s] */
523 fc = v9fs_create_common(bufp, size, TVERSION); 534 fc = p9_create_common(bufp, size, P9_TVERSION);
524 if (IS_ERR(fc)) 535 if (IS_ERR(fc))
525 goto error; 536 goto error;
526 537
527 v9fs_put_int32(bufp, msize, &fc->params.tversion.msize); 538 p9_put_int32(bufp, msize, &fc->params.tversion.msize);
528 v9fs_put_str(bufp, version, &fc->params.tversion.version); 539 p9_put_str(bufp, version, &fc->params.tversion.version);
529 540
530 if (buf_check_overflow(bufp)) { 541 if (buf_check_overflow(bufp)) {
531 kfree(fc); 542 kfree(fc);
532 fc = ERR_PTR(-ENOMEM); 543 fc = ERR_PTR(-ENOMEM);
533 } 544 }
534 error: 545error:
535 return fc; 546 return fc;
536} 547}
548EXPORT_SYMBOL(p9_create_tversion);
537 549
538#if 0 550struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
539struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
540{ 551{
541 int size; 552 int size;
542 struct v9fs_fcall *fc; 553 struct p9_fcall *fc;
543 struct cbuf buffer; 554 struct cbuf buffer;
544 struct cbuf *bufp = &buffer; 555 struct cbuf *bufp = &buffer;
545 556
546 size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */ 557 /* afid[4] uname[s] aname[s] */
547 fc = v9fs_create_common(bufp, size, TAUTH); 558 size = 4 + 2 + strlen(uname) + 2 + strlen(aname);
559 fc = p9_create_common(bufp, size, P9_TAUTH);
548 if (IS_ERR(fc)) 560 if (IS_ERR(fc))
549 goto error; 561 goto error;
550 562
551 v9fs_put_int32(bufp, afid, &fc->params.tauth.afid); 563 p9_put_int32(bufp, afid, &fc->params.tauth.afid);
552 v9fs_put_str(bufp, uname, &fc->params.tauth.uname); 564 p9_put_str(bufp, uname, &fc->params.tauth.uname);
553 v9fs_put_str(bufp, aname, &fc->params.tauth.aname); 565 p9_put_str(bufp, aname, &fc->params.tauth.aname);
554 566
555 if (buf_check_overflow(bufp)) { 567 if (buf_check_overflow(bufp)) {
556 kfree(fc); 568 kfree(fc);
557 fc = ERR_PTR(-ENOMEM); 569 fc = ERR_PTR(-ENOMEM);
558 } 570 }
559 error: 571error:
560 return fc; 572 return fc;
561} 573}
562#endif /* 0 */ 574EXPORT_SYMBOL(p9_create_tauth);
563 575
564struct v9fs_fcall * 576struct p9_fcall *
565v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname) 577p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
566{ 578{
567 int size; 579 int size;
568 struct v9fs_fcall *fc; 580 struct p9_fcall *fc;
569 struct cbuf buffer; 581 struct cbuf buffer;
570 struct cbuf *bufp = &buffer; 582 struct cbuf *bufp = &buffer;
571 583
572 size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */ 584 /* fid[4] afid[4] uname[s] aname[s] */
573 fc = v9fs_create_common(bufp, size, TATTACH); 585 size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);
586 fc = p9_create_common(bufp, size, P9_TATTACH);
574 if (IS_ERR(fc)) 587 if (IS_ERR(fc))
575 goto error; 588 goto error;
576 589
577 v9fs_put_int32(bufp, fid, &fc->params.tattach.fid); 590 p9_put_int32(bufp, fid, &fc->params.tattach.fid);
578 v9fs_put_int32(bufp, afid, &fc->params.tattach.afid); 591 p9_put_int32(bufp, afid, &fc->params.tattach.afid);
579 v9fs_put_str(bufp, uname, &fc->params.tattach.uname); 592 p9_put_str(bufp, uname, &fc->params.tattach.uname);
580 v9fs_put_str(bufp, aname, &fc->params.tattach.aname); 593 p9_put_str(bufp, aname, &fc->params.tattach.aname);
581 594
582 error: 595error:
583 return fc; 596 return fc;
584} 597}
598EXPORT_SYMBOL(p9_create_tattach);
585 599
586struct v9fs_fcall *v9fs_create_tflush(u16 oldtag) 600struct p9_fcall *p9_create_tflush(u16 oldtag)
587{ 601{
588 int size; 602 int size;
589 struct v9fs_fcall *fc; 603 struct p9_fcall *fc;
590 struct cbuf buffer; 604 struct cbuf buffer;
591 struct cbuf *bufp = &buffer; 605 struct cbuf *bufp = &buffer;
592 606
593 size = 2; /* oldtag[2] */ 607 size = 2; /* oldtag[2] */
594 fc = v9fs_create_common(bufp, size, TFLUSH); 608 fc = p9_create_common(bufp, size, P9_TFLUSH);
595 if (IS_ERR(fc)) 609 if (IS_ERR(fc))
596 goto error; 610 goto error;
597 611
598 v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag); 612 p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
599 613
600 if (buf_check_overflow(bufp)) { 614 if (buf_check_overflow(bufp)) {
601 kfree(fc); 615 kfree(fc);
602 fc = ERR_PTR(-ENOMEM); 616 fc = ERR_PTR(-ENOMEM);
603 } 617 }
604 error: 618error:
605 return fc; 619 return fc;
606} 620}
621EXPORT_SYMBOL(p9_create_tflush);
607 622
608struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname, 623struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
609 char **wnames) 624 char **wnames)
610{ 625{
611 int i, size; 626 int i, size;
612 struct v9fs_fcall *fc; 627 struct p9_fcall *fc;
613 struct cbuf buffer; 628 struct cbuf buffer;
614 struct cbuf *bufp = &buffer; 629 struct cbuf *bufp = &buffer;
615 630
616 if (nwname > V9FS_MAXWELEM) { 631 if (nwname > P9_MAXWELEM) {
617 dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM); 632 P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM);
618 return NULL; 633 return NULL;
619 } 634 }
620 635
@@ -623,122 +638,160 @@ struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
623 size += 2 + strlen(wnames[i]); /* wname[s] */ 638 size += 2 + strlen(wnames[i]); /* wname[s] */
624 } 639 }
625 640
626 fc = v9fs_create_common(bufp, size, TWALK); 641 fc = p9_create_common(bufp, size, P9_TWALK);
627 if (IS_ERR(fc)) 642 if (IS_ERR(fc))
628 goto error; 643 goto error;
629 644
630 v9fs_put_int32(bufp, fid, &fc->params.twalk.fid); 645 p9_put_int32(bufp, fid, &fc->params.twalk.fid);
631 v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid); 646 p9_put_int32(bufp, newfid, &fc->params.twalk.newfid);
632 v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname); 647 p9_put_int16(bufp, nwname, &fc->params.twalk.nwname);
633 for (i = 0; i < nwname; i++) { 648 for (i = 0; i < nwname; i++) {
634 v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]); 649 p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
635 } 650 }
636 651
637 if (buf_check_overflow(bufp)) { 652 if (buf_check_overflow(bufp)) {
638 kfree(fc); 653 kfree(fc);
639 fc = ERR_PTR(-ENOMEM); 654 fc = ERR_PTR(-ENOMEM);
640 } 655 }
641 error: 656error:
642 return fc; 657 return fc;
643} 658}
659EXPORT_SYMBOL(p9_create_twalk);
644 660
645struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode) 661struct p9_fcall *p9_create_topen(u32 fid, u8 mode)
646{ 662{
647 int size; 663 int size;
648 struct v9fs_fcall *fc; 664 struct p9_fcall *fc;
649 struct cbuf buffer; 665 struct cbuf buffer;
650 struct cbuf *bufp = &buffer; 666 struct cbuf *bufp = &buffer;
651 667
652 size = 4 + 1; /* fid[4] mode[1] */ 668 size = 4 + 1; /* fid[4] mode[1] */
653 fc = v9fs_create_common(bufp, size, TOPEN); 669 fc = p9_create_common(bufp, size, P9_TOPEN);
654 if (IS_ERR(fc)) 670 if (IS_ERR(fc))
655 goto error; 671 goto error;
656 672
657 v9fs_put_int32(bufp, fid, &fc->params.topen.fid); 673 p9_put_int32(bufp, fid, &fc->params.topen.fid);
658 v9fs_put_int8(bufp, mode, &fc->params.topen.mode); 674 p9_put_int8(bufp, mode, &fc->params.topen.mode);
659 675
660 if (buf_check_overflow(bufp)) { 676 if (buf_check_overflow(bufp)) {
661 kfree(fc); 677 kfree(fc);
662 fc = ERR_PTR(-ENOMEM); 678 fc = ERR_PTR(-ENOMEM);
663 } 679 }
664 error: 680error:
665 return fc; 681 return fc;
666} 682}
683EXPORT_SYMBOL(p9_create_topen);
667 684
668struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, 685struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
669 char *extension, int extended) 686 char *extension, int dotu)
670{ 687{
671 int size; 688 int size;
672 struct v9fs_fcall *fc; 689 struct p9_fcall *fc;
673 struct cbuf buffer; 690 struct cbuf buffer;
674 struct cbuf *bufp = &buffer; 691 struct cbuf *bufp = &buffer;
675 692
676 size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ 693 /* fid[4] name[s] perm[4] mode[1] */
677 if (extended) { 694 size = 4 + 2 + strlen(name) + 4 + 1;
695 if (dotu) {
678 size += 2 + /* extension[s] */ 696 size += 2 + /* extension[s] */
679 (extension == NULL ? 0 : strlen(extension)); 697 (extension == NULL ? 0 : strlen(extension));
680 } 698 }
681 699
682 fc = v9fs_create_common(bufp, size, TCREATE); 700 fc = p9_create_common(bufp, size, P9_TCREATE);
683 if (IS_ERR(fc)) 701 if (IS_ERR(fc))
684 goto error; 702 goto error;
685 703
686 v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid); 704 p9_put_int32(bufp, fid, &fc->params.tcreate.fid);
687 v9fs_put_str(bufp, name, &fc->params.tcreate.name); 705 p9_put_str(bufp, name, &fc->params.tcreate.name);
688 v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm); 706 p9_put_int32(bufp, perm, &fc->params.tcreate.perm);
689 v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode); 707 p9_put_int8(bufp, mode, &fc->params.tcreate.mode);
690 if (extended) 708 if (dotu)
691 v9fs_put_str(bufp, extension, &fc->params.tcreate.extension); 709 p9_put_str(bufp, extension, &fc->params.tcreate.extension);
692 710
693 if (buf_check_overflow(bufp)) { 711 if (buf_check_overflow(bufp)) {
694 kfree(fc); 712 kfree(fc);
695 fc = ERR_PTR(-ENOMEM); 713 fc = ERR_PTR(-ENOMEM);
696 } 714 }
697 error: 715error:
698 return fc; 716 return fc;
699} 717}
718EXPORT_SYMBOL(p9_create_tcreate);
700 719
701struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count) 720struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count)
702{ 721{
703 int size; 722 int size;
704 struct v9fs_fcall *fc; 723 struct p9_fcall *fc;
705 struct cbuf buffer; 724 struct cbuf buffer;
706 struct cbuf *bufp = &buffer; 725 struct cbuf *bufp = &buffer;
707 726
708 size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */ 727 size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */
709 fc = v9fs_create_common(bufp, size, TREAD); 728 fc = p9_create_common(bufp, size, P9_TREAD);
729 if (IS_ERR(fc))
730 goto error;
731
732 p9_put_int32(bufp, fid, &fc->params.tread.fid);
733 p9_put_int64(bufp, offset, &fc->params.tread.offset);
734 p9_put_int32(bufp, count, &fc->params.tread.count);
735
736 if (buf_check_overflow(bufp)) {
737 kfree(fc);
738 fc = ERR_PTR(-ENOMEM);
739 }
740error:
741 return fc;
742}
743EXPORT_SYMBOL(p9_create_tread);
744
745struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
746 const char *data)
747{
748 int size, err;
749 struct p9_fcall *fc;
750 struct cbuf buffer;
751 struct cbuf *bufp = &buffer;
752
753 /* fid[4] offset[8] count[4] data[count] */
754 size = 4 + 8 + 4 + count;
755 fc = p9_create_common(bufp, size, P9_TWRITE);
710 if (IS_ERR(fc)) 756 if (IS_ERR(fc))
711 goto error; 757 goto error;
712 758
713 v9fs_put_int32(bufp, fid, &fc->params.tread.fid); 759 p9_put_int32(bufp, fid, &fc->params.twrite.fid);
714 v9fs_put_int64(bufp, offset, &fc->params.tread.offset); 760 p9_put_int64(bufp, offset, &fc->params.twrite.offset);
715 v9fs_put_int32(bufp, count, &fc->params.tread.count); 761 p9_put_int32(bufp, count, &fc->params.twrite.count);
762 err = p9_put_data(bufp, data, count, &fc->params.twrite.data);
763 if (err) {
764 kfree(fc);
765 fc = ERR_PTR(err);
766 }
716 767
717 if (buf_check_overflow(bufp)) { 768 if (buf_check_overflow(bufp)) {
718 kfree(fc); 769 kfree(fc);
719 fc = ERR_PTR(-ENOMEM); 770 fc = ERR_PTR(-ENOMEM);
720 } 771 }
721 error: 772error:
722 return fc; 773 return fc;
723} 774}
775EXPORT_SYMBOL(p9_create_twrite);
724 776
725struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count, 777struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
726 const char __user * data) 778 const char __user *data)
727{ 779{
728 int size, err; 780 int size, err;
729 struct v9fs_fcall *fc; 781 struct p9_fcall *fc;
730 struct cbuf buffer; 782 struct cbuf buffer;
731 struct cbuf *bufp = &buffer; 783 struct cbuf *bufp = &buffer;
732 784
733 size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */ 785 /* fid[4] offset[8] count[4] data[count] */
734 fc = v9fs_create_common(bufp, size, TWRITE); 786 size = 4 + 8 + 4 + count;
787 fc = p9_create_common(bufp, size, P9_TWRITE);
735 if (IS_ERR(fc)) 788 if (IS_ERR(fc))
736 goto error; 789 goto error;
737 790
738 v9fs_put_int32(bufp, fid, &fc->params.twrite.fid); 791 p9_put_int32(bufp, fid, &fc->params.twrite.fid);
739 v9fs_put_int64(bufp, offset, &fc->params.twrite.offset); 792 p9_put_int64(bufp, offset, &fc->params.twrite.offset);
740 v9fs_put_int32(bufp, count, &fc->params.twrite.count); 793 p9_put_int32(bufp, count, &fc->params.twrite.count);
741 err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data); 794 err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data);
742 if (err) { 795 if (err) {
743 kfree(fc); 796 kfree(fc);
744 fc = ERR_PTR(err); 797 fc = ERR_PTR(err);
@@ -748,98 +801,103 @@ struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
748 kfree(fc); 801 kfree(fc);
749 fc = ERR_PTR(-ENOMEM); 802 fc = ERR_PTR(-ENOMEM);
750 } 803 }
751 error: 804error:
752 return fc; 805 return fc;
753} 806}
807EXPORT_SYMBOL(p9_create_twrite_u);
754 808
755struct v9fs_fcall *v9fs_create_tclunk(u32 fid) 809struct p9_fcall *p9_create_tclunk(u32 fid)
756{ 810{
757 int size; 811 int size;
758 struct v9fs_fcall *fc; 812 struct p9_fcall *fc;
759 struct cbuf buffer; 813 struct cbuf buffer;
760 struct cbuf *bufp = &buffer; 814 struct cbuf *bufp = &buffer;
761 815
762 size = 4; /* fid[4] */ 816 size = 4; /* fid[4] */
763 fc = v9fs_create_common(bufp, size, TCLUNK); 817 fc = p9_create_common(bufp, size, P9_TCLUNK);
764 if (IS_ERR(fc)) 818 if (IS_ERR(fc))
765 goto error; 819 goto error;
766 820
767 v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid); 821 p9_put_int32(bufp, fid, &fc->params.tclunk.fid);
768 822
769 if (buf_check_overflow(bufp)) { 823 if (buf_check_overflow(bufp)) {
770 kfree(fc); 824 kfree(fc);
771 fc = ERR_PTR(-ENOMEM); 825 fc = ERR_PTR(-ENOMEM);
772 } 826 }
773 error: 827error:
774 return fc; 828 return fc;
775} 829}
830EXPORT_SYMBOL(p9_create_tclunk);
776 831
777struct v9fs_fcall *v9fs_create_tremove(u32 fid) 832struct p9_fcall *p9_create_tremove(u32 fid)
778{ 833{
779 int size; 834 int size;
780 struct v9fs_fcall *fc; 835 struct p9_fcall *fc;
781 struct cbuf buffer; 836 struct cbuf buffer;
782 struct cbuf *bufp = &buffer; 837 struct cbuf *bufp = &buffer;
783 838
784 size = 4; /* fid[4] */ 839 size = 4; /* fid[4] */
785 fc = v9fs_create_common(bufp, size, TREMOVE); 840 fc = p9_create_common(bufp, size, P9_TREMOVE);
786 if (IS_ERR(fc)) 841 if (IS_ERR(fc))
787 goto error; 842 goto error;
788 843
789 v9fs_put_int32(bufp, fid, &fc->params.tremove.fid); 844 p9_put_int32(bufp, fid, &fc->params.tremove.fid);
790 845
791 if (buf_check_overflow(bufp)) { 846 if (buf_check_overflow(bufp)) {
792 kfree(fc); 847 kfree(fc);
793 fc = ERR_PTR(-ENOMEM); 848 fc = ERR_PTR(-ENOMEM);
794 } 849 }
795 error: 850error:
796 return fc; 851 return fc;
797} 852}
853EXPORT_SYMBOL(p9_create_tremove);
798 854
799struct v9fs_fcall *v9fs_create_tstat(u32 fid) 855struct p9_fcall *p9_create_tstat(u32 fid)
800{ 856{
801 int size; 857 int size;
802 struct v9fs_fcall *fc; 858 struct p9_fcall *fc;
803 struct cbuf buffer; 859 struct cbuf buffer;
804 struct cbuf *bufp = &buffer; 860 struct cbuf *bufp = &buffer;
805 861
806 size = 4; /* fid[4] */ 862 size = 4; /* fid[4] */
807 fc = v9fs_create_common(bufp, size, TSTAT); 863 fc = p9_create_common(bufp, size, P9_TSTAT);
808 if (IS_ERR(fc)) 864 if (IS_ERR(fc))
809 goto error; 865 goto error;
810 866
811 v9fs_put_int32(bufp, fid, &fc->params.tstat.fid); 867 p9_put_int32(bufp, fid, &fc->params.tstat.fid);
812 868
813 if (buf_check_overflow(bufp)) { 869 if (buf_check_overflow(bufp)) {
814 kfree(fc); 870 kfree(fc);
815 fc = ERR_PTR(-ENOMEM); 871 fc = ERR_PTR(-ENOMEM);
816 } 872 }
817 error: 873error:
818 return fc; 874 return fc;
819} 875}
876EXPORT_SYMBOL(p9_create_tstat);
820 877
821struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat, 878struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
822 int extended) 879 int dotu)
823{ 880{
824 int size, statsz; 881 int size, statsz;
825 struct v9fs_fcall *fc; 882 struct p9_fcall *fc;
826 struct cbuf buffer; 883 struct cbuf buffer;
827 struct cbuf *bufp = &buffer; 884 struct cbuf *bufp = &buffer;
828 885
829 statsz = v9fs_size_wstat(wstat, extended); 886 statsz = p9_size_wstat(wstat, dotu);
830 size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */ 887 size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */
831 fc = v9fs_create_common(bufp, size, TWSTAT); 888 fc = p9_create_common(bufp, size, P9_TWSTAT);
832 if (IS_ERR(fc)) 889 if (IS_ERR(fc))
833 goto error; 890 goto error;
834 891
835 v9fs_put_int32(bufp, fid, &fc->params.twstat.fid); 892 p9_put_int32(bufp, fid, &fc->params.twstat.fid);
836 buf_put_int16(bufp, statsz + 2); 893 buf_put_int16(bufp, statsz + 2);
837 v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended); 894 p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu);
838 895
839 if (buf_check_overflow(bufp)) { 896 if (buf_check_overflow(bufp)) {
840 kfree(fc); 897 kfree(fc);
841 fc = ERR_PTR(-ENOMEM); 898 fc = ERR_PTR(-ENOMEM);
842 } 899 }
843 error: 900error:
844 return fc; 901 return fc;
845} 902}
903EXPORT_SYMBOL(p9_create_twstat);
diff --git a/fs/9p/error.h b/net/9p/error.c
index 5f3ca522b316..ab2458b6c903 100644
--- a/fs/9p/error.h
+++ b/net/9p/error.c
@@ -1,12 +1,11 @@
1/* 1/*
2 * linux/fs/9p/error.h 2 * linux/fs/9p/error.c
3 * 3 *
4 * Huge Nasty Error Table 4 * Error string handling
5 * 5 *
6 * Plan 9 uses error strings, Unix uses error numbers. This table tries to 6 * Plan 9 uses error strings, Unix uses error numbers. These functions
7 * match UNIX strings and Plan 9 strings to unix error numbers. It is used 7 * try to help manage that and provide for dynamically adding error
8 * to preload the dynamic error table which can also track user-specific error 8 * mappings.
9 * strings.
10 * 9 *
11 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 10 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
12 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 11 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
@@ -28,8 +27,11 @@
28 * 27 *
29 */ 28 */
30 29
30#include <linux/module.h>
31#include <linux/list.h>
32#include <linux/jhash.h>
31#include <linux/errno.h> 33#include <linux/errno.h>
32#include <asm/errno.h> 34#include <net/9p/9p.h>
33 35
34struct errormap { 36struct errormap {
35 char *name; 37 char *name;
@@ -174,4 +176,65 @@ static struct errormap errmap[] = {
174 {NULL, -1} 176 {NULL, -1}
175}; 177};
176 178
177extern int v9fs_error_init(void); 179/**
180 * p9_error_init - preload
181 * @errstr: error string
182 *
183 */
184
185int p9_error_init(void)
186{
187 struct errormap *c;
188 int bucket;
189
190 /* initialize hash table */
191 for (bucket = 0; bucket < ERRHASHSZ; bucket++)
192 INIT_HLIST_HEAD(&hash_errmap[bucket]);
193
194 /* load initial error map into hash table */
195 for (c = errmap; c->name != NULL; c++) {
196 c->namelen = strlen(c->name);
197 bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
198 INIT_HLIST_NODE(&c->list);
199 hlist_add_head(&c->list, &hash_errmap[bucket]);
200 }
201
202 return 1;
203}
204EXPORT_SYMBOL(p9_error_init);
205
206/**
207 * errstr2errno - convert error string to error number
208 * @errstr: error string
209 *
210 */
211
212int p9_errstr2errno(char *errstr, int len)
213{
214 int errno;
215 struct hlist_node *p;
216 struct errormap *c;
217 int bucket;
218
219 errno = 0;
220 p = NULL;
221 c = NULL;
222 bucket = jhash(errstr, len, 0) % ERRHASHSZ;
223 hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
224 if (c->namelen == len && !memcmp(c->name, errstr, len)) {
225 errno = c->val;
226 break;
227 }
228 }
229
230 if (errno == 0) {
231 /* TODO: if error isn't found, add it dynamically */
232 errstr[len] = 0;
233 printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
234 errstr);
235 errno = 1;
236 }
237
238 return -errno;
239}
240EXPORT_SYMBOL(p9_errstr2errno);
diff --git a/fs/9p/fcprint.c b/net/9p/fcprint.c
index 34b96114a28d..b1ae8ec57d54 100644
--- a/fs/9p/fcprint.c
+++ b/net/9p/fcprint.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/fs/9p/fcprint.c 2 * net/9p/fcprint.c
3 * 3 *
4 * Print 9P call. 4 * Print 9P call.
5 * 5 *
@@ -25,61 +25,59 @@
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/idr.h> 27#include <linux/idr.h>
28#include <net/9p/9p.h>
28 29
29#include "debug.h" 30#ifdef CONFIG_NET_9P_DEBUG
30#include "v9fs.h"
31#include "9p.h"
32#include "mux.h"
33 31
34static int 32static int
35v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q) 33p9_printqid(char *buf, int buflen, struct p9_qid *q)
36{ 34{
37 int n; 35 int n;
38 char b[10]; 36 char b[10];
39 37
40 n = 0; 38 n = 0;
41 if (q->type & V9FS_QTDIR) 39 if (q->type & P9_QTDIR)
42 b[n++] = 'd'; 40 b[n++] = 'd';
43 if (q->type & V9FS_QTAPPEND) 41 if (q->type & P9_QTAPPEND)
44 b[n++] = 'a'; 42 b[n++] = 'a';
45 if (q->type & V9FS_QTAUTH) 43 if (q->type & P9_QTAUTH)
46 b[n++] = 'A'; 44 b[n++] = 'A';
47 if (q->type & V9FS_QTEXCL) 45 if (q->type & P9_QTEXCL)
48 b[n++] = 'l'; 46 b[n++] = 'l';
49 if (q->type & V9FS_QTTMP) 47 if (q->type & P9_QTTMP)
50 b[n++] = 't'; 48 b[n++] = 't';
51 if (q->type & V9FS_QTSYMLINK) 49 if (q->type & P9_QTSYMLINK)
52 b[n++] = 'L'; 50 b[n++] = 'L';
53 b[n] = '\0'; 51 b[n] = '\0';
54 52
55 return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path, 53 return scnprintf(buf, buflen, "(%.16llx %x %s)",
56 q->version, b); 54 (long long int) q->path, q->version, b);
57} 55}
58 56
59static int 57static int
60v9fs_printperm(char *buf, int buflen, int perm) 58p9_printperm(char *buf, int buflen, int perm)
61{ 59{
62 int n; 60 int n;
63 char b[15]; 61 char b[15];
64 62
65 n = 0; 63 n = 0;
66 if (perm & V9FS_DMDIR) 64 if (perm & P9_DMDIR)
67 b[n++] = 'd'; 65 b[n++] = 'd';
68 if (perm & V9FS_DMAPPEND) 66 if (perm & P9_DMAPPEND)
69 b[n++] = 'a'; 67 b[n++] = 'a';
70 if (perm & V9FS_DMAUTH) 68 if (perm & P9_DMAUTH)
71 b[n++] = 'A'; 69 b[n++] = 'A';
72 if (perm & V9FS_DMEXCL) 70 if (perm & P9_DMEXCL)
73 b[n++] = 'l'; 71 b[n++] = 'l';
74 if (perm & V9FS_DMTMP) 72 if (perm & P9_DMTMP)
75 b[n++] = 't'; 73 b[n++] = 't';
76 if (perm & V9FS_DMDEVICE) 74 if (perm & P9_DMDEVICE)
77 b[n++] = 'D'; 75 b[n++] = 'D';
78 if (perm & V9FS_DMSOCKET) 76 if (perm & P9_DMSOCKET)
79 b[n++] = 'S'; 77 b[n++] = 'S';
80 if (perm & V9FS_DMNAMEDPIPE) 78 if (perm & P9_DMNAMEDPIPE)
81 b[n++] = 'P'; 79 b[n++] = 'P';
82 if (perm & V9FS_DMSYMLINK) 80 if (perm & P9_DMSYMLINK)
83 b[n++] = 'L'; 81 b[n++] = 'L';
84 b[n] = '\0'; 82 b[n] = '\0';
85 83
@@ -87,7 +85,7 @@ v9fs_printperm(char *buf, int buflen, int perm)
87} 85}
88 86
89static int 87static int
90v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended) 88p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended)
91{ 89{
92 int n; 90 int n;
93 91
@@ -105,9 +103,9 @@ v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
105 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid); 103 n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
106 104
107 n += scnprintf(buf+n, buflen-n, " q "); 105 n += scnprintf(buf+n, buflen-n, " q ");
108 n += v9fs_printqid(buf+n, buflen-n, &st->qid); 106 n += p9_printqid(buf+n, buflen-n, &st->qid);
109 n += scnprintf(buf+n, buflen-n, " m "); 107 n += scnprintf(buf+n, buflen-n, " m ");
110 n += v9fs_printperm(buf+n, buflen-n, st->mode); 108 n += p9_printperm(buf+n, buflen-n, st->mode);
111 n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld", 109 n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
112 st->atime, st->mtime, (long long int) st->length); 110 st->atime, st->mtime, (long long int) st->length);
113 111
@@ -119,7 +117,7 @@ v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
119} 117}
120 118
121static int 119static int
122v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen) 120p9_dumpdata(char *buf, int buflen, u8 *data, int datalen)
123{ 121{
124 int i, n; 122 int i, n;
125 123
@@ -139,13 +137,13 @@ v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
139} 137}
140 138
141static int 139static int
142v9fs_printdata(char *buf, int buflen, u8 *data, int datalen) 140p9_printdata(char *buf, int buflen, u8 *data, int datalen)
143{ 141{
144 return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16); 142 return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16);
145} 143}
146 144
147int 145int
148v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended) 146p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
149{ 147{
150 int i, ret, type, tag; 148 int i, ret, type, tag;
151 149
@@ -157,21 +155,23 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
157 155
158 ret = 0; 156 ret = 0;
159 switch (type) { 157 switch (type) {
160 case TVERSION: 158 case P9_TVERSION:
161 ret += scnprintf(buf+ret, buflen-ret, 159 ret += scnprintf(buf+ret, buflen-ret,
162 "Tversion tag %u msize %u version '%.*s'", tag, 160 "Tversion tag %u msize %u version '%.*s'", tag,
163 fc->params.tversion.msize, fc->params.tversion.version.len, 161 fc->params.tversion.msize,
164 fc->params.tversion.version.str); 162 fc->params.tversion.version.len,
163 fc->params.tversion.version.str);
165 break; 164 break;
166 165
167 case RVERSION: 166 case P9_RVERSION:
168 ret += scnprintf(buf+ret, buflen-ret, 167 ret += scnprintf(buf+ret, buflen-ret,
169 "Rversion tag %u msize %u version '%.*s'", tag, 168 "Rversion tag %u msize %u version '%.*s'", tag,
170 fc->params.rversion.msize, fc->params.rversion.version.len, 169 fc->params.rversion.msize,
171 fc->params.rversion.version.str); 170 fc->params.rversion.version.len,
171 fc->params.rversion.version.str);
172 break; 172 break;
173 173
174 case TAUTH: 174 case P9_TAUTH:
175 ret += scnprintf(buf+ret, buflen-ret, 175 ret += scnprintf(buf+ret, buflen-ret,
176 "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag, 176 "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
177 fc->params.tauth.afid, fc->params.tauth.uname.len, 177 fc->params.tauth.afid, fc->params.tauth.uname.len,
@@ -179,93 +179,97 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
179 fc->params.tauth.aname.str); 179 fc->params.tauth.aname.str);
180 break; 180 break;
181 181
182 case RAUTH: 182 case P9_RAUTH:
183 ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag); 183 ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
184 v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid); 184 p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
185 break; 185 break;
186 186
187 case TATTACH: 187 case P9_TATTACH:
188 ret += scnprintf(buf+ret, buflen-ret, 188 ret += scnprintf(buf+ret, buflen-ret,
189 "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", 189 "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag,
190 tag, fc->params.tattach.fid, fc->params.tattach.afid, 190 fc->params.tattach.fid, fc->params.tattach.afid,
191 fc->params.tattach.uname.len, fc->params.tattach.uname.str, 191 fc->params.tattach.uname.len, fc->params.tattach.uname.str,
192 fc->params.tattach.aname.len, fc->params.tattach.aname.str); 192 fc->params.tattach.aname.len, fc->params.tattach.aname.str);
193 break; 193 break;
194 194
195 case RATTACH: 195 case P9_RATTACH:
196 ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag); 196 ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ",
197 v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid); 197 tag);
198 p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
198 break; 199 break;
199 200
200 case RERROR: 201 case P9_RERROR:
201 ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'", 202 ret += scnprintf(buf+ret, buflen-ret,
202 tag, fc->params.rerror.error.len, 203 "Rerror tag %u ename '%.*s'", tag,
203 fc->params.rerror.error.str); 204 fc->params.rerror.error.len,
205 fc->params.rerror.error.str);
204 if (extended) 206 if (extended)
205 ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n", 207 ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
206 fc->params.rerror.errno); 208 fc->params.rerror.errno);
207 break; 209 break;
208 210
209 case TFLUSH: 211 case P9_TFLUSH:
210 ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u", 212 ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
211 tag, fc->params.tflush.oldtag); 213 tag, fc->params.tflush.oldtag);
212 break; 214 break;
213 215
214 case RFLUSH: 216 case P9_RFLUSH:
215 ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag); 217 ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
216 break; 218 break;
217 219
218 case TWALK: 220 case P9_TWALK:
219 ret += scnprintf(buf+ret, buflen-ret, 221 ret += scnprintf(buf+ret, buflen-ret,
220 "Twalk tag %u fid %d newfid %d nwname %d", tag, 222 "Twalk tag %u fid %d newfid %d nwname %d", tag,
221 fc->params.twalk.fid, fc->params.twalk.newfid, 223 fc->params.twalk.fid, fc->params.twalk.newfid,
222 fc->params.twalk.nwname); 224 fc->params.twalk.nwname);
223 for(i = 0; i < fc->params.twalk.nwname; i++) 225 for (i = 0; i < fc->params.twalk.nwname; i++)
224 ret += scnprintf(buf+ret, buflen-ret," '%.*s'", 226 ret += scnprintf(buf+ret, buflen-ret, " '%.*s'",
225 fc->params.twalk.wnames[i].len, 227 fc->params.twalk.wnames[i].len,
226 fc->params.twalk.wnames[i].str); 228 fc->params.twalk.wnames[i].str);
227 break; 229 break;
228 230
229 case RWALK: 231 case P9_RWALK:
230 ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d", 232 ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
231 tag, fc->params.rwalk.nwqid); 233 tag, fc->params.rwalk.nwqid);
232 for(i = 0; i < fc->params.rwalk.nwqid; i++) 234 for (i = 0; i < fc->params.rwalk.nwqid; i++)
233 ret += v9fs_printqid(buf+ret, buflen-ret, 235 ret += p9_printqid(buf+ret, buflen-ret,
234 &fc->params.rwalk.wqids[i]); 236 &fc->params.rwalk.wqids[i]);
235 break; 237 break;
236 238
237 case TOPEN: 239 case P9_TOPEN:
238 ret += scnprintf(buf+ret, buflen-ret, 240 ret += scnprintf(buf+ret, buflen-ret,
239 "Topen tag %u fid %d mode %d", tag, 241 "Topen tag %u fid %d mode %d", tag,
240 fc->params.topen.fid, fc->params.topen.mode); 242 fc->params.topen.fid, fc->params.topen.mode);
241 break; 243 break;
242 244
243 case ROPEN: 245 case P9_ROPEN:
244 ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag); 246 ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
245 ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid); 247 ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
246 ret += scnprintf(buf+ret, buflen-ret," iounit %d", 248 ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
247 fc->params.ropen.iounit); 249 fc->params.ropen.iounit);
248 break; 250 break;
249 251
250 case TCREATE: 252 case P9_TCREATE:
251 ret += scnprintf(buf+ret, buflen-ret, 253 ret += scnprintf(buf+ret, buflen-ret,
252 "Tcreate tag %u fid %d name '%.*s' perm ", tag, 254 "Tcreate tag %u fid %d name '%.*s' perm ", tag,
253 fc->params.tcreate.fid, fc->params.tcreate.name.len, 255 fc->params.tcreate.fid, fc->params.tcreate.name.len,
254 fc->params.tcreate.name.str); 256 fc->params.tcreate.name.str);
255 257
256 ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm); 258 ret += p9_printperm(buf+ret, buflen-ret,
259 fc->params.tcreate.perm);
257 ret += scnprintf(buf+ret, buflen-ret, " mode %d", 260 ret += scnprintf(buf+ret, buflen-ret, " mode %d",
258 fc->params.tcreate.mode); 261 fc->params.tcreate.mode);
259 break; 262 break;
260 263
261 case RCREATE: 264 case P9_RCREATE:
262 ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag); 265 ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
263 ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid); 266 ret += p9_printqid(buf+ret, buflen-ret,
267 &fc->params.rcreate.qid);
264 ret += scnprintf(buf+ret, buflen-ret, " iounit %d", 268 ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
265 fc->params.rcreate.iounit); 269 fc->params.rcreate.iounit);
266 break; 270 break;
267 271
268 case TREAD: 272 case P9_TREAD:
269 ret += scnprintf(buf+ret, buflen-ret, 273 ret += scnprintf(buf+ret, buflen-ret,
270 "Tread tag %u fid %d offset %lld count %u", tag, 274 "Tread tag %u fid %d offset %lld count %u", tag,
271 fc->params.tread.fid, 275 fc->params.tread.fid,
@@ -273,66 +277,66 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
273 fc->params.tread.count); 277 fc->params.tread.count);
274 break; 278 break;
275 279
276 case RREAD: 280 case P9_RREAD:
277 ret += scnprintf(buf+ret, buflen-ret, 281 ret += scnprintf(buf+ret, buflen-ret,
278 "Rread tag %u count %u data ", tag, 282 "Rread tag %u count %u data ", tag,
279 fc->params.rread.count); 283 fc->params.rread.count);
280 ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data, 284 ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data,
281 fc->params.rread.count); 285 fc->params.rread.count);
282 break; 286 break;
283 287
284 case TWRITE: 288 case P9_TWRITE:
285 ret += scnprintf(buf+ret, buflen-ret, 289 ret += scnprintf(buf+ret, buflen-ret,
286 "Twrite tag %u fid %d offset %lld count %u data ", 290 "Twrite tag %u fid %d offset %lld count %u data ",
287 tag, fc->params.twrite.fid, 291 tag, fc->params.twrite.fid,
288 (long long int) fc->params.twrite.offset, 292 (long long int) fc->params.twrite.offset,
289 fc->params.twrite.count); 293 fc->params.twrite.count);
290 ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data, 294 ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
291 fc->params.twrite.count); 295 fc->params.twrite.count);
292 break; 296 break;
293 297
294 case RWRITE: 298 case P9_RWRITE:
295 ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u", 299 ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
296 tag, fc->params.rwrite.count); 300 tag, fc->params.rwrite.count);
297 break; 301 break;
298 302
299 case TCLUNK: 303 case P9_TCLUNK:
300 ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d", 304 ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
301 tag, fc->params.tclunk.fid); 305 tag, fc->params.tclunk.fid);
302 break; 306 break;
303 307
304 case RCLUNK: 308 case P9_RCLUNK:
305 ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag); 309 ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
306 break; 310 break;
307 311
308 case TREMOVE: 312 case P9_TREMOVE:
309 ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d", 313 ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
310 tag, fc->params.tremove.fid); 314 tag, fc->params.tremove.fid);
311 break; 315 break;
312 316
313 case RREMOVE: 317 case P9_RREMOVE:
314 ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag); 318 ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
315 break; 319 break;
316 320
317 case TSTAT: 321 case P9_TSTAT:
318 ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d", 322 ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
319 tag, fc->params.tstat.fid); 323 tag, fc->params.tstat.fid);
320 break; 324 break;
321 325
322 case RSTAT: 326 case P9_RSTAT:
323 ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag); 327 ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
324 ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat, 328 ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
325 extended); 329 extended);
326 break; 330 break;
327 331
328 case TWSTAT: 332 case P9_TWSTAT:
329 ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ", 333 ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
330 tag, fc->params.twstat.fid); 334 tag, fc->params.twstat.fid);
331 ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat, 335 ret += p9_printstat(buf+ret, buflen-ret,
332 extended); 336 &fc->params.twstat.stat, extended);
333 break; 337 break;
334 338
335 case RWSTAT: 339 case P9_RWSTAT:
336 ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag); 340 ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
337 break; 341 break;
338 342
@@ -343,3 +347,12 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
343 347
344 return ret; 348 return ret;
345} 349}
350
351#else
352int
353p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
354{
355 return 0;
356}
357EXPORT_SYMBOL(p9_printfcall);
358#endif /* CONFIG_NET_9P_DEBUG */
diff --git a/net/9p/mod.c b/net/9p/mod.c
new file mode 100644
index 000000000000..4f9e1d2ac257
--- /dev/null
+++ b/net/9p/mod.c
@@ -0,0 +1,85 @@
1/*
2 * net/9p/9p.c
3 *
4 * 9P entry point
5 *
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <net/9p/9p.h>
30
31#ifdef CONFIG_NET_9P_DEBUG
32unsigned int p9_debug_level = 0; /* feature-rific global debug level */
33EXPORT_SYMBOL(p9_debug_level);
34module_param_named(debug, p9_debug_level, uint, 0);
35MODULE_PARM_DESC(debug, "9P debugging level");
36#endif
37
38extern int p9_mux_global_init(void);
39extern void p9_mux_global_exit(void);
40extern int p9_sysctl_register(void);
41extern void p9_sysctl_unregister(void);
42
43/**
44 * v9fs_init - Initialize module
45 *
46 */
47static int __init init_p9(void)
48{
49 int ret;
50
51 p9_error_init();
52 printk(KERN_INFO "Installing 9P2000 support\n");
53 ret = p9_mux_global_init();
54 if (ret) {
55 printk(KERN_WARNING "9p: starting mux failed\n");
56 return ret;
57 }
58
59 ret = p9_sysctl_register();
60 if (ret) {
61 printk(KERN_WARNING "9p: registering sysctl failed\n");
62 return ret;
63 }
64
65 return ret;
66}
67
68/**
69 * v9fs_init - shutdown module
70 *
71 */
72
73static void __exit exit_p9(void)
74{
75 p9_sysctl_unregister();
76 p9_mux_global_exit();
77}
78
79module_init(init_p9)
80module_exit(exit_p9)
81
82MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
83MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
84MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
85MODULE_LICENSE("GPL");
diff --git a/fs/9p/mux.c b/net/9p/mux.c
index c783874a9caf..acb038810f39 100644
--- a/fs/9p/mux.c
+++ b/net/9p/mux.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/fs/9p/mux.c 2 * net/9p/mux.c
3 * 3 *
4 * Protocol Multiplexer 4 * Protocol Multiplexer
5 * 5 *
@@ -30,13 +30,9 @@
30#include <linux/kthread.h> 30#include <linux/kthread.h>
31#include <linux/idr.h> 31#include <linux/idr.h>
32#include <linux/mutex.h> 32#include <linux/mutex.h>
33 33#include <net/9p/9p.h>
34#include "debug.h" 34#include <net/9p/transport.h>
35#include "v9fs.h" 35#include <net/9p/conn.h>
36#include "9p.h"
37#include "conv.h"
38#include "transport.h"
39#include "mux.h"
40 36
41#define ERREQFLUSH 1 37#define ERREQFLUSH 1
42#define SCHED_TIMEOUT 10 38#define SCHED_TIMEOUT 10
@@ -55,33 +51,33 @@ enum {
55 Flushed, 51 Flushed,
56}; 52};
57 53
58struct v9fs_mux_poll_task; 54struct p9_mux_poll_task;
59 55
60struct v9fs_req { 56struct p9_req {
61 spinlock_t lock; 57 spinlock_t lock; /* protect request structure */
62 int tag; 58 int tag;
63 struct v9fs_fcall *tcall; 59 struct p9_fcall *tcall;
64 struct v9fs_fcall *rcall; 60 struct p9_fcall *rcall;
65 int err; 61 int err;
66 v9fs_mux_req_callback cb; 62 p9_conn_req_callback cb;
67 void *cba; 63 void *cba;
68 int flush; 64 int flush;
69 struct list_head req_list; 65 struct list_head req_list;
70}; 66};
71 67
72struct v9fs_mux_data { 68struct p9_conn {
73 spinlock_t lock; 69 spinlock_t lock; /* protect lock structure */
74 struct list_head mux_list; 70 struct list_head mux_list;
75 struct v9fs_mux_poll_task *poll_task; 71 struct p9_mux_poll_task *poll_task;
76 int msize; 72 int msize;
77 unsigned char *extended; 73 unsigned char *extended;
78 struct v9fs_transport *trans; 74 struct p9_transport *trans;
79 struct v9fs_idpool tagpool; 75 struct p9_idpool *tagpool;
80 int err; 76 int err;
81 wait_queue_head_t equeue; 77 wait_queue_head_t equeue;
82 struct list_head req_list; 78 struct list_head req_list;
83 struct list_head unsent_req_list; 79 struct list_head unsent_req_list;
84 struct v9fs_fcall *rcall; 80 struct p9_fcall *rcall;
85 int rpos; 81 int rpos;
86 char *rbuf; 82 char *rbuf;
87 int wpos; 83 int wpos;
@@ -95,44 +91,44 @@ struct v9fs_mux_data {
95 unsigned long wsched; 91 unsigned long wsched;
96}; 92};
97 93
98struct v9fs_mux_poll_task { 94struct p9_mux_poll_task {
99 struct task_struct *task; 95 struct task_struct *task;
100 struct list_head mux_list; 96 struct list_head mux_list;
101 int muxnum; 97 int muxnum;
102}; 98};
103 99
104struct v9fs_mux_rpc { 100struct p9_mux_rpc {
105 struct v9fs_mux_data *m; 101 struct p9_conn *m;
106 int err; 102 int err;
107 struct v9fs_fcall *tcall; 103 struct p9_fcall *tcall;
108 struct v9fs_fcall *rcall; 104 struct p9_fcall *rcall;
109 wait_queue_head_t wqueue; 105 wait_queue_head_t wqueue;
110}; 106};
111 107
112static int v9fs_poll_proc(void *); 108static int p9_poll_proc(void *);
113static void v9fs_read_work(struct work_struct *work); 109static void p9_read_work(struct work_struct *work);
114static void v9fs_write_work(struct work_struct *work); 110static void p9_write_work(struct work_struct *work);
115static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, 111static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
116 poll_table * p); 112 poll_table * p);
117static u16 v9fs_mux_get_tag(struct v9fs_mux_data *); 113static u16 p9_mux_get_tag(struct p9_conn *);
118static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16); 114static void p9_mux_put_tag(struct p9_conn *, u16);
119 115
120static DEFINE_MUTEX(v9fs_mux_task_lock); 116static DEFINE_MUTEX(p9_mux_task_lock);
121static struct workqueue_struct *v9fs_mux_wq; 117static struct workqueue_struct *p9_mux_wq;
122 118
123static int v9fs_mux_num; 119static int p9_mux_num;
124static int v9fs_mux_poll_task_num; 120static int p9_mux_poll_task_num;
125static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100]; 121static struct p9_mux_poll_task p9_mux_poll_tasks[100];
126 122
127int v9fs_mux_global_init(void) 123int p9_mux_global_init(void)
128{ 124{
129 int i; 125 int i;
130 126
131 for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) 127 for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++)
132 v9fs_mux_poll_tasks[i].task = NULL; 128 p9_mux_poll_tasks[i].task = NULL;
133 129
134 v9fs_mux_wq = create_workqueue("v9fs"); 130 p9_mux_wq = create_workqueue("v9fs");
135 if (!v9fs_mux_wq) { 131 if (!p9_mux_wq) {
136 printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); 132 printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
137 return -ENOMEM; 133 return -ENOMEM;
138 } 134 }
@@ -140,114 +136,117 @@ int v9fs_mux_global_init(void)
140 return 0; 136 return 0;
141} 137}
142 138
143void v9fs_mux_global_exit(void) 139void p9_mux_global_exit(void)
144{ 140{
145 destroy_workqueue(v9fs_mux_wq); 141 destroy_workqueue(p9_mux_wq);
146} 142}
147 143
148/** 144/**
149 * v9fs_mux_calc_poll_procs - calculates the number of polling procs 145 * p9_mux_calc_poll_procs - calculates the number of polling procs
150 * based on the number of mounted v9fs filesystems. 146 * based on the number of mounted v9fs filesystems.
151 * 147 *
152 * The current implementation returns sqrt of the number of mounts. 148 * The current implementation returns sqrt of the number of mounts.
153 */ 149 */
154static int v9fs_mux_calc_poll_procs(int muxnum) 150static int p9_mux_calc_poll_procs(int muxnum)
155{ 151{
156 int n; 152 int n;
157 153
158 if (v9fs_mux_poll_task_num) 154 if (p9_mux_poll_task_num)
159 n = muxnum / v9fs_mux_poll_task_num + 155 n = muxnum / p9_mux_poll_task_num +
160 (muxnum % v9fs_mux_poll_task_num ? 1 : 0); 156 (muxnum % p9_mux_poll_task_num ? 1 : 0);
161 else 157 else
162 n = 1; 158 n = 1;
163 159
164 if (n > ARRAY_SIZE(v9fs_mux_poll_tasks)) 160 if (n > ARRAY_SIZE(p9_mux_poll_tasks))
165 n = ARRAY_SIZE(v9fs_mux_poll_tasks); 161 n = ARRAY_SIZE(p9_mux_poll_tasks);
166 162
167 return n; 163 return n;
168} 164}
169 165
170static int v9fs_mux_poll_start(struct v9fs_mux_data *m) 166static int p9_mux_poll_start(struct p9_conn *m)
171{ 167{
172 int i, n; 168 int i, n;
173 struct v9fs_mux_poll_task *vpt, *vptlast; 169 struct p9_mux_poll_task *vpt, *vptlast;
174 struct task_struct *pproc; 170 struct task_struct *pproc;
175 171
176 dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num, 172 P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num,
177 v9fs_mux_poll_task_num); 173 p9_mux_poll_task_num);
178 mutex_lock(&v9fs_mux_task_lock); 174 mutex_lock(&p9_mux_task_lock);
179 175
180 n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1); 176 n = p9_mux_calc_poll_procs(p9_mux_num + 1);
181 if (n > v9fs_mux_poll_task_num) { 177 if (n > p9_mux_poll_task_num) {
182 for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { 178 for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
183 if (v9fs_mux_poll_tasks[i].task == NULL) { 179 if (p9_mux_poll_tasks[i].task == NULL) {
184 vpt = &v9fs_mux_poll_tasks[i]; 180 vpt = &p9_mux_poll_tasks[i];
185 dprintk(DEBUG_MUX, "create proc %p\n", vpt); 181 P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n",
186 pproc = kthread_create(v9fs_poll_proc, vpt, 182 vpt);
187 "v9fs-poll"); 183 pproc = kthread_create(p9_poll_proc, vpt,
184 "v9fs-poll");
188 185
189 if (!IS_ERR(pproc)) { 186 if (!IS_ERR(pproc)) {
190 vpt->task = pproc; 187 vpt->task = pproc;
191 INIT_LIST_HEAD(&vpt->mux_list); 188 INIT_LIST_HEAD(&vpt->mux_list);
192 vpt->muxnum = 0; 189 vpt->muxnum = 0;
193 v9fs_mux_poll_task_num++; 190 p9_mux_poll_task_num++;
194 wake_up_process(vpt->task); 191 wake_up_process(vpt->task);
195 } 192 }
196 break; 193 break;
197 } 194 }
198 } 195 }
199 196
200 if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) 197 if (i >= ARRAY_SIZE(p9_mux_poll_tasks))
201 dprintk(DEBUG_ERROR, "warning: no free poll slots\n"); 198 P9_DPRINTK(P9_DEBUG_ERROR,
199 "warning: no free poll slots\n");
202 } 200 }
203 201
204 n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num + 202 n = (p9_mux_num + 1) / p9_mux_poll_task_num +
205 ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0); 203 ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0);
206 204
207 vptlast = NULL; 205 vptlast = NULL;
208 for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) { 206 for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
209 vpt = &v9fs_mux_poll_tasks[i]; 207 vpt = &p9_mux_poll_tasks[i];
210 if (vpt->task != NULL) { 208 if (vpt->task != NULL) {
211 vptlast = vpt; 209 vptlast = vpt;
212 if (vpt->muxnum < n) { 210 if (vpt->muxnum < n) {
213 dprintk(DEBUG_MUX, "put in proc %d\n", i); 211 P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
214 list_add(&m->mux_list, &vpt->mux_list); 212 list_add(&m->mux_list, &vpt->mux_list);
215 vpt->muxnum++; 213 vpt->muxnum++;
216 m->poll_task = vpt; 214 m->poll_task = vpt;
217 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 215 memset(&m->poll_waddr, 0,
218 init_poll_funcptr(&m->pt, v9fs_pollwait); 216 sizeof(m->poll_waddr));
217 init_poll_funcptr(&m->pt, p9_pollwait);
219 break; 218 break;
220 } 219 }
221 } 220 }
222 } 221 }
223 222
224 if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) { 223 if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) {
225 if (vptlast == NULL) 224 if (vptlast == NULL)
226 return -ENOMEM; 225 return -ENOMEM;
227 226
228 dprintk(DEBUG_MUX, "put in proc %d\n", i); 227 P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
229 list_add(&m->mux_list, &vptlast->mux_list); 228 list_add(&m->mux_list, &vptlast->mux_list);
230 vptlast->muxnum++; 229 vptlast->muxnum++;
231 m->poll_task = vptlast; 230 m->poll_task = vptlast;
232 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 231 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
233 init_poll_funcptr(&m->pt, v9fs_pollwait); 232 init_poll_funcptr(&m->pt, p9_pollwait);
234 } 233 }
235 234
236 v9fs_mux_num++; 235 p9_mux_num++;
237 mutex_unlock(&v9fs_mux_task_lock); 236 mutex_unlock(&p9_mux_task_lock);
238 237
239 return 0; 238 return 0;
240} 239}
241 240
242static void v9fs_mux_poll_stop(struct v9fs_mux_data *m) 241static void p9_mux_poll_stop(struct p9_conn *m)
243{ 242{
244 int i; 243 int i;
245 struct v9fs_mux_poll_task *vpt; 244 struct p9_mux_poll_task *vpt;
246 245
247 mutex_lock(&v9fs_mux_task_lock); 246 mutex_lock(&p9_mux_task_lock);
248 vpt = m->poll_task; 247 vpt = m->poll_task;
249 list_del(&m->mux_list); 248 list_del(&m->mux_list);
250 for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 249 for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
251 if (m->poll_waddr[i] != NULL) { 250 if (m->poll_waddr[i] != NULL) {
252 remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]); 251 remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]);
253 m->poll_waddr[i] = NULL; 252 m->poll_waddr[i] = NULL;
@@ -255,31 +254,31 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
255 } 254 }
256 vpt->muxnum--; 255 vpt->muxnum--;
257 if (!vpt->muxnum) { 256 if (!vpt->muxnum) {
258 dprintk(DEBUG_MUX, "destroy proc %p\n", vpt); 257 P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt);
259 kthread_stop(vpt->task); 258 kthread_stop(vpt->task);
260 vpt->task = NULL; 259 vpt->task = NULL;
261 v9fs_mux_poll_task_num--; 260 p9_mux_poll_task_num--;
262 } 261 }
263 v9fs_mux_num--; 262 p9_mux_num--;
264 mutex_unlock(&v9fs_mux_task_lock); 263 mutex_unlock(&p9_mux_task_lock);
265} 264}
266 265
267/** 266/**
268 * v9fs_mux_init - allocate and initialize the per-session mux data 267 * p9_conn_create - allocate and initialize the per-session mux data
269 * Creates the polling task if this is the first session. 268 * Creates the polling task if this is the first session.
270 * 269 *
271 * @trans - transport structure 270 * @trans - transport structure
272 * @msize - maximum message size 271 * @msize - maximum message size
273 * @extended - pointer to the extended flag 272 * @extended - pointer to the extended flag
274 */ 273 */
275struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, 274struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
276 unsigned char *extended) 275 unsigned char *extended)
277{ 276{
278 int i, n; 277 int i, n;
279 struct v9fs_mux_data *m, *mtmp; 278 struct p9_conn *m, *mtmp;
280 279
281 dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize); 280 P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize);
282 m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL); 281 m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL);
283 if (!m) 282 if (!m)
284 return ERR_PTR(-ENOMEM); 283 return ERR_PTR(-ENOMEM);
285 284
@@ -288,8 +287,12 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
288 m->msize = msize; 287 m->msize = msize;
289 m->extended = extended; 288 m->extended = extended;
290 m->trans = trans; 289 m->trans = trans;
291 idr_init(&m->tagpool.pool); 290 m->tagpool = p9_idpool_create();
292 init_MUTEX(&m->tagpool.lock); 291 if (!m->tagpool) {
292 kfree(m);
293 return ERR_PTR(PTR_ERR(m->tagpool));
294 }
295
293 m->err = 0; 296 m->err = 0;
294 init_waitqueue_head(&m->equeue); 297 init_waitqueue_head(&m->equeue);
295 INIT_LIST_HEAD(&m->req_list); 298 INIT_LIST_HEAD(&m->req_list);
@@ -299,29 +302,29 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
299 m->rbuf = NULL; 302 m->rbuf = NULL;
300 m->wpos = m->wsize = 0; 303 m->wpos = m->wsize = 0;
301 m->wbuf = NULL; 304 m->wbuf = NULL;
302 INIT_WORK(&m->rq, v9fs_read_work); 305 INIT_WORK(&m->rq, p9_read_work);
303 INIT_WORK(&m->wq, v9fs_write_work); 306 INIT_WORK(&m->wq, p9_write_work);
304 m->wsched = 0; 307 m->wsched = 0;
305 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); 308 memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
306 m->poll_task = NULL; 309 m->poll_task = NULL;
307 n = v9fs_mux_poll_start(m); 310 n = p9_mux_poll_start(m);
308 if (n) 311 if (n)
309 return ERR_PTR(n); 312 return ERR_PTR(n);
310 313
311 n = trans->poll(trans, &m->pt); 314 n = trans->poll(trans, &m->pt);
312 if (n & POLLIN) { 315 if (n & POLLIN) {
313 dprintk(DEBUG_MUX, "mux %p can read\n", m); 316 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
314 set_bit(Rpending, &m->wsched); 317 set_bit(Rpending, &m->wsched);
315 } 318 }
316 319
317 if (n & POLLOUT) { 320 if (n & POLLOUT) {
318 dprintk(DEBUG_MUX, "mux %p can write\n", m); 321 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
319 set_bit(Wpending, &m->wsched); 322 set_bit(Wpending, &m->wsched);
320 } 323 }
321 324
322 for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { 325 for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
323 if (IS_ERR(m->poll_waddr[i])) { 326 if (IS_ERR(m->poll_waddr[i])) {
324 v9fs_mux_poll_stop(m); 327 p9_mux_poll_stop(m);
325 mtmp = (void *)m->poll_waddr; /* the error code */ 328 mtmp = (void *)m->poll_waddr; /* the error code */
326 kfree(m); 329 kfree(m);
327 m = mtmp; 330 m = mtmp;
@@ -331,56 +334,58 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
331 334
332 return m; 335 return m;
333} 336}
337EXPORT_SYMBOL(p9_conn_create);
334 338
335/** 339/**
336 * v9fs_mux_destroy - cancels all pending requests and frees mux resources 340 * p9_mux_destroy - cancels all pending requests and frees mux resources
337 */ 341 */
338void v9fs_mux_destroy(struct v9fs_mux_data *m) 342void p9_conn_destroy(struct p9_conn *m)
339{ 343{
340 dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m, 344 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
341 m->mux_list.prev, m->mux_list.next); 345 m->mux_list.prev, m->mux_list.next);
342 v9fs_mux_cancel(m, -ECONNRESET); 346 p9_conn_cancel(m, -ECONNRESET);
343 347
344 if (!list_empty(&m->req_list)) { 348 if (!list_empty(&m->req_list)) {
345 /* wait until all processes waiting on this session exit */ 349 /* wait until all processes waiting on this session exit */
346 dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n", 350 P9_DPRINTK(P9_DEBUG_MUX,
347 m); 351 "mux %p waiting for empty request queue\n", m);
348 wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); 352 wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000);
349 dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m, 353 P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m,
350 list_empty(&m->req_list)); 354 list_empty(&m->req_list));
351 } 355 }
352 356
353 v9fs_mux_poll_stop(m); 357 p9_mux_poll_stop(m);
354 m->trans = NULL; 358 m->trans = NULL;
355 359 p9_idpool_destroy(m->tagpool);
356 kfree(m); 360 kfree(m);
357} 361}
362EXPORT_SYMBOL(p9_conn_destroy);
358 363
359/** 364/**
360 * v9fs_pollwait - called by files poll operation to add v9fs-poll task 365 * p9_pollwait - called by files poll operation to add v9fs-poll task
361 * to files wait queue 366 * to files wait queue
362 */ 367 */
363static void 368static void
364v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address, 369p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
365 poll_table * p) 370 poll_table * p)
366{ 371{
367 int i; 372 int i;
368 struct v9fs_mux_data *m; 373 struct p9_conn *m;
369 374
370 m = container_of(p, struct v9fs_mux_data, pt); 375 m = container_of(p, struct p9_conn, pt);
371 for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) 376 for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
372 if (m->poll_waddr[i] == NULL) 377 if (m->poll_waddr[i] == NULL)
373 break; 378 break;
374 379
375 if (i >= ARRAY_SIZE(m->poll_waddr)) { 380 if (i >= ARRAY_SIZE(m->poll_waddr)) {
376 dprintk(DEBUG_ERROR, "not enough wait_address slots\n"); 381 P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
377 return; 382 return;
378 } 383 }
379 384
380 m->poll_waddr[i] = wait_address; 385 m->poll_waddr[i] = wait_address;
381 386
382 if (!wait_address) { 387 if (!wait_address) {
383 dprintk(DEBUG_ERROR, "no wait_address\n"); 388 P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
384 m->poll_waddr[i] = ERR_PTR(-EIO); 389 m->poll_waddr[i] = ERR_PTR(-EIO);
385 return; 390 return;
386 } 391 }
@@ -390,9 +395,9 @@ v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
390} 395}
391 396
392/** 397/**
393 * v9fs_poll_mux - polls a mux and schedules read or write works if necessary 398 * p9_poll_mux - polls a mux and schedules read or write works if necessary
394 */ 399 */
395static void v9fs_poll_mux(struct v9fs_mux_data *m) 400static void p9_poll_mux(struct p9_conn *m)
396{ 401{
397 int n; 402 int n;
398 403
@@ -401,69 +406,69 @@ static void v9fs_poll_mux(struct v9fs_mux_data *m)
401 406
402 n = m->trans->poll(m->trans, NULL); 407 n = m->trans->poll(m->trans, NULL);
403 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { 408 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
404 dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n); 409 P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
405 if (n >= 0) 410 if (n >= 0)
406 n = -ECONNRESET; 411 n = -ECONNRESET;
407 v9fs_mux_cancel(m, n); 412 p9_conn_cancel(m, n);
408 } 413 }
409 414
410 if (n & POLLIN) { 415 if (n & POLLIN) {
411 set_bit(Rpending, &m->wsched); 416 set_bit(Rpending, &m->wsched);
412 dprintk(DEBUG_MUX, "mux %p can read\n", m); 417 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
413 if (!test_and_set_bit(Rworksched, &m->wsched)) { 418 if (!test_and_set_bit(Rworksched, &m->wsched)) {
414 dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); 419 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
415 queue_work(v9fs_mux_wq, &m->rq); 420 queue_work(p9_mux_wq, &m->rq);
416 } 421 }
417 } 422 }
418 423
419 if (n & POLLOUT) { 424 if (n & POLLOUT) {
420 set_bit(Wpending, &m->wsched); 425 set_bit(Wpending, &m->wsched);
421 dprintk(DEBUG_MUX, "mux %p can write\n", m); 426 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
422 if ((m->wsize || !list_empty(&m->unsent_req_list)) 427 if ((m->wsize || !list_empty(&m->unsent_req_list))
423 && !test_and_set_bit(Wworksched, &m->wsched)) { 428 && !test_and_set_bit(Wworksched, &m->wsched)) {
424 dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); 429 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
425 queue_work(v9fs_mux_wq, &m->wq); 430 queue_work(p9_mux_wq, &m->wq);
426 } 431 }
427 } 432 }
428} 433}
429 434
430/** 435/**
431 * v9fs_poll_proc - polls all v9fs transports for new events and queues 436 * p9_poll_proc - polls all v9fs transports for new events and queues
432 * the appropriate work to the work queue 437 * the appropriate work to the work queue
433 */ 438 */
434static int v9fs_poll_proc(void *a) 439static int p9_poll_proc(void *a)
435{ 440{
436 struct v9fs_mux_data *m, *mtmp; 441 struct p9_conn *m, *mtmp;
437 struct v9fs_mux_poll_task *vpt; 442 struct p9_mux_poll_task *vpt;
438 443
439 vpt = a; 444 vpt = a;
440 dprintk(DEBUG_MUX, "start %p %p\n", current, vpt); 445 P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt);
441 while (!kthread_should_stop()) { 446 while (!kthread_should_stop()) {
442 set_current_state(TASK_INTERRUPTIBLE); 447 set_current_state(TASK_INTERRUPTIBLE);
443 448
444 list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) { 449 list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
445 v9fs_poll_mux(m); 450 p9_poll_mux(m);
446 } 451 }
447 452
448 dprintk(DEBUG_MUX, "sleeping...\n"); 453 P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
449 schedule_timeout(SCHED_TIMEOUT * HZ); 454 schedule_timeout(SCHED_TIMEOUT * HZ);
450 } 455 }
451 456
452 __set_current_state(TASK_RUNNING); 457 __set_current_state(TASK_RUNNING);
453 dprintk(DEBUG_MUX, "finish\n"); 458 P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
454 return 0; 459 return 0;
455} 460}
456 461
457/** 462/**
458 * v9fs_write_work - called when a transport can send some data 463 * p9_write_work - called when a transport can send some data
459 */ 464 */
460static void v9fs_write_work(struct work_struct *work) 465static void p9_write_work(struct work_struct *work)
461{ 466{
462 int n, err; 467 int n, err;
463 struct v9fs_mux_data *m; 468 struct p9_conn *m;
464 struct v9fs_req *req; 469 struct p9_req *req;
465 470
466 m = container_of(work, struct v9fs_mux_data, wq); 471 m = container_of(work, struct p9_conn, wq);
467 472
468 if (m->err < 0) { 473 if (m->err < 0) {
469 clear_bit(Wworksched, &m->wsched); 474 clear_bit(Wworksched, &m->wsched);
@@ -478,7 +483,7 @@ static void v9fs_write_work(struct work_struct *work)
478 483
479 spin_lock(&m->lock); 484 spin_lock(&m->lock);
480again: 485again:
481 req = list_entry(m->unsent_req_list.next, struct v9fs_req, 486 req = list_entry(m->unsent_req_list.next, struct p9_req,
482 req_list); 487 req_list);
483 list_move_tail(&req->req_list, &m->req_list); 488 list_move_tail(&req->req_list, &m->req_list);
484 if (req->err == ERREQFLUSH) 489 if (req->err == ERREQFLUSH)
@@ -487,21 +492,25 @@ again:
487 m->wbuf = req->tcall->sdata; 492 m->wbuf = req->tcall->sdata;
488 m->wsize = req->tcall->size; 493 m->wsize = req->tcall->size;
489 m->wpos = 0; 494 m->wpos = 0;
490 dump_data(m->wbuf, m->wsize);
491 spin_unlock(&m->lock); 495 spin_unlock(&m->lock);
492 } 496 }
493 497
494 dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize); 498 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
499 m->wsize);
495 clear_bit(Wpending, &m->wsched); 500 clear_bit(Wpending, &m->wsched);
496 err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); 501 err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos);
497 dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err); 502 P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
498 if (err == -EAGAIN) { 503 if (err == -EAGAIN) {
499 clear_bit(Wworksched, &m->wsched); 504 clear_bit(Wworksched, &m->wsched);
500 return; 505 return;
501 } 506 }
502 507
503 if (err <= 0) 508 if (err < 0)
509 goto error;
510 else if (err == 0) {
511 err = -EREMOTEIO;
504 goto error; 512 goto error;
513 }
505 514
506 m->wpos += err; 515 m->wpos += err;
507 if (m->wpos == m->wsize) 516 if (m->wpos == m->wsize)
@@ -514,8 +523,8 @@ again:
514 n = m->trans->poll(m->trans, NULL); 523 n = m->trans->poll(m->trans, NULL);
515 524
516 if (n & POLLOUT) { 525 if (n & POLLOUT) {
517 dprintk(DEBUG_MUX, "schedule write work mux %p\n", m); 526 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
518 queue_work(v9fs_mux_wq, &m->wq); 527 queue_work(p9_mux_wq, &m->wq);
519 } else 528 } else
520 clear_bit(Wworksched, &m->wsched); 529 clear_bit(Wworksched, &m->wsched);
521 } else 530 } else
@@ -523,27 +532,28 @@ again:
523 532
524 return; 533 return;
525 534
526 error: 535error:
527 v9fs_mux_cancel(m, err); 536 p9_conn_cancel(m, err);
528 clear_bit(Wworksched, &m->wsched); 537 clear_bit(Wworksched, &m->wsched);
529} 538}
530 539
531static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req) 540static void process_request(struct p9_conn *m, struct p9_req *req)
532{ 541{
533 int ecode; 542 int ecode;
534 struct v9fs_str *ename; 543 struct p9_str *ename;
535 544
536 if (!req->err && req->rcall->id == RERROR) { 545 if (!req->err && req->rcall->id == P9_RERROR) {
537 ecode = req->rcall->params.rerror.errno; 546 ecode = req->rcall->params.rerror.errno;
538 ename = &req->rcall->params.rerror.error; 547 ename = &req->rcall->params.rerror.error;
539 548
540 dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str); 549 P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
550 ename->str);
541 551
542 if (*m->extended) 552 if (*m->extended)
543 req->err = -ecode; 553 req->err = -ecode;
544 554
545 if (!req->err) { 555 if (!req->err) {
546 req->err = v9fs_errstr2errno(ename->str, ename->len); 556 req->err = p9_errstr2errno(ename->str, ename->len);
547 557
548 if (!req->err) { /* string match failed */ 558 if (!req->err) { /* string match failed */
549 PRINT_FCALL_ERROR("unknown error", req->rcall); 559 PRINT_FCALL_ERROR("unknown error", req->rcall);
@@ -553,47 +563,48 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
553 req->err = -ESERVERFAULT; 563 req->err = -ESERVERFAULT;
554 } 564 }
555 } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { 565 } else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
556 dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n", 566 P9_DPRINTK(P9_DEBUG_ERROR,
557 req->tcall->id + 1, req->rcall->id); 567 "fcall mismatch: expected %d, got %d\n",
568 req->tcall->id + 1, req->rcall->id);
558 if (!req->err) 569 if (!req->err)
559 req->err = -EIO; 570 req->err = -EIO;
560 } 571 }
561} 572}
562 573
563/** 574/**
564 * v9fs_read_work - called when there is some data to be read from a transport 575 * p9_read_work - called when there is some data to be read from a transport
565 */ 576 */
566static void v9fs_read_work(struct work_struct *work) 577static void p9_read_work(struct work_struct *work)
567{ 578{
568 int n, err; 579 int n, err;
569 struct v9fs_mux_data *m; 580 struct p9_conn *m;
570 struct v9fs_req *req, *rptr, *rreq; 581 struct p9_req *req, *rptr, *rreq;
571 struct v9fs_fcall *rcall; 582 struct p9_fcall *rcall;
572 char *rbuf; 583 char *rbuf;
573 584
574 m = container_of(work, struct v9fs_mux_data, rq); 585 m = container_of(work, struct p9_conn, rq);
575 586
576 if (m->err < 0) 587 if (m->err < 0)
577 return; 588 return;
578 589
579 rcall = NULL; 590 rcall = NULL;
580 dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); 591 P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
581 592
582 if (!m->rcall) { 593 if (!m->rcall) {
583 m->rcall = 594 m->rcall =
584 kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL); 595 kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL);
585 if (!m->rcall) { 596 if (!m->rcall) {
586 err = -ENOMEM; 597 err = -ENOMEM;
587 goto error; 598 goto error;
588 } 599 }
589 600
590 m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); 601 m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
591 m->rpos = 0; 602 m->rpos = 0;
592 } 603 }
593 604
594 clear_bit(Rpending, &m->wsched); 605 clear_bit(Rpending, &m->wsched);
595 err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); 606 err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
596 dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err); 607 P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
597 if (err == -EAGAIN) { 608 if (err == -EAGAIN) {
598 clear_bit(Rworksched, &m->wsched); 609 clear_bit(Rworksched, &m->wsched);
599 return; 610 return;
@@ -606,7 +617,7 @@ static void v9fs_read_work(struct work_struct *work)
606 while (m->rpos > 4) { 617 while (m->rpos > 4) {
607 n = le32_to_cpu(*(__le32 *) m->rbuf); 618 n = le32_to_cpu(*(__le32 *) m->rbuf);
608 if (n >= m->msize) { 619 if (n >= m->msize) {
609 dprintk(DEBUG_ERROR, 620 P9_DPRINTK(P9_DEBUG_ERROR,
610 "requested packet size too big: %d\n", n); 621 "requested packet size too big: %d\n", n);
611 err = -EIO; 622 err = -EIO;
612 goto error; 623 goto error;
@@ -615,32 +626,33 @@ static void v9fs_read_work(struct work_struct *work)
615 if (m->rpos < n) 626 if (m->rpos < n)
616 break; 627 break;
617 628
618 dump_data(m->rbuf, n);
619 err = 629 err =
620 v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended); 630 p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
621 if (err < 0) { 631 if (err < 0) {
622 goto error; 632 goto error;
623 } 633 }
624 634
625 if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { 635#ifdef CONFIG_NET_9P_DEBUG
636 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
626 char buf[150]; 637 char buf[150];
627 638
628 v9fs_printfcall(buf, sizeof(buf), m->rcall, 639 p9_printfcall(buf, sizeof(buf), m->rcall,
629 *m->extended); 640 *m->extended);
630 printk(KERN_NOTICE ">>> %p %s\n", m, buf); 641 printk(KERN_NOTICE ">>> %p %s\n", m, buf);
631 } 642 }
643#endif
632 644
633 rcall = m->rcall; 645 rcall = m->rcall;
634 rbuf = m->rbuf; 646 rbuf = m->rbuf;
635 if (m->rpos > n) { 647 if (m->rpos > n) {
636 m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize, 648 m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize,
637 GFP_KERNEL); 649 GFP_KERNEL);
638 if (!m->rcall) { 650 if (!m->rcall) {
639 err = -ENOMEM; 651 err = -ENOMEM;
640 goto error; 652 goto error;
641 } 653 }
642 654
643 m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall); 655 m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
644 memmove(m->rbuf, rbuf + n, m->rpos - n); 656 memmove(m->rbuf, rbuf + n, m->rpos - n);
645 m->rpos -= n; 657 m->rpos -= n;
646 } else { 658 } else {
@@ -649,8 +661,8 @@ static void v9fs_read_work(struct work_struct *work)
649 m->rpos = 0; 661 m->rpos = 0;
650 } 662 }
651 663
652 dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id, 664 P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
653 rcall->tag); 665 rcall->id, rcall->tag);
654 666
655 req = NULL; 667 req = NULL;
656 spin_lock(&m->lock); 668 spin_lock(&m->lock);
@@ -677,10 +689,10 @@ static void v9fs_read_work(struct work_struct *work)
677 wake_up(&m->equeue); 689 wake_up(&m->equeue);
678 } 690 }
679 } else { 691 } else {
680 if (err >= 0 && rcall->id != RFLUSH) 692 if (err >= 0 && rcall->id != P9_RFLUSH)
681 dprintk(DEBUG_ERROR, 693 P9_DPRINTK(P9_DEBUG_ERROR,
682 "unexpected response mux %p id %d tag %d\n", 694 "unexpected response mux %p id %d tag %d\n",
683 m, rcall->id, rcall->tag); 695 m, rcall->id, rcall->tag);
684 kfree(rcall); 696 kfree(rcall);
685 } 697 }
686 } 698 }
@@ -692,8 +704,8 @@ static void v9fs_read_work(struct work_struct *work)
692 n = m->trans->poll(m->trans, NULL); 704 n = m->trans->poll(m->trans, NULL);
693 705
694 if (n & POLLIN) { 706 if (n & POLLIN) {
695 dprintk(DEBUG_MUX, "schedule read work mux %p\n", m); 707 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
696 queue_work(v9fs_mux_wq, &m->rq); 708 queue_work(p9_mux_wq, &m->rq);
697 } else 709 } else
698 clear_bit(Rworksched, &m->wsched); 710 clear_bit(Rworksched, &m->wsched);
699 } else 711 } else
@@ -701,13 +713,13 @@ static void v9fs_read_work(struct work_struct *work)
701 713
702 return; 714 return;
703 715
704 error: 716error:
705 v9fs_mux_cancel(m, err); 717 p9_conn_cancel(m, err);
706 clear_bit(Rworksched, &m->wsched); 718 clear_bit(Rworksched, &m->wsched);
707} 719}
708 720
709/** 721/**
710 * v9fs_send_request - send 9P request 722 * p9_send_request - send 9P request
711 * The function can sleep until the request is scheduled for sending. 723 * The function can sleep until the request is scheduled for sending.
712 * The function can be interrupted. Return from the function is not 724 * The function can be interrupted. Return from the function is not
713 * a guarantee that the request is sent successfully. Can return errors 725 * a guarantee that the request is sent successfully. Can return errors
@@ -718,37 +730,40 @@ static void v9fs_read_work(struct work_struct *work)
718 * @cb: callback function to call when response is received 730 * @cb: callback function to call when response is received
719 * @cba: parameter to pass to the callback function 731 * @cba: parameter to pass to the callback function
720 */ 732 */
721static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m, 733static struct p9_req *p9_send_request(struct p9_conn *m,
722 struct v9fs_fcall *tc, 734 struct p9_fcall *tc,
723 v9fs_mux_req_callback cb, void *cba) 735 p9_conn_req_callback cb, void *cba)
724{ 736{
725 int n; 737 int n;
726 struct v9fs_req *req; 738 struct p9_req *req;
727 739
728 dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, 740 P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
729 tc, tc->id); 741 tc, tc->id);
730 if (m->err < 0) 742 if (m->err < 0)
731 return ERR_PTR(m->err); 743 return ERR_PTR(m->err);
732 744
733 req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL); 745 req = kmalloc(sizeof(struct p9_req), GFP_KERNEL);
734 if (!req) 746 if (!req)
735 return ERR_PTR(-ENOMEM); 747 return ERR_PTR(-ENOMEM);
736 748
737 if (tc->id == TVERSION) 749 if (tc->id == P9_TVERSION)
738 n = V9FS_NOTAG; 750 n = P9_NOTAG;
739 else 751 else
740 n = v9fs_mux_get_tag(m); 752 n = p9_mux_get_tag(m);
741 753
742 if (n < 0) 754 if (n < 0)
743 return ERR_PTR(-ENOMEM); 755 return ERR_PTR(-ENOMEM);
744 756
745 v9fs_set_tag(tc, n); 757 p9_set_tag(tc, n);
746 if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) { 758
759#ifdef CONFIG_NET_9P_DEBUG
760 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
747 char buf[150]; 761 char buf[150];
748 762
749 v9fs_printfcall(buf, sizeof(buf), tc, *m->extended); 763 p9_printfcall(buf, sizeof(buf), tc, *m->extended);
750 printk(KERN_NOTICE "<<< %p %s\n", m, buf); 764 printk(KERN_NOTICE "<<< %p %s\n", m, buf);
751 } 765 }
766#endif
752 767
753 spin_lock_init(&req->lock); 768 spin_lock_init(&req->lock);
754 req->tag = n; 769 req->tag = n;
@@ -769,26 +784,26 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
769 n = m->trans->poll(m->trans, NULL); 784 n = m->trans->poll(m->trans, NULL);
770 785
771 if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) 786 if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
772 queue_work(v9fs_mux_wq, &m->wq); 787 queue_work(p9_mux_wq, &m->wq);
773 788
774 return req; 789 return req;
775} 790}
776 791
777static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req) 792static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req)
778{ 793{
779 v9fs_mux_put_tag(m, req->tag); 794 p9_mux_put_tag(m, req->tag);
780 kfree(req); 795 kfree(req);
781} 796}
782 797
783static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a) 798static void p9_mux_flush_cb(struct p9_req *freq, void *a)
784{ 799{
785 v9fs_mux_req_callback cb; 800 p9_conn_req_callback cb;
786 int tag; 801 int tag;
787 struct v9fs_mux_data *m; 802 struct p9_conn *m;
788 struct v9fs_req *req, *rreq, *rptr; 803 struct p9_req *req, *rreq, *rptr;
789 804
790 m = a; 805 m = a;
791 dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, 806 P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
792 freq->tcall, freq->rcall, freq->err, 807 freq->tcall, freq->rcall, freq->err,
793 freq->tcall->params.tflush.oldtag); 808 freq->tcall->params.tflush.oldtag);
794 809
@@ -820,22 +835,23 @@ static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
820 835
821 kfree(freq->tcall); 836 kfree(freq->tcall);
822 kfree(freq->rcall); 837 kfree(freq->rcall);
823 v9fs_mux_free_request(m, freq); 838 p9_mux_free_request(m, freq);
824} 839}
825 840
826static int 841static int
827v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req) 842p9_mux_flush_request(struct p9_conn *m, struct p9_req *req)
828{ 843{
829 struct v9fs_fcall *fc; 844 struct p9_fcall *fc;
830 struct v9fs_req *rreq, *rptr; 845 struct p9_req *rreq, *rptr;
831 846
832 dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); 847 P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
833 848
834 /* if a response was received for a request, do nothing */ 849 /* if a response was received for a request, do nothing */
835 spin_lock(&req->lock); 850 spin_lock(&req->lock);
836 if (req->rcall || req->err) { 851 if (req->rcall || req->err) {
837 spin_unlock(&req->lock); 852 spin_unlock(&req->lock);
838 dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req); 853 P9_DPRINTK(P9_DEBUG_MUX,
854 "mux %p req %p response already received\n", m, req);
839 return 0; 855 return 0;
840 } 856 }
841 857
@@ -846,7 +862,8 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
846 /* if the request is not sent yet, just remove it from the list */ 862 /* if the request is not sent yet, just remove it from the list */
847 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { 863 list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
848 if (rreq->tag == req->tag) { 864 if (rreq->tag == req->tag) {
849 dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req); 865 P9_DPRINTK(P9_DEBUG_MUX,
866 "mux %p req %p request is not sent yet\n", m, req);
850 list_del(&rreq->req_list); 867 list_del(&rreq->req_list);
851 req->flush = Flushed; 868 req->flush = Flushed;
852 spin_unlock(&m->lock); 869 spin_unlock(&m->lock);
@@ -858,42 +875,42 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
858 spin_unlock(&m->lock); 875 spin_unlock(&m->lock);
859 876
860 clear_thread_flag(TIF_SIGPENDING); 877 clear_thread_flag(TIF_SIGPENDING);
861 fc = v9fs_create_tflush(req->tag); 878 fc = p9_create_tflush(req->tag);
862 v9fs_send_request(m, fc, v9fs_mux_flush_cb, m); 879 p9_send_request(m, fc, p9_mux_flush_cb, m);
863 return 1; 880 return 1;
864} 881}
865 882
866static void 883static void
867v9fs_mux_rpc_cb(struct v9fs_req *req, void *a) 884p9_conn_rpc_cb(struct p9_req *req, void *a)
868{ 885{
869 struct v9fs_mux_rpc *r; 886 struct p9_mux_rpc *r;
870 887
871 dprintk(DEBUG_MUX, "req %p r %p\n", req, a); 888 P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a);
872 r = a; 889 r = a;
873 r->rcall = req->rcall; 890 r->rcall = req->rcall;
874 r->err = req->err; 891 r->err = req->err;
875 892
876 if (req->flush!=None && !req->err) 893 if (req->flush != None && !req->err)
877 r->err = -ERESTARTSYS; 894 r->err = -ERESTARTSYS;
878 895
879 wake_up(&r->wqueue); 896 wake_up(&r->wqueue);
880} 897}
881 898
882/** 899/**
883 * v9fs_mux_rpc - sends 9P request and waits until a response is available. 900 * p9_mux_rpc - sends 9P request and waits until a response is available.
884 * The function can be interrupted. 901 * The function can be interrupted.
885 * @m: mux data 902 * @m: mux data
886 * @tc: request to be sent 903 * @tc: request to be sent
887 * @rc: pointer where a pointer to the response is stored 904 * @rc: pointer where a pointer to the response is stored
888 */ 905 */
889int 906int
890v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, 907p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc,
891 struct v9fs_fcall **rc) 908 struct p9_fcall **rc)
892{ 909{
893 int err, sigpending; 910 int err, sigpending;
894 unsigned long flags; 911 unsigned long flags;
895 struct v9fs_req *req; 912 struct p9_req *req;
896 struct v9fs_mux_rpc r; 913 struct p9_mux_rpc r;
897 914
898 r.err = 0; 915 r.err = 0;
899 r.tcall = tc; 916 r.tcall = tc;
@@ -910,10 +927,10 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
910 clear_thread_flag(TIF_SIGPENDING); 927 clear_thread_flag(TIF_SIGPENDING);
911 } 928 }
912 929
913 req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r); 930 req = p9_send_request(m, tc, p9_conn_rpc_cb, &r);
914 if (IS_ERR(req)) { 931 if (IS_ERR(req)) {
915 err = PTR_ERR(req); 932 err = PTR_ERR(req);
916 dprintk(DEBUG_MUX, "error %d\n", err); 933 P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
917 return err; 934 return err;
918 } 935 }
919 936
@@ -921,15 +938,16 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
921 if (r.err < 0) 938 if (r.err < 0)
922 err = r.err; 939 err = r.err;
923 940
924 if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) { 941 if (err == -ERESTARTSYS && m->trans->status == Connected
925 if (v9fs_mux_flush_request(m, req)) { 942 && m->err == 0) {
943 if (p9_mux_flush_request(m, req)) {
926 /* wait until we get response of the flush message */ 944 /* wait until we get response of the flush message */
927 do { 945 do {
928 clear_thread_flag(TIF_SIGPENDING); 946 clear_thread_flag(TIF_SIGPENDING);
929 err = wait_event_interruptible(r.wqueue, 947 err = wait_event_interruptible(r.wqueue,
930 r.rcall || r.err); 948 r.rcall || r.err);
931 } while (!r.rcall && !r.err && err==-ERESTARTSYS && 949 } while (!r.rcall && !r.err && err == -ERESTARTSYS &&
932 m->trans->status==Connected && !m->err); 950 m->trans->status == Connected && !m->err);
933 951
934 err = -ERESTARTSYS; 952 err = -ERESTARTSYS;
935 } 953 }
@@ -947,50 +965,52 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
947 else 965 else
948 kfree(r.rcall); 966 kfree(r.rcall);
949 967
950 v9fs_mux_free_request(m, req); 968 p9_mux_free_request(m, req);
951 if (err > 0) 969 if (err > 0)
952 err = -EIO; 970 err = -EIO;
953 971
954 return err; 972 return err;
955} 973}
974EXPORT_SYMBOL(p9_conn_rpc);
956 975
957#if 0 976#ifdef P9_NONBLOCK
958/** 977/**
959 * v9fs_mux_rpcnb - sends 9P request without waiting for response. 978 * p9_conn_rpcnb - sends 9P request without waiting for response.
960 * @m: mux data 979 * @m: mux data
961 * @tc: request to be sent 980 * @tc: request to be sent
962 * @cb: callback function to be called when response arrives 981 * @cb: callback function to be called when response arrives
963 * @cba: value to pass to the callback function 982 * @cba: value to pass to the callback function
964 */ 983 */
965int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc, 984int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
966 v9fs_mux_req_callback cb, void *a) 985 p9_conn_req_callback cb, void *a)
967{ 986{
968 int err; 987 int err;
969 struct v9fs_req *req; 988 struct p9_req *req;
970 989
971 req = v9fs_send_request(m, tc, cb, a); 990 req = p9_send_request(m, tc, cb, a);
972 if (IS_ERR(req)) { 991 if (IS_ERR(req)) {
973 err = PTR_ERR(req); 992 err = PTR_ERR(req);
974 dprintk(DEBUG_MUX, "error %d\n", err); 993 P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
975 return PTR_ERR(req); 994 return PTR_ERR(req);
976 } 995 }
977 996
978 dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag); 997 P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
979 return 0; 998 return 0;
980} 999}
981#endif /* 0 */ 1000EXPORT_SYMBOL(p9_conn_rpcnb);
1001#endif /* P9_NONBLOCK */
982 1002
983/** 1003/**
984 * v9fs_mux_cancel - cancel all pending requests with error 1004 * p9_conn_cancel - cancel all pending requests with error
985 * @m: mux data 1005 * @m: mux data
986 * @err: error code 1006 * @err: error code
987 */ 1007 */
988void v9fs_mux_cancel(struct v9fs_mux_data *m, int err) 1008void p9_conn_cancel(struct p9_conn *m, int err)
989{ 1009{
990 struct v9fs_req *req, *rtmp; 1010 struct p9_req *req, *rtmp;
991 LIST_HEAD(cancel_list); 1011 LIST_HEAD(cancel_list);
992 1012
993 dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err); 1013 P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
994 m->err = err; 1014 m->err = err;
995 spin_lock(&m->lock); 1015 spin_lock(&m->lock);
996 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { 1016 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
@@ -1014,20 +1034,21 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
1014 1034
1015 wake_up(&m->equeue); 1035 wake_up(&m->equeue);
1016} 1036}
1037EXPORT_SYMBOL(p9_conn_cancel);
1017 1038
1018static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m) 1039static u16 p9_mux_get_tag(struct p9_conn *m)
1019{ 1040{
1020 int tag; 1041 int tag;
1021 1042
1022 tag = v9fs_get_idpool(&m->tagpool); 1043 tag = p9_idpool_get(m->tagpool);
1023 if (tag < 0) 1044 if (tag < 0)
1024 return V9FS_NOTAG; 1045 return P9_NOTAG;
1025 else 1046 else
1026 return (u16) tag; 1047 return (u16) tag;
1027} 1048}
1028 1049
1029static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag) 1050static void p9_mux_put_tag(struct p9_conn *m, u16 tag)
1030{ 1051{
1031 if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool)) 1052 if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool))
1032 v9fs_put_idpool(tag, &m->tagpool); 1053 p9_idpool_put(tag, m->tagpool);
1033} 1054}
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c
new file mode 100644
index 000000000000..e7fe706ab95a
--- /dev/null
+++ b/net/9p/sysctl.c
@@ -0,0 +1,86 @@
1/*
2 * net/9p/sysctl.c
3 *
4 * 9P sysctl interface
5 *
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to:
19 * Free Software Foundation
20 * 51 Franklin Street, Fifth Floor
21 * Boston, MA 02111-1301 USA
22 *
23 */
24
25#include <linux/kernel.h>
26#include <linux/mm.h>
27#include <linux/sysctl.h>
28#include <linux/init.h>
29#include <net/9p/9p.h>
30
31enum {
32 P9_SYSCTL_NET = 487,
33 P9_SYSCTL_DEBUG = 1,
34};
35
36static ctl_table p9_table[] = {
37#ifdef CONFIG_NET_9P_DEBUG
38 {
39 .ctl_name = P9_SYSCTL_DEBUG,
40 .procname = "debug",
41 .data = &p9_debug_level,
42 .maxlen = sizeof(int),
43 .mode = 0644,
44 .proc_handler = &proc_dointvec
45 },
46#endif
47 { .ctl_name = 0 },
48};
49
50static ctl_table p9_net_table[] = {
51 {
52 .ctl_name = P9_SYSCTL_NET,
53 .procname = "9p",
54 .maxlen = 0,
55 .mode = 0555,
56 .child = p9_table,
57 },
58 { .ctl_name = 0 },
59};
60
61static ctl_table p9_ctl_table[] = {
62 {
63 .ctl_name = CTL_NET,
64 .procname = "net",
65 .maxlen = 0,
66 .mode = 0555,
67 .child = p9_net_table,
68 },
69 { .ctl_name = 0 },
70};
71
72static struct ctl_table_header *p9_table_header;
73
74int __init p9_sysctl_register(void)
75{
76 p9_table_header = register_sysctl_table(p9_ctl_table);
77 if (!p9_table_header)
78 return -ENOMEM;
79
80 return 0;
81}
82
83void __exit p9_sysctl_unregister(void)
84{
85 unregister_sysctl_table(p9_table_header);
86}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
new file mode 100644
index 000000000000..fd636e94358f
--- /dev/null
+++ b/net/9p/trans_fd.c
@@ -0,0 +1,363 @@
1/*
2 * linux/fs/9p/trans_fd.c
3 *
4 * Fd transport layer. Includes deprecated socket layer.
5 *
6 * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
7 * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
8 * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
9 * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to:
22 * Free Software Foundation
23 * 51 Franklin Street, Fifth Floor
24 * Boston, MA 02111-1301 USA
25 *
26 */
27
28#include <linux/in.h>
29#include <linux/module.h>
30#include <linux/net.h>
31#include <linux/ipv6.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
34#include <linux/un.h>
35#include <linux/uaccess.h>
36#include <linux/inet.h>
37#include <linux/idr.h>
38#include <linux/file.h>
39#include <net/9p/9p.h>
40#include <net/9p/transport.h>
41
42#define P9_PORT 564
43
44struct p9_trans_fd {
45 struct file *rd;
46 struct file *wr;
47};
48
49static int p9_socket_open(struct p9_transport *trans, struct socket *csocket);
50static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd);
51static int p9_fd_read(struct p9_transport *trans, void *v, int len);
52static int p9_fd_write(struct p9_transport *trans, void *v, int len);
53static unsigned int p9_fd_poll(struct p9_transport *trans,
54 struct poll_table_struct *pt);
55static void p9_fd_close(struct p9_transport *trans);
56
57struct p9_transport *p9_trans_create_tcp(const char *addr, int port)
58{
59 int err;
60 struct p9_transport *trans;
61 struct socket *csocket;
62 struct sockaddr_in sin_server;
63
64 csocket = NULL;
65 trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
66 if (!trans)
67 return ERR_PTR(-ENOMEM);
68
69 trans->write = p9_fd_write;
70 trans->read = p9_fd_read;
71 trans->close = p9_fd_close;
72 trans->poll = p9_fd_poll;
73
74 sin_server.sin_family = AF_INET;
75 sin_server.sin_addr.s_addr = in_aton(addr);
76 sin_server.sin_port = htons(port);
77 sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
78
79 if (!csocket) {
80 P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
81 err = -EIO;
82 goto error;
83 }
84
85 err = csocket->ops->connect(csocket,
86 (struct sockaddr *)&sin_server,
87 sizeof(struct sockaddr_in), 0);
88 if (err < 0) {
89 P9_EPRINTK(KERN_ERR,
90 "p9_trans_tcp: problem connecting socket to %s\n",
91 addr);
92 goto error;
93 }
94
95 err = p9_socket_open(trans, csocket);
96 if (err < 0)
97 goto error;
98
99 return trans;
100
101error:
102 if (csocket)
103 sock_release(csocket);
104
105 kfree(trans);
106 return ERR_PTR(err);
107}
108EXPORT_SYMBOL(p9_trans_create_tcp);
109
110struct p9_transport *p9_trans_create_unix(const char *addr)
111{
112 int err;
113 struct socket *csocket;
114 struct sockaddr_un sun_server;
115 struct p9_transport *trans;
116
117 csocket = NULL;
118 trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
119 if (!trans)
120 return ERR_PTR(-ENOMEM);
121
122 trans->write = p9_fd_write;
123 trans->read = p9_fd_read;
124 trans->close = p9_fd_close;
125 trans->poll = p9_fd_poll;
126
127 if (strlen(addr) > UNIX_PATH_MAX) {
128 P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
129 addr);
130 err = -ENAMETOOLONG;
131 goto error;
132 }
133
134 sun_server.sun_family = PF_UNIX;
135 strcpy(sun_server.sun_path, addr);
136 sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
137 err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
138 sizeof(struct sockaddr_un) - 1, 0);
139 if (err < 0) {
140 P9_EPRINTK(KERN_ERR,
141 "p9_trans_unix: problem connecting socket: %s: %d\n",
142 addr, err);
143 goto error;
144 }
145
146 err = p9_socket_open(trans, csocket);
147 if (err < 0)
148 goto error;
149
150 return trans;
151
152error:
153 if (csocket)
154 sock_release(csocket);
155
156 kfree(trans);
157 return ERR_PTR(err);
158}
159EXPORT_SYMBOL(p9_trans_create_unix);
160
161struct p9_transport *p9_trans_create_fd(int rfd, int wfd)
162{
163 int err;
164 struct p9_transport *trans;
165
166 if (rfd == ~0 || wfd == ~0) {
167 printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
168 return ERR_PTR(-ENOPROTOOPT);
169 }
170
171 trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
172 if (!trans)
173 return ERR_PTR(-ENOMEM);
174
175 trans->write = p9_fd_write;
176 trans->read = p9_fd_read;
177 trans->close = p9_fd_close;
178 trans->poll = p9_fd_poll;
179
180 err = p9_fd_open(trans, rfd, wfd);
181 if (err < 0)
182 goto error;
183
184 return trans;
185
186error:
187 kfree(trans);
188 return ERR_PTR(err);
189}
190EXPORT_SYMBOL(p9_trans_create_fd);
191
192static int p9_socket_open(struct p9_transport *trans, struct socket *csocket)
193{
194 int fd, ret;
195
196 csocket->sk->sk_allocation = GFP_NOIO;
197 fd = sock_map_fd(csocket);
198 if (fd < 0) {
199 P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
200 return fd;
201 }
202
203 ret = p9_fd_open(trans, fd, fd);
204 if (ret < 0) {
205 P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
206 sockfd_put(csocket);
207 return ret;
208 }
209
210 ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK;
211
212 return 0;
213}
214
215static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd)
216{
217 struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
218 GFP_KERNEL);
219 if (!ts)
220 return -ENOMEM;
221
222 ts->rd = fget(rfd);
223 ts->wr = fget(wfd);
224 if (!ts->rd || !ts->wr) {
225 if (ts->rd)
226 fput(ts->rd);
227 if (ts->wr)
228 fput(ts->wr);
229 kfree(ts);
230 return -EIO;
231 }
232
233 trans->priv = ts;
234 trans->status = Connected;
235
236 return 0;
237}
238
239/**
240 * p9_fd_read- read from a fd
241 * @v9ses: session information
242 * @v: buffer to receive data into
243 * @len: size of receive buffer
244 *
245 */
246static int p9_fd_read(struct p9_transport *trans, void *v, int len)
247{
248 int ret;
249 struct p9_trans_fd *ts = NULL;
250
251 if (trans && trans->status != Disconnected)
252 ts = trans->priv;
253
254 if (!ts)
255 return -EREMOTEIO;
256
257 if (!(ts->rd->f_flags & O_NONBLOCK))
258 P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
259
260 ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
261 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
262 trans->status = Disconnected;
263 return ret;
264}
265
266/**
267 * p9_fd_write - write to a socket
268 * @v9ses: session information
269 * @v: buffer to send data from
270 * @len: size of send buffer
271 *
272 */
273static int p9_fd_write(struct p9_transport *trans, void *v, int len)
274{
275 int ret;
276 mm_segment_t oldfs;
277 struct p9_trans_fd *ts = NULL;
278
279 if (trans && trans->status != Disconnected)
280 ts = trans->priv;
281
282 if (!ts)
283 return -EREMOTEIO;
284
285 if (!(ts->wr->f_flags & O_NONBLOCK))
286 P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
287
288 oldfs = get_fs();
289 set_fs(get_ds());
290 /* The cast to a user pointer is valid due to the set_fs() */
291 ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
292 set_fs(oldfs);
293
294 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
295 trans->status = Disconnected;
296 return ret;
297}
298
299static unsigned int
300p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt)
301{
302 int ret, n;
303 struct p9_trans_fd *ts = NULL;
304 mm_segment_t oldfs;
305
306 if (trans && trans->status == Connected)
307 ts = trans->priv;
308
309 if (!ts)
310 return -EREMOTEIO;
311
312 if (!ts->rd->f_op || !ts->rd->f_op->poll)
313 return -EIO;
314
315 if (!ts->wr->f_op || !ts->wr->f_op->poll)
316 return -EIO;
317
318 oldfs = get_fs();
319 set_fs(get_ds());
320
321 ret = ts->rd->f_op->poll(ts->rd, pt);
322 if (ret < 0)
323 goto end;
324
325 if (ts->rd != ts->wr) {
326 n = ts->wr->f_op->poll(ts->wr, pt);
327 if (n < 0) {
328 ret = n;
329 goto end;
330 }
331 ret = (ret & ~POLLOUT) | (n & ~POLLIN);
332 }
333
334end:
335 set_fs(oldfs);
336 return ret;
337}
338
339/**
340 * p9_sock_close - shutdown socket
341 * @trans: private socket structure
342 *
343 */
344static void p9_fd_close(struct p9_transport *trans)
345{
346 struct p9_trans_fd *ts;
347
348 if (!trans)
349 return;
350
351 ts = xchg(&trans->priv, NULL);
352
353 if (!ts)
354 return;
355
356 trans->status = Disconnected;
357 if (ts->rd)
358 fput(ts->rd);
359 if (ts->wr)
360 fput(ts->wr);
361 kfree(ts);
362}
363
diff --git a/net/9p/util.c b/net/9p/util.c
new file mode 100644
index 000000000000..22077b79395d
--- /dev/null
+++ b/net/9p/util.c
@@ -0,0 +1,125 @@
1/*
2 * net/9p/util.c
3 *
4 * This file contains some helper functions
5 *
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to:
21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA
24 *
25 */
26
27#include <linux/module.h>
28#include <linux/errno.h>
29#include <linux/fs.h>
30#include <linux/sched.h>
31#include <linux/parser.h>
32#include <linux/idr.h>
33#include <net/9p/9p.h>
34
35struct p9_idpool {
36 struct semaphore lock;
37 struct idr pool;
38};
39
40struct p9_idpool *p9_idpool_create(void)
41{
42 struct p9_idpool *p;
43
44 p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL);
45 if (!p)
46 return ERR_PTR(-ENOMEM);
47
48 init_MUTEX(&p->lock);
49 idr_init(&p->pool);
50
51 return p;
52}
53EXPORT_SYMBOL(p9_idpool_create);
54
55void p9_idpool_destroy(struct p9_idpool *p)
56{
57 idr_destroy(&p->pool);
58 kfree(p);
59}
60EXPORT_SYMBOL(p9_idpool_destroy);
61
62/**
63 * p9_idpool_get - allocate numeric id from pool
64 * @p - pool to allocate from
65 *
66 * XXX - This seems to be an awful generic function, should it be in idr.c with
67 * the lock included in struct idr?
68 */
69
70int p9_idpool_get(struct p9_idpool *p)
71{
72 int i = 0;
73 int error;
74
75retry:
76 if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
77 return 0;
78
79 if (down_interruptible(&p->lock) == -EINTR) {
80 P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
81 return -1;
82 }
83
84 /* no need to store exactly p, we just need something non-null */
85 error = idr_get_new(&p->pool, p, &i);
86 up(&p->lock);
87
88 if (error == -EAGAIN)
89 goto retry;
90 else if (error)
91 return -1;
92
93 return i;
94}
95EXPORT_SYMBOL(p9_idpool_get);
96
97/**
98 * p9_idpool_put - release numeric id from pool
99 * @p - pool to allocate from
100 *
101 * XXX - This seems to be an awful generic function, should it be in idr.c with
102 * the lock included in struct idr?
103 */
104
105void p9_idpool_put(int id, struct p9_idpool *p)
106{
107 if (down_interruptible(&p->lock) == -EINTR) {
108 P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
109 return;
110 }
111 idr_remove(&p->pool, id);
112 up(&p->lock);
113}
114EXPORT_SYMBOL(p9_idpool_put);
115
116/**
117 * p9_idpool_check - check if the specified id is available
118 * @id - id to check
119 * @p - pool
120 */
121int p9_idpool_check(int id, struct p9_idpool *p)
122{
123 return idr_find(&p->pool, id) != NULL;
124}
125EXPORT_SYMBOL(p9_idpool_check);
diff --git a/net/Kconfig b/net/Kconfig
index f3de72978ab6..cdba08ca2efe 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -227,6 +227,7 @@ source "net/ieee80211/Kconfig"
227endmenu 227endmenu
228 228
229source "net/rfkill/Kconfig" 229source "net/rfkill/Kconfig"
230source "net/9p/Kconfig"
230 231
231endif # if NET 232endif # if NET
232endmenu # Networking 233endmenu # Networking
diff --git a/net/Makefile b/net/Makefile
index a87a88963432..bbe7d2a41486 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_TIPC) += tipc/
51obj-$(CONFIG_NETLABEL) += netlabel/ 51obj-$(CONFIG_NETLABEL) += netlabel/
52obj-$(CONFIG_IUCV) += iucv/ 52obj-$(CONFIG_IUCV) += iucv/
53obj-$(CONFIG_RFKILL) += rfkill/ 53obj-$(CONFIG_RFKILL) += rfkill/
54obj-$(CONFIG_NET_9P) += 9p/
54 55
55ifeq ($(CONFIG_NET),y) 56ifeq ($(CONFIG_NET),y)
56obj-$(CONFIG_SYSCTL) += sysctl_net.o 57obj-$(CONFIG_SYSCTL) += sysctl_net.o