]>
Commit | Line | Data |
---|---|---|
b8cf945b EVH |
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; | |
3cf6429a | 55 | msg.tag = ~0; |
b8cf945b EVH |
56 | msg.params.tversion.msize = msize; |
57 | msg.params.tversion.version = version; | |
58 | ||
3cf6429a | 59 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
60 | } |
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 | ||
73 | int | |
74 | v9fs_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 | ||
3cf6429a LI |
87 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
88 | } | |
89 | ||
90 | static 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); | |
b8cf945b EVH |
111 | } |
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 | */ | |
b8cf945b | 120 | int |
3cf6429a | 121 | v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) |
b8cf945b | 122 | { |
3cf6429a LI |
123 | int err; |
124 | struct v9fs_fcall *tc, *rc; | |
125 | ||
126 | tc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL); | |
b8cf945b EVH |
127 | |
128 | dprintk(DEBUG_9P, "fid %d\n", fid); | |
3cf6429a LI |
129 | tc->id = TCLUNK; |
130 | tc->params.tclunk.fid = fid; | |
b8cf945b | 131 | |
3cf6429a LI |
132 | 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; | |
b8cf945b EVH |
138 | } |
139 | ||
140 | /** | |
141 | * v9fs_v9fs_t_flush - flush a pending transaction | |
142 | * @v9ses: 9P2000 session information | |
143 | * @tag: tid to release | |
144 | * | |
145 | */ | |
146 | ||
147 | int 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; | |
3cf6429a | 154 | return v9fs_mux_rpc(v9ses->mux, &msg, NULL); |
b8cf945b EVH |
155 | } |
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 | ||
165 | int | |
166 | v9fs_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; | |
3cf6429a | 176 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
177 | } |
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 | ||
188 | int | |
189 | v9fs_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 | ||
3cf6429a | 199 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
200 | } |
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 | ||
214 | int | |
215 | v9fs_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 | ||
3cf6429a | 232 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
233 | } |
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 | ||
245 | int | |
246 | v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, | |
247 | struct v9fs_fcall **fcall) | |
248 | { | |
249 | struct v9fs_fcall msg; | |
3cf6429a | 250 | int errorno = -1; |
b8cf945b EVH |
251 | |
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 | ||
3cf6429a | 257 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
258 | |
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 | ||
270 | int | |
271 | v9fs_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; | |
3cf6429a | 279 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
280 | } |
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 | ||
293 | int | |
294 | v9fs_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 | ||
3cf6429a | 308 | return v9fs_mux_rpc(v9ses->mux, &msg, fcall); |
b8cf945b EVH |
309 | } |
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 | ||
321 | int | |
322 | v9fs_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; | |
3cf6429a | 335 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc); |
b8cf945b EVH |
336 | |
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 | ||
360 | int | |
361 | v9fs_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 | ||
3cf6429a | 378 | errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc); |
b8cf945b EVH |
379 | |
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 | } |