From: Trond Myklebust NFSv4/RPCSEC_GSS: Ensure that RPC userland upcalls time out correctly if the corresponding userland daemon is not up and running. --- fs/nfs/idmap.c | 1 + include/linux/sunrpc/rpc_pipe_fs.h | 1 + net/sunrpc/auth_gss/auth_gss.c | 1 + net/sunrpc/clnt.c | 1 + net/sunrpc/rpc_pipe.c | 29 +++++++++++++++++++++++++++-- net/sunrpc/sunrpc_syms.c | 1 + 6 files changed, 32 insertions(+), 2 deletions(-) diff -puN fs/nfs/idmap.c~nfs-01-rpc_pipe_timeout fs/nfs/idmap.c --- 25/fs/nfs/idmap.c~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/fs/nfs/idmap.c 2004-01-09 22:16:03.000000000 -0800 @@ -43,6 +43,7 @@ #include #include +#include #include #include diff -puN include/linux/sunrpc/rpc_pipe_fs.h~nfs-01-rpc_pipe_timeout include/linux/sunrpc/rpc_pipe_fs.h --- 25/include/linux/sunrpc/rpc_pipe_fs.h~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/include/linux/sunrpc/rpc_pipe_fs.h 2004-01-09 22:16:03.000000000 -0800 @@ -27,6 +27,7 @@ struct rpc_inode { #define RPC_PIPE_WAIT_FOR_OPEN 1 int flags; struct rpc_pipe_ops *ops; + struct work_struct queue_timeout; }; static inline struct rpc_inode * diff -puN net/sunrpc/auth_gss/auth_gss.c~nfs-01-rpc_pipe_timeout net/sunrpc/auth_gss/auth_gss.c --- 25/net/sunrpc/auth_gss/auth_gss.c~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/net/sunrpc/auth_gss/auth_gss.c 2004-01-09 22:16:03.000000000 -0800 @@ -49,6 +49,7 @@ #include #include #include +#include #include #include diff -puN net/sunrpc/clnt.c~nfs-01-rpc_pipe_timeout net/sunrpc/clnt.c --- 25/net/sunrpc/clnt.c~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/net/sunrpc/clnt.c 2004-01-09 22:16:03.000000000 -0800 @@ -30,6 +30,7 @@ #include #include +#include #include #include diff -puN net/sunrpc/rpc_pipe.c~nfs-01-rpc_pipe_timeout net/sunrpc/rpc_pipe.c --- 25/net/sunrpc/rpc_pipe.c~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/net/sunrpc/rpc_pipe.c 2004-01-09 22:16:03.000000000 -0800 @@ -25,6 +25,7 @@ #include #include +#include #include static struct vfsmount *rpc_mount; @@ -35,6 +36,8 @@ static struct file_system_type rpc_pipe_ static kmem_cache_t *rpc_inode_cachep; +#define RPC_UPCALL_TIMEOUT (30*HZ) + static void __rpc_purge_upcall(struct inode *inode, int err) { @@ -59,6 +62,18 @@ rpc_purge_upcall(struct inode *inode, in up(&inode->i_sem); } +static void +rpc_timeout_upcall_queue(void *data) +{ + struct rpc_inode *rpci = (struct rpc_inode *)data; + struct inode *inode = &rpci->vfs_inode; + + down(&inode->i_sem); + if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) + __rpc_purge_upcall(inode, -ETIMEDOUT); + up(&inode->i_sem); +} + int rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) { @@ -66,7 +81,13 @@ rpc_queue_upcall(struct inode *inode, st int res = 0; down(&inode->i_sem); - if (rpci->nreaders || (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN)) { + if (rpci->nreaders) { + list_add_tail(&msg->list, &rpci->pipe); + rpci->pipelen += msg->len; + } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) { + if (list_empty(&rpci->pipe)) + schedule_delayed_work(&rpci->queue_timeout, + RPC_UPCALL_TIMEOUT); list_add_tail(&msg->list, &rpci->pipe); rpci->pipelen += msg->len; } else @@ -80,6 +101,9 @@ void rpc_inode_setowner(struct inode *inode, void *private) { struct rpc_inode *rpci = RPC_I(inode); + + cancel_delayed_work(&rpci->queue_timeout); + flush_scheduled_work(); down(&inode->i_sem); rpci->private = private; if (!private) @@ -133,7 +157,7 @@ rpc_pipe_release(struct inode *inode, st down(&inode->i_sem); if (filp->f_mode & FMODE_READ) rpci->nreaders --; - if (!rpci->nreaders && !(rpci->flags & RPC_PIPE_WAIT_FOR_OPEN)) + if (!rpci->nreaders) __rpc_purge_upcall(inode, -EPIPE); up(&inode->i_sem); return 0; @@ -769,6 +793,7 @@ init_once(void * foo, kmem_cache_t * cac INIT_LIST_HEAD(&rpci->pipe); rpci->pipelen = 0; init_waitqueue_head(&rpci->waitq); + INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci); rpci->ops = NULL; } } diff -puN net/sunrpc/sunrpc_syms.c~nfs-01-rpc_pipe_timeout net/sunrpc/sunrpc_syms.c --- 25/net/sunrpc/sunrpc_syms.c~nfs-01-rpc_pipe_timeout 2004-01-09 22:16:03.000000000 -0800 +++ 25-akpm/net/sunrpc/sunrpc_syms.c 2004-01-09 22:16:03.000000000 -0800 @@ -21,6 +21,7 @@ #include #include #include +#include #include _