]> err.no Git - linux-2.6/blobdiff - net/sunrpc/rpc_pipe.c
Merge master.kernel.org:/home/rmk/linux-2.6-serial
[linux-2.6] / net / sunrpc / rpc_pipe.c
index 81e00a6c19def97230e09f0302029c5ef04f82e9..24cc23af9b95d7d0ca1950ce7bcaf5ac098bdc6f 100644 (file)
@@ -39,23 +39,26 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly;
 #define RPC_UPCALL_TIMEOUT (30*HZ)
 
 static void
-__rpc_purge_upcall(struct inode *inode, int err)
+__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err)
 {
-       struct rpc_inode *rpci = RPC_I(inode);
        struct rpc_pipe_msg *msg;
+       void (*destroy_msg)(struct rpc_pipe_msg *);
 
-       while (!list_empty(&rpci->pipe)) {
-               msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list);
-               list_del_init(&msg->list);
-               msg->errno = err;
-               rpci->ops->destroy_msg(msg);
-       }
-       while (!list_empty(&rpci->in_upcall)) {
-               msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list);
+       destroy_msg = rpci->ops->destroy_msg;
+       while (!list_empty(head)) {
+               msg = list_entry(head->next, struct rpc_pipe_msg, list);
                list_del_init(&msg->list);
                msg->errno = err;
-               rpci->ops->destroy_msg(msg);
+               destroy_msg(msg);
        }
+}
+
+static void
+__rpc_purge_upcall(struct inode *inode, int err)
+{
+       struct rpc_inode *rpci = RPC_I(inode);
+
+       __rpc_purge_list(rpci, &rpci->pipe, err);
        rpci->pipelen = 0;
        wake_up(&rpci->waitq);
 }
@@ -67,8 +70,11 @@ rpc_timeout_upcall_queue(void *data)
        struct inode *inode = &rpci->vfs_inode;
 
        down(&inode->i_sem);
+       if (rpci->ops == NULL)
+               goto out;
        if (rpci->nreaders == 0 && !list_empty(&rpci->pipe))
                __rpc_purge_upcall(inode, -ETIMEDOUT);
+out:
        up(&inode->i_sem);
 }
 
@@ -110,11 +116,10 @@ rpc_close_pipes(struct inode *inode)
 {
        struct rpc_inode *rpci = RPC_I(inode);
 
-       cancel_delayed_work(&rpci->queue_timeout);
-       flush_scheduled_work();
        down(&inode->i_sem);
        if (rpci->ops != NULL) {
                rpci->nreaders = 0;
+               __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE);
                __rpc_purge_upcall(inode, -EPIPE);
                rpci->nwriters = 0;
                if (rpci->ops->release_pipe)
@@ -123,6 +128,8 @@ rpc_close_pipes(struct inode *inode)
        }
        rpc_inode_setowner(inode, NULL);
        up(&inode->i_sem);
+       cancel_delayed_work(&rpci->queue_timeout);
+       flush_scheduled_work();
 }
 
 static struct inode *
@@ -162,7 +169,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp)
 static int
 rpc_pipe_release(struct inode *inode, struct file *filp)
 {
-       struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+       struct rpc_inode *rpci = RPC_I(inode);
        struct rpc_pipe_msg *msg;
 
        down(&inode->i_sem);
@@ -170,7 +177,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
                goto out;
        msg = (struct rpc_pipe_msg *)filp->private_data;
        if (msg != NULL) {
-               msg->errno = -EPIPE;
+               msg->errno = -EAGAIN;
                list_del_init(&msg->list);
                rpci->ops->destroy_msg(msg);
        }
@@ -179,7 +186,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
        if (filp->f_mode & FMODE_READ)
                rpci->nreaders --;
        if (!rpci->nreaders)
-               __rpc_purge_upcall(inode, -EPIPE);
+               __rpc_purge_upcall(inode, -EAGAIN);
        if (rpci->ops->release_pipe)
                rpci->ops->release_pipe(inode);
 out: