diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-27 15:44:19 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-28 13:42:41 -0400 |
commit | e9ab41b620e4b679ed069ab05cb85e67870b7c87 (patch) | |
tree | 4b61840469aadfc05296e8b6859b6640e9d43193 /fs/nfs/idmap.c | |
parent | 0e24d849c4ea777c59955b241fd3af14a1b84af5 (diff) |
NFSv4: Clean up the legacy idmapper upcall
Replace the BUG_ON(idmap->idmap_key_cons != NULL) with a
WARN_ON_ONCE(). Then get rid of the ACCESS_ONCE(idmap->idmap_key_cons).
Then add helper functions for starting, finishing and aborting the
legacy upcall.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Bryan Schumaker <bjschuma@netapp.com>
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r-- | fs/nfs/idmap.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 79f6424aa081..8222ad861456 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -330,7 +330,6 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | |||
330 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | 330 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, |
331 | name, namelen, type, data, | 331 | name, namelen, type, data, |
332 | data_size, idmap); | 332 | data_size, idmap); |
333 | idmap->idmap_key_cons = NULL; | ||
334 | mutex_unlock(&idmap->idmap_mutex); | 333 | mutex_unlock(&idmap->idmap_mutex); |
335 | } | 334 | } |
336 | return ret; | 335 | return ret; |
@@ -662,6 +661,34 @@ out: | |||
662 | return ret; | 661 | return ret; |
663 | } | 662 | } |
664 | 663 | ||
664 | static bool | ||
665 | nfs_idmap_prepare_pipe_upcall(struct idmap *idmap, | ||
666 | struct key_construction *cons) | ||
667 | { | ||
668 | if (idmap->idmap_key_cons != NULL) { | ||
669 | WARN_ON_ONCE(1); | ||
670 | return false; | ||
671 | } | ||
672 | idmap->idmap_key_cons = cons; | ||
673 | return true; | ||
674 | } | ||
675 | |||
676 | static void | ||
677 | nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret) | ||
678 | { | ||
679 | struct key_construction *cons = idmap->idmap_key_cons; | ||
680 | |||
681 | idmap->idmap_key_cons = NULL; | ||
682 | complete_request_key(cons, ret); | ||
683 | } | ||
684 | |||
685 | static void | ||
686 | nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret) | ||
687 | { | ||
688 | if (idmap->idmap_key_cons != NULL) | ||
689 | nfs_idmap_complete_pipe_upcall_locked(idmap, ret); | ||
690 | } | ||
691 | |||
665 | static int nfs_idmap_legacy_upcall(struct key_construction *cons, | 692 | static int nfs_idmap_legacy_upcall(struct key_construction *cons, |
666 | const char *op, | 693 | const char *op, |
667 | void *aux) | 694 | void *aux) |
@@ -686,21 +713,17 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
686 | if (ret < 0) | 713 | if (ret < 0) |
687 | goto out2; | 714 | goto out2; |
688 | 715 | ||
689 | if (idmap->idmap_key_cons != NULL) { | 716 | ret = -EAGAIN; |
690 | WARN_ON_ONCE(1); | 717 | if (!nfs_idmap_prepare_pipe_upcall(idmap, cons)) |
691 | ret = -EAGAIN; | ||
692 | goto out2; | 718 | goto out2; |
693 | } | ||
694 | idmap->idmap_key_cons = cons; | ||
695 | 719 | ||
696 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); | 720 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); |
697 | if (ret < 0) | 721 | if (ret < 0) { |
698 | goto out3; | 722 | nfs_idmap_abort_pipe_upcall(idmap, ret); |
723 | kfree(data); | ||
724 | } | ||
699 | 725 | ||
700 | return ret; | 726 | return ret; |
701 | |||
702 | out3: | ||
703 | idmap->idmap_key_cons = NULL; | ||
704 | out2: | 727 | out2: |
705 | kfree(data); | 728 | kfree(data); |
706 | out1: | 729 | out1: |
@@ -741,14 +764,15 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
741 | struct key_construction *cons; | 764 | struct key_construction *cons; |
742 | struct idmap_msg im; | 765 | struct idmap_msg im; |
743 | size_t namelen_in; | 766 | size_t namelen_in; |
744 | int ret; | 767 | int ret = -ENOKEY; |
745 | 768 | ||
746 | /* If instantiation is successful, anyone waiting for key construction | 769 | /* If instantiation is successful, anyone waiting for key construction |
747 | * will have been woken up and someone else may now have used | 770 | * will have been woken up and someone else may now have used |
748 | * idmap_key_cons - so after this point we may no longer touch it. | 771 | * idmap_key_cons - so after this point we may no longer touch it. |
749 | */ | 772 | */ |
750 | cons = idmap->idmap_key_cons; | 773 | cons = idmap->idmap_key_cons; |
751 | idmap->idmap_key_cons = NULL; | 774 | if (cons == NULL) |
775 | goto out_noupcall; | ||
752 | 776 | ||
753 | if (mlen != sizeof(im)) { | 777 | if (mlen != sizeof(im)) { |
754 | ret = -ENOSPC; | 778 | ret = -ENOSPC; |
@@ -778,7 +802,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
778 | } | 802 | } |
779 | 803 | ||
780 | out: | 804 | out: |
781 | complete_request_key(cons, ret); | 805 | nfs_idmap_complete_pipe_upcall_locked(idmap, ret); |
806 | out_noupcall: | ||
782 | return ret; | 807 | return ret; |
783 | } | 808 | } |
784 | 809 | ||
@@ -789,12 +814,9 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
789 | struct idmap_legacy_upcalldata, | 814 | struct idmap_legacy_upcalldata, |
790 | pipe_msg); | 815 | pipe_msg); |
791 | struct idmap *idmap = data->idmap; | 816 | struct idmap *idmap = data->idmap; |
792 | struct key_construction *cons; | 817 | |
793 | if (msg->errno) { | 818 | if (msg->errno) |
794 | cons = idmap->idmap_key_cons; | 819 | nfs_idmap_abort_pipe_upcall(idmap, msg->errno); |
795 | idmap->idmap_key_cons = NULL; | ||
796 | complete_request_key(cons, msg->errno); | ||
797 | } | ||
798 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ | 820 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ |
799 | kfree(data); | 821 | kfree(data); |
800 | } | 822 | } |
@@ -804,7 +826,8 @@ idmap_release_pipe(struct inode *inode) | |||
804 | { | 826 | { |
805 | struct rpc_inode *rpci = RPC_I(inode); | 827 | struct rpc_inode *rpci = RPC_I(inode); |
806 | struct idmap *idmap = (struct idmap *)rpci->private; | 828 | struct idmap *idmap = (struct idmap *)rpci->private; |
807 | idmap->idmap_key_cons = NULL; | 829 | |
830 | nfs_idmap_abort_pipe_upcall(idmap, -EPIPE); | ||
808 | } | 831 | } |
809 | 832 | ||
810 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 833 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) |