aboutsummaryrefslogtreecommitdiffstats
path: root/fs/orangefs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-02-18 18:59:44 -0500
committerMike Marshall <hubcap@omnibond.com>2016-02-19 13:45:56 -0500
commit05a50a5be897004b6c1399645256bcf2e768b4ef (patch)
tree084ec3b056a0eca7773dcb58b90177677f487b50 /fs/orangefs
parent5964c1b83912dd5052f66ceb50634df958129981 (diff)
orangefs: have ..._clean_interrupted_...() wait for copy to/from daemon
* turn all those list_del(&op->list) into list_del_init() * don't pick ops that are already given up in control device ->read()/->write_iter(). * have orangefs_clean_interrupted_operation() notice if op is currently being copied to/from daemon (by said ->read()/->write_iter()) and wait for that to finish. * when we are done copying to/from daemon and find that it had been given up while we were doing that, wake the waiting ..._clean_interrupted_... As the result, we are guaranteed that orangefs_clean_interrupted_operation(op) doesn't return until nobody else can see op. Moreover, we don't need to play with op refcounts anymore. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs')
-rw-r--r--fs/orangefs/devorangefs-req.c20
-rw-r--r--fs/orangefs/orangefs-kernel.h2
-rw-r--r--fs/orangefs/waitqueue.c22
3 files changed, 21 insertions, 23 deletions
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index 89c282afeb29..f7914f5d296f 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -58,9 +58,9 @@ static struct orangefs_kernel_op_s *orangefs_devreq_remove_op(__u64 tag)
58 next, 58 next,
59 &htable_ops_in_progress[index], 59 &htable_ops_in_progress[index],
60 list) { 60 list) {
61 if (op->tag == tag && !op_state_purged(op)) { 61 if (op->tag == tag && !op_state_purged(op) &&
62 !op_state_given_up(op)) {
62 list_del_init(&op->list); 63 list_del_init(&op->list);
63 get_op(op); /* increase ref count. */
64 spin_unlock(&htable_ops_in_progress_lock); 64 spin_unlock(&htable_ops_in_progress_lock);
65 return op; 65 return op;
66 } 66 }
@@ -133,7 +133,7 @@ restart:
133 __s32 fsid; 133 __s32 fsid;
134 /* This lock is held past the end of the loop when we break. */ 134 /* This lock is held past the end of the loop when we break. */
135 spin_lock(&op->lock); 135 spin_lock(&op->lock);
136 if (unlikely(op_state_purged(op))) { 136 if (unlikely(op_state_purged(op) || op_state_given_up(op))) {
137 spin_unlock(&op->lock); 137 spin_unlock(&op->lock);
138 continue; 138 continue;
139 } 139 }
@@ -199,13 +199,12 @@ restart:
199 */ 199 */
200 if (op_state_in_progress(cur_op) || op_state_serviced(cur_op)) { 200 if (op_state_in_progress(cur_op) || op_state_serviced(cur_op)) {
201 gossip_err("orangefs: ERROR: Current op already queued.\n"); 201 gossip_err("orangefs: ERROR: Current op already queued.\n");
202 list_del(&cur_op->list); 202 list_del_init(&cur_op->list);
203 spin_unlock(&cur_op->lock); 203 spin_unlock(&cur_op->lock);
204 spin_unlock(&orangefs_request_list_lock); 204 spin_unlock(&orangefs_request_list_lock);
205 return -EAGAIN; 205 return -EAGAIN;
206 } 206 }
207 list_del_init(&cur_op->list); 207 list_del_init(&cur_op->list);
208 get_op(op);
209 spin_unlock(&orangefs_request_list_lock); 208 spin_unlock(&orangefs_request_list_lock);
210 209
211 spin_unlock(&cur_op->lock); 210 spin_unlock(&cur_op->lock);
@@ -230,7 +229,7 @@ restart:
230 if (unlikely(op_state_given_up(cur_op))) { 229 if (unlikely(op_state_given_up(cur_op))) {
231 spin_unlock(&cur_op->lock); 230 spin_unlock(&cur_op->lock);
232 spin_unlock(&htable_ops_in_progress_lock); 231 spin_unlock(&htable_ops_in_progress_lock);
233 op_release(cur_op); 232 complete(&cur_op->waitq);
234 goto restart; 233 goto restart;
235 } 234 }
236 235
@@ -242,7 +241,6 @@ restart:
242 orangefs_devreq_add_op(cur_op); 241 orangefs_devreq_add_op(cur_op);
243 spin_unlock(&cur_op->lock); 242 spin_unlock(&cur_op->lock);
244 spin_unlock(&htable_ops_in_progress_lock); 243 spin_unlock(&htable_ops_in_progress_lock);
245 op_release(cur_op);
246 244
247 /* The client only asks to read one size buffer. */ 245 /* The client only asks to read one size buffer. */
248 return MAX_DEV_REQ_UPSIZE; 246 return MAX_DEV_REQ_UPSIZE;
@@ -258,10 +256,12 @@ error:
258 if (likely(!op_state_given_up(cur_op))) { 256 if (likely(!op_state_given_up(cur_op))) {
259 set_op_state_waiting(cur_op); 257 set_op_state_waiting(cur_op);
260 list_add(&cur_op->list, &orangefs_request_list); 258 list_add(&cur_op->list, &orangefs_request_list);
259 spin_unlock(&cur_op->lock);
260 } else {
261 spin_unlock(&cur_op->lock);
262 complete(&cur_op->waitq);
261 } 263 }
262 spin_unlock(&cur_op->lock);
263 spin_unlock(&orangefs_request_list_lock); 264 spin_unlock(&orangefs_request_list_lock);
264 op_release(cur_op);
265 return -EFAULT; 265 return -EFAULT;
266} 266}
267 267
@@ -405,11 +405,11 @@ wakeup:
405 put_cancel(op); 405 put_cancel(op);
406 } else if (unlikely(op_state_given_up(op))) { 406 } else if (unlikely(op_state_given_up(op))) {
407 spin_unlock(&op->lock); 407 spin_unlock(&op->lock);
408 complete(&op->waitq);
408 } else { 409 } else {
409 set_op_state_serviced(op); 410 set_op_state_serviced(op);
410 spin_unlock(&op->lock); 411 spin_unlock(&op->lock);
411 } 412 }
412 op_release(op);
413 return ret; 413 return ret;
414 414
415Efault: 415Efault:
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 1d20eadaefd8..7d0c8b3afc7e 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -259,7 +259,7 @@ static inline void set_op_state_purged(struct orangefs_kernel_op_s *op)
259{ 259{
260 spin_lock(&op->lock); 260 spin_lock(&op->lock);
261 if (unlikely(op_is_cancel(op))) { 261 if (unlikely(op_is_cancel(op))) {
262 list_del(&op->list); 262 list_del_init(&op->list);
263 spin_unlock(&op->lock); 263 spin_unlock(&op->lock);
264 put_cancel(op); 264 put_cancel(op);
265 } else { 265 } else {
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c
index d980240b0fa7..3f9e43066444 100644
--- a/fs/orangefs/waitqueue.c
+++ b/fs/orangefs/waitqueue.c
@@ -208,15 +208,20 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
208 * Called with op->lock held. 208 * Called with op->lock held.
209 */ 209 */
210 op->op_state |= OP_VFS_STATE_GIVEN_UP; 210 op->op_state |= OP_VFS_STATE_GIVEN_UP;
211 211 /* from that point on it can't be moved by anybody else */
212 if (op_state_waiting(op)) { 212 if (list_empty(&op->list)) {
213 /* caught copying to/from daemon */
214 BUG_ON(op_state_serviced(op));
215 spin_unlock(&op->lock);
216 wait_for_completion(&op->waitq);
217 } else if (op_state_waiting(op)) {
213 /* 218 /*
214 * upcall hasn't been read; remove op from upcall request 219 * upcall hasn't been read; remove op from upcall request
215 * list. 220 * list.
216 */ 221 */
217 spin_unlock(&op->lock); 222 spin_unlock(&op->lock);
218 spin_lock(&orangefs_request_list_lock); 223 spin_lock(&orangefs_request_list_lock);
219 list_del(&op->list); 224 list_del_init(&op->list);
220 spin_unlock(&orangefs_request_list_lock); 225 spin_unlock(&orangefs_request_list_lock);
221 gossip_debug(GOSSIP_WAIT_DEBUG, 226 gossip_debug(GOSSIP_WAIT_DEBUG,
222 "Interrupted: Removed op %p from request_list\n", 227 "Interrupted: Removed op %p from request_list\n",
@@ -225,23 +230,16 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
225 /* op must be removed from the in progress htable */ 230 /* op must be removed from the in progress htable */
226 spin_unlock(&op->lock); 231 spin_unlock(&op->lock);
227 spin_lock(&htable_ops_in_progress_lock); 232 spin_lock(&htable_ops_in_progress_lock);
228 list_del(&op->list); 233 list_del_init(&op->list);
229 spin_unlock(&htable_ops_in_progress_lock); 234 spin_unlock(&htable_ops_in_progress_lock);
230 gossip_debug(GOSSIP_WAIT_DEBUG, 235 gossip_debug(GOSSIP_WAIT_DEBUG,
231 "Interrupted: Removed op %p" 236 "Interrupted: Removed op %p"
232 " from htable_ops_in_progress\n", 237 " from htable_ops_in_progress\n",
233 op); 238 op);
234 } else if (!op_state_serviced(op)) { 239 } else {
235 spin_unlock(&op->lock); 240 spin_unlock(&op->lock);
236 gossip_err("interrupted operation is in a weird state 0x%x\n", 241 gossip_err("interrupted operation is in a weird state 0x%x\n",
237 op->op_state); 242 op->op_state);
238 } else {
239 /*
240 * It is not intended for execution to flow here,
241 * but having this unlock here makes sparse happy.
242 */
243 gossip_err("%s: can't get here.\n", __func__);
244 spin_unlock(&op->lock);
245 } 243 }
246 reinit_completion(&op->waitq); 244 reinit_completion(&op->waitq);
247} 245}