diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-08 14:14:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:33 -0400 |
commit | 62e1761ceff5dbb78c4b4b9486d8ca9fed11b660 (patch) | |
tree | 6d8a31738beec2340ccfe662b352f5aa9b5659f8 /net/sunrpc/rpc_pipe.c | |
parent | 34f308960818e514fadd9365cb5b14cca319320b (diff) |
SUNRPC: Clean up rpc_pipefs.
Add a dentry_ops with a d_delete() method in order to ensure that dentries
are removed as soon as the last reference is gone.
Clean up rpc_depopulate() so that it only removes files that were created
via rpc_populate().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index ebcb8053836e..e5fd796e897e 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -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,17 +621,10 @@ 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 * |
@@ -630,7 +637,9 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusiv | |||
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 && exclusive) { | 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; |
@@ -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); |
@@ -764,14 +773,10 @@ rpc_unlink(struct dentry *dentry) | |||
764 | parent = dget_parent(dentry); | 773 | parent = dget_parent(dentry); |
765 | dir = parent->d_inode; | 774 | dir = parent->d_inode; |
766 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 775 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
767 | if (!d_unhashed(dentry)) { | 776 | rpc_close_pipes(dentry->d_inode); |
768 | d_drop(dentry); | 777 | error = simple_unlink(dir, dentry); |
769 | if (dentry->d_inode) { | 778 | if (!error) |
770 | rpc_close_pipes(dentry->d_inode); | 779 | d_delete(dentry); |
771 | error = simple_unlink(dir, dentry); | ||
772 | } | ||
773 | inode_dir_notify(dir, DN_DELETE); | ||
774 | } | ||
775 | dput(dentry); | 780 | dput(dentry); |
776 | mutex_unlock(&dir->i_mutex); | 781 | mutex_unlock(&dir->i_mutex); |
777 | dput(parent); | 782 | dput(parent); |