+/**
+ * Common request handler for OST_SEEK RPC.
+ *
+ * Unified request handling for OST_SEEK RPC.
+ * It takes object by its FID, does needed lseek and packs result
+ * into reply. Only SEEK_HOLE and SEEK_DATA are supported.
+ *
+ * \param[in] tsi target session environment for this request
+ *
+ * \retval 0 if successful
+ * \retval negative value on error
+ */
+int tgt_lseek(struct tgt_session_info *tsi)
+{
+ struct lustre_handle lh = { 0 };
+ struct dt_object *dob;
+ struct ost_body *repbody;
+ loff_t offset = tsi->tsi_ost_body->oa.o_size;
+ int whence = tsi->tsi_ost_body->oa.o_mode;
+ bool srvlock;
+ int rc = 0;
+
+ ENTRY;
+
+ if (whence != SEEK_HOLE && whence != SEEK_DATA)
+ RETURN(-EPROTO);
+
+ /* Negative offset is prohibited on wire and must be handled on client
+ * prior sending RPC.
+ */
+ if (offset < 0)
+ RETURN(-EPROTO);
+
+ repbody = req_capsule_server_get(tsi->tsi_pill, &RMF_OST_BODY);
+ if (repbody == NULL)
+ RETURN(-ENOMEM);
+ repbody->oa = tsi->tsi_ost_body->oa;
+
+ srvlock = tsi->tsi_ost_body->oa.o_valid & OBD_MD_FLFLAGS &&
+ tsi->tsi_ost_body->oa.o_flags & OBD_FL_SRVLOCK;
+ if (srvlock) {
+ rc = tgt_data_lock(tsi->tsi_env, tsi->tsi_exp, &tsi->tsi_resid,
+ offset, OBD_OBJECT_EOF, &lh, LCK_PR);
+ if (rc)
+ RETURN(rc);
+ }
+
+ dob = dt_locate(tsi->tsi_env, tsi->tsi_tgt->lut_bottom, &tsi->tsi_fid);
+ if (IS_ERR(dob))
+ GOTO(out, rc = PTR_ERR(dob));
+
+ if (!dt_object_exists(dob))
+ GOTO(obj_put, rc = -ENOENT);
+
+ repbody->oa.o_size = dt_lseek(tsi->tsi_env, dob, offset, whence);
+ rc = 0;
+obj_put:
+ dt_object_put(tsi->tsi_env, dob);
+out:
+ if (srvlock)
+ tgt_data_unlock(&lh, LCK_PR);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(tgt_lseek);
+