diff options
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 5887457dc936..e787b6a43eee 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -344,7 +344,7 @@ rpc_info_open(struct inode *inode, struct file *file) | |||
344 | mutex_lock(&inode->i_mutex); | 344 | mutex_lock(&inode->i_mutex); |
345 | clnt = RPC_I(inode)->private; | 345 | clnt = RPC_I(inode)->private; |
346 | if (clnt) { | 346 | if (clnt) { |
347 | atomic_inc(&clnt->cl_users); | 347 | kref_get(&clnt->cl_kref); |
348 | m->private = clnt; | 348 | m->private = clnt; |
349 | } else { | 349 | } else { |
350 | single_release(inode, file); | 350 | single_release(inode, file); |
@@ -448,6 +448,15 @@ void rpc_put_mount(void) | |||
448 | simple_release_fs(&rpc_mount, &rpc_mount_count); | 448 | simple_release_fs(&rpc_mount, &rpc_mount_count); |
449 | } | 449 | } |
450 | 450 | ||
451 | static int rpc_delete_dentry(struct dentry *dentry) | ||
452 | { | ||
453 | return 1; | ||
454 | } | ||
455 | |||
456 | static struct dentry_operations rpc_dentry_operations = { | ||
457 | .d_delete = rpc_delete_dentry, | ||
458 | }; | ||
459 | |||
451 | static int | 460 | static int |
452 | rpc_lookup_parent(char *path, struct nameidata *nd) | 461 | rpc_lookup_parent(char *path, struct nameidata *nd) |
453 | { | 462 | { |
@@ -506,7 +515,7 @@ rpc_get_inode(struct super_block *sb, int mode) | |||
506 | * FIXME: This probably has races. | 515 | * FIXME: This probably has races. |
507 | */ | 516 | */ |
508 | static void | 517 | static void |
509 | rpc_depopulate(struct dentry *parent) | 518 | rpc_depopulate(struct dentry *parent, int start, int eof) |
510 | { | 519 | { |
511 | struct inode *dir = parent->d_inode; | 520 | struct inode *dir = parent->d_inode; |
512 | struct list_head *pos, *next; | 521 | struct list_head *pos, *next; |
@@ -518,6 +527,10 @@ repeat: | |||
518 | spin_lock(&dcache_lock); | 527 | spin_lock(&dcache_lock); |
519 | list_for_each_safe(pos, next, &parent->d_subdirs) { | 528 | list_for_each_safe(pos, next, &parent->d_subdirs) { |
520 | dentry = list_entry(pos, struct dentry, d_u.d_child); | 529 | dentry = list_entry(pos, struct dentry, d_u.d_child); |
530 | if (!dentry->d_inode || | ||
531 | dentry->d_inode->i_ino < start || | ||
532 | dentry->d_inode->i_ino >= eof) | ||
533 | continue; | ||
521 | spin_lock(&dentry->d_lock); | 534 | spin_lock(&dentry->d_lock); |
522 | if (!d_unhashed(dentry)) { | 535 | if (!d_unhashed(dentry)) { |
523 | dget_locked(dentry); | 536 | dget_locked(dentry); |
@@ -533,11 +546,11 @@ repeat: | |||
533 | if (n) { | 546 | if (n) { |
534 | do { | 547 | do { |
535 | dentry = dvec[--n]; | 548 | dentry = dvec[--n]; |
536 | if (dentry->d_inode) { | 549 | if (S_ISREG(dentry->d_inode->i_mode)) |
537 | rpc_close_pipes(dentry->d_inode); | ||
538 | simple_unlink(dir, dentry); | 550 | simple_unlink(dir, dentry); |
539 | } | 551 | else if (S_ISDIR(dentry->d_inode->i_mode)) |
540 | inode_dir_notify(dir, DN_DELETE); | 552 | simple_rmdir(dir, dentry); |
553 | d_delete(dentry); | ||
541 | dput(dentry); | 554 | dput(dentry); |
542 | } while (n); | 555 | } while (n); |
543 | goto repeat; | 556 | goto repeat; |
@@ -560,6 +573,7 @@ rpc_populate(struct dentry *parent, | |||
560 | dentry = d_alloc_name(parent, files[i].name); | 573 | dentry = d_alloc_name(parent, files[i].name); |
561 | if (!dentry) | 574 | if (!dentry) |
562 | goto out_bad; | 575 | goto out_bad; |
576 | dentry->d_op = &rpc_dentry_operations; | ||
563 | mode = files[i].mode; | 577 | mode = files[i].mode; |
564 | inode = rpc_get_inode(dir->i_sb, mode); | 578 | inode = rpc_get_inode(dir->i_sb, mode); |
565 | if (!inode) { | 579 | if (!inode) { |
@@ -607,21 +621,14 @@ static int | |||
607 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) | 621 | __rpc_rmdir(struct inode *dir, struct dentry *dentry) |
608 | { | 622 | { |
609 | int error; | 623 | int error; |
610 | 624 | error = simple_rmdir(dir, dentry); | |
611 | shrink_dcache_parent(dentry); | 625 | if (!error) |
612 | if (d_unhashed(dentry)) | 626 | d_delete(dentry); |
613 | return 0; | 627 | return error; |
614 | if ((error = simple_rmdir(dir, dentry)) != 0) | ||
615 | return error; | ||
616 | if (!error) { | ||
617 | inode_dir_notify(dir, DN_DELETE); | ||
618 | d_drop(dentry); | ||
619 | } | ||
620 | return 0; | ||
621 | } | 628 | } |
622 | 629 | ||
623 | static struct dentry * | 630 | static struct dentry * |
624 | rpc_lookup_create(struct dentry *parent, const char *name, int len) | 631 | rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive) |
625 | { | 632 | { |
626 | struct inode *dir = parent->d_inode; | 633 | struct inode *dir = parent->d_inode; |
627 | struct dentry *dentry; | 634 | struct dentry *dentry; |
@@ -630,7 +637,9 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len) | |||
630 | dentry = lookup_one_len(name, parent, len); | 637 | dentry = lookup_one_len(name, parent, len); |
631 | if (IS_ERR(dentry)) | 638 | if (IS_ERR(dentry)) |
632 | goto out_err; | 639 | goto out_err; |
633 | if (dentry->d_inode) { | 640 | if (!dentry->d_inode) |
641 | dentry->d_op = &rpc_dentry_operations; | ||
642 | else if (exclusive) { | ||
634 | dput(dentry); | 643 | dput(dentry); |
635 | dentry = ERR_PTR(-EEXIST); | 644 | dentry = ERR_PTR(-EEXIST); |
636 | goto out_err; | 645 | goto out_err; |
@@ -649,7 +658,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) | |||
649 | 658 | ||
650 | if ((error = rpc_lookup_parent(path, nd)) != 0) | 659 | if ((error = rpc_lookup_parent(path, nd)) != 0) |
651 | return ERR_PTR(error); | 660 | return ERR_PTR(error); |
652 | dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len); | 661 | dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1); |
653 | if (IS_ERR(dentry)) | 662 | if (IS_ERR(dentry)) |
654 | rpc_release_path(nd); | 663 | rpc_release_path(nd); |
655 | return dentry; | 664 | return dentry; |
@@ -681,7 +690,7 @@ out: | |||
681 | rpc_release_path(&nd); | 690 | rpc_release_path(&nd); |
682 | return dentry; | 691 | return dentry; |
683 | err_depopulate: | 692 | err_depopulate: |
684 | rpc_depopulate(dentry); | 693 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); |
685 | __rpc_rmdir(dir, dentry); | 694 | __rpc_rmdir(dir, dentry); |
686 | err_dput: | 695 | err_dput: |
687 | dput(dentry); | 696 | dput(dentry); |
@@ -701,7 +710,7 @@ rpc_rmdir(struct dentry *dentry) | |||
701 | parent = dget_parent(dentry); | 710 | parent = dget_parent(dentry); |
702 | dir = parent->d_inode; | 711 | dir = parent->d_inode; |
703 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 712 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
704 | rpc_depopulate(dentry); | 713 | rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); |
705 | error = __rpc_rmdir(dir, dentry); | 714 | error = __rpc_rmdir(dir, dentry); |
706 | dput(dentry); | 715 | dput(dentry); |
707 | mutex_unlock(&dir->i_mutex); | 716 | mutex_unlock(&dir->i_mutex); |
@@ -716,10 +725,21 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
716 | struct inode *dir, *inode; | 725 | struct inode *dir, *inode; |
717 | struct rpc_inode *rpci; | 726 | struct rpc_inode *rpci; |
718 | 727 | ||
719 | dentry = rpc_lookup_create(parent, name, strlen(name)); | 728 | dentry = rpc_lookup_create(parent, name, strlen(name), 0); |
720 | if (IS_ERR(dentry)) | 729 | if (IS_ERR(dentry)) |
721 | return dentry; | 730 | return dentry; |
722 | dir = parent->d_inode; | 731 | dir = parent->d_inode; |
732 | if (dentry->d_inode) { | ||
733 | rpci = RPC_I(dentry->d_inode); | ||
734 | if (rpci->private != private || | ||
735 | rpci->ops != ops || | ||
736 | rpci->flags != flags) { | ||
737 | dput (dentry); | ||
738 | dentry = ERR_PTR(-EBUSY); | ||
739 | } | ||
740 | rpci->nkern_readwriters++; | ||
741 | goto out; | ||
742 | } | ||
723 | inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR); | 743 | inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR); |
724 | if (!inode) | 744 | if (!inode) |
725 | goto err_dput; | 745 | goto err_dput; |
@@ -730,6 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
730 | rpci->private = private; | 750 | rpci->private = private; |
731 | rpci->flags = flags; | 751 | rpci->flags = flags; |
732 | rpci->ops = ops; | 752 | rpci->ops = ops; |
753 | rpci->nkern_readwriters = 1; | ||
733 | inode_dir_notify(dir, DN_CREATE); | 754 | inode_dir_notify(dir, DN_CREATE); |
734 | dget(dentry); | 755 | dget(dentry); |
735 | out: | 756 | out: |
@@ -754,13 +775,11 @@ rpc_unlink(struct dentry *dentry) | |||
754 | parent = dget_parent(dentry); | 775 | parent = dget_parent(dentry); |
755 | dir = parent->d_inode; | 776 | dir = parent->d_inode; |
756 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 777 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
757 | if (!d_unhashed(dentry)) { | 778 | if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) { |
758 | d_drop(dentry); | 779 | rpc_close_pipes(dentry->d_inode); |
759 | if (dentry->d_inode) { | 780 | error = simple_unlink(dir, dentry); |
760 | rpc_close_pipes(dentry->d_inode); | 781 | if (!error) |
761 | error = simple_unlink(dir, dentry); | 782 | d_delete(dentry); |
762 | } | ||
763 | inode_dir_notify(dir, DN_DELETE); | ||
764 | } | 783 | } |
765 | dput(dentry); | 784 | dput(dentry); |
766 | mutex_unlock(&dir->i_mutex); | 785 | mutex_unlock(&dir->i_mutex); |
@@ -833,6 +852,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) | |||
833 | rpci->nreaders = 0; | 852 | rpci->nreaders = 0; |
834 | rpci->nwriters = 0; | 853 | rpci->nwriters = 0; |
835 | INIT_LIST_HEAD(&rpci->in_upcall); | 854 | INIT_LIST_HEAD(&rpci->in_upcall); |
855 | INIT_LIST_HEAD(&rpci->in_downcall); | ||
836 | INIT_LIST_HEAD(&rpci->pipe); | 856 | INIT_LIST_HEAD(&rpci->pipe); |
837 | rpci->pipelen = 0; | 857 | rpci->pipelen = 0; |
838 | init_waitqueue_head(&rpci->waitq); | 858 | init_waitqueue_head(&rpci->waitq); |