+static int ost_brw_lock_get(int mode, struct obd_export *exp,
+ struct obd_ioobj *obj, struct niobuf_remote *nb,
+ struct lustre_handle *lh)
+{
+ int flags = 0;
+ int nrbufs = obj->ioo_bufcnt;
+ struct ldlm_res_id res_id = { .name = { obj->ioo_id, 0,
+ obj->ioo_gr, 0} };
+ ldlm_policy_data_t policy;
+ int i;
+
+ ENTRY;
+
+ LASSERT(mode == LCK_PR || mode == LCK_PW);
+ LASSERT(!lustre_handle_is_used(lh));
+
+ if (nrbufs == 0 || !(nb[0].flags & OBD_BRW_SRVLOCK))
+ RETURN(0);
+
+ /* EXPENSIVE ASSERTION */
+ for (i = 1; i < nrbufs; i ++)
+ LASSERT((nb[0].flags & OBD_BRW_SRVLOCK) ==
+ (nb[i].flags & OBD_BRW_SRVLOCK));
+
+ policy.l_extent.start = nb[0].offset & CFS_PAGE_MASK;
+ policy.l_extent.end = (nb[nrbufs - 1].offset +
+ nb[nrbufs - 1].len - 1) | ~CFS_PAGE_MASK;
+
+ RETURN(ldlm_cli_enqueue_local(exp->exp_obd->obd_namespace, &res_id,
+ LDLM_EXTENT, &policy, mode, &flags,
+ ldlm_blocking_ast, ldlm_completion_ast,
+ ldlm_glimpse_ast, NULL, 0, NULL, lh));
+}
+
+static void ost_brw_lock_put(int mode,
+ struct obd_ioobj *obj, struct niobuf_remote *niob,
+ struct lustre_handle *lh)
+{
+ ENTRY;
+ LASSERT(mode == LCK_PR || mode == LCK_PW);
+ LASSERT((obj->ioo_bufcnt > 0 && (niob[0].flags & OBD_BRW_SRVLOCK)) ==
+ lustre_handle_is_used(lh));
+ if (lustre_handle_is_used(lh))
+ ldlm_lock_decref(lh, mode);
+ EXIT;
+}
+
+struct ost_prolong_data {
+ struct obd_export *opd_exp;
+ ldlm_policy_data_t opd_policy;
+ ldlm_mode_t opd_mode;
+};
+
+static int ost_prolong_locks_iter(struct ldlm_lock *lock, void *data)
+{
+ struct ost_prolong_data *opd = data;
+
+ LASSERT(lock->l_resource->lr_type == LDLM_EXTENT);
+
+ if (lock->l_req_mode != lock->l_granted_mode) {
+ /* scan granted locks only */
+ return LDLM_ITER_STOP;
+ }
+
+ if (lock->l_export != opd->opd_exp) {
+ /* prolong locks only for given client */
+ return LDLM_ITER_CONTINUE;
+ }
+
+ if (!(lock->l_granted_mode & opd->opd_mode)) {
+ /* we aren't interesting in all type of locks */
+ return LDLM_ITER_CONTINUE;
+ }
+
+ if (lock->l_policy_data.l_extent.end < opd->opd_policy.l_extent.start ||
+ lock->l_policy_data.l_extent.start > opd->opd_policy.l_extent.end) {
+ /* the request doesn't cross the lock, skip it */
+ return LDLM_ITER_CONTINUE;
+ }
+
+ if (!(lock->l_flags & LDLM_FL_AST_SENT)) {
+ /* ignore locks not being cancelled */
+ return LDLM_ITER_CONTINUE;
+ }
+
+ /* OK. this is a possible lock the user holds doing I/O
+ * let's refresh eviction timer for it */
+ ldlm_refresh_waiting_lock(lock);
+
+ return LDLM_ITER_CONTINUE;
+}
+
+static void ost_prolong_locks(struct obd_export *exp, struct obd_ioobj *obj,
+ struct niobuf_remote *nb, ldlm_mode_t mode)
+{
+ struct ldlm_res_id res_id = { .name = { obj->ioo_id, 0,
+ obj->ioo_gr, 0} };
+ int nrbufs = obj->ioo_bufcnt;
+ struct ost_prolong_data opd;
+
+ ENTRY;
+
+ opd.opd_mode = mode;
+ opd.opd_exp = exp;
+ opd.opd_policy.l_extent.start = nb[0].offset & CFS_PAGE_MASK;
+ opd.opd_policy.l_extent.end = (nb[nrbufs - 1].offset +
+ nb[nrbufs - 1].len - 1) | ~CFS_PAGE_MASK;
+
+ CDEBUG(D_DLMTRACE,"refresh locks: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
+ res_id.name[0], res_id.name[1], opd.opd_policy.l_extent.start,
+ opd.opd_policy.l_extent.end);
+ ldlm_resource_iterate(exp->exp_obd->obd_namespace, &res_id,
+ ost_prolong_locks_iter, &opd);
+}
+
+static int ost_brw_read(struct ptlrpc_request *req, struct obd_trans_info *oti)