- Linus: drop support for old-style Makefiles entirely. Big.
[davej-history.git] / fs / nfs / nfs3proc.c
blob86cfd1b811ef96af8696905a7067e519c138e0de
1 /*
2 * linux/fs/nfs/nfs3proc.c
4 * Client-side NFSv3 procedures stubs.
6 * Copyright (C) 1997, Olaf Kirch
7 */
9 #include <linux/mm.h>
10 #include <linux/utsname.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
13 #include <linux/sunrpc/clnt.h>
14 #include <linux/nfs.h>
15 #include <linux/nfs3.h>
16 #include <linux/nfs_fs.h>
18 #define NFSDBG_FACILITY NFSDBG_PROC
21 * Bare-bones access to getattr: this is for nfs_read_super.
23 static int
24 nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
25 struct nfs_fattr *fattr)
27 int status;
29 dprintk("NFS call getroot\n");
30 fattr->valid = 0;
31 status = rpc_call(server->client, NFS3PROC_GETATTR, fhandle, fattr, 0);
32 dprintk("NFS reply getroot\n");
33 return status;
37 * One function for each procedure in the NFS protocol.
39 static int
40 nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
42 int status;
44 dprintk("NFS call getattr\n");
45 fattr->valid = 0;
46 status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
47 NFS_FH(inode), fattr, 0);
48 dprintk("NFS reply getattr\n");
49 return status;
52 static int
53 nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
54 struct iattr *sattr)
56 struct nfs3_sattrargs arg = { NFS_FH(inode), sattr, 0, 0 };
57 int status;
59 dprintk("NFS call setattr\n");
60 fattr->valid = 0;
61 status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
62 dprintk("NFS reply setattr\n");
63 return status;
66 static int
67 nfs3_proc_lookup(struct inode *dir, struct qstr *name,
68 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
70 struct nfs_fattr dir_attr;
71 struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
72 struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
73 int status;
75 dprintk("NFS call lookup %s\n", name->name);
76 dir_attr.valid = 0;
77 fattr->valid = 0;
78 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
79 if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
80 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
81 fhandle, fattr, 0);
82 dprintk("NFS reply lookup: %d\n", status);
83 nfs_refresh_inode(dir, &dir_attr);
84 return status;
87 static int
88 nfs3_proc_access(struct inode *inode, int mode, int ruid)
90 struct nfs_fattr fattr;
91 struct nfs3_accessargs arg = { NFS_FH(inode), 0 };
92 struct nfs3_accessres res = { &fattr, 0 };
93 int status, flags;
95 dprintk("NFS call access\n");
96 fattr.valid = 0;
98 if (mode & MAY_READ)
99 arg.access |= NFS3_ACCESS_READ;
100 if (S_ISDIR(inode->i_mode)) {
101 if (mode & MAY_WRITE)
102 arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
103 if (mode & MAY_EXEC)
104 arg.access |= NFS3_ACCESS_LOOKUP;
105 } else {
106 if (mode & MAY_WRITE)
107 arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
108 if (mode & MAY_EXEC)
109 arg.access |= NFS3_ACCESS_EXECUTE;
111 flags = (ruid) ? RPC_CALL_REALUID : 0;
112 status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
113 nfs_refresh_inode(inode, &fattr);
114 dprintk("NFS reply access\n");
116 if (status == 0 && (arg.access & res.access) != arg.access)
117 status = -EACCES;
118 return status;
121 static int
122 nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
124 struct nfs_fattr fattr;
125 struct nfs3_readlinkargs args = { NFS_FH(inode), buffer, buflen };
126 struct nfs3_readlinkres res = { &fattr, buffer, buflen };
127 int status;
129 dprintk("NFS call readlink\n");
130 fattr.valid = 0;
131 status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
132 &args, &res, 0);
133 nfs_refresh_inode(inode, &fattr);
134 dprintk("NFS reply readlink: %d\n", status);
135 return status;
138 static int
139 nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
140 struct nfs_fattr *fattr, int flags,
141 loff_t offset, unsigned int count, void *buffer, int *eofp)
143 struct nfs_readargs arg = { NFS_FH(inode), offset, count, 1,
144 {{buffer, count}, {0,0}, {0,0}, {0,0},
145 {0,0}, {0,0}, {0,0}, {0,0}} };
146 struct nfs_readres res = { fattr, count, 0 };
147 struct rpc_message msg = { NFS3PROC_READ, &arg, &res, cred };
148 int status;
150 dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
151 fattr->valid = 0;
152 status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
153 dprintk("NFS reply read: %d\n", status);
154 *eofp = res.eof;
155 return status;
158 static int
159 nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
160 struct nfs_fattr *fattr, int flags,
161 loff_t offset, unsigned int count,
162 void *buffer, struct nfs_writeverf *verf)
164 struct nfs_writeargs arg = { NFS_FH(inode), offset, count,
165 NFS_FILE_SYNC, 1,
166 {{buffer, count}, {0,0}, {0,0}, {0,0},
167 {0,0}, {0,0}, {0,0}, {0,0}} };
168 struct nfs_writeres res = { fattr, verf, 0 };
169 struct rpc_message msg = { NFS3PROC_WRITE, &arg, &res, cred };
170 int status, rpcflags = 0;
172 dprintk("NFS call write %d @ %Ld\n", count, (long long)offset);
173 fattr->valid = 0;
174 if (flags & NFS_RW_SWAP)
175 rpcflags |= NFS_RPC_SWAPFLAGS;
176 arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
178 status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
180 dprintk("NFS reply read: %d\n", status);
181 return status < 0? status : res.count;
185 * Create a regular file.
186 * For now, we don't implement O_EXCL.
188 static int
189 nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
190 int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
192 struct nfs_fattr dir_attr;
193 struct nfs3_createargs arg = { NFS_FH(dir), name->name, name->len,
194 sattr, 0, { 0, 0 } };
195 struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
196 int status;
198 dprintk("NFS call create %s\n", name->name);
199 arg.createmode = NFS3_CREATE_UNCHECKED;
200 if (flags & O_EXCL) {
201 arg.createmode = NFS3_CREATE_EXCLUSIVE;
202 arg.verifier[0] = jiffies;
203 arg.verifier[1] = current->pid;
206 again:
207 dir_attr.valid = 0;
208 fattr->valid = 0;
209 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
210 nfs_refresh_inode(dir, &dir_attr);
212 /* If the server doesn't support the exclusive creation semantics,
213 * try again with simple 'guarded' mode. */
214 if (status == NFSERR_NOTSUPP) {
215 switch (arg.createmode) {
216 case NFS3_CREATE_EXCLUSIVE:
217 arg.createmode = NFS3_CREATE_GUARDED;
218 break;
220 case NFS3_CREATE_GUARDED:
221 arg.createmode = NFS3_CREATE_UNCHECKED;
222 break;
224 case NFS3_CREATE_UNCHECKED:
225 goto exit;
227 goto again;
230 exit:
231 dprintk("NFS reply create: %d\n", status);
233 /* When we created the file with exclusive semantics, make
234 * sure we set the attributes afterwards. */
235 if (status == 0 && arg.createmode == NFS3_CREATE_EXCLUSIVE) {
236 struct nfs3_sattrargs arg = { fhandle, sattr, 0, 0 };
237 dprintk("NFS call setattr (post-create)\n");
239 /* Note: we could use a guarded setattr here, but I'm
240 * not sure this buys us anything (and I'd have
241 * to revamp the NFSv3 XDR code) */
242 fattr->valid = 0;
243 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
244 &arg, fattr, 0);
245 dprintk("NFS reply setattr (post-create): %d\n", status);
248 return status;
251 static int
252 nfs3_proc_remove(struct inode *dir, struct qstr *name)
254 struct nfs_fattr dir_attr;
255 struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
256 struct rpc_message msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL };
257 int status;
259 dprintk("NFS call remove %s\n", name->name);
260 dir_attr.valid = 0;
261 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
262 nfs_refresh_inode(dir, &dir_attr);
263 dprintk("NFS reply remove: %d\n", status);
264 return status;
267 static int
268 nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
270 struct nfs3_diropargs *arg;
271 struct nfs_fattr *res;
273 arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL);
274 if (!arg)
275 return -ENOMEM;
276 res = (struct nfs_fattr*)(arg + 1);
277 arg->fh = NFS_FH(dir->d_inode);
278 arg->name = name->name;
279 arg->len = name->len;
280 res->valid = 0;
281 msg->rpc_proc = NFS3PROC_REMOVE;
282 msg->rpc_argp = arg;
283 msg->rpc_resp = res;
284 return 0;
287 static void
288 nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
290 struct nfs_fattr *dir_attr;
292 if (msg->rpc_argp) {
293 dir_attr = (struct nfs_fattr*)msg->rpc_resp;
294 nfs_refresh_inode(dir->d_inode, dir_attr);
295 kfree(msg->rpc_argp);
299 static int
300 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
301 struct inode *new_dir, struct qstr *new_name)
303 struct nfs_fattr old_dir_attr, new_dir_attr;
304 struct nfs3_renameargs arg = { NFS_FH(old_dir),
305 old_name->name, old_name->len,
306 NFS_FH(new_dir),
307 new_name->name, new_name->len };
308 struct nfs3_renameres res = { &old_dir_attr, &new_dir_attr };
309 int status;
311 dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
312 old_dir_attr.valid = 0;
313 new_dir_attr.valid = 0;
314 status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
315 nfs_refresh_inode(old_dir, &old_dir_attr);
316 nfs_refresh_inode(new_dir, &new_dir_attr);
317 dprintk("NFS reply rename: %d\n", status);
318 return status;
321 static int
322 nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
324 struct nfs_fattr dir_attr, fattr;
325 struct nfs3_linkargs arg = { NFS_FH(inode), NFS_FH(dir),
326 name->name, name->len };
327 struct nfs3_linkres res = { &dir_attr, &fattr };
328 int status;
330 dprintk("NFS call link %s\n", name->name);
331 dir_attr.valid = 0;
332 fattr.valid = 0;
333 status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
334 nfs_refresh_inode(dir, &dir_attr);
335 nfs_refresh_inode(inode, &fattr);
336 dprintk("NFS reply link: %d\n", status);
337 return status;
340 static int
341 nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
342 struct iattr *sattr, struct nfs_fh *fhandle,
343 struct nfs_fattr *fattr)
345 struct nfs_fattr dir_attr;
346 struct nfs3_symlinkargs arg = { NFS_FH(dir), name->name, name->len,
347 path->name, path->len, sattr };
348 struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
349 int status;
351 dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
352 dir_attr.valid = 0;
353 fattr->valid = 0;
354 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
355 nfs_refresh_inode(dir, &dir_attr);
356 dprintk("NFS reply symlink: %d\n", status);
357 return status;
360 static int
361 nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
362 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
364 struct nfs_fattr dir_attr;
365 struct nfs3_createargs arg = { NFS_FH(dir), name->name, name->len,
366 sattr, 0, { 0, 0 } };
367 struct nfs3_diropres res = { &dir_attr, fhandle, fattr };
368 int status;
370 dprintk("NFS call mkdir %s\n", name->name);
371 dir_attr.valid = 0;
372 fattr->valid = 0;
373 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
374 nfs_refresh_inode(dir, &dir_attr);
375 dprintk("NFS reply mkdir: %d\n", status);
376 return status;
379 static int
380 nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
382 struct nfs_fattr dir_attr;
383 struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len };
384 int status;
386 dprintk("NFS call rmdir %s\n", name->name);
387 dir_attr.valid = 0;
388 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
389 nfs_refresh_inode(dir, &dir_attr);
390 dprintk("NFS reply rmdir: %d\n", status);
391 return status;
395 * The READDIR implementation is somewhat hackish - we pass the user buffer
396 * to the encode function, which installs it in the receive iovec.
397 * The decode function itself doesn't perform any decoding, it just makes
398 * sure the reply is syntactically correct.
400 * Also note that this implementation handles both plain readdir and
401 * readdirplus.
403 static int
404 nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
405 u64 cookie, void *entry,
406 unsigned int size, int plus)
408 struct nfs_fattr dir_attr;
409 struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
410 struct nfs3_readdirres res = { &dir_attr, 0, 0, 0, 0 };
411 struct rpc_message msg = { NFS3PROC_READDIR, &arg, &res, cred };
412 u32 *verf = NFS_COOKIEVERF(dir);
413 int status;
415 arg.buffer = entry;
416 arg.bufsiz = size;
417 arg.verf[0] = verf[0];
418 arg.verf[1] = verf[1];
419 arg.plus = plus;
420 res.buffer = entry;
421 res.bufsiz = size;
422 res.verf = verf;
423 res.plus = plus;
425 if (plus)
426 msg.rpc_proc = NFS3PROC_READDIRPLUS;
428 dprintk("NFS call readdir%s %d\n",
429 plus? "plus" : "", (unsigned int) cookie);
431 dir_attr.valid = 0;
432 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
433 nfs_refresh_inode(dir, &dir_attr);
434 dprintk("NFS reply readdir: %d\n", status);
435 return status;
438 static int
439 nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
440 dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
442 struct nfs_fattr dir_attr;
443 struct nfs3_mknodargs arg = { NFS_FH(dir), name->name, name->len, 0,
444 sattr, rdev };
445 struct nfs3_diropres res = { &dir_attr, fh, fattr };
446 int status;
448 switch (sattr->ia_mode & S_IFMT) {
449 case S_IFBLK: arg.type = NF3BLK; break;
450 case S_IFCHR: arg.type = NF3CHR; break;
451 case S_IFIFO: arg.type = NF3FIFO; break;
452 case S_IFSOCK: arg.type = NF3SOCK; break;
453 default: return -EINVAL;
456 dprintk("NFS call mknod %s %x\n", name->name, rdev);
457 dir_attr.valid = 0;
458 fattr->valid = 0;
459 status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
460 nfs_refresh_inode(dir, &dir_attr);
461 dprintk("NFS reply mknod: %d\n", status);
462 return status;
466 * This is a combo call of fsstat and fsinfo
468 static int
469 nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
470 struct nfs_fsinfo *info)
472 int status;
474 dprintk("NFS call fsstat\n");
475 memset((char *)info, 0, sizeof(*info));
476 status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, info, 0);
477 if (status < 0)
478 goto error;
479 status = rpc_call(server->client, NFS3PROC_FSINFO, fhandle, info, 0);
481 error:
482 dprintk("NFS reply statfs: %d\n", status);
483 return status;
486 extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
488 struct nfs_rpc_ops nfs_v3_clientops = {
489 3, /* protocol version */
490 nfs3_proc_get_root,
491 nfs3_proc_getattr,
492 nfs3_proc_setattr,
493 nfs3_proc_lookup,
494 nfs3_proc_access,
495 nfs3_proc_readlink,
496 nfs3_proc_read,
497 nfs3_proc_write,
498 NULL, /* commit */
499 nfs3_proc_create,
500 nfs3_proc_remove,
501 nfs3_proc_unlink_setup,
502 nfs3_proc_unlink_done,
503 nfs3_proc_rename,
504 nfs3_proc_link,
505 nfs3_proc_symlink,
506 nfs3_proc_mkdir,
507 nfs3_proc_rmdir,
508 nfs3_proc_readdir,
509 nfs3_proc_mknod,
510 nfs3_proc_statfs,
511 nfs3_decode_dirent,