blob: a3a1ac61072369705be2b08356853f330f000bb2 [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;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -080055 msg.tag = ~0;
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -070056 msg.params.tversion.msize = msize;
57 msg.params.tversion.version = version;
58
Latchesar Ionkov3cf64292006-01-08 01:04:58 -080059 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -070060}
61
62/**
63 * v9fs_t_attach - mount the server
64 * @v9ses: 9P2000 session information
65 * @uname: user name doing the attach
66 * @aname: remote name being attached to
67 * @fid: mount fid to attatch to root node
68 * @afid: authentication fid (in this case result key)
69 * @fcall: pointer to response fcall pointer
70 *
71 */
72
73int
74v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
75 u32 fid, u32 afid, struct v9fs_fcall **fcall)
76{
77 struct v9fs_fcall msg;
78
79 dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
80 aname, fid, afid);
81 msg.id = TATTACH;
82 msg.params.tattach.fid = fid;
83 msg.params.tattach.afid = afid;
84 msg.params.tattach.uname = uname;
85 msg.params.tattach.aname = aname;
86
Latchesar Ionkov3cf64292006-01-08 01:04:58 -080087 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
88}
89
90static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
91 struct v9fs_fcall *rc, int err)
92{
93 int fid;
94 struct v9fs_session_info *v9ses;
95
96 if (err)
97 return;
98
99 fid = tc->params.tclunk.fid;
100 kfree(tc);
101
102 if (!rc)
103 return;
104
105 dprintk(DEBUG_9P, "tcall id %d rcall id %d\n", tc->id, rc->id);
106 v9ses = a;
107 if (rc->id == RCLUNK)
108 v9fs_put_idpool(fid, &v9ses->fidpool);
109
110 kfree(rc);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700111}
112
113/**
114 * v9fs_t_clunk - release a fid (finish a transaction)
115 * @v9ses: 9P2000 session information
116 * @fid: fid to release
117 * @fcall: pointer to response fcall pointer
118 *
119 */
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700120int
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800121v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700122{
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800123 int err;
124 struct v9fs_fcall *tc, *rc;
125
126 tc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700127
128 dprintk(DEBUG_9P, "fid %d\n", fid);
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800129 tc->id = TCLUNK;
130 tc->params.tclunk.fid = fid;
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700131
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800132 err = v9fs_mux_rpc(v9ses->mux, tc, &rc);
133 if (err >= 0) {
134 v9fs_t_clunk_cb(v9ses, tc, rc, 0);
135 }
136
137 return err;
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700138}
139
140/**
141 * v9fs_v9fs_t_flush - flush a pending transaction
142 * @v9ses: 9P2000 session information
143 * @tag: tid to release
144 *
145 */
146
147int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
148{
149 struct v9fs_fcall msg;
150
151 dprintk(DEBUG_9P, "oldtag %d\n", tag);
152 msg.id = TFLUSH;
153 msg.params.tflush.oldtag = tag;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800154 return v9fs_mux_rpc(v9ses->mux, &msg, NULL);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700155}
156
157/**
158 * v9fs_t_stat - read a file's meta-data
159 * @v9ses: 9P2000 session information
160 * @fid: fid pointing to file or directory to get info about
161 * @fcall: pointer to response fcall
162 *
163 */
164
165int
166v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
167{
168 struct v9fs_fcall msg;
169
170 dprintk(DEBUG_9P, "fid %d\n", fid);
171 if (fcall)
172 *fcall = NULL;
173
174 msg.id = TSTAT;
175 msg.params.tstat.fid = fid;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800176 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700177}
178
179/**
180 * v9fs_t_wstat - write a file's meta-data
181 * @v9ses: 9P2000 session information
182 * @fid: fid pointing to file or directory to write info about
183 * @stat: metadata
184 * @fcall: pointer to response fcall
185 *
186 */
187
188int
189v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
190 struct v9fs_stat *stat, struct v9fs_fcall **fcall)
191{
192 struct v9fs_fcall msg;
193
194 dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length);
195 msg.id = TWSTAT;
196 msg.params.twstat.fid = fid;
197 msg.params.twstat.stat = stat;
198
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800199 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700200}
201
202/**
203 * v9fs_t_walk - walk a fid to a new file or directory
204 * @v9ses: 9P2000 session information
205 * @fid: fid to walk
206 * @newfid: new fid (for clone operations)
207 * @name: path to walk fid to
208 * @fcall: pointer to response fcall
209 *
210 */
211
212/* TODO: support multiple walk */
213
214int
215v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
216 char *name, struct v9fs_fcall **fcall)
217{
218 struct v9fs_fcall msg;
219
220 dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
221 msg.id = TWALK;
222 msg.params.twalk.fid = fid;
223 msg.params.twalk.newfid = newfid;
224
225 if (name) {
226 msg.params.twalk.nwname = 1;
227 msg.params.twalk.wnames = &name;
228 } else {
229 msg.params.twalk.nwname = 0;
230 }
231
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800232 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700233}
234
235/**
236 * v9fs_t_open - open a file
237 *
238 * @v9ses - 9P2000 session information
239 * @fid - fid to open
240 * @mode - mode to open file (R, RW, etc)
241 * @fcall - pointer to response fcall
242 *
243 */
244
245int
246v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
247 struct v9fs_fcall **fcall)
248{
249 struct v9fs_fcall msg;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800250 int errorno = -1;
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700251
252 dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
253 msg.id = TOPEN;
254 msg.params.topen.fid = fid;
255 msg.params.topen.mode = mode;
256
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800257 errorno = v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700258
259 return errorno;
260}
261
262/**
263 * v9fs_t_remove - remove a file or directory
264 * @v9ses: 9P2000 session information
265 * @fid: fid to remove
266 * @fcall: pointer to response fcall
267 *
268 */
269
270int
271v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
272 struct v9fs_fcall **fcall)
273{
274 struct v9fs_fcall msg;
275
276 dprintk(DEBUG_9P, "fid %d\n", fid);
277 msg.id = TREMOVE;
278 msg.params.tremove.fid = fid;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800279 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700280}
281
282/**
283 * v9fs_t_create - create a file or directory
284 * @v9ses: 9P2000 session information
285 * @fid: fid to create
286 * @name: name of the file or directory to create
287 * @perm: permissions to create with
288 * @mode: mode to open file (R, RW, etc)
289 * @fcall: pointer to response fcall
290 *
291 */
292
293int
294v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
295 u32 perm, u8 mode, struct v9fs_fcall **fcall)
296{
297 struct v9fs_fcall msg;
298
299 dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
300 fid, name, perm, mode);
301
302 msg.id = TCREATE;
303 msg.params.tcreate.fid = fid;
304 msg.params.tcreate.name = name;
305 msg.params.tcreate.perm = perm;
306 msg.params.tcreate.mode = mode;
307
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800308 return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700309}
310
311/**
312 * v9fs_t_read - read data
313 * @v9ses: 9P2000 session information
314 * @fid: fid to read from
315 * @offset: offset to start read at
316 * @count: how many bytes to read
317 * @fcall: pointer to response fcall (with data)
318 *
319 */
320
321int
322v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
323 u32 count, struct v9fs_fcall **fcall)
324{
325 struct v9fs_fcall msg;
326 struct v9fs_fcall *rc = NULL;
327 long errorno = -1;
328
329 dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid,
330 (long unsigned int)offset, count);
331 msg.id = TREAD;
332 msg.params.tread.fid = fid;
333 msg.params.tread.offset = offset;
334 msg.params.tread.count = count;
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800335 errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700336
337 if (!errorno) {
338 errorno = rc->params.rread.count;
339 dump_data(rc->params.rread.data, rc->params.rread.count);
340 }
341
342 if (fcall)
343 *fcall = rc;
344 else
345 kfree(rc);
346
347 return errorno;
348}
349
350/**
351 * v9fs_t_write - write data
352 * @v9ses: 9P2000 session information
353 * @fid: fid to write to
354 * @offset: offset to start write at
355 * @count: how many bytes to write
356 * @fcall: pointer to response fcall
357 *
358 */
359
360int
361v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
362 u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
363{
364 struct v9fs_fcall msg;
365 struct v9fs_fcall *rc = NULL;
366 long errorno = -1;
367
368 dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
369 (unsigned long long)offset, count);
370 dump_data(data, count);
371
372 msg.id = TWRITE;
373 msg.params.twrite.fid = fid;
374 msg.params.twrite.offset = offset;
375 msg.params.twrite.count = count;
376 msg.params.twrite.data = data;
377
Latchesar Ionkov3cf64292006-01-08 01:04:58 -0800378 errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc);
Eric Van Hensbergenb8cf9452005-09-09 13:04:21 -0700379
380 if (!errorno)
381 errorno = rc->params.rwrite.count;
382
383 if (fcall)
384 *fcall = rc;
385 else
386 kfree(rc);
387
388 return errorno;
389}