Commit 8758819a authored by Trond Myklebust's avatar Trond Myklebust

NFSv4/RPCSEC_GSS: Ensure that RPC userland upcalls time out

correctly if the corresponding userland daemon is not up
and running.
parent 29052d81
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/nfs_fs_sb.h> #include <linux/nfs_fs_sb.h>
......
...@@ -27,6 +27,7 @@ struct rpc_inode { ...@@ -27,6 +27,7 @@ struct rpc_inode {
#define RPC_PIPE_WAIT_FOR_OPEN 1 #define RPC_PIPE_WAIT_FOR_OPEN 1
int flags; int flags;
struct rpc_pipe_ops *ops; struct rpc_pipe_ops *ops;
struct work_struct queue_timeout;
}; };
static inline struct rpc_inode * static inline struct rpc_inode *
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/sunrpc/auth.h> #include <linux/sunrpc/auth.h>
#include <linux/sunrpc/auth_gss.h> #include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/gss_err.h> #include <linux/sunrpc/gss_err.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/nfs.h> #include <linux/nfs.h>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h>
static struct vfsmount *rpc_mount; static struct vfsmount *rpc_mount;
...@@ -35,6 +36,8 @@ static struct file_system_type rpc_pipe_fs_type; ...@@ -35,6 +36,8 @@ static struct file_system_type rpc_pipe_fs_type;
static kmem_cache_t *rpc_inode_cachep; static kmem_cache_t *rpc_inode_cachep;
#define RPC_UPCALL_TIMEOUT (30*HZ)
static void static void
__rpc_purge_upcall(struct inode *inode, int err) __rpc_purge_upcall(struct inode *inode, int err)
{ {
...@@ -59,6 +62,18 @@ rpc_purge_upcall(struct inode *inode, int err) ...@@ -59,6 +62,18 @@ rpc_purge_upcall(struct inode *inode, int err)
up(&inode->i_sem); 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 int
rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
{ {
...@@ -66,7 +81,13 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) ...@@ -66,7 +81,13 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
int res = 0; int res = 0;
down(&inode->i_sem); 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); list_add_tail(&msg->list, &rpci->pipe);
rpci->pipelen += msg->len; rpci->pipelen += msg->len;
} else } else
...@@ -80,6 +101,9 @@ void ...@@ -80,6 +101,9 @@ void
rpc_inode_setowner(struct inode *inode, void *private) rpc_inode_setowner(struct inode *inode, void *private)
{ {
struct rpc_inode *rpci = RPC_I(inode); struct rpc_inode *rpci = RPC_I(inode);
cancel_delayed_work(&rpci->queue_timeout);
flush_scheduled_work();
down(&inode->i_sem); down(&inode->i_sem);
rpci->private = private; rpci->private = private;
if (!private) if (!private)
...@@ -133,7 +157,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) ...@@ -133,7 +157,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
down(&inode->i_sem); down(&inode->i_sem);
if (filp->f_mode & FMODE_READ) if (filp->f_mode & FMODE_READ)
rpci->nreaders --; rpci->nreaders --;
if (!rpci->nreaders && !(rpci->flags & RPC_PIPE_WAIT_FOR_OPEN)) if (!rpci->nreaders)
__rpc_purge_upcall(inode, -EPIPE); __rpc_purge_upcall(inode, -EPIPE);
up(&inode->i_sem); up(&inode->i_sem);
return 0; return 0;
...@@ -769,6 +793,7 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -769,6 +793,7 @@ init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
INIT_LIST_HEAD(&rpci->pipe); INIT_LIST_HEAD(&rpci->pipe);
rpci->pipelen = 0; rpci->pipelen = 0;
init_waitqueue_head(&rpci->waitq); init_waitqueue_head(&rpci->waitq);
INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci);
rpci->ops = NULL; rpci->ops = NULL;
} }
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/sunrpc/svc.h> #include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/auth.h> #include <linux/sunrpc/auth.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/rpc_pipe_fs.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment