aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs3proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs3proc.c')
-rw-r--r--fs/nfs/nfs3proc.c275
1 files changed, 144 insertions, 131 deletions
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index c3523ad03ed1..1e750e4574a9 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -129,6 +129,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
129 int status; 129 int status;
130 130
131 dprintk("NFS call setattr\n"); 131 dprintk("NFS call setattr\n");
132 if (sattr->ia_valid & ATTR_FILE)
133 msg.rpc_cred = nfs_file_cred(sattr->ia_file);
132 nfs_fattr_init(fattr); 134 nfs_fattr_init(fattr);
133 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 135 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
134 if (status == 0) 136 if (status == 0)
@@ -248,6 +250,53 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
248 return status; 250 return status;
249} 251}
250 252
253struct nfs3_createdata {
254 struct rpc_message msg;
255 union {
256 struct nfs3_createargs create;
257 struct nfs3_mkdirargs mkdir;
258 struct nfs3_symlinkargs symlink;
259 struct nfs3_mknodargs mknod;
260 } arg;
261 struct nfs3_diropres res;
262 struct nfs_fh fh;
263 struct nfs_fattr fattr;
264 struct nfs_fattr dir_attr;
265};
266
267static struct nfs3_createdata *nfs3_alloc_createdata(void)
268{
269 struct nfs3_createdata *data;
270
271 data = kzalloc(sizeof(*data), GFP_KERNEL);
272 if (data != NULL) {
273 data->msg.rpc_argp = &data->arg;
274 data->msg.rpc_resp = &data->res;
275 data->res.fh = &data->fh;
276 data->res.fattr = &data->fattr;
277 data->res.dir_attr = &data->dir_attr;
278 nfs_fattr_init(data->res.fattr);
279 nfs_fattr_init(data->res.dir_attr);
280 }
281 return data;
282}
283
284static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data)
285{
286 int status;
287
288 status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
289 nfs_post_op_update_inode(dir, data->res.dir_attr);
290 if (status == 0)
291 status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
292 return status;
293}
294
295static void nfs3_free_createdata(struct nfs3_createdata *data)
296{
297 kfree(data);
298}
299
251/* 300/*
252 * Create a regular file. 301 * Create a regular file.
253 * For now, we don't implement O_EXCL. 302 * For now, we don't implement O_EXCL.
@@ -256,70 +305,60 @@ static int
256nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 305nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
257 int flags, struct nameidata *nd) 306 int flags, struct nameidata *nd)
258{ 307{
259 struct nfs_fh fhandle; 308 struct nfs3_createdata *data;
260 struct nfs_fattr fattr;
261 struct nfs_fattr dir_attr;
262 struct nfs3_createargs arg = {
263 .fh = NFS_FH(dir),
264 .name = dentry->d_name.name,
265 .len = dentry->d_name.len,
266 .sattr = sattr,
267 };
268 struct nfs3_diropres res = {
269 .dir_attr = &dir_attr,
270 .fh = &fhandle,
271 .fattr = &fattr
272 };
273 struct rpc_message msg = {
274 .rpc_proc = &nfs3_procedures[NFS3PROC_CREATE],
275 .rpc_argp = &arg,
276 .rpc_resp = &res,
277 };
278 mode_t mode = sattr->ia_mode; 309 mode_t mode = sattr->ia_mode;
279 int status; 310 int status = -ENOMEM;
280 311
281 dprintk("NFS call create %s\n", dentry->d_name.name); 312 dprintk("NFS call create %s\n", dentry->d_name.name);
282 arg.createmode = NFS3_CREATE_UNCHECKED; 313
314 data = nfs3_alloc_createdata();
315 if (data == NULL)
316 goto out;
317
318 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_CREATE];
319 data->arg.create.fh = NFS_FH(dir);
320 data->arg.create.name = dentry->d_name.name;
321 data->arg.create.len = dentry->d_name.len;
322 data->arg.create.sattr = sattr;
323
324 data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
283 if (flags & O_EXCL) { 325 if (flags & O_EXCL) {
284 arg.createmode = NFS3_CREATE_EXCLUSIVE; 326 data->arg.create.createmode = NFS3_CREATE_EXCLUSIVE;
285 arg.verifier[0] = jiffies; 327 data->arg.create.verifier[0] = jiffies;
286 arg.verifier[1] = current->pid; 328 data->arg.create.verifier[1] = current->pid;
287 } 329 }
288 330
289 sattr->ia_mode &= ~current->fs->umask; 331 sattr->ia_mode &= ~current->fs->umask;
290 332
291again: 333 for (;;) {
292 nfs_fattr_init(&dir_attr); 334 status = nfs3_do_create(dir, dentry, data);
293 nfs_fattr_init(&fattr);
294 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
295 nfs_refresh_inode(dir, &dir_attr);
296 335
297 /* If the server doesn't support the exclusive creation semantics, 336 if (status != -ENOTSUPP)
298 * try again with simple 'guarded' mode. */ 337 break;
299 if (status == -ENOTSUPP) { 338 /* If the server doesn't support the exclusive creation
300 switch (arg.createmode) { 339 * semantics, try again with simple 'guarded' mode. */
340 switch (data->arg.create.createmode) {
301 case NFS3_CREATE_EXCLUSIVE: 341 case NFS3_CREATE_EXCLUSIVE:
302 arg.createmode = NFS3_CREATE_GUARDED; 342 data->arg.create.createmode = NFS3_CREATE_GUARDED;
303 break; 343 break;
304 344
305 case NFS3_CREATE_GUARDED: 345 case NFS3_CREATE_GUARDED:
306 arg.createmode = NFS3_CREATE_UNCHECKED; 346 data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
307 break; 347 break;
308 348
309 case NFS3_CREATE_UNCHECKED: 349 case NFS3_CREATE_UNCHECKED:
310 goto out; 350 goto out;
311 } 351 }
312 goto again; 352 nfs_fattr_init(data->res.dir_attr);
353 nfs_fattr_init(data->res.fattr);
313 } 354 }
314 355
315 if (status == 0)
316 status = nfs_instantiate(dentry, &fhandle, &fattr);
317 if (status != 0) 356 if (status != 0)
318 goto out; 357 goto out;
319 358
320 /* When we created the file with exclusive semantics, make 359 /* When we created the file with exclusive semantics, make
321 * sure we set the attributes afterwards. */ 360 * sure we set the attributes afterwards. */
322 if (arg.createmode == NFS3_CREATE_EXCLUSIVE) { 361 if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) {
323 dprintk("NFS call setattr (post-create)\n"); 362 dprintk("NFS call setattr (post-create)\n");
324 363
325 if (!(sattr->ia_valid & ATTR_ATIME_SET)) 364 if (!(sattr->ia_valid & ATTR_ATIME_SET))
@@ -330,14 +369,15 @@ again:
330 /* Note: we could use a guarded setattr here, but I'm 369 /* Note: we could use a guarded setattr here, but I'm
331 * not sure this buys us anything (and I'd have 370 * not sure this buys us anything (and I'd have
332 * to revamp the NFSv3 XDR code) */ 371 * to revamp the NFSv3 XDR code) */
333 status = nfs3_proc_setattr(dentry, &fattr, sattr); 372 status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
334 nfs_post_op_update_inode(dentry->d_inode, &fattr); 373 nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
335 dprintk("NFS reply setattr (post-create): %d\n", status); 374 dprintk("NFS reply setattr (post-create): %d\n", status);
375 if (status != 0)
376 goto out;
336 } 377 }
337 if (status != 0)
338 goto out;
339 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 378 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
340out: 379out:
380 nfs3_free_createdata(data);
341 dprintk("NFS reply create: %d\n", status); 381 dprintk("NFS reply create: %d\n", status);
342 return status; 382 return status;
343} 383}
@@ -452,40 +492,28 @@ static int
452nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, 492nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
453 unsigned int len, struct iattr *sattr) 493 unsigned int len, struct iattr *sattr)
454{ 494{
455 struct nfs_fh fhandle; 495 struct nfs3_createdata *data;
456 struct nfs_fattr fattr, dir_attr; 496 int status = -ENOMEM;
457 struct nfs3_symlinkargs arg = {
458 .fromfh = NFS_FH(dir),
459 .fromname = dentry->d_name.name,
460 .fromlen = dentry->d_name.len,
461 .pages = &page,
462 .pathlen = len,
463 .sattr = sattr
464 };
465 struct nfs3_diropres res = {
466 .dir_attr = &dir_attr,
467 .fh = &fhandle,
468 .fattr = &fattr
469 };
470 struct rpc_message msg = {
471 .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK],
472 .rpc_argp = &arg,
473 .rpc_resp = &res,
474 };
475 int status;
476 497
477 if (len > NFS3_MAXPATHLEN) 498 if (len > NFS3_MAXPATHLEN)
478 return -ENAMETOOLONG; 499 return -ENAMETOOLONG;
479 500
480 dprintk("NFS call symlink %s\n", dentry->d_name.name); 501 dprintk("NFS call symlink %s\n", dentry->d_name.name);
481 502
482 nfs_fattr_init(&dir_attr); 503 data = nfs3_alloc_createdata();
483 nfs_fattr_init(&fattr); 504 if (data == NULL)
484 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
485 nfs_post_op_update_inode(dir, &dir_attr);
486 if (status != 0)
487 goto out; 505 goto out;
488 status = nfs_instantiate(dentry, &fhandle, &fattr); 506 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK];
507 data->arg.symlink.fromfh = NFS_FH(dir);
508 data->arg.symlink.fromname = dentry->d_name.name;
509 data->arg.symlink.fromlen = dentry->d_name.len;
510 data->arg.symlink.pages = &page;
511 data->arg.symlink.pathlen = len;
512 data->arg.symlink.sattr = sattr;
513
514 status = nfs3_do_create(dir, dentry, data);
515
516 nfs3_free_createdata(data);
489out: 517out:
490 dprintk("NFS reply symlink: %d\n", status); 518 dprintk("NFS reply symlink: %d\n", status);
491 return status; 519 return status;
@@ -494,42 +522,31 @@ out:
494static int 522static int
495nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) 523nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
496{ 524{
497 struct nfs_fh fhandle; 525 struct nfs3_createdata *data;
498 struct nfs_fattr fattr, dir_attr;
499 struct nfs3_mkdirargs arg = {
500 .fh = NFS_FH(dir),
501 .name = dentry->d_name.name,
502 .len = dentry->d_name.len,
503 .sattr = sattr
504 };
505 struct nfs3_diropres res = {
506 .dir_attr = &dir_attr,
507 .fh = &fhandle,
508 .fattr = &fattr
509 };
510 struct rpc_message msg = {
511 .rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR],
512 .rpc_argp = &arg,
513 .rpc_resp = &res,
514 };
515 int mode = sattr->ia_mode; 526 int mode = sattr->ia_mode;
516 int status; 527 int status = -ENOMEM;
517 528
518 dprintk("NFS call mkdir %s\n", dentry->d_name.name); 529 dprintk("NFS call mkdir %s\n", dentry->d_name.name);
519 530
520 sattr->ia_mode &= ~current->fs->umask; 531 sattr->ia_mode &= ~current->fs->umask;
521 532
522 nfs_fattr_init(&dir_attr); 533 data = nfs3_alloc_createdata();
523 nfs_fattr_init(&fattr); 534 if (data == NULL)
524 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
525 nfs_post_op_update_inode(dir, &dir_attr);
526 if (status != 0)
527 goto out; 535 goto out;
528 status = nfs_instantiate(dentry, &fhandle, &fattr); 536
537 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
538 data->arg.mkdir.fh = NFS_FH(dir);
539 data->arg.mkdir.name = dentry->d_name.name;
540 data->arg.mkdir.len = dentry->d_name.len;
541 data->arg.mkdir.sattr = sattr;
542
543 status = nfs3_do_create(dir, dentry, data);
529 if (status != 0) 544 if (status != 0)
530 goto out; 545 goto out;
546
531 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 547 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
532out: 548out:
549 nfs3_free_createdata(data);
533 dprintk("NFS reply mkdir: %d\n", status); 550 dprintk("NFS reply mkdir: %d\n", status);
534 return status; 551 return status;
535} 552}
@@ -615,52 +632,50 @@ static int
615nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 632nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
616 dev_t rdev) 633 dev_t rdev)
617{ 634{
618 struct nfs_fh fh; 635 struct nfs3_createdata *data;
619 struct nfs_fattr fattr, dir_attr;
620 struct nfs3_mknodargs arg = {
621 .fh = NFS_FH(dir),
622 .name = dentry->d_name.name,
623 .len = dentry->d_name.len,
624 .sattr = sattr,
625 .rdev = rdev
626 };
627 struct nfs3_diropres res = {
628 .dir_attr = &dir_attr,
629 .fh = &fh,
630 .fattr = &fattr
631 };
632 struct rpc_message msg = {
633 .rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD],
634 .rpc_argp = &arg,
635 .rpc_resp = &res,
636 };
637 mode_t mode = sattr->ia_mode; 636 mode_t mode = sattr->ia_mode;
638 int status; 637 int status = -ENOMEM;
639
640 switch (sattr->ia_mode & S_IFMT) {
641 case S_IFBLK: arg.type = NF3BLK; break;
642 case S_IFCHR: arg.type = NF3CHR; break;
643 case S_IFIFO: arg.type = NF3FIFO; break;
644 case S_IFSOCK: arg.type = NF3SOCK; break;
645 default: return -EINVAL;
646 }
647 638
648 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, 639 dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
649 MAJOR(rdev), MINOR(rdev)); 640 MAJOR(rdev), MINOR(rdev));
650 641
651 sattr->ia_mode &= ~current->fs->umask; 642 sattr->ia_mode &= ~current->fs->umask;
652 643
653 nfs_fattr_init(&dir_attr); 644 data = nfs3_alloc_createdata();
654 nfs_fattr_init(&fattr); 645 if (data == NULL)
655 status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
656 nfs_post_op_update_inode(dir, &dir_attr);
657 if (status != 0)
658 goto out; 646 goto out;
659 status = nfs_instantiate(dentry, &fh, &fattr); 647
648 data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
649 data->arg.mknod.fh = NFS_FH(dir);
650 data->arg.mknod.name = dentry->d_name.name;
651 data->arg.mknod.len = dentry->d_name.len;
652 data->arg.mknod.sattr = sattr;
653 data->arg.mknod.rdev = rdev;
654
655 switch (sattr->ia_mode & S_IFMT) {
656 case S_IFBLK:
657 data->arg.mknod.type = NF3BLK;
658 break;
659 case S_IFCHR:
660 data->arg.mknod.type = NF3CHR;
661 break;
662 case S_IFIFO:
663 data->arg.mknod.type = NF3FIFO;
664 break;
665 case S_IFSOCK:
666 data->arg.mknod.type = NF3SOCK;
667 break;
668 default:
669 status = -EINVAL;
670 goto out;
671 }
672
673 status = nfs3_do_create(dir, dentry, data);
660 if (status != 0) 674 if (status != 0)
661 goto out; 675 goto out;
662 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); 676 status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
663out: 677out:
678 nfs3_free_createdata(data);
664 dprintk("NFS reply mknod: %d\n", status); 679 dprintk("NFS reply mknod: %d\n", status);
665 return status; 680 return status;
666} 681}
@@ -801,8 +816,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
801 .write_done = nfs3_write_done, 816 .write_done = nfs3_write_done,
802 .commit_setup = nfs3_proc_commit_setup, 817 .commit_setup = nfs3_proc_commit_setup,
803 .commit_done = nfs3_commit_done, 818 .commit_done = nfs3_commit_done,
804 .file_open = nfs_open,
805 .file_release = nfs_release,
806 .lock = nfs3_proc_lock, 819 .lock = nfs3_proc_lock,
807 .clear_acl_cache = nfs3_forget_cached_acls, 820 .clear_acl_cache = nfs3_forget_cached_acls,
808}; 821};