e847f504a47c7e807f0fe97ad191b9164eb54320
[pandora-kernel.git] / fs / 9p / 9p.c
1 /*
2  *  linux/fs/9p/9p.c
3  *
4  *  This file contains functions 9P2000 functions
5  *
6  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
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/config.h>
28 #include <linux/module.h>
29 #include <linux/errno.h>
30 #include <linux/fs.h>
31 #include <linux/idr.h>
32
33 #include "debug.h"
34 #include "v9fs.h"
35 #include "9p.h"
36 #include "mux.h"
37
38 /**
39  * v9fs_t_version - negotiate protocol parameters with sever
40  * @v9ses: 9P2000 session information
41  * @msize: requested max size packet
42  * @version: requested version.extension string
43  * @fcall: pointer to response fcall pointer
44  *
45  */
46
47 int
48 v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
49                char *version, struct v9fs_fcall **fcall)
50 {
51         struct v9fs_fcall msg;
52
53         dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
54         msg.id = TVERSION;
55         msg.params.tversion.msize = msize;
56         msg.params.tversion.version = version;
57
58         return v9fs_mux_rpc(v9ses, &msg, fcall);
59 }
60
61 /**
62  * v9fs_t_attach - mount the server
63  * @v9ses: 9P2000 session information
64  * @uname: user name doing the attach
65  * @aname: remote name being attached to
66  * @fid: mount fid to attatch to root node
67  * @afid: authentication fid (in this case result key)
68  * @fcall: pointer to response fcall pointer
69  *
70  */
71
72 int
73 v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
74               u32 fid, u32 afid, struct v9fs_fcall **fcall)
75 {
76         struct v9fs_fcall msg;
77
78         dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
79                 aname, fid, afid);
80         msg.id = TATTACH;
81         msg.params.tattach.fid = fid;
82         msg.params.tattach.afid = afid;
83         msg.params.tattach.uname = uname;
84         msg.params.tattach.aname = aname;
85
86         return v9fs_mux_rpc(v9ses, &msg, fcall);
87 }
88
89 /**
90  * v9fs_t_clunk - release a fid (finish a transaction)
91  * @v9ses: 9P2000 session information
92  * @fid: fid to release
93  * @fcall: pointer to response fcall pointer
94  *
95  */
96
97 int
98 v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
99              struct v9fs_fcall **fcall)
100 {
101         struct v9fs_fcall msg;
102
103         dprintk(DEBUG_9P, "fid %d\n", fid);
104         msg.id = TCLUNK;
105         msg.params.tclunk.fid = fid;
106
107         return v9fs_mux_rpc(v9ses, &msg, fcall);
108 }
109
110 /**
111  * v9fs_v9fs_t_flush - flush a pending transaction
112  * @v9ses: 9P2000 session information
113  * @tag: tid to release
114  *
115  */
116
117 int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
118 {
119         struct v9fs_fcall msg;
120
121         dprintk(DEBUG_9P, "oldtag %d\n", tag);
122         msg.id = TFLUSH;
123         msg.params.tflush.oldtag = tag;
124         return v9fs_mux_rpc(v9ses, &msg, NULL);
125 }
126
127 /**
128  * v9fs_t_stat - read a file's meta-data
129  * @v9ses: 9P2000 session information
130  * @fid: fid pointing to file or directory to get info about
131  * @fcall: pointer to response fcall
132  *
133  */
134
135 int
136 v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
137 {
138         struct v9fs_fcall msg;
139
140         dprintk(DEBUG_9P, "fid %d\n", fid);
141         if (fcall)
142                 *fcall = NULL;
143
144         msg.id = TSTAT;
145         msg.params.tstat.fid = fid;
146         return v9fs_mux_rpc(v9ses, &msg, fcall);
147 }
148
149 /**
150  * v9fs_t_wstat - write a file's meta-data
151  * @v9ses: 9P2000 session information
152  * @fid: fid pointing to file or directory to write info about
153  * @stat: metadata
154  * @fcall: pointer to response fcall
155  *
156  */
157
158 int
159 v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
160              struct v9fs_stat *stat, struct v9fs_fcall **fcall)
161 {
162         struct v9fs_fcall msg;
163
164         dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length);
165         msg.id = TWSTAT;
166         msg.params.twstat.fid = fid;
167         msg.params.twstat.stat = stat;
168
169         return v9fs_mux_rpc(v9ses, &msg, fcall);
170 }
171
172 /**
173  * v9fs_t_walk - walk a fid to a new file or directory
174  * @v9ses: 9P2000 session information
175  * @fid: fid to walk
176  * @newfid: new fid (for clone operations)
177  * @name: path to walk fid to
178  * @fcall: pointer to response fcall
179  *
180  */
181
182 /* TODO: support multiple walk */
183
184 int
185 v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
186             char *name, struct v9fs_fcall **fcall)
187 {
188         struct v9fs_fcall msg;
189
190         dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
191         msg.id = TWALK;
192         msg.params.twalk.fid = fid;
193         msg.params.twalk.newfid = newfid;
194
195         if (name) {
196                 msg.params.twalk.nwname = 1;
197                 msg.params.twalk.wnames = &name;
198         } else {
199                 msg.params.twalk.nwname = 0;
200         }
201
202         return v9fs_mux_rpc(v9ses, &msg, fcall);
203 }
204
205 /**
206  * v9fs_t_open - open a file
207  *
208  * @v9ses - 9P2000 session information
209  * @fid - fid to open
210  * @mode - mode to open file (R, RW, etc)
211  * @fcall - pointer to response fcall
212  *
213  */
214
215 int
216 v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
217             struct v9fs_fcall **fcall)
218 {
219         struct v9fs_fcall msg;
220         long errorno = -1;
221
222         dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
223         msg.id = TOPEN;
224         msg.params.topen.fid = fid;
225         msg.params.topen.mode = mode;
226
227         errorno = v9fs_mux_rpc(v9ses, &msg, fcall);
228
229         return errorno;
230 }
231
232 /**
233  * v9fs_t_remove - remove a file or directory
234  * @v9ses: 9P2000 session information
235  * @fid: fid to remove
236  * @fcall: pointer to response fcall
237  *
238  */
239
240 int
241 v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
242               struct v9fs_fcall **fcall)
243 {
244         struct v9fs_fcall msg;
245
246         dprintk(DEBUG_9P, "fid %d\n", fid);
247         msg.id = TREMOVE;
248         msg.params.tremove.fid = fid;
249         return v9fs_mux_rpc(v9ses, &msg, fcall);
250 }
251
252 /**
253  * v9fs_t_create - create a file or directory
254  * @v9ses: 9P2000 session information
255  * @fid: fid to create
256  * @name: name of the file or directory to create
257  * @perm: permissions to create with
258  * @mode: mode to open file (R, RW, etc)
259  * @fcall: pointer to response fcall
260  *
261  */
262
263 int
264 v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
265               u32 perm, u8 mode, struct v9fs_fcall **fcall)
266 {
267         struct v9fs_fcall msg;
268
269         dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
270                 fid, name, perm, mode);
271
272         msg.id = TCREATE;
273         msg.params.tcreate.fid = fid;
274         msg.params.tcreate.name = name;
275         msg.params.tcreate.perm = perm;
276         msg.params.tcreate.mode = mode;
277
278         return v9fs_mux_rpc(v9ses, &msg, fcall);
279 }
280
281 /**
282  * v9fs_t_read - read data
283  * @v9ses: 9P2000 session information
284  * @fid: fid to read from
285  * @offset: offset to start read at
286  * @count: how many bytes to read
287  * @fcall: pointer to response fcall (with data)
288  *
289  */
290
291 int
292 v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
293             u32 count, struct v9fs_fcall **fcall)
294 {
295         struct v9fs_fcall msg;
296         struct v9fs_fcall *rc = NULL;
297         long errorno = -1;
298
299         dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid,
300                 (long unsigned int)offset, count);
301         msg.id = TREAD;
302         msg.params.tread.fid = fid;
303         msg.params.tread.offset = offset;
304         msg.params.tread.count = count;
305         errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
306
307         if (!errorno) {
308                 errorno = rc->params.rread.count;
309                 dump_data(rc->params.rread.data, rc->params.rread.count);
310         }
311
312         if (fcall)
313                 *fcall = rc;
314         else
315                 kfree(rc);
316
317         return errorno;
318 }
319
320 /**
321  * v9fs_t_write - write data
322  * @v9ses: 9P2000 session information
323  * @fid: fid to write to
324  * @offset: offset to start write at
325  * @count: how many bytes to write
326  * @fcall: pointer to response fcall
327  *
328  */
329
330 int
331 v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
332              u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
333 {
334         struct v9fs_fcall msg;
335         struct v9fs_fcall *rc = NULL;
336         long errorno = -1;
337
338         dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
339                 (unsigned long long)offset, count);
340         dump_data(data, count);
341
342         msg.id = TWRITE;
343         msg.params.twrite.fid = fid;
344         msg.params.twrite.offset = offset;
345         msg.params.twrite.count = count;
346         msg.params.twrite.data = data;
347
348         errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
349
350         if (!errorno)
351                 errorno = rc->params.rwrite.count;
352
353         if (fcall)
354                 *fcall = rc;
355         else
356                 kfree(rc);
357
358         return errorno;
359 }