diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-01-10 07:12:38 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 18:20:26 -0500 |
commit | ad6b134008f4e765dd19976552b929273ae523bd (patch) | |
tree | 5f5fbafe5739155cfce6bb0b1e07a9418a72666f /net/sunrpc/rpc_pipe.c | |
parent | 39cb67b9a04300df41e201d9e6392691cdad080f (diff) |
SUNRPC: fix pipe->ops cleanup on pipe dentry unlink
This patch looks late due to GSS AUTH patches sent already. But it fixes a flaw
in RPC PipeFS pipes handling.
I've added this patch in the series, because this series related to pipes. But
it should be a part of previous series named "SUNPRC: cleanup PipeFS for
network-namespace-aware users".
Pipe dentry can be created and destroyed many times during pipe life cycle.
This actually means, that we can't set pipe->ops to NULL in rpc_close_pipes()
and use this variable as a flag, indicating, that pipe's dentry is unlinking.
To follow this restriction, this patch replaces "pipe->ops = NULL" assignment
and checks for NULL with "pipe->dentry = NULL" assignment and checks for
NULL respectively.
This patch also removes check for non-NULL pipe->ops (or pipe->dentry) in
rpc_close_pipes() because it always non-NULL now.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
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 | 51 |
1 files changed, 20 insertions, 31 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 910de4169a8d..6b417fcabdbf 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -86,10 +86,6 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
86 | void (*destroy_msg)(struct rpc_pipe_msg *); | 86 | void (*destroy_msg)(struct rpc_pipe_msg *); |
87 | 87 | ||
88 | spin_lock(&pipe->lock); | 88 | spin_lock(&pipe->lock); |
89 | if (pipe->ops == NULL) { | ||
90 | spin_unlock(&pipe->lock); | ||
91 | return; | ||
92 | } | ||
93 | destroy_msg = pipe->ops->destroy_msg; | 89 | destroy_msg = pipe->ops->destroy_msg; |
94 | if (pipe->nreaders == 0) { | 90 | if (pipe->nreaders == 0) { |
95 | list_splice_init(&pipe->pipe, &free_list); | 91 | list_splice_init(&pipe->pipe, &free_list); |
@@ -135,8 +131,6 @@ rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) | |||
135 | int res = -EPIPE; | 131 | int res = -EPIPE; |
136 | 132 | ||
137 | spin_lock(&pipe->lock); | 133 | spin_lock(&pipe->lock); |
138 | if (pipe->ops == NULL) | ||
139 | goto out; | ||
140 | if (pipe->nreaders) { | 134 | if (pipe->nreaders) { |
141 | list_add_tail(&msg->list, &pipe->pipe); | 135 | list_add_tail(&msg->list, &pipe->pipe); |
142 | pipe->pipelen += msg->len; | 136 | pipe->pipelen += msg->len; |
@@ -150,7 +144,6 @@ rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) | |||
150 | pipe->pipelen += msg->len; | 144 | pipe->pipelen += msg->len; |
151 | res = 0; | 145 | res = 0; |
152 | } | 146 | } |
153 | out: | ||
154 | spin_unlock(&pipe->lock); | 147 | spin_unlock(&pipe->lock); |
155 | wake_up(&pipe->waitq); | 148 | wake_up(&pipe->waitq); |
156 | return res; | 149 | return res; |
@@ -167,27 +160,23 @@ static void | |||
167 | rpc_close_pipes(struct inode *inode) | 160 | rpc_close_pipes(struct inode *inode) |
168 | { | 161 | { |
169 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 162 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
170 | const struct rpc_pipe_ops *ops; | ||
171 | int need_release; | 163 | int need_release; |
164 | LIST_HEAD(free_list); | ||
172 | 165 | ||
173 | mutex_lock(&inode->i_mutex); | 166 | mutex_lock(&inode->i_mutex); |
174 | ops = pipe->ops; | 167 | spin_lock(&pipe->lock); |
175 | if (ops != NULL) { | 168 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; |
176 | LIST_HEAD(free_list); | 169 | pipe->nreaders = 0; |
177 | spin_lock(&pipe->lock); | 170 | list_splice_init(&pipe->in_upcall, &free_list); |
178 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; | 171 | list_splice_init(&pipe->pipe, &free_list); |
179 | pipe->nreaders = 0; | 172 | pipe->pipelen = 0; |
180 | list_splice_init(&pipe->in_upcall, &free_list); | 173 | pipe->dentry = NULL; |
181 | list_splice_init(&pipe->pipe, &free_list); | 174 | spin_unlock(&pipe->lock); |
182 | pipe->pipelen = 0; | 175 | rpc_purge_list(pipe, &free_list, pipe->ops->destroy_msg, -EPIPE); |
183 | pipe->ops = NULL; | 176 | pipe->nwriters = 0; |
184 | spin_unlock(&pipe->lock); | 177 | if (need_release && pipe->ops->release_pipe) |
185 | rpc_purge_list(pipe, &free_list, ops->destroy_msg, -EPIPE); | 178 | pipe->ops->release_pipe(inode); |
186 | pipe->nwriters = 0; | 179 | cancel_delayed_work_sync(&pipe->queue_timeout); |
187 | if (need_release && ops->release_pipe) | ||
188 | ops->release_pipe(inode); | ||
189 | cancel_delayed_work_sync(&pipe->queue_timeout); | ||
190 | } | ||
191 | rpc_inode_setowner(inode, NULL); | 180 | rpc_inode_setowner(inode, NULL); |
192 | mutex_unlock(&inode->i_mutex); | 181 | mutex_unlock(&inode->i_mutex); |
193 | } | 182 | } |
@@ -223,7 +212,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) | |||
223 | int res = -ENXIO; | 212 | int res = -ENXIO; |
224 | 213 | ||
225 | mutex_lock(&inode->i_mutex); | 214 | mutex_lock(&inode->i_mutex); |
226 | if (pipe->ops == NULL) | 215 | if (pipe->dentry == NULL) |
227 | goto out; | 216 | goto out; |
228 | first_open = pipe->nreaders == 0 && pipe->nwriters == 0; | 217 | first_open = pipe->nreaders == 0 && pipe->nwriters == 0; |
229 | if (first_open && pipe->ops->open_pipe) { | 218 | if (first_open && pipe->ops->open_pipe) { |
@@ -249,7 +238,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
249 | int last_close; | 238 | int last_close; |
250 | 239 | ||
251 | mutex_lock(&inode->i_mutex); | 240 | mutex_lock(&inode->i_mutex); |
252 | if (pipe->ops == NULL) | 241 | if (pipe->dentry == NULL) |
253 | goto out; | 242 | goto out; |
254 | msg = filp->private_data; | 243 | msg = filp->private_data; |
255 | if (msg != NULL) { | 244 | if (msg != NULL) { |
@@ -290,7 +279,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
290 | int res = 0; | 279 | int res = 0; |
291 | 280 | ||
292 | mutex_lock(&inode->i_mutex); | 281 | mutex_lock(&inode->i_mutex); |
293 | if (pipe->ops == NULL) { | 282 | if (pipe->dentry == NULL) { |
294 | res = -EPIPE; | 283 | res = -EPIPE; |
295 | goto out_unlock; | 284 | goto out_unlock; |
296 | } | 285 | } |
@@ -333,7 +322,7 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
333 | 322 | ||
334 | mutex_lock(&inode->i_mutex); | 323 | mutex_lock(&inode->i_mutex); |
335 | res = -EPIPE; | 324 | res = -EPIPE; |
336 | if (pipe->ops != NULL) | 325 | if (pipe->dentry != NULL) |
337 | res = pipe->ops->downcall(filp, buf, len); | 326 | res = pipe->ops->downcall(filp, buf, len); |
338 | mutex_unlock(&inode->i_mutex); | 327 | mutex_unlock(&inode->i_mutex); |
339 | return res; | 328 | return res; |
@@ -348,7 +337,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | |||
348 | poll_wait(filp, &pipe->waitq, wait); | 337 | poll_wait(filp, &pipe->waitq, wait); |
349 | 338 | ||
350 | mask = POLLOUT | POLLWRNORM; | 339 | mask = POLLOUT | POLLWRNORM; |
351 | if (pipe->ops == NULL) | 340 | if (pipe->dentry == NULL) |
352 | mask |= POLLERR | POLLHUP; | 341 | mask |= POLLERR | POLLHUP; |
353 | if (filp->private_data || !list_empty(&pipe->pipe)) | 342 | if (filp->private_data || !list_empty(&pipe->pipe)) |
354 | mask |= POLLIN | POLLRDNORM; | 343 | mask |= POLLIN | POLLRDNORM; |
@@ -365,7 +354,7 @@ rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
365 | switch (cmd) { | 354 | switch (cmd) { |
366 | case FIONREAD: | 355 | case FIONREAD: |
367 | spin_lock(&pipe->lock); | 356 | spin_lock(&pipe->lock); |
368 | if (pipe->ops == NULL) { | 357 | if (pipe->dentry == NULL) { |
369 | spin_unlock(&pipe->lock); | 358 | spin_unlock(&pipe->lock); |
370 | return -EPIPE; | 359 | return -EPIPE; |
371 | } | 360 | } |