diff options
-rw-r--r-- | include/linux/sunrpc/rpc_pipe_fs.h | 2 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 39 |
2 files changed, 27 insertions, 14 deletions
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index 426ce6eeee66..a7b422b33eda 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h | |||
@@ -28,7 +28,6 @@ struct rpc_pipe { | |||
28 | int pipelen; | 28 | int pipelen; |
29 | int nreaders; | 29 | int nreaders; |
30 | int nwriters; | 30 | int nwriters; |
31 | wait_queue_head_t waitq; | ||
32 | #define RPC_PIPE_WAIT_FOR_OPEN 1 | 31 | #define RPC_PIPE_WAIT_FOR_OPEN 1 |
33 | int flags; | 32 | int flags; |
34 | struct delayed_work queue_timeout; | 33 | struct delayed_work queue_timeout; |
@@ -41,6 +40,7 @@ struct rpc_inode { | |||
41 | struct inode vfs_inode; | 40 | struct inode vfs_inode; |
42 | void *private; | 41 | void *private; |
43 | struct rpc_pipe *pipe; | 42 | struct rpc_pipe *pipe; |
43 | wait_queue_head_t waitq; | ||
44 | }; | 44 | }; |
45 | 45 | ||
46 | static inline struct rpc_inode * | 46 | static inline struct rpc_inode * |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index b67b2aecc4ff..ac9ee1590739 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -57,7 +57,7 @@ void rpc_pipefs_notifier_unregister(struct notifier_block *nb) | |||
57 | } | 57 | } |
58 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister); | 58 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister); |
59 | 59 | ||
60 | static void rpc_purge_list(struct rpc_pipe *pipe, struct list_head *head, | 60 | static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, |
61 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) | 61 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) |
62 | { | 62 | { |
63 | struct rpc_pipe_msg *msg; | 63 | struct rpc_pipe_msg *msg; |
@@ -70,7 +70,7 @@ static void rpc_purge_list(struct rpc_pipe *pipe, struct list_head *head, | |||
70 | msg->errno = err; | 70 | msg->errno = err; |
71 | destroy_msg(msg); | 71 | destroy_msg(msg); |
72 | } while (!list_empty(head)); | 72 | } while (!list_empty(head)); |
73 | wake_up(&pipe->waitq); | 73 | wake_up(waitq); |
74 | } | 74 | } |
75 | 75 | ||
76 | static void | 76 | static void |
@@ -80,6 +80,7 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
80 | struct rpc_pipe *pipe = | 80 | struct rpc_pipe *pipe = |
81 | container_of(work, struct rpc_pipe, queue_timeout.work); | 81 | container_of(work, struct rpc_pipe, queue_timeout.work); |
82 | void (*destroy_msg)(struct rpc_pipe_msg *); | 82 | void (*destroy_msg)(struct rpc_pipe_msg *); |
83 | struct dentry *dentry; | ||
83 | 84 | ||
84 | spin_lock(&pipe->lock); | 85 | spin_lock(&pipe->lock); |
85 | destroy_msg = pipe->ops->destroy_msg; | 86 | destroy_msg = pipe->ops->destroy_msg; |
@@ -87,8 +88,13 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
87 | list_splice_init(&pipe->pipe, &free_list); | 88 | list_splice_init(&pipe->pipe, &free_list); |
88 | pipe->pipelen = 0; | 89 | pipe->pipelen = 0; |
89 | } | 90 | } |
91 | dentry = dget(pipe->dentry); | ||
90 | spin_unlock(&pipe->lock); | 92 | spin_unlock(&pipe->lock); |
91 | rpc_purge_list(pipe, &free_list, destroy_msg, -ETIMEDOUT); | 93 | if (dentry) { |
94 | rpc_purge_list(&RPC_I(dentry->d_inode)->waitq, | ||
95 | &free_list, destroy_msg, -ETIMEDOUT); | ||
96 | dput(dentry); | ||
97 | } | ||
92 | } | 98 | } |
93 | 99 | ||
94 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | 100 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, |
@@ -125,6 +131,7 @@ int | |||
125 | rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) | 131 | rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) |
126 | { | 132 | { |
127 | int res = -EPIPE; | 133 | int res = -EPIPE; |
134 | struct dentry *dentry; | ||
128 | 135 | ||
129 | spin_lock(&pipe->lock); | 136 | spin_lock(&pipe->lock); |
130 | if (pipe->nreaders) { | 137 | if (pipe->nreaders) { |
@@ -140,8 +147,12 @@ rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) | |||
140 | pipe->pipelen += msg->len; | 147 | pipe->pipelen += msg->len; |
141 | res = 0; | 148 | res = 0; |
142 | } | 149 | } |
150 | dentry = dget(pipe->dentry); | ||
143 | spin_unlock(&pipe->lock); | 151 | spin_unlock(&pipe->lock); |
144 | wake_up(&pipe->waitq); | 152 | if (dentry) { |
153 | wake_up(&RPC_I(dentry->d_inode)->waitq); | ||
154 | dput(dentry); | ||
155 | } | ||
145 | return res; | 156 | return res; |
146 | } | 157 | } |
147 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); | 158 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); |
@@ -168,7 +179,7 @@ rpc_close_pipes(struct inode *inode) | |||
168 | pipe->pipelen = 0; | 179 | pipe->pipelen = 0; |
169 | pipe->dentry = NULL; | 180 | pipe->dentry = NULL; |
170 | spin_unlock(&pipe->lock); | 181 | spin_unlock(&pipe->lock); |
171 | rpc_purge_list(pipe, &free_list, pipe->ops->destroy_msg, -EPIPE); | 182 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE); |
172 | pipe->nwriters = 0; | 183 | pipe->nwriters = 0; |
173 | if (need_release && pipe->ops->release_pipe) | 184 | if (need_release && pipe->ops->release_pipe) |
174 | pipe->ops->release_pipe(inode); | 185 | pipe->ops->release_pipe(inode); |
@@ -257,7 +268,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
257 | list_splice_init(&pipe->pipe, &free_list); | 268 | list_splice_init(&pipe->pipe, &free_list); |
258 | pipe->pipelen = 0; | 269 | pipe->pipelen = 0; |
259 | spin_unlock(&pipe->lock); | 270 | spin_unlock(&pipe->lock); |
260 | rpc_purge_list(pipe, &free_list, | 271 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, |
261 | pipe->ops->destroy_msg, -EAGAIN); | 272 | pipe->ops->destroy_msg, -EAGAIN); |
262 | } | 273 | } |
263 | } | 274 | } |
@@ -330,16 +341,18 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
330 | static unsigned int | 341 | static unsigned int |
331 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | 342 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) |
332 | { | 343 | { |
333 | struct rpc_pipe *pipe = RPC_I(filp->f_path.dentry->d_inode)->pipe; | 344 | struct inode *inode = filp->f_path.dentry->d_inode; |
334 | unsigned int mask = 0; | 345 | struct rpc_inode *rpci = RPC_I(inode); |
346 | unsigned int mask = POLLOUT | POLLWRNORM; | ||
335 | 347 | ||
336 | poll_wait(filp, &pipe->waitq, wait); | 348 | poll_wait(filp, &rpci->waitq, wait); |
337 | 349 | ||
338 | mask = POLLOUT | POLLWRNORM; | 350 | mutex_lock(&inode->i_mutex); |
339 | if (pipe->dentry == NULL) | 351 | if (rpci->pipe == NULL) |
340 | mask |= POLLERR | POLLHUP; | 352 | mask |= POLLERR | POLLHUP; |
341 | if (filp->private_data || !list_empty(&pipe->pipe)) | 353 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) |
342 | mask |= POLLIN | POLLRDNORM; | 354 | mask |= POLLIN | POLLRDNORM; |
355 | mutex_unlock(&inode->i_mutex); | ||
343 | return mask; | 356 | return mask; |
344 | } | 357 | } |
345 | 358 | ||
@@ -543,7 +556,6 @@ init_pipe(struct rpc_pipe *pipe) | |||
543 | INIT_LIST_HEAD(&pipe->in_downcall); | 556 | INIT_LIST_HEAD(&pipe->in_downcall); |
544 | INIT_LIST_HEAD(&pipe->pipe); | 557 | INIT_LIST_HEAD(&pipe->pipe); |
545 | pipe->pipelen = 0; | 558 | pipe->pipelen = 0; |
546 | init_waitqueue_head(&pipe->waitq); | ||
547 | INIT_DELAYED_WORK(&pipe->queue_timeout, | 559 | INIT_DELAYED_WORK(&pipe->queue_timeout, |
548 | rpc_timeout_upcall_queue); | 560 | rpc_timeout_upcall_queue); |
549 | pipe->ops = NULL; | 561 | pipe->ops = NULL; |
@@ -1165,6 +1177,7 @@ init_once(void *foo) | |||
1165 | inode_init_once(&rpci->vfs_inode); | 1177 | inode_init_once(&rpci->vfs_inode); |
1166 | rpci->private = NULL; | 1178 | rpci->private = NULL; |
1167 | rpci->pipe = NULL; | 1179 | rpci->pipe = NULL; |
1180 | init_waitqueue_head(&rpci->waitq); | ||
1168 | } | 1181 | } |
1169 | 1182 | ||
1170 | int register_rpc_pipefs(void) | 1183 | int register_rpc_pipefs(void) |