

Add a key to struct gss_msg. While the uid will still be used to search the
upcall message list in __gss_find_upcall() to determine if a request is already
posted, the new gss_msg->rq_mkey will be used by gss_pipe_downcall to match
a received downcall with the appropriate upcall message in the struct
rpc_upcall_info upcall queue.

Signed-off-by: Andy Adamson <andros@citi.umich.edu>

---


diff -puN net/sunrpc/auth_gss/auth_gss.c~gss-common-pipe net/sunrpc/auth_gss/auth_gss.c
--- linux-2.6.18-rc5/net/sunrpc/auth_gss/auth_gss.c~gss-common-pipe	2006-10-17 15:38:54.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth_gss/auth_gss.c	2006-10-17 15:42:29.000000000 -0400
@@ -114,6 +114,7 @@ struct gss_auth {
 	struct rpc_auth rpc_auth;
 	struct rpc_upcall_info *info;
 	struct gss_api_mech *mech;
+	u32 mkey;
 	enum rpc_gss_svc service;
 	struct rpc_clnt *client;
 	struct dentry *dentry;
@@ -322,6 +323,7 @@ err:
 struct gss_upcall_msg {
 	atomic_t count;
 	uid_t	uid;
+	u32	rq_mkey;
 	struct rpc_pipe_msg msg;
 	struct list_head list;
 	struct gss_auth *auth;
@@ -343,6 +345,21 @@ gss_release_msg(struct gss_upcall_msg *g
 }
 
 static struct gss_upcall_msg *
+__gss_find_upcall_msg(struct gss_auth *gss_auth, u32 mkey)
+{
+	struct gss_upcall_msg *pos;
+	list_for_each_entry(pos, &gss_auth->info->upcalls, list) {
+		if (pos->rq_mkey != mkey)
+			continue;
+		atomic_inc(&pos->count);
+		dprintk("RPC:      gss_find_upcall_msg found msg %p\n", pos);
+		return pos;
+	}
+	dprintk("RPC:      gss_find_upcall_msg found nothing\n");
+	return NULL;
+}
+
+static struct gss_upcall_msg *
 __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
 {
 	struct gss_upcall_msg *pos;
@@ -462,9 +479,10 @@ gss_init_msg_upcall_info(struct gss_upca
 	get_current_keyrings(&skey, &pkey, &tkey);
 
 	len = snprintf(gss_msg->upcall_info, sizeof(gss_msg->upcall_info),
-		 "%s %d %d %d %d %d %d %d",
-		 krinfo->op, tsk->fsuid, tsk->fsgid, krinfo->key->serial,
-		 krinfo->authkey->serial, tkey, pkey, skey);
+		 "%s %d %d %d %d %d %d %d %d",
+		 krinfo->op, tsk->fsuid, gss_msg->rq_mkey, tsk->fsgid,
+		 krinfo->key->serial, krinfo->authkey->serial,
+		 tkey, pkey, skey);
 	if (len >= sizeof(gss_msg->upcall_info)) {
 		dprintk("%s: returning error (len %d)\n", __FUNCTION__, len);
 		return -1;
@@ -486,6 +504,9 @@ gss_alloc_msg(struct gss_auth *gss_auth,
 		INIT_LIST_HEAD(&gss_msg->list);
 		rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
 		atomic_set(&gss_msg->count, 1);
+		spin_lock(&gss_auth->info->lock);
+		gss_msg->rq_mkey = gss_auth->info->mkey++;
+		spin_unlock(&gss_auth->info->lock);
 #ifdef CONFIG_RPCSEC_GSS_KEYRING
 		if (gss_init_msg_upcall_info(gss_msg, krinfo)) {
 			gss_release_msg(gss_msg);
@@ -499,6 +520,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
 #else
 		gss_msg->msg.data = &gss_msg->uid;
 		gss_msg->msg.len = sizeof(gss_msg->uid);
+		gss_msg->msg.len = sizeof(gss_msg->uid) + sizeof(gss_msg->rq_mkey);
 #endif
 		gss_msg->uid = uid;
 		gss_msg->auth = gss_auth;
@@ -666,6 +688,7 @@ gss_pipe_downcall(struct file *filp, con
 	struct gss_upcall_msg *gss_msg;
 	struct gss_cl_ctx *ctx;
 	char principal[32];
+	u32 mkey;
 	uid_t uid;
 #ifdef CONFIG_RPCSEC_GSS_KEYRING
 	key_serial_t skey, pkey, tkey;
@@ -691,6 +714,12 @@ gss_pipe_downcall(struct file *filp, con
 		err = PTR_ERR(p);
 		goto err;
 	}
+	p = simple_get_bytes(p, end, &mkey, sizeof(mkey));
+	if (IS_ERR(p)) {
+		err = PTR_ERR(p);
+		goto err;
+	}
+
 #ifdef CONFIG_RPCSEC_GSS_KEYRING
 	p = simple_get_bytes(p, end, &skey, sizeof(skey));
 	if (IS_ERR(p)) {
@@ -723,7 +752,7 @@ gss_pipe_downcall(struct file *filp, con
 			goto err_put_ctx;
 	}
 	spin_lock(&gss_auth->info->lock);
-	gss_msg = __gss_find_upcall(gss_auth, uid);
+	gss_msg = __gss_find_upcall_msg(gss_auth, mkey);
 	if (gss_msg) {
 		if (err == 0 && gss_msg->ctx == NULL)
 			gss_msg->ctx = gss_get_ctx(ctx);
_
