aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpc_pipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r--net/sunrpc/rpc_pipe.c268
1 files changed, 174 insertions, 94 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index b382809726d..ded6c63f11e 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -414,6 +414,38 @@ rpc_put_mount(void)
414 simple_release_fs(&rpc_mount, &rpc_mount_count); 414 simple_release_fs(&rpc_mount, &rpc_mount_count);
415} 415}
416 416
417static int
418rpc_lookup_parent(char *path, struct nameidata *nd)
419{
420 if (path[0] == '\0')
421 return -ENOENT;
422 if (rpc_get_mount()) {
423 printk(KERN_WARNING "%s: %s failed to mount "
424 "pseudofilesystem \n", __FILE__, __FUNCTION__);
425 return -ENODEV;
426 }
427 nd->mnt = mntget(rpc_mount);
428 nd->dentry = dget(rpc_mount->mnt_root);
429 nd->last_type = LAST_ROOT;
430 nd->flags = LOOKUP_PARENT;
431 nd->depth = 0;
432
433 if (path_walk(path, nd)) {
434 printk(KERN_WARNING "%s: %s failed to find path %s\n",
435 __FILE__, __FUNCTION__, path);
436 rpc_put_mount();
437 return -ENOENT;
438 }
439 return 0;
440}
441
442static void
443rpc_release_path(struct nameidata *nd)
444{
445 path_release(nd);
446 rpc_put_mount();
447}
448
417static struct inode * 449static struct inode *
418rpc_get_inode(struct super_block *sb, int mode) 450rpc_get_inode(struct super_block *sb, int mode)
419{ 451{
@@ -518,149 +550,197 @@ out_bad:
518 return -ENOMEM; 550 return -ENOMEM;
519} 551}
520 552
521struct dentry * 553static int
522rpc_mkdir(struct dentry *parent, char *name, struct rpc_clnt *rpc_client) 554__rpc_mkdir(struct inode *dir, struct dentry *dentry)
523{ 555{
524 struct inode *dir;
525 struct dentry *dentry;
526 struct inode *inode; 556 struct inode *inode;
557
558 inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR);
559 if (!inode)
560 goto out_err;
561 inode->i_ino = iunique(dir->i_sb, 100);
562 d_instantiate(dentry, inode);
563 dir->i_nlink++;
564 inode_dir_notify(dir, DN_CREATE);
565 rpc_get_mount();
566 return 0;
567out_err:
568 printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
569 __FILE__, __FUNCTION__, dentry->d_name.name);
570 return -ENOMEM;
571}
572
573static int
574__rpc_rmdir(struct inode *dir, struct dentry *dentry)
575{
527 int error; 576 int error;
528 577
529 if (!parent) 578 shrink_dcache_parent(dentry);
530 parent = rpc_mount->mnt_root; 579 if (dentry->d_inode) {
580 rpc_close_pipes(dentry->d_inode);
581 rpc_inode_setowner(dentry->d_inode, NULL);
582 }
583 if ((error = simple_rmdir(dir, dentry)) != 0)
584 return error;
585 if (!error) {
586 inode_dir_notify(dir, DN_DELETE);
587 d_drop(dentry);
588 rpc_put_mount();
589 }
590 return 0;
591}
531 592
532 dir = parent->d_inode; 593static struct dentry *
533 594rpc_lookup_negative(char *path, struct nameidata *nd)
534 error = rpc_get_mount(); 595{
535 if (error) 596 struct dentry *dentry;
536 return ERR_PTR(error); 597 struct inode *dir;
598 int error;
537 599
600 if ((error = rpc_lookup_parent(path, nd)) != 0)
601 return ERR_PTR(error);
602 dir = nd->dentry->d_inode;
538 down(&dir->i_sem); 603 down(&dir->i_sem);
539 dentry = lookup_one_len(name, parent, strlen(name)); 604 dentry = lookup_hash(&nd->last, nd->dentry);
540 if (IS_ERR(dentry)) 605 if (IS_ERR(dentry))
541 goto out_unlock; 606 goto out_err;
542 if (dentry->d_inode) { 607 if (dentry->d_inode) {
608 dput(dentry);
543 dentry = ERR_PTR(-EEXIST); 609 dentry = ERR_PTR(-EEXIST);
544 goto out_dput; 610 goto out_err;
545 } 611 }
546 612 return dentry;
547 inode = rpc_get_inode(dir->i_sb, S_IFDIR | S_IRUSR | S_IXUSR); 613out_err:
548 if (!inode)
549 goto out_dput;
550 inode->i_ino = iunique(dir->i_sb, 100);
551 dir->i_nlink++;
552 RPC_I(dentry->d_inode)->private = rpc_client;
553
554 d_instantiate(dentry, inode);
555 dget(dentry);
556 up(&dir->i_sem); 614 up(&dir->i_sem);
615 rpc_release_path(nd);
616 return dentry;
617}
557 618
558 inode_dir_notify(dir, DN_CREATE);
559 619
620struct dentry *
621rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
622{
623 struct nameidata nd;
624 struct dentry *dentry;
625 struct inode *dir;
626 int error;
627
628 dentry = rpc_lookup_negative(path, &nd);
629 if (IS_ERR(dentry))
630 return dentry;
631 dir = nd.dentry->d_inode;
632 if ((error = __rpc_mkdir(dir, dentry)) != 0)
633 goto err_dput;
634 RPC_I(dentry->d_inode)->private = rpc_client;
560 error = rpc_populate(dentry, authfiles, 635 error = rpc_populate(dentry, authfiles,
561 RPCAUTH_info, RPCAUTH_EOF); 636 RPCAUTH_info, RPCAUTH_EOF);
562 if (error) 637 if (error)
563 goto out_depopulate; 638 goto err_depopulate;
564 639out:
565 return dentry;
566
567 out_depopulate:
568 rpc_rmdir(dentry);
569 out_dput:
570 dput(dentry);
571 out_unlock:
572 up(&dir->i_sem); 640 up(&dir->i_sem);
573 rpc_put_mount(); 641 rpc_release_path(&nd);
574 return dentry; 642 return dentry;
643err_depopulate:
644 rpc_depopulate(dentry);
645 __rpc_rmdir(dir, dentry);
646err_dput:
647 dput(dentry);
648 printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
649 __FILE__, __FUNCTION__, path, error);
650 dentry = ERR_PTR(error);
651 goto out;
575} 652}
576 653
577void 654int
578rpc_rmdir(struct dentry *dentry) 655rpc_rmdir(char *path)
579{ 656{
580 struct dentry *parent = dentry->d_parent; 657 struct nameidata nd;
581 658 struct dentry *dentry;
582 rpc_depopulate(dentry); 659 struct inode *dir;
660 int error;
583 661
584 down(&parent->d_inode->i_sem); 662 if ((error = rpc_lookup_parent(path, &nd)) != 0)
585 if (dentry->d_inode) { 663 return error;
586 rpc_close_pipes(dentry->d_inode); 664 dir = nd.dentry->d_inode;
587 rpc_inode_setowner(dentry->d_inode, NULL); 665 down(&dir->i_sem);
588 simple_rmdir(parent->d_inode, dentry); 666 dentry = lookup_hash(&nd.last, nd.dentry);
667 if (IS_ERR(dentry)) {
668 error = PTR_ERR(dentry);
669 goto out_release;
589 } 670 }
590 up(&parent->d_inode->i_sem); 671 rpc_depopulate(dentry);
591 672 error = __rpc_rmdir(dir, dentry);
592 inode_dir_notify(parent->d_inode, DN_DELETE); 673 dput(dentry);
593 rpc_put_mount(); 674out_release:
675 up(&dir->i_sem);
676 rpc_release_path(&nd);
677 return error;
594} 678}
595 679
596struct dentry * 680struct dentry *
597rpc_mkpipe(struct dentry *parent, char *name, void *private, 681rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
598 struct rpc_pipe_ops *ops, int flags)
599{ 682{
600 struct inode *dir = parent->d_inode; 683 struct nameidata nd;
601 struct dentry *dentry; 684 struct dentry *dentry;
602 struct inode *inode; 685 struct inode *dir, *inode;
603 struct rpc_inode *rpci; 686 struct rpc_inode *rpci;
604 int error;
605
606 error = rpc_get_mount();
607 if (error)
608 return ERR_PTR(error);
609 687
610 down(&parent->d_inode->i_sem); 688 dentry = rpc_lookup_negative(path, &nd);
611 dentry = lookup_one_len(name, parent, strlen(name));
612 if (IS_ERR(dentry)) 689 if (IS_ERR(dentry))
613 goto out_unlock; 690 return dentry;
614 if (dentry->d_inode) { 691 dir = nd.dentry->d_inode;
615 dentry = ERR_PTR(-EEXIST); 692 inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR);
616 goto out_dput; 693 if (!inode)
617 } 694 goto err_dput;
618
619 inode = rpc_get_inode(parent->d_inode->i_sb,
620 S_IFSOCK | S_IRUSR | S_IWUSR);
621 if (!inode) {
622 dentry = ERR_PTR(-ENOMEM);
623 goto out_dput;
624 }
625
626 inode->i_ino = iunique(dir->i_sb, 100); 695 inode->i_ino = iunique(dir->i_sb, 100);
627 inode->i_fop = &rpc_pipe_fops; 696 inode->i_fop = &rpc_pipe_fops;
628 697 d_instantiate(dentry, inode);
629 rpci = RPC_I(inode); 698 rpci = RPC_I(inode);
630 rpci->private = private; 699 rpci->private = private;
631 rpci->flags = flags; 700 rpci->flags = flags;
632 rpci->ops = ops; 701 rpci->ops = ops;
633
634 d_instantiate(dentry, inode);
635 dget(dentry);
636 up(&parent->d_inode->i_sem);
637
638 inode_dir_notify(dir, DN_CREATE); 702 inode_dir_notify(dir, DN_CREATE);
703out:
704 up(&dir->i_sem);
705 rpc_release_path(&nd);
639 return dentry; 706 return dentry;
640 707err_dput:
641 out_dput:
642 dput(dentry); 708 dput(dentry);
643 out_unlock: 709 dentry = ERR_PTR(-ENOMEM);
644 up(&parent->d_inode->i_sem); 710 printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n",
645 rpc_put_mount(); 711 __FILE__, __FUNCTION__, path, -ENOMEM);
646 return dentry; 712 goto out;
647} 713}
648 714
649void 715int
650rpc_unlink(struct dentry *dentry) 716rpc_unlink(char *path)
651{ 717{
652 struct dentry *parent = dentry->d_parent; 718 struct nameidata nd;
719 struct dentry *dentry;
720 struct inode *dir;
721 int error;
653 722
654 down(&parent->d_inode->i_sem); 723 if ((error = rpc_lookup_parent(path, &nd)) != 0)
724 return error;
725 dir = nd.dentry->d_inode;
726 down(&dir->i_sem);
727 dentry = lookup_hash(&nd.last, nd.dentry);
728 if (IS_ERR(dentry)) {
729 error = PTR_ERR(dentry);
730 goto out_release;
731 }
732 d_drop(dentry);
655 if (dentry->d_inode) { 733 if (dentry->d_inode) {
656 rpc_close_pipes(dentry->d_inode); 734 rpc_close_pipes(dentry->d_inode);
657 rpc_inode_setowner(dentry->d_inode, NULL); 735 rpc_inode_setowner(dentry->d_inode, NULL);
658 simple_unlink(parent->d_inode, dentry); 736 error = simple_unlink(dir, dentry);
659 } 737 }
660 up(&parent->d_inode->i_sem); 738 dput(dentry);
661 739 inode_dir_notify(dir, DN_DELETE);
662 inode_dir_notify(parent->d_inode, DN_DELETE); 740out_release:
663 rpc_put_mount(); 741 up(&dir->i_sem);
742 rpc_release_path(&nd);
743 return error;
664} 744}
665 745
666/* 746/*