+struct ost_prolong_data {
+ struct ptlrpc_request *opd_req;
+ struct obd_export *opd_exp;
+ struct obdo *opd_oa;
+ struct ldlm_res_id opd_resid;
+ struct ldlm_extent opd_extent;
+ ldlm_mode_t opd_mode;
+ unsigned int opd_locks;
+ int opd_timeout;
+};
+
+/* prolong locks for the current service time of the corresponding
+ * portal (= OST_IO_PORTAL)
+ */
+static inline int prolong_timeout(struct ptlrpc_request *req)
+{
+ struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
+
+ if (AT_OFF)
+ return obd_timeout / 2;
+
+ return max(at_est2timeout(at_get(&svcpt->scp_at_estimate)),
+ ldlm_timeout);
+}
+
+static void ost_prolong_lock_one(struct ost_prolong_data *opd,
+ struct ldlm_lock *lock)
+{
+ LASSERT(lock->l_export == opd->opd_exp);
+
+ if (lock->l_destroyed) /* lock already cancelled */
+ return;
+
+ /* XXX: never try to grab resource lock here because we're inside
+ * exp_bl_list_lock; in ldlm_lockd.c to handle waiting list we take
+ * res lock and then exp_bl_list_lock. */
+
+ if (!(lock->l_flags & LDLM_FL_AST_SENT))
+ /* ignore locks not being cancelled */
+ return;
+
+ LDLM_DEBUG(lock,
+ "refreshed for req x"LPU64" ext("LPU64"->"LPU64") to %ds.\n",
+ opd->opd_req->rq_xid, opd->opd_extent.start,
+ opd->opd_extent.end, opd->opd_timeout);
+
+ /* OK. this is a possible lock the user holds doing I/O
+ * let's refresh eviction timer for it */
+ ldlm_refresh_waiting_lock(lock, opd->opd_timeout);
+ ++opd->opd_locks;
+}
+
+static void ost_prolong_locks(struct ost_prolong_data *data)
+{
+ struct obd_export *exp = data->opd_exp;
+ struct obdo *oa = data->opd_oa;
+ struct ldlm_lock *lock;
+ ENTRY;
+
+ if (oa->o_valid & OBD_MD_FLHANDLE) {
+ /* mostly a request should be covered by only one lock, try
+ * fast path. */
+ lock = ldlm_handle2lock(&oa->o_handle);
+ if (lock != NULL) {
+ /* Fast path to check if the lock covers the whole IO
+ * region exclusively. */
+ if (lock->l_granted_mode == LCK_PW &&
+ ldlm_extent_contain(&lock->l_policy_data.l_extent,
+ &data->opd_extent)) {
+ /* bingo */
+ ost_prolong_lock_one(data, lock);
+ LDLM_LOCK_PUT(lock);
+ RETURN_EXIT;
+ }
+ LDLM_LOCK_PUT(lock);
+ }
+ }
+
+
+ spin_lock_bh(&exp->exp_bl_list_lock);
+ cfs_list_for_each_entry(lock, &exp->exp_bl_list, l_exp_list) {
+ LASSERT(lock->l_flags & LDLM_FL_AST_SENT);
+ LASSERT(lock->l_resource->lr_type == LDLM_EXTENT);
+
+ if (!ldlm_res_eq(&data->opd_resid, &lock->l_resource->lr_name))
+ continue;
+
+ if (!ldlm_extent_overlap(&lock->l_policy_data.l_extent,
+ &data->opd_extent))
+ continue;
+
+ ost_prolong_lock_one(data, lock);
+ }
+ spin_unlock_bh(&exp->exp_bl_list_lock);
+
+ EXIT;
+}
+