diff -u --recursive --new-file linux-2.6.0-02-auth_gss/include/linux/sunrpc/rpc_pipe_fs.h linux-2.6.0-03-pipe_close/include/linux/sunrpc/rpc_pipe_fs.h --- linux-2.6.0-02-auth_gss/include/linux/sunrpc/rpc_pipe_fs.h 2003-10-14 02:06:23.000000000 -0400 +++ linux-2.6.0-03-pipe_close/include/linux/sunrpc/rpc_pipe_fs.h 2003-10-14 02:07:17.000000000 -0400 @@ -14,6 +14,7 @@ struct rpc_pipe_ops { ssize_t (*upcall)(struct file *, struct rpc_pipe_msg *, char __user *, size_t); ssize_t (*downcall)(struct file *, const char __user *, size_t); + void (*release_pipe)(struct inode *, int, int); void (*destroy_msg)(struct rpc_pipe_msg *); }; @@ -23,6 +24,7 @@ struct list_head pipe; int pipelen; int nreaders; + int nwriters; wait_queue_head_t waitq; #define RPC_PIPE_WAIT_FOR_OPEN 1 int flags; diff -u --recursive --new-file linux-2.6.0-02-auth_gss/net/sunrpc/auth_gss/auth_gss.c linux-2.6.0-03-pipe_close/net/sunrpc/auth_gss/auth_gss.c --- linux-2.6.0-02-auth_gss/net/sunrpc/auth_gss/auth_gss.c 2003-10-14 09:25:59.000000000 -0400 +++ linux-2.6.0-03-pipe_close/net/sunrpc/auth_gss/auth_gss.c 2003-10-14 09:21:17.000000000 -0400 @@ -474,6 +474,37 @@ return err; } +static void +gss_pipe_release(struct inode *inode, int nreaders, int nwriters) +{ + struct rpc_inode *rpci = RPC_I(inode); + struct rpc_clnt *clnt; + struct rpc_auth *auth; + struct gss_auth *gss_auth; + + if (nreaders != 0 || nwriters != 0) + return; + clnt = rpci->private; + atomic_inc(&clnt->cl_users); + auth = clnt->cl_auth; + gss_auth = container_of(auth, struct gss_auth, rpc_auth); + spin_lock(&gss_auth->lock); + while (!list_empty(&gss_auth->upcalls)) { + struct gss_upcall_msg *gss_msg; + + gss_msg = list_entry(gss_auth->upcalls.next, + struct gss_upcall_msg, list); + gss_msg->msg.errno = -EPIPE; + atomic_inc(&gss_msg->count); + __gss_unhash_msg(gss_msg); + spin_unlock(&gss_auth->lock); + gss_release_msg(gss_msg); + spin_lock(&gss_auth->lock); + } + spin_unlock(&gss_auth->lock); + rpc_release_client(clnt); +} + void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) { @@ -773,6 +804,7 @@ .upcall = gss_pipe_upcall, .downcall = gss_pipe_downcall, .destroy_msg = gss_pipe_destroy_msg, + .release_pipe = gss_pipe_release, }; /* diff -u --recursive --new-file linux-2.6.0-02-auth_gss/net/sunrpc/rpc_pipe.c linux-2.6.0-03-pipe_close/net/sunrpc/rpc_pipe.c --- linux-2.6.0-02-auth_gss/net/sunrpc/rpc_pipe.c 2003-10-14 02:06:23.000000000 -0400 +++ linux-2.6.0-03-pipe_close/net/sunrpc/rpc_pipe.c 2003-10-14 02:07:17.000000000 -0400 @@ -137,6 +137,8 @@ if (rpci->private != NULL) { if (filp->f_mode & FMODE_READ) rpci->nreaders ++; + if (filp->f_mode & FMODE_WRITE) + rpci->nwriters ++; res = 0; } up(&inode->i_sem); @@ -155,10 +157,14 @@ rpci->ops->destroy_msg(msg); } down(&inode->i_sem); + if (filp->f_mode & FMODE_WRITE) + rpci->nwriters --; if (filp->f_mode & FMODE_READ) rpci->nreaders --; if (!rpci->nreaders) __rpc_purge_upcall(inode, -EPIPE); + if (rpci->ops->release_pipe) + rpci->ops->release_pipe(inode, rpci->nreaders, rpci->nwriters); up(&inode->i_sem); return 0; }