aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpc_pipe.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-27 22:12:46 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-27 22:12:46 -0400
commit6070fe6f82c67021367092855c0812a98becf0fa (patch)
treee3269c7d155bbed9dc701ca00bfb253ed2f7c2c0 /net/sunrpc/rpc_pipe.c
parentbec273b491bd16351a9cdb8e9a51d30afa7fe9f4 (diff)
RPC: Ensure that nobody can queue up new upcalls after rpc_close_pipes()
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r--net/sunrpc/rpc_pipe.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ded6c63f11ec..4f188d0a5d11 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -76,25 +76,35 @@ int
76rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) 76rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
77{ 77{
78 struct rpc_inode *rpci = RPC_I(inode); 78 struct rpc_inode *rpci = RPC_I(inode);
79 int res = 0; 79 int res = -EPIPE;
80 80
81 down(&inode->i_sem); 81 down(&inode->i_sem);
82 if (rpci->ops == NULL)
83 goto out;
82 if (rpci->nreaders) { 84 if (rpci->nreaders) {
83 list_add_tail(&msg->list, &rpci->pipe); 85 list_add_tail(&msg->list, &rpci->pipe);
84 rpci->pipelen += msg->len; 86 rpci->pipelen += msg->len;
87 res = 0;
85 } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) { 88 } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
86 if (list_empty(&rpci->pipe)) 89 if (list_empty(&rpci->pipe))
87 schedule_delayed_work(&rpci->queue_timeout, 90 schedule_delayed_work(&rpci->queue_timeout,
88 RPC_UPCALL_TIMEOUT); 91 RPC_UPCALL_TIMEOUT);
89 list_add_tail(&msg->list, &rpci->pipe); 92 list_add_tail(&msg->list, &rpci->pipe);
90 rpci->pipelen += msg->len; 93 rpci->pipelen += msg->len;
91 } else 94 res = 0;
92 res = -EPIPE; 95 }
96out:
93 up(&inode->i_sem); 97 up(&inode->i_sem);
94 wake_up(&rpci->waitq); 98 wake_up(&rpci->waitq);
95 return res; 99 return res;
96} 100}
97 101
102static inline void
103rpc_inode_setowner(struct inode *inode, void *private)
104{
105 RPC_I(inode)->private = private;
106}
107
98static void 108static void
99rpc_close_pipes(struct inode *inode) 109rpc_close_pipes(struct inode *inode)
100{ 110{
@@ -111,15 +121,10 @@ rpc_close_pipes(struct inode *inode)
111 rpci->ops->release_pipe(inode); 121 rpci->ops->release_pipe(inode);
112 rpci->ops = NULL; 122 rpci->ops = NULL;
113 } 123 }
124 rpc_inode_setowner(inode, NULL);
114 up(&inode->i_sem); 125 up(&inode->i_sem);
115} 126}
116 127
117static inline void
118rpc_inode_setowner(struct inode *inode, void *private)
119{
120 RPC_I(inode)->private = private;
121}
122
123static struct inode * 128static struct inode *
124rpc_alloc_inode(struct super_block *sb) 129rpc_alloc_inode(struct super_block *sb)
125{ 130{
@@ -501,7 +506,6 @@ repeat:
501 dentry = dvec[--n]; 506 dentry = dvec[--n];
502 if (dentry->d_inode) { 507 if (dentry->d_inode) {
503 rpc_close_pipes(dentry->d_inode); 508 rpc_close_pipes(dentry->d_inode);
504 rpc_inode_setowner(dentry->d_inode, NULL);
505 simple_unlink(dir, dentry); 509 simple_unlink(dir, dentry);
506 } 510 }
507 dput(dentry); 511 dput(dentry);
@@ -576,10 +580,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
576 int error; 580 int error;
577 581
578 shrink_dcache_parent(dentry); 582 shrink_dcache_parent(dentry);
579 if (dentry->d_inode) { 583 if (dentry->d_inode)
580 rpc_close_pipes(dentry->d_inode); 584 rpc_close_pipes(dentry->d_inode);
581 rpc_inode_setowner(dentry->d_inode, NULL);
582 }
583 if ((error = simple_rmdir(dir, dentry)) != 0) 585 if ((error = simple_rmdir(dir, dentry)) != 0)
584 return error; 586 return error;
585 if (!error) { 587 if (!error) {
@@ -732,7 +734,6 @@ rpc_unlink(char *path)
732 d_drop(dentry); 734 d_drop(dentry);
733 if (dentry->d_inode) { 735 if (dentry->d_inode) {
734 rpc_close_pipes(dentry->d_inode); 736 rpc_close_pipes(dentry->d_inode);
735 rpc_inode_setowner(dentry->d_inode, NULL);
736 error = simple_unlink(dir, dentry); 737 error = simple_unlink(dir, dentry);
737 } 738 }
738 dput(dentry); 739 dput(dentry);