~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/nfs/nfs3proc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/nfs/nfs3proc.c
  3  *
  4  *  Client-side NFSv3 procedures stubs.
  5  *
  6  *  Copyright (C) 1997, Olaf Kirch
  7  */
  8 
  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>
 17 
 18 #define NFSDBG_FACILITY         NFSDBG_PROC
 19 
 20 /*
 21  * Bare-bones access to getattr: this is for nfs_read_super.
 22  */
 23 static int
 24 nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 25                    struct nfs_fattr *fattr)
 26 {
 27         int     status;
 28 
 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;
 34 }
 35 
 36 /*
 37  * One function for each procedure in the NFS protocol.
 38  */
 39 static int
 40 nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
 41 {
 42         int     status;
 43 
 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;
 50 }
 51 
 52 static int
 53 nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
 54                         struct iattr *sattr)
 55 {
 56         struct nfs3_sattrargs   arg = { NFS_FH(inode), sattr, 0, 0 };
 57         int     status;
 58 
 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;
 64 }
 65 
 66 static int
 67 nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 68                  struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 69 {
 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;
 74 
 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;
 85 }
 86 
 87 static int
 88 nfs3_proc_access(struct inode *inode, int mode, int ruid)
 89 {
 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;
 94 
 95         dprintk("NFS call  access\n");
 96         fattr.valid = 0;
 97 
 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;
110         }
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");
115 
116         if (status == 0 && (arg.access & res.access) != arg.access)
117                 status = -EACCES;
118         return status;
119 }
120 
121 static int
122 nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
123 {
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;
128 
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;
136 }
137 
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)
142 {
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;
149 
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;
156 }
157 
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)
163 {
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;
171 
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;
177 
178         status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
179 
180         dprintk("NFS reply read: %d\n", status);
181         return status < 0? status : res.count;
182 }
183 
184 /*
185  * Create a regular file.
186  * For now, we don't implement O_EXCL.
187  */
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)
191 {
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;
197 
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;
204         }
205 
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);
211 
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;
219 
220                         case NFS3_CREATE_GUARDED:
221                                 arg.createmode = NFS3_CREATE_UNCHECKED;
222                                 break;
223 
224                         case NFS3_CREATE_UNCHECKED:
225                                 goto exit;
226                 }
227                 goto again;
228         }
229 
230 exit:
231         dprintk("NFS reply create: %d\n", status);
232 
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");
238 
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);
246         }
247 
248         return status;
249 }
250 
251 static int
252 nfs3_proc_remove(struct inode *dir, struct qstr *name)
253 {
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;
258 
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;
265 }
266 
267 static int
268 nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
269 {
270         struct nfs3_diropargs   *arg;
271         struct nfs_fattr        *res;
272 
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;
285 }
286 
287 static void
288 nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
289 {
290         struct nfs_fattr        *dir_attr;
291 
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);
296         }
297 }
298 
299 static int
300 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
301                  struct inode *new_dir, struct qstr *new_name)
302 {
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;
310 
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;
319 }
320 
321 static int
322 nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
323 {
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;
329 
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;
338 }
339 
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)
344 {
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;
350 
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;
358 }
359 
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)
363 {
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;
369 
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;
377 }
378 
379 static int
380 nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
381 {
382         struct nfs_fattr        dir_attr;
383         struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
384         int                     status;
385 
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;
392 }
393 
394 /*
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.
399  *
400  * Also note that this implementation handles both plain readdir and
401  * readdirplus.
402  */
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)
407 {
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;
414 
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;
424 
425         if (plus)
426                 msg.rpc_proc = NFS3PROC_READDIRPLUS;
427 
428         dprintk("NFS call  readdir%s %d\n",
429                         plus? "plus" : "", (unsigned int) cookie);
430 
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;
436 }
437 
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)
441 {
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;
447 
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;
454         }
455 
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;
463 }
464 
465 /*
466  * This is a combo call of fsstat and fsinfo
467  */
468 static int
469 nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
470                  struct nfs_fsinfo *info)
471 {
472         int     status;
473 
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);
480 
481 error:
482         dprintk("NFS reply statfs: %d\n", status);
483         return status;
484 }
485 
486 extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
487 
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,
512 };
513 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.