Declare a new struct rpc_upcall_info to be added to struct rpc_cred_cache to bookeep a common upcall interface for all gss security mechanisms using the common credcache. The struct rpc_cred_cache reference counting is sufficient to protect this addiion. The first fsid that exports AUTH_GSS will create the upcall pipe. Signed-off-by: Andy Adamson --- diff -puN include/linux/sunrpc/auth.h~gss-common-upcall-init include/linux/sunrpc/auth.h --- linux-2.6.18-rc5/include/linux/sunrpc/auth.h~gss-common-upcall-init 2006-10-17 15:05:43.000000000 -0400 +++ linux-2.6.18-rc5-andros/include/linux/sunrpc/auth.h 2006-10-17 15:05:43.000000000 -0400 @@ -59,8 +59,17 @@ struct rpc_cred { */ #define RPC_CREDCACHE_NR 8 #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1) +struct rpc_upcall_info { + struct list_head upcalls; /* upcalls in progress */ + spinlock_t lock; /* protects upcall list */ + u32 mkey; /* message key enumerator */ + wait_queue_head_t waitqueue; /* RPC task waiting on upcall */ + struct dentry *dentry; /* upcall pipe */ +}; + struct rpc_cred_cache { struct hlist_head hashtable[RPC_CREDCACHE_NR]; + struct rpc_upcall_info *info; /* common gss upcall */ struct kref ref; struct list_head auth_list; /* cred cache entry auth types */ }; @@ -162,6 +171,7 @@ void rpcauth_invalcred(struct rpc_task int rpcauth_uptodatecred(struct rpc_task *); int rpcauth_init_credcache(struct rpc_clnt *); void rpcauth_free_credcache(struct rpc_clnt *); +struct rpc_upcall_info * rpcauth_create_upcall_info(void); static inline struct rpc_cred * get_rpccred(struct rpc_cred *cred) diff -puN net/sunrpc/auth.c~gss-common-upcall-init net/sunrpc/auth.c --- linux-2.6.18-rc5/net/sunrpc/auth.c~gss-common-upcall-init 2006-10-17 15:05:43.000000000 -0400 +++ linux-2.6.18-rc5-andros/net/sunrpc/auth.c 2006-10-17 15:05:43.000000000 -0400 @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH @@ -61,6 +62,33 @@ rpcauth_unregister(struct rpc_authops *o return 0; } +struct rpc_upcall_info * +rpcauth_create_upcall_info(void) +{ + struct rpc_upcall_info *info; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + info = ERR_PTR(-ENOMEM); + goto out; + } + INIT_LIST_HEAD(&info->upcalls); + spin_lock_init(&info->lock); + info->mkey = 0; + init_waitqueue_head(&info->waitqueue); + info->dentry = NULL; +out: + return info; +} + +/*Caller releases rpc_upcall_info->upcalls */ +void +rpcauth_free_upcall_info(struct rpc_upcall_info *info) +{ + rpc_unlink(info->dentry); + kfree(info); +} + static DEFINE_SPINLOCK(rpc_credcache_lock); static struct rpc_auth * @@ -140,6 +168,7 @@ rpcauth_init_credcache(struct rpc_clnt * err = 0; for (i = 0; i < RPC_CREDCACHE_NR; i++) INIT_HLIST_HEAD(&new->hashtable[i]); + new->info = NULL; kref_init(&new->ref); INIT_LIST_HEAD(&new->auth_list); done: _