diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-27 22:12:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-27 22:12:46 -0400 |
commit | 6070fe6f82c67021367092855c0812a98becf0fa (patch) | |
tree | e3269c7d155bbed9dc701ca00bfb253ed2f7c2c0 /net/sunrpc/rpc_pipe.c | |
parent | bec273b491bd16351a9cdb8e9a51d30afa7fe9f4 (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.c | 29 |
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 | |||
76 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | 76 | rpc_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 | } |
96 | out: | ||
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 | ||
102 | static inline void | ||
103 | rpc_inode_setowner(struct inode *inode, void *private) | ||
104 | { | ||
105 | RPC_I(inode)->private = private; | ||
106 | } | ||
107 | |||
98 | static void | 108 | static void |
99 | rpc_close_pipes(struct inode *inode) | 109 | rpc_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 | ||
117 | static inline void | ||
118 | rpc_inode_setowner(struct inode *inode, void *private) | ||
119 | { | ||
120 | RPC_I(inode)->private = private; | ||
121 | } | ||
122 | |||
123 | static struct inode * | 128 | static struct inode * |
124 | rpc_alloc_inode(struct super_block *sb) | 129 | rpc_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); |