diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-02-11 23:07:19 -0500 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2016-02-19 13:45:53 -0500 |
commit | 78699e29fd784a4613d254a22627f336c55c4a76 (patch) | |
tree | c3a8d93a89dd7abed775cdd27a9349cbbd0e539c /fs/orangefs | |
parent | 1357d06d49d1f87af48ab768d34af55bff18b0c3 (diff) |
orangefs: delay freeing slot until cancel completes
Make cancels reuse the aborted read/write op, to make sure they do not
fail on lack of memory.
Don't issue a cancel unless the daemon has seen our read/write, has not
replied and isn't being shut down.
If cancel *is* issued, don't wait for it to complete; stash the slot
in there and just have it freed when cancel is finally replied to or
purged (and delay dropping the reference until then, obviously).
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.c | 7 | ||||
-rw-r--r-- | fs/orangefs/file.c | 16 | ||||
-rw-r--r-- | fs/orangefs/orangefs-cache.c | 16 | ||||
-rw-r--r-- | fs/orangefs/orangefs-kernel.h | 40 | ||||
-rw-r--r-- | fs/orangefs/orangefs-mod.c | 2 | ||||
-rw-r--r-- | fs/orangefs/orangefs-utils.c | 32 | ||||
-rw-r--r-- | fs/orangefs/waitqueue.c | 133 |
7 files changed, 93 insertions, 153 deletions
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index 37278f5878b3..6a7df1204bfc 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c | |||
@@ -438,6 +438,8 @@ wakeup: | |||
438 | } | 438 | } |
439 | } | 439 | } |
440 | out: | 440 | out: |
441 | if (unlikely(op_is_cancel(op))) | ||
442 | put_cancel(op); | ||
441 | op_release(op); | 443 | op_release(op); |
442 | return ret; | 444 | return ret; |
443 | 445 | ||
@@ -546,6 +548,11 @@ int is_daemon_in_service(void) | |||
546 | return in_service; | 548 | return in_service; |
547 | } | 549 | } |
548 | 550 | ||
551 | bool __is_daemon_in_service(void) | ||
552 | { | ||
553 | return open_access_count == 1; | ||
554 | } | ||
555 | |||
549 | static inline long check_ioctl_command(unsigned int command) | 556 | static inline long check_ioctl_command(unsigned int command) |
550 | { | 557 | { |
551 | /* Check for valid ioctl codes */ | 558 | /* Check for valid ioctl codes */ |
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index 193671c137c3..3b1e9e83eb91 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c | |||
@@ -182,17 +182,6 @@ populate_shared_memory: | |||
182 | 182 | ||
183 | if (ret < 0) { | 183 | if (ret < 0) { |
184 | /* | 184 | /* |
185 | * XXX: needs to be optimized - we only need to cancel if it | ||
186 | * had been seen by daemon and not completed | ||
187 | */ | ||
188 | if (!op_state_serviced(new_op)) { | ||
189 | orangefs_cancel_op_in_progress(new_op->tag); | ||
190 | } else { | ||
191 | complete(&new_op->done); | ||
192 | } | ||
193 | orangefs_bufmap_put(buffer_index); | ||
194 | buffer_index = -1; | ||
195 | /* | ||
196 | * don't write an error to syslog on signaled operation | 185 | * don't write an error to syslog on signaled operation |
197 | * termination unless we've got debugging turned on, as | 186 | * termination unless we've got debugging turned on, as |
198 | * this can happen regularly (i.e. ctrl-c) | 187 | * this can happen regularly (i.e. ctrl-c) |
@@ -207,7 +196,10 @@ populate_shared_memory: | |||
207 | type == ORANGEFS_IO_READ ? | 196 | type == ORANGEFS_IO_READ ? |
208 | "read from" : "write to", | 197 | "read from" : "write to", |
209 | handle, ret); | 198 | handle, ret); |
210 | goto out; | 199 | if (orangefs_cancel_op_in_progress(new_op)) |
200 | return ret; | ||
201 | |||
202 | goto done_copying; | ||
211 | } | 203 | } |
212 | 204 | ||
213 | /* | 205 | /* |
diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c index 3b3de91406ca..59ab0c207e90 100644 --- a/fs/orangefs/orangefs-cache.c +++ b/fs/orangefs/orangefs-cache.c | |||
@@ -101,6 +101,15 @@ char *get_opname_string(struct orangefs_kernel_op_s *new_op) | |||
101 | return "OP_UNKNOWN?"; | 101 | return "OP_UNKNOWN?"; |
102 | } | 102 | } |
103 | 103 | ||
104 | void orangefs_new_tag(struct orangefs_kernel_op_s *op) | ||
105 | { | ||
106 | spin_lock(&next_tag_value_lock); | ||
107 | op->tag = next_tag_value++; | ||
108 | if (next_tag_value == 0) | ||
109 | next_tag_value = 100; | ||
110 | spin_unlock(&next_tag_value_lock); | ||
111 | } | ||
112 | |||
104 | struct orangefs_kernel_op_s *op_alloc(__s32 type) | 113 | struct orangefs_kernel_op_s *op_alloc(__s32 type) |
105 | { | 114 | { |
106 | struct orangefs_kernel_op_s *new_op = NULL; | 115 | struct orangefs_kernel_op_s *new_op = NULL; |
@@ -120,14 +129,9 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type) | |||
120 | new_op->downcall.status = -1; | 129 | new_op->downcall.status = -1; |
121 | 130 | ||
122 | new_op->op_state = OP_VFS_STATE_UNKNOWN; | 131 | new_op->op_state = OP_VFS_STATE_UNKNOWN; |
123 | new_op->tag = 0; | ||
124 | 132 | ||
125 | /* initialize the op specific tag and upcall credentials */ | 133 | /* initialize the op specific tag and upcall credentials */ |
126 | spin_lock(&next_tag_value_lock); | 134 | orangefs_new_tag(new_op); |
127 | new_op->tag = next_tag_value++; | ||
128 | if (next_tag_value == 0) | ||
129 | next_tag_value = 100; | ||
130 | spin_unlock(&next_tag_value_lock); | ||
131 | new_op->upcall.type = type; | 135 | new_op->upcall.type = type; |
132 | new_op->attempts = 0; | 136 | new_op->attempts = 0; |
133 | gossip_debug(GOSSIP_CACHE_DEBUG, | 137 | gossip_debug(GOSSIP_CACHE_DEBUG, |
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index a8cde9019efe..3ceeeaed4143 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h | |||
@@ -190,9 +190,14 @@ struct orangefs_kernel_op_s { | |||
190 | /* | 190 | /* |
191 | * Set uses_shared_memory to 1 if this operation uses shared memory. | 191 | * Set uses_shared_memory to 1 if this operation uses shared memory. |
192 | * If true, then a retry on the op must also get a new shared memory | 192 | * If true, then a retry on the op must also get a new shared memory |
193 | * buffer and re-populate it. | 193 | * buffer and re-populate it. Cancels don't care - it only matters |
194 | * for service_operation() retry logics and cancels don't go through | ||
195 | * it anymore. | ||
194 | */ | 196 | */ |
195 | int uses_shared_memory; | 197 | union { |
198 | int uses_shared_memory; | ||
199 | int slot_to_free; | ||
200 | }; | ||
196 | 201 | ||
197 | struct orangefs_upcall_s upcall; | 202 | struct orangefs_upcall_s upcall; |
198 | struct orangefs_downcall_s downcall; | 203 | struct orangefs_downcall_s downcall; |
@@ -219,17 +224,13 @@ static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op) | |||
219 | op->op_state = OP_VFS_STATE_SERVICED; | 224 | op->op_state = OP_VFS_STATE_SERVICED; |
220 | wake_up_interruptible(&op->waitq); | 225 | wake_up_interruptible(&op->waitq); |
221 | } | 226 | } |
222 | static inline void set_op_state_purged(struct orangefs_kernel_op_s *op) | ||
223 | { | ||
224 | op->op_state |= OP_VFS_STATE_PURGED; | ||
225 | wake_up_interruptible(&op->waitq); | ||
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) |
229 | #define op_state_in_progress(op) ((op)->op_state & OP_VFS_STATE_INPROGR) | 229 | #define op_state_in_progress(op) ((op)->op_state & OP_VFS_STATE_INPROGR) |
230 | #define op_state_serviced(op) ((op)->op_state & OP_VFS_STATE_SERVICED) | 230 | #define op_state_serviced(op) ((op)->op_state & OP_VFS_STATE_SERVICED) |
231 | #define op_state_purged(op) ((op)->op_state & OP_VFS_STATE_PURGED) | 231 | #define op_state_purged(op) ((op)->op_state & OP_VFS_STATE_PURGED) |
232 | #define op_state_given_up(op) ((op)->op_state & OP_VFS_STATE_GIVEN_UP) | 232 | #define op_state_given_up(op) ((op)->op_state & OP_VFS_STATE_GIVEN_UP) |
233 | #define op_is_cancel(op) ((op)->upcall.type == ORANGEFS_VFS_OP_CANCEL) | ||
233 | 234 | ||
234 | static inline void get_op(struct orangefs_kernel_op_s *op) | 235 | static inline void get_op(struct orangefs_kernel_op_s *op) |
235 | { | 236 | { |
@@ -249,6 +250,27 @@ static inline void op_release(struct orangefs_kernel_op_s *op) | |||
249 | } | 250 | } |
250 | } | 251 | } |
251 | 252 | ||
253 | extern void orangefs_bufmap_put(int); | ||
254 | static inline void put_cancel(struct orangefs_kernel_op_s *op) | ||
255 | { | ||
256 | orangefs_bufmap_put(op->slot_to_free); | ||
257 | op_release(op); | ||
258 | } | ||
259 | |||
260 | static inline void set_op_state_purged(struct orangefs_kernel_op_s *op) | ||
261 | { | ||
262 | spin_lock(&op->lock); | ||
263 | if (unlikely(op_is_cancel(op))) { | ||
264 | list_del(&op->list); | ||
265 | spin_unlock(&op->lock); | ||
266 | put_cancel(op); | ||
267 | } else { | ||
268 | op->op_state |= OP_VFS_STATE_PURGED; | ||
269 | wake_up_interruptible(&op->waitq); | ||
270 | spin_unlock(&op->lock); | ||
271 | } | ||
272 | } | ||
273 | |||
252 | /* per inode private orangefs info */ | 274 | /* per inode private orangefs info */ |
253 | struct orangefs_inode_s { | 275 | struct orangefs_inode_s { |
254 | struct orangefs_object_kref refn; | 276 | struct orangefs_object_kref refn; |
@@ -448,6 +470,7 @@ static inline int match_handle(struct orangefs_khandle resp_handle, | |||
448 | int op_cache_initialize(void); | 470 | int op_cache_initialize(void); |
449 | int op_cache_finalize(void); | 471 | int op_cache_finalize(void); |
450 | struct orangefs_kernel_op_s *op_alloc(__s32 type); | 472 | struct orangefs_kernel_op_s *op_alloc(__s32 type); |
473 | void orangefs_new_tag(struct orangefs_kernel_op_s *op); | ||
451 | char *get_opname_string(struct orangefs_kernel_op_s *new_op); | 474 | char *get_opname_string(struct orangefs_kernel_op_s *new_op); |
452 | 475 | ||
453 | int orangefs_inode_cache_initialize(void); | 476 | int orangefs_inode_cache_initialize(void); |
@@ -528,6 +551,7 @@ ssize_t orangefs_inode_read(struct inode *inode, | |||
528 | int orangefs_dev_init(void); | 551 | int orangefs_dev_init(void); |
529 | void orangefs_dev_cleanup(void); | 552 | void orangefs_dev_cleanup(void); |
530 | int is_daemon_in_service(void); | 553 | int is_daemon_in_service(void); |
554 | bool __is_daemon_in_service(void); | ||
531 | int fs_mount_pending(__s32 fsid); | 555 | int fs_mount_pending(__s32 fsid); |
532 | 556 | ||
533 | /* | 557 | /* |
@@ -562,7 +586,7 @@ void orangefs_set_signals(sigset_t *); | |||
562 | 586 | ||
563 | int orangefs_unmount_sb(struct super_block *sb); | 587 | int orangefs_unmount_sb(struct super_block *sb); |
564 | 588 | ||
565 | int orangefs_cancel_op_in_progress(__u64 tag); | 589 | bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op); |
566 | 590 | ||
567 | static inline __u64 orangefs_convert_time_field(const struct timespec *ts) | 591 | static inline __u64 orangefs_convert_time_field(const struct timespec *ts) |
568 | { | 592 | { |
diff --git a/fs/orangefs/orangefs-mod.c b/fs/orangefs/orangefs-mod.c index 7639ab2df711..965959cb11d1 100644 --- a/fs/orangefs/orangefs-mod.c +++ b/fs/orangefs/orangefs-mod.c | |||
@@ -260,14 +260,12 @@ void purge_inprogress_ops(void) | |||
260 | next, | 260 | next, |
261 | &htable_ops_in_progress[i], | 261 | &htable_ops_in_progress[i], |
262 | list) { | 262 | list) { |
263 | spin_lock(&op->lock); | ||
264 | gossip_debug(GOSSIP_INIT_DEBUG, | 263 | gossip_debug(GOSSIP_INIT_DEBUG, |
265 | "pvfs2-client-core: purging in-progress op tag " | 264 | "pvfs2-client-core: purging in-progress op tag " |
266 | "%llu %s\n", | 265 | "%llu %s\n", |
267 | llu(op->tag), | 266 | llu(op->tag), |
268 | get_opname_string(op)); | 267 | get_opname_string(op)); |
269 | set_op_state_purged(op); | 268 | set_op_state_purged(op); |
270 | spin_unlock(&op->lock); | ||
271 | } | 269 | } |
272 | spin_unlock(&htable_ops_in_progress_lock); | 270 | spin_unlock(&htable_ops_in_progress_lock); |
273 | } | 271 | } |
diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index fa3ed8ad35be..08f9c2dab0fe 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c | |||
@@ -688,38 +688,6 @@ int orangefs_unmount_sb(struct super_block *sb) | |||
688 | return ret; | 688 | return ret; |
689 | } | 689 | } |
690 | 690 | ||
691 | /* | ||
692 | * NOTE: on successful cancellation, be sure to return -EINTR, as | ||
693 | * that's the return value the caller expects | ||
694 | */ | ||
695 | int orangefs_cancel_op_in_progress(__u64 tag) | ||
696 | { | ||
697 | int ret = -EINVAL; | ||
698 | struct orangefs_kernel_op_s *new_op = NULL; | ||
699 | |||
700 | gossip_debug(GOSSIP_UTILS_DEBUG, | ||
701 | "orangefs_cancel_op_in_progress called on tag %llu\n", | ||
702 | llu(tag)); | ||
703 | |||
704 | new_op = op_alloc(ORANGEFS_VFS_OP_CANCEL); | ||
705 | if (!new_op) | ||
706 | return -ENOMEM; | ||
707 | new_op->upcall.req.cancel.op_tag = tag; | ||
708 | |||
709 | gossip_debug(GOSSIP_UTILS_DEBUG, | ||
710 | "Attempting ORANGEFS operation cancellation of tag %llu\n", | ||
711 | llu(new_op->upcall.req.cancel.op_tag)); | ||
712 | |||
713 | ret = service_operation(new_op, "orangefs_cancel", ORANGEFS_OP_CANCELLATION); | ||
714 | |||
715 | gossip_debug(GOSSIP_UTILS_DEBUG, | ||
716 | "orangefs_cancel_op_in_progress: got return value of %d\n", | ||
717 | ret); | ||
718 | |||
719 | op_release(new_op); | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | void orangefs_make_bad_inode(struct inode *inode) | 691 | void orangefs_make_bad_inode(struct inode *inode) |
724 | { | 692 | { |
725 | if (is_root_handle(inode)) { | 693 | if (is_root_handle(inode)) { |
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c index 191d886ccc57..3ea1665efdf0 100644 --- a/fs/orangefs/waitqueue.c +++ b/fs/orangefs/waitqueue.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include "orangefs-kernel.h" | 16 | #include "orangefs-kernel.h" |
17 | #include "orangefs-bufmap.h" | 17 | #include "orangefs-bufmap.h" |
18 | 18 | ||
19 | static int wait_for_cancellation_downcall(struct orangefs_kernel_op_s *); | ||
20 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *); | 19 | static int wait_for_matching_downcall(struct orangefs_kernel_op_s *); |
21 | 20 | ||
22 | /* | 21 | /* |
@@ -36,25 +35,29 @@ void purge_waiting_ops(void) | |||
36 | "pvfs2-client-core: purging op tag %llu %s\n", | 35 | "pvfs2-client-core: purging op tag %llu %s\n", |
37 | llu(op->tag), | 36 | llu(op->tag), |
38 | get_opname_string(op)); | 37 | get_opname_string(op)); |
39 | spin_lock(&op->lock); | ||
40 | set_op_state_purged(op); | 38 | set_op_state_purged(op); |
41 | spin_unlock(&op->lock); | ||
42 | } | 39 | } |
43 | spin_unlock(&orangefs_request_list_lock); | 40 | spin_unlock(&orangefs_request_list_lock); |
44 | } | 41 | } |
45 | 42 | ||
46 | static inline void | 43 | static inline void |
47 | add_op_to_request_list(struct orangefs_kernel_op_s *op) | 44 | __add_op_to_request_list(struct orangefs_kernel_op_s *op) |
48 | { | 45 | { |
49 | spin_lock(&orangefs_request_list_lock); | ||
50 | spin_lock(&op->lock); | 46 | spin_lock(&op->lock); |
51 | set_op_state_waiting(op); | 47 | set_op_state_waiting(op); |
52 | list_add_tail(&op->list, &orangefs_request_list); | 48 | list_add_tail(&op->list, &orangefs_request_list); |
53 | spin_unlock(&orangefs_request_list_lock); | ||
54 | spin_unlock(&op->lock); | 49 | spin_unlock(&op->lock); |
55 | wake_up_interruptible(&orangefs_request_list_waitq); | 50 | wake_up_interruptible(&orangefs_request_list_waitq); |
56 | } | 51 | } |
57 | 52 | ||
53 | static inline void | ||
54 | add_op_to_request_list(struct orangefs_kernel_op_s *op) | ||
55 | { | ||
56 | spin_lock(&orangefs_request_list_lock); | ||
57 | __add_op_to_request_list(op); | ||
58 | spin_unlock(&orangefs_request_list_lock); | ||
59 | } | ||
60 | |||
58 | static inline | 61 | static inline |
59 | void add_priority_op_to_request_list(struct orangefs_kernel_op_s *op) | 62 | void add_priority_op_to_request_list(struct orangefs_kernel_op_s *op) |
60 | { | 63 | { |
@@ -159,15 +162,7 @@ retry_servicing: | |||
159 | if (flags & ORANGEFS_OP_ASYNC) | 162 | if (flags & ORANGEFS_OP_ASYNC) |
160 | return 0; | 163 | return 0; |
161 | 164 | ||
162 | if (flags & ORANGEFS_OP_CANCELLATION) { | 165 | ret = wait_for_matching_downcall(op); |
163 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
164 | "%s:" | ||
165 | "About to call wait_for_cancellation_downcall.\n", | ||
166 | __func__); | ||
167 | ret = wait_for_cancellation_downcall(op); | ||
168 | } else { | ||
169 | ret = wait_for_matching_downcall(op); | ||
170 | } | ||
171 | 166 | ||
172 | if (ret < 0) { | 167 | if (ret < 0) { |
173 | /* failed to get matching downcall */ | 168 | /* failed to get matching downcall */ |
@@ -273,6 +268,36 @@ retry_servicing: | |||
273 | return ret; | 268 | return ret; |
274 | } | 269 | } |
275 | 270 | ||
271 | bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op) | ||
272 | { | ||
273 | u64 tag = op->tag; | ||
274 | if (!op_state_in_progress(op)) | ||
275 | return false; | ||
276 | |||
277 | op->slot_to_free = op->upcall.req.io.buf_index; | ||
278 | memset(&op->upcall, 0, sizeof(op->upcall)); | ||
279 | memset(&op->downcall, 0, sizeof(op->downcall)); | ||
280 | op->upcall.type = ORANGEFS_VFS_OP_CANCEL; | ||
281 | op->upcall.req.cancel.op_tag = tag; | ||
282 | op->downcall.type = ORANGEFS_VFS_OP_INVALID; | ||
283 | op->downcall.status = -1; | ||
284 | orangefs_new_tag(op); | ||
285 | |||
286 | spin_lock(&orangefs_request_list_lock); | ||
287 | /* orangefs_request_list_lock is enough of a barrier here */ | ||
288 | if (!__is_daemon_in_service()) { | ||
289 | spin_unlock(&orangefs_request_list_lock); | ||
290 | return false; | ||
291 | } | ||
292 | __add_op_to_request_list(op); | ||
293 | spin_unlock(&orangefs_request_list_lock); | ||
294 | |||
295 | gossip_debug(GOSSIP_UTILS_DEBUG, | ||
296 | "Attempting ORANGEFS operation cancellation of tag %llu\n", | ||
297 | llu(tag)); | ||
298 | return true; | ||
299 | } | ||
300 | |||
276 | static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op) | 301 | static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op) |
277 | { | 302 | { |
278 | /* | 303 | /* |
@@ -426,81 +451,3 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op) | |||
426 | 451 | ||
427 | return ret; | 452 | return ret; |
428 | } | 453 | } |
429 | |||
430 | /* | ||
431 | * similar to wait_for_matching_downcall(), but used in the special case | ||
432 | * of I/O cancellations. | ||
433 | * | ||
434 | * Note we need a special wait function because if this is called we already | ||
435 | * know that a signal is pending in current and need to service the | ||
436 | * cancellation upcall anyway. the only way to exit this is to either | ||
437 | * timeout or have the cancellation be serviced properly. | ||
438 | */ | ||
439 | static int wait_for_cancellation_downcall(struct orangefs_kernel_op_s *op) | ||
440 | { | ||
441 | int ret = -EINVAL; | ||
442 | DEFINE_WAIT(wait_entry); | ||
443 | |||
444 | while (1) { | ||
445 | spin_lock(&op->lock); | ||
446 | prepare_to_wait(&op->waitq, &wait_entry, TASK_INTERRUPTIBLE); | ||
447 | if (op_state_serviced(op)) { | ||
448 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
449 | "%s:op-state is SERVICED.\n", | ||
450 | __func__); | ||
451 | spin_unlock(&op->lock); | ||
452 | ret = 0; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | if (signal_pending(current)) { | ||
457 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
458 | "%s:operation interrupted by a signal (tag" | ||
459 | " %llu, op %p)\n", | ||
460 | __func__, | ||
461 | llu(op->tag), | ||
462 | op); | ||
463 | orangefs_clean_up_interrupted_operation(op); | ||
464 | ret = -EINTR; | ||
465 | break; | ||
466 | } | ||
467 | |||
468 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
469 | "%s:About to call schedule_timeout.\n", | ||
470 | __func__); | ||
471 | spin_unlock(&op->lock); | ||
472 | ret = schedule_timeout(op_timeout_secs * HZ); | ||
473 | |||
474 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
475 | "%s:Value returned from schedule_timeout(%d).\n", | ||
476 | __func__, | ||
477 | ret); | ||
478 | if (!ret) { | ||
479 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
480 | "%s:*** operation timed out: %p\n", | ||
481 | __func__, | ||
482 | op); | ||
483 | spin_lock(&op->lock); | ||
484 | orangefs_clean_up_interrupted_operation(op); | ||
485 | ret = -ETIMEDOUT; | ||
486 | break; | ||
487 | } | ||
488 | |||
489 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
490 | "%s:Breaking out of loop, regardless of value returned by schedule_timeout.\n", | ||
491 | __func__); | ||
492 | ret = -ETIMEDOUT; | ||
493 | break; | ||
494 | } | ||
495 | |||
496 | spin_lock(&op->lock); | ||
497 | finish_wait(&op->waitq, &wait_entry); | ||
498 | spin_unlock(&op->lock); | ||
499 | |||
500 | gossip_debug(GOSSIP_WAIT_DEBUG, | ||
501 | "%s:returning ret(%d)\n", | ||
502 | __func__, | ||
503 | ret); | ||
504 | |||
505 | return ret; | ||
506 | } | ||