diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-02-13 10:15:22 -0500 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2016-02-19 13:45:53 -0500 |
commit | d2d87a3b6df3088a991e277d42cd6a549ff2bc66 (patch) | |
tree | 7ca20690b8305a13283568762d2e2ab7b69574da /fs/orangefs | |
parent | cf22644a0e5f1a66c61e90da15784effe3ba7ced (diff) |
orangefs: get rid of loop in wait_for_matching_downcall()
turn op->waitq into struct completion...
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/orangefs-cache.c | 2 | ||||
-rw-r--r-- | fs/orangefs/orangefs-kernel.h | 6 | ||||
-rw-r--r-- | fs/orangefs/waitqueue.c | 129 |
3 files changed, 49 insertions, 88 deletions
diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c index 59ab0c207e90..09194e69875f 100644 --- a/fs/orangefs/orangefs-cache.c +++ b/fs/orangefs/orangefs-cache.c | |||
@@ -118,7 +118,7 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type) | |||
118 | if (new_op) { | 118 | if (new_op) { |
119 | INIT_LIST_HEAD(&new_op->list); | 119 | INIT_LIST_HEAD(&new_op->list); |
120 | spin_lock_init(&new_op->lock); | 120 | spin_lock_init(&new_op->lock); |
121 | init_waitqueue_head(&new_op->waitq); | 121 | init_completion(&new_op->waitq); |
122 | 122 | ||
123 | atomic_set(&new_op->ref_count, 1); | 123 | atomic_set(&new_op->ref_count, 1); |
124 | 124 | ||
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 3ceeeaed4143..de898bda7859 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h | |||
@@ -202,7 +202,7 @@ struct orangefs_kernel_op_s { | |||
202 | struct orangefs_upcall_s upcall; | 202 | struct orangefs_upcall_s upcall; |
203 | struct orangefs_downcall_s downcall; | 203 | struct orangefs_downcall_s downcall; |
204 | 204 | ||
205 | wait_queue_head_t waitq; | 205 | struct completion waitq; |
206 | spinlock_t lock; | 206 | spinlock_t lock; |
207 | 207 | ||
208 | struct completion done; | 208 | struct completion done; |
@@ -222,7 +222,7 @@ struct orangefs_kernel_op_s { | |||
222 | static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op) | 222 | static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op) |
223 | { | 223 | { |
224 | op->op_state = OP_VFS_STATE_SERVICED; | 224 | op->op_state = OP_VFS_STATE_SERVICED; |
225 | wake_up_interruptible(&op->waitq); | 225 | complete(&op->waitq); |
226 | } | 226 | } |
227 | 227 | ||
228 | #define op_state_waiting(op) ((op)->op_state & OP_VFS_STATE_WAITING) | 228 | #define op_state_waiting(op) ((op)->op_state & OP_VFS_STATE_WAITING) |
@@ -266,7 +266,7 @@ static inline void set_op_state_purged(struct orangefs_kernel_op_s *op) | |||
266 | put_cancel(op); | 266 | put_cancel(op); |
267 | } else { | 267 | } else { |
268 | op->op_state |= OP_VFS_STATE_PURGED; | 268 | op->op_state |= OP_VFS_STATE_PURGED; |
269 | wake_up_interruptible(&op->waitq); | 269 | complete(&op->waitq); |
270 | spin_unlock(&op->lock); | 270 | spin_unlock(&op->lock); |
271 | } | 271 | } |
272 | } | 272 | } |
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c index 3ea1665efdf0..89622717a06d 100644 --- a/fs/orangefs/waitqueue.c +++ b/fs/orangefs/waitqueue.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "orangefs-bufmap.h" | 17 | #include "orangefs-bufmap.h" |
18 | 18 | ||
19 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *); | 19 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *); |
20 | static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *); | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * What we do in this function is to walk the list of operations that are | 23 | * What we do in this function is to walk the list of operations that are |
@@ -170,8 +171,10 @@ retry_servicing: | |||
170 | gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n", | 171 | gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n", |
171 | op_name); | 172 | op_name); |
172 | } | 173 | } |
174 | orangefs_clean_up_interrupted_operation(op); | ||
173 | op->downcall.status = ret; | 175 | op->downcall.status = ret; |
174 | } else { | 176 | } else { |
177 | spin_unlock(&op->lock); | ||
175 | /* got matching downcall; make sure status is in errno format */ | 178 | /* got matching downcall; make sure status is in errno format */ |
176 | op->downcall.status = | 179 | op->downcall.status = |
177 | orangefs_normalize_to_errno(op->downcall.status); | 180 | orangefs_normalize_to_errno(op->downcall.status); |
@@ -343,6 +346,7 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s | |||
343 | gossip_err("%s: can't get here.\n", __func__); | 346 | gossip_err("%s: can't get here.\n", __func__); |
344 | spin_unlock(&op->lock); | 347 | spin_unlock(&op->lock); |
345 | } | 348 | } |
349 | reinit_completion(&op->waitq); | ||
346 | } | 350 | } |
347 | 351 | ||
348 | /* | 352 | /* |
@@ -359,95 +363,52 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s | |||
359 | * EINTR/EIO/ETIMEDOUT indicating we are done trying to service this | 363 | * EINTR/EIO/ETIMEDOUT indicating we are done trying to service this |
360 | * operation since client-core seems to be exiting too often | 364 | * operation since client-core seems to be exiting too often |
361 | * or if we were interrupted. | 365 | * or if we were interrupted. |
366 | * | ||
367 | * Returns with op->lock taken. | ||
362 | */ | 368 | */ |
363 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op) | 369 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op) |
364 | { | 370 | { |
365 | int ret = -EINVAL; | 371 | long timeout, n; |
366 | DEFINE_WAIT(wait_entry); | ||
367 | 372 | ||
368 | while (1) { | 373 | timeout = op->attempts ? op_timeout_secs * HZ : MAX_SCHEDULE_TIMEOUT; |
369 | spin_lock(&op->lock); | 374 | n = wait_for_completion_interruptible_timeout(&op->waitq, timeout); |
370 | prepare_to_wait(&op->waitq, &wait_entry, TASK_INTERRUPTIBLE); | 375 | spin_lock(&op->lock); |
371 | if (op_state_serviced(op)) { | ||
372 | spin_unlock(&op->lock); | ||
373 | ret = 0; | ||
374 | break; | ||
375 | } | ||
376 | 376 | ||
377 | if (unlikely(signal_pending(current))) { | 377 | if (op_state_serviced(op)) |
378 | gossip_debug(GOSSIP_WAIT_DEBUG, | 378 | return 0; |
379 | "*** %s:" | ||
380 | " operation interrupted by a signal (tag " | ||
381 | "%llu, op %p)\n", | ||
382 | __func__, | ||
383 | llu(op->tag), | ||
384 | op); | ||
385 | orangefs_clean_up_interrupted_operation(op); | ||
386 | ret = -EINTR; | ||
387 | break; | ||
388 | } | ||
389 | 379 | ||
390 | /* | 380 | if (unlikely(n < 0)) { |
391 | * if this was our first attempt and client-core | 381 | gossip_debug(GOSSIP_WAIT_DEBUG, |
392 | * has not purged our operation, we are happy to | 382 | "*** %s:" |
393 | * simply wait | 383 | " operation interrupted by a signal (tag " |
394 | */ | 384 | "%llu, op %p)\n", |
395 | if (op->attempts == 0 && !op_state_purged(op)) { | 385 | __func__, |
396 | spin_unlock(&op->lock); | 386 | llu(op->tag), |
397 | schedule(); | 387 | op); |
398 | } else { | 388 | return -EINTR; |
399 | spin_unlock(&op->lock); | ||
400 | /* | ||
401 | * subsequent attempts, we retry exactly once | ||
402 | * with timeouts | ||
403 | */ | ||
404 | if (!schedule_timeout(op_timeout_secs * HZ)) { | ||
405 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
406 | "*** %s:" | ||
407 | " operation timed out (tag" | ||
408 | " %llu, %p, att %d)\n", | ||
409 | __func__, | ||
410 | llu(op->tag), | ||
411 | op, | ||
412 | op->attempts); | ||
413 | ret = -ETIMEDOUT; | ||
414 | spin_lock(&op->lock); | ||
415 | orangefs_clean_up_interrupted_operation(op); | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | spin_lock(&op->lock); | ||
420 | op->attempts++; | ||
421 | /* | ||
422 | * if the operation was purged in the meantime, it | ||
423 | * is better to requeue it afresh but ensure that | ||
424 | * we have not been purged repeatedly. This could | ||
425 | * happen if client-core crashes when an op | ||
426 | * is being serviced, so we requeue the op, client | ||
427 | * core crashes again so we requeue the op, client | ||
428 | * core starts, and so on... | ||
429 | */ | ||
430 | if (op_state_purged(op)) { | ||
431 | ret = (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ? | ||
432 | -EAGAIN : | ||
433 | -EIO; | ||
434 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
435 | "*** %s:" | ||
436 | " operation purged (tag " | ||
437 | "%llu, %p, att %d)\n", | ||
438 | __func__, | ||
439 | llu(op->tag), | ||
440 | op, | ||
441 | op->attempts); | ||
442 | orangefs_clean_up_interrupted_operation(op); | ||
443 | break; | ||
444 | } | ||
445 | spin_unlock(&op->lock); | ||
446 | } | 389 | } |
447 | 390 | op->attempts++; | |
448 | spin_lock(&op->lock); | 391 | if (op_state_purged(op)) { |
449 | finish_wait(&op->waitq, &wait_entry); | 392 | gossip_debug(GOSSIP_WAIT_DEBUG, |
450 | spin_unlock(&op->lock); | 393 | "*** %s:" |
451 | 394 | " operation purged (tag " | |
452 | return ret; | 395 | "%llu, %p, att %d)\n", |
396 | __func__, | ||
397 | llu(op->tag), | ||
398 | op, | ||
399 | op->attempts); | ||
400 | return (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ? | ||
401 | -EAGAIN : | ||
402 | -EIO; | ||
403 | } | ||
404 | /* must have timed out, then... */ | ||
405 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
406 | "*** %s:" | ||
407 | " operation timed out (tag" | ||
408 | " %llu, %p, att %d)\n", | ||
409 | __func__, | ||
410 | llu(op->tag), | ||
411 | op, | ||
412 | op->attempts); | ||
413 | return -ETIMEDOUT; | ||
453 | } | 414 | } |