blob: e847f504a47c7e807f0fe97ad191b9164eb54320 [file] [log] [blame]
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -07001/*
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
47int
48v9fs_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
72int
73v9fs_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
97int
98v9fs_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
117int 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
135int
136v9fs_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
158int
159v9fs_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
184int
185v9fs_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
215int
216v9fs_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
240int
241v9fs_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
263int
264v9fs_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
291int
292v9fs_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
330int
331v9fs_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}