0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "protocol.h"
0017 #include "orangefs-kernel.h"
0018 #include "orangefs-bufmap.h"
0019
0020 static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
0021 long timeout,
0022 int flags)
0023 __acquires(op->lock);
0024 static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op)
0025 __releases(op->lock);
0026
0027
0028
0029
0030
0031
0032
0033
0034 void purge_waiting_ops(void)
0035 {
0036 struct orangefs_kernel_op_s *op, *tmp;
0037
0038 spin_lock(&orangefs_request_list_lock);
0039 list_for_each_entry_safe(op, tmp, &orangefs_request_list, list) {
0040 gossip_debug(GOSSIP_WAIT_DEBUG,
0041 "pvfs2-client-core: purging op tag %llu %s\n",
0042 llu(op->tag),
0043 get_opname_string(op));
0044 set_op_state_purged(op);
0045 gossip_debug(GOSSIP_DEV_DEBUG,
0046 "%s: op:%s: op_state:%d: process:%s:\n",
0047 __func__,
0048 get_opname_string(op),
0049 op->op_state,
0050 current->comm);
0051 }
0052 spin_unlock(&orangefs_request_list_lock);
0053 }
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 int service_operation(struct orangefs_kernel_op_s *op,
0066 const char *op_name,
0067 int flags)
0068 {
0069 long timeout = MAX_SCHEDULE_TIMEOUT;
0070 int ret = 0;
0071
0072 DEFINE_WAIT(wait_entry);
0073
0074 op->upcall.tgid = current->tgid;
0075 op->upcall.pid = current->pid;
0076
0077 retry_servicing:
0078 op->downcall.status = 0;
0079 gossip_debug(GOSSIP_WAIT_DEBUG,
0080 "%s: %s op:%p: process:%s: pid:%d:\n",
0081 __func__,
0082 op_name,
0083 op,
0084 current->comm,
0085 current->pid);
0086
0087
0088
0089
0090
0091
0092
0093 if (!(flags & ORANGEFS_OP_NO_MUTEX)) {
0094 if (flags & ORANGEFS_OP_INTERRUPTIBLE)
0095 ret = mutex_lock_interruptible(&orangefs_request_mutex);
0096 else
0097 ret = mutex_lock_killable(&orangefs_request_mutex);
0098
0099
0100
0101
0102 if (ret < 0) {
0103 op->downcall.status = ret;
0104 gossip_debug(GOSSIP_WAIT_DEBUG,
0105 "%s: service_operation interrupted.\n",
0106 __func__);
0107 return ret;
0108 }
0109 }
0110
0111
0112 spin_lock(&orangefs_request_list_lock);
0113 spin_lock(&op->lock);
0114 set_op_state_waiting(op);
0115 gossip_debug(GOSSIP_DEV_DEBUG,
0116 "%s: op:%s: op_state:%d: process:%s:\n",
0117 __func__,
0118 get_opname_string(op),
0119 op->op_state,
0120 current->comm);
0121
0122 if (flags & ORANGEFS_OP_PRIORITY)
0123 list_add(&op->list, &orangefs_request_list);
0124 else
0125 list_add_tail(&op->list, &orangefs_request_list);
0126 spin_unlock(&op->lock);
0127 wake_up_interruptible(&orangefs_request_list_waitq);
0128 if (!__is_daemon_in_service()) {
0129 gossip_debug(GOSSIP_WAIT_DEBUG,
0130 "%s:client core is NOT in service.\n",
0131 __func__);
0132
0133
0134
0135
0136 if (op->upcall.type == ORANGEFS_VFS_OP_FS_UMOUNT)
0137 timeout = 0;
0138 else
0139 timeout = op_timeout_secs * HZ;
0140 }
0141 spin_unlock(&orangefs_request_list_lock);
0142
0143 if (!(flags & ORANGEFS_OP_NO_MUTEX))
0144 mutex_unlock(&orangefs_request_mutex);
0145
0146 ret = wait_for_matching_downcall(op, timeout, flags);
0147 gossip_debug(GOSSIP_WAIT_DEBUG,
0148 "%s: wait_for_matching_downcall returned %d for %p\n",
0149 __func__,
0150 ret,
0151 op);
0152
0153
0154 if (!ret) {
0155 spin_unlock(&op->lock);
0156 op->downcall.status =
0157 orangefs_normalize_to_errno(op->downcall.status);
0158 ret = op->downcall.status;
0159 goto out;
0160 }
0161
0162
0163 if (ret == -ETIMEDOUT) {
0164 gossip_err("%s: %s -- wait timed out; aborting attempt.\n",
0165 __func__,
0166 op_name);
0167 }
0168
0169
0170
0171
0172
0173 orangefs_clean_up_interrupted_operation(op);
0174
0175 op->downcall.status = ret;
0176
0177 if (ret == -EAGAIN) {
0178 op->attempts++;
0179 timeout = op_timeout_secs * HZ;
0180 gossip_debug(GOSSIP_WAIT_DEBUG,
0181 "orangefs: tag %llu (%s)"
0182 " -- operation to be retried (%d attempt)\n",
0183 llu(op->tag),
0184 op_name,
0185 op->attempts);
0186
0187
0188
0189
0190
0191
0192 if (!op->uses_shared_memory)
0193 goto retry_servicing;
0194 }
0195
0196 out:
0197 gossip_debug(GOSSIP_WAIT_DEBUG,
0198 "%s: %s returning: %d for %p.\n",
0199 __func__,
0200 op_name,
0201 ret,
0202 op);
0203 return ret;
0204 }
0205
0206
0207 bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op)
0208 {
0209 u64 tag = op->tag;
0210 if (!op_state_in_progress(op))
0211 return false;
0212
0213 op->slot_to_free = op->upcall.req.io.buf_index;
0214 memset(&op->upcall, 0, sizeof(op->upcall));
0215 memset(&op->downcall, 0, sizeof(op->downcall));
0216 op->upcall.type = ORANGEFS_VFS_OP_CANCEL;
0217 op->upcall.req.cancel.op_tag = tag;
0218 op->downcall.type = ORANGEFS_VFS_OP_INVALID;
0219 op->downcall.status = -1;
0220 orangefs_new_tag(op);
0221
0222 spin_lock(&orangefs_request_list_lock);
0223
0224 if (!__is_daemon_in_service()) {
0225 spin_unlock(&orangefs_request_list_lock);
0226 return false;
0227 }
0228 spin_lock(&op->lock);
0229 set_op_state_waiting(op);
0230 gossip_debug(GOSSIP_DEV_DEBUG,
0231 "%s: op:%s: op_state:%d: process:%s:\n",
0232 __func__,
0233 get_opname_string(op),
0234 op->op_state,
0235 current->comm);
0236 list_add(&op->list, &orangefs_request_list);
0237 spin_unlock(&op->lock);
0238 spin_unlock(&orangefs_request_list_lock);
0239
0240 gossip_debug(GOSSIP_WAIT_DEBUG,
0241 "Attempting ORANGEFS operation cancellation of tag %llu\n",
0242 llu(tag));
0243 return true;
0244 }
0245
0246
0247
0248
0249 static void
0250 orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op)
0251 __releases(op->lock)
0252 {
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 op->op_state |= OP_VFS_STATE_GIVEN_UP;
0265
0266 if (list_empty(&op->list)) {
0267
0268 BUG_ON(op_state_serviced(op));
0269 spin_unlock(&op->lock);
0270 wait_for_completion(&op->waitq);
0271 } else if (op_state_waiting(op)) {
0272
0273
0274
0275
0276 spin_unlock(&op->lock);
0277 spin_lock(&orangefs_request_list_lock);
0278 list_del_init(&op->list);
0279 spin_unlock(&orangefs_request_list_lock);
0280 gossip_debug(GOSSIP_WAIT_DEBUG,
0281 "Interrupted: Removed op %p from request_list\n",
0282 op);
0283 } else if (op_state_in_progress(op)) {
0284
0285 spin_unlock(&op->lock);
0286 spin_lock(&orangefs_htable_ops_in_progress_lock);
0287 list_del_init(&op->list);
0288 spin_unlock(&orangefs_htable_ops_in_progress_lock);
0289 gossip_debug(GOSSIP_WAIT_DEBUG,
0290 "Interrupted: Removed op %p"
0291 " from htable_ops_in_progress\n",
0292 op);
0293 } else {
0294 spin_unlock(&op->lock);
0295 gossip_err("interrupted operation is in a weird state 0x%x\n",
0296 op->op_state);
0297 }
0298 reinit_completion(&op->waitq);
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
0319 long timeout,
0320 int flags)
0321 __acquires(op->lock)
0322 {
0323 long n;
0324 int writeback = flags & ORANGEFS_OP_WRITEBACK,
0325 interruptible = flags & ORANGEFS_OP_INTERRUPTIBLE;
0326
0327
0328
0329
0330
0331
0332
0333 if (writeback)
0334 n = wait_for_completion_io_timeout(&op->waitq, timeout);
0335 else if (!writeback && interruptible)
0336 n = wait_for_completion_interruptible_timeout(&op->waitq,
0337 timeout);
0338 else
0339 n = wait_for_completion_killable_timeout(&op->waitq, timeout);
0340
0341 spin_lock(&op->lock);
0342
0343 if (op_state_serviced(op))
0344 return 0;
0345
0346 if (unlikely(n < 0)) {
0347 gossip_debug(GOSSIP_WAIT_DEBUG,
0348 "%s: operation interrupted, tag %llu, %p\n",
0349 __func__,
0350 llu(op->tag),
0351 op);
0352 return -EINTR;
0353 }
0354 if (op_state_purged(op)) {
0355 gossip_debug(GOSSIP_WAIT_DEBUG,
0356 "%s: operation purged, tag %llu, %p, %d\n",
0357 __func__,
0358 llu(op->tag),
0359 op,
0360 op->attempts);
0361 return (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ?
0362 -EAGAIN :
0363 -EIO;
0364 }
0365
0366 gossip_debug(GOSSIP_WAIT_DEBUG,
0367 "%s: operation timed out, tag %llu, %p, %d)\n",
0368 __func__,
0369 llu(op->tag),
0370 op,
0371 op->attempts);
0372 return -ETIMEDOUT;
0373 }