aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 18:42:14 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 18:42:14 -0400
commit2afdfa5a846246de50e1881f71ba5c0aac0b415f (patch)
treeec9feec128aa105cabb1122806a8078a39be4ebb /fs
parent7297cb682acb506ada2e01fbc9b447b04d69936c (diff)
parent0cac120233305b614cfe3ad419f3655876066017 (diff)
Merge branch 'bugfixes' into nfs-for-next
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/idmap.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 27dde503a6b..675b389cba5 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -55,18 +55,19 @@
55static const struct cred *id_resolver_cache; 55static const struct cred *id_resolver_cache;
56static struct key_type key_type_id_resolver_legacy; 56static struct key_type key_type_id_resolver_legacy;
57 57
58struct idmap {
59 struct rpc_pipe *idmap_pipe;
60 struct key_construction *idmap_key_cons;
61 struct mutex idmap_mutex;
62};
63
64struct idmap_legacy_upcalldata { 58struct idmap_legacy_upcalldata {
65 struct rpc_pipe_msg pipe_msg; 59 struct rpc_pipe_msg pipe_msg;
66 struct idmap_msg idmap_msg; 60 struct idmap_msg idmap_msg;
61 struct key_construction *key_cons;
67 struct idmap *idmap; 62 struct idmap *idmap;
68}; 63};
69 64
65struct idmap {
66 struct rpc_pipe *idmap_pipe;
67 struct idmap_legacy_upcalldata *idmap_upcall_data;
68 struct mutex idmap_mutex;
69};
70
70/** 71/**
71 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields 72 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
72 * @fattr: fully initialised struct nfs_fattr 73 * @fattr: fully initialised struct nfs_fattr
@@ -330,7 +331,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, 331 ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,
331 name, namelen, type, data, 332 name, namelen, type, data,
332 data_size, idmap); 333 data_size, idmap);
333 idmap->idmap_key_cons = NULL;
334 mutex_unlock(&idmap->idmap_mutex); 334 mutex_unlock(&idmap->idmap_mutex);
335 } 335 }
336 return ret; 336 return ret;
@@ -465,8 +465,6 @@ nfs_idmap_new(struct nfs_client *clp)
465 struct rpc_pipe *pipe; 465 struct rpc_pipe *pipe;
466 int error; 466 int error;
467 467
468 BUG_ON(clp->cl_idmap != NULL);
469
470 idmap = kzalloc(sizeof(*idmap), GFP_KERNEL); 468 idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
471 if (idmap == NULL) 469 if (idmap == NULL)
472 return -ENOMEM; 470 return -ENOMEM;
@@ -510,7 +508,6 @@ static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
510 508
511 switch (event) { 509 switch (event) {
512 case RPC_PIPEFS_MOUNT: 510 case RPC_PIPEFS_MOUNT:
513 BUG_ON(clp->cl_rpcclient->cl_dentry == NULL);
514 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, 511 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
515 clp->cl_idmap, 512 clp->cl_idmap,
516 clp->cl_idmap->idmap_pipe); 513 clp->cl_idmap->idmap_pipe);
@@ -662,6 +659,35 @@ out:
662 return ret; 659 return ret;
663} 660}
664 661
662static bool
663nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
664 struct idmap_legacy_upcalldata *data)
665{
666 if (idmap->idmap_upcall_data != NULL) {
667 WARN_ON_ONCE(1);
668 return false;
669 }
670 idmap->idmap_upcall_data = data;
671 return true;
672}
673
674static void
675nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
676{
677 struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
678
679 kfree(idmap->idmap_upcall_data);
680 idmap->idmap_upcall_data = NULL;
681 complete_request_key(cons, ret);
682}
683
684static void
685nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
686{
687 if (idmap->idmap_upcall_data != NULL)
688 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
689}
690
665static int nfs_idmap_legacy_upcall(struct key_construction *cons, 691static int nfs_idmap_legacy_upcall(struct key_construction *cons,
666 const char *op, 692 const char *op,
667 void *aux) 693 void *aux)
@@ -686,17 +712,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
686 if (ret < 0) 712 if (ret < 0)
687 goto out2; 713 goto out2;
688 714
689 BUG_ON(idmap->idmap_key_cons != NULL); 715 ret = -EAGAIN;
690 idmap->idmap_key_cons = cons; 716 if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
717 goto out2;
691 718
692 ret = rpc_queue_upcall(idmap->idmap_pipe, msg); 719 ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
693 if (ret < 0) 720 if (ret < 0)
694 goto out3; 721 nfs_idmap_abort_pipe_upcall(idmap, ret);
695 722
696 return ret; 723 return ret;
697
698out3:
699 idmap->idmap_key_cons = NULL;
700out2: 724out2:
701 kfree(data); 725 kfree(data);
702out1: 726out1:
@@ -711,21 +735,32 @@ static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *dat
711 authkey); 735 authkey);
712} 736}
713 737
714static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey) 738static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
739 struct idmap_msg *upcall,
740 struct key *key, struct key *authkey)
715{ 741{
716 char id_str[NFS_UINT_MAXLEN]; 742 char id_str[NFS_UINT_MAXLEN];
717 int ret = -EINVAL; 743 int ret = -ENOKEY;
718 744
745 /* ret = -ENOKEY */
746 if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
747 goto out;
719 switch (im->im_conv) { 748 switch (im->im_conv) {
720 case IDMAP_CONV_NAMETOID: 749 case IDMAP_CONV_NAMETOID:
750 if (strcmp(upcall->im_name, im->im_name) != 0)
751 break;
721 sprintf(id_str, "%d", im->im_id); 752 sprintf(id_str, "%d", im->im_id);
722 ret = nfs_idmap_instantiate(key, authkey, id_str); 753 ret = nfs_idmap_instantiate(key, authkey, id_str);
723 break; 754 break;
724 case IDMAP_CONV_IDTONAME: 755 case IDMAP_CONV_IDTONAME:
756 if (upcall->im_id != im->im_id)
757 break;
725 ret = nfs_idmap_instantiate(key, authkey, im->im_name); 758 ret = nfs_idmap_instantiate(key, authkey, im->im_name);
726 break; 759 break;
760 default:
761 ret = -EINVAL;
727 } 762 }
728 763out:
729 return ret; 764 return ret;
730} 765}
731 766
@@ -737,14 +772,16 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
737 struct key_construction *cons; 772 struct key_construction *cons;
738 struct idmap_msg im; 773 struct idmap_msg im;
739 size_t namelen_in; 774 size_t namelen_in;
740 int ret; 775 int ret = -ENOKEY;
741 776
742 /* If instantiation is successful, anyone waiting for key construction 777 /* If instantiation is successful, anyone waiting for key construction
743 * will have been woken up and someone else may now have used 778 * will have been woken up and someone else may now have used
744 * idmap_key_cons - so after this point we may no longer touch it. 779 * idmap_key_cons - so after this point we may no longer touch it.
745 */ 780 */
746 cons = ACCESS_ONCE(idmap->idmap_key_cons); 781 if (idmap->idmap_upcall_data == NULL)
747 idmap->idmap_key_cons = NULL; 782 goto out_noupcall;
783
784 cons = idmap->idmap_upcall_data->key_cons;
748 785
749 if (mlen != sizeof(im)) { 786 if (mlen != sizeof(im)) {
750 ret = -ENOSPC; 787 ret = -ENOSPC;
@@ -765,16 +802,19 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
765 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) { 802 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
766 ret = -EINVAL; 803 ret = -EINVAL;
767 goto out; 804 goto out;
768 } 805}
769 806
770 ret = nfs_idmap_read_message(&im, cons->key, cons->authkey); 807 ret = nfs_idmap_read_and_verify_message(&im,
808 &idmap->idmap_upcall_data->idmap_msg,
809 cons->key, cons->authkey);
771 if (ret >= 0) { 810 if (ret >= 0) {
772 key_set_timeout(cons->key, nfs_idmap_cache_timeout); 811 key_set_timeout(cons->key, nfs_idmap_cache_timeout);
773 ret = mlen; 812 ret = mlen;
774 } 813 }
775 814
776out: 815out:
777 complete_request_key(cons, ret); 816 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
817out_noupcall:
778 return ret; 818 return ret;
779} 819}
780 820
@@ -785,14 +825,9 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
785 struct idmap_legacy_upcalldata, 825 struct idmap_legacy_upcalldata,
786 pipe_msg); 826 pipe_msg);
787 struct idmap *idmap = data->idmap; 827 struct idmap *idmap = data->idmap;
788 struct key_construction *cons; 828
789 if (msg->errno) { 829 if (msg->errno)
790 cons = ACCESS_ONCE(idmap->idmap_key_cons); 830 nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
791 idmap->idmap_key_cons = NULL;
792 complete_request_key(cons, msg->errno);
793 }
794 /* Free memory allocated in nfs_idmap_legacy_upcall() */
795 kfree(data);
796} 831}
797 832
798static void 833static void
@@ -800,7 +835,8 @@ idmap_release_pipe(struct inode *inode)
800{ 835{
801 struct rpc_inode *rpci = RPC_I(inode); 836 struct rpc_inode *rpci = RPC_I(inode);
802 struct idmap *idmap = (struct idmap *)rpci->private; 837 struct idmap *idmap = (struct idmap *)rpci->private;
803 idmap->idmap_key_cons = NULL; 838
839 nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
804} 840}
805 841
806int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) 842int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)