+/**
+ * Cleanup the open handle that is cached on MDT-side.
+ *
+ * For open case, the client side open handling thread may hit error
+ * after the MDT grant the open. Under such case, the client should
+ * send close RPC to the MDT as cleanup; otherwise, the open handle
+ * on the MDT will be leaked there until the client umount or evicted.
+ *
+ * In further, if someone unlinked the file, because the open handle
+ * holds the reference on such file/object, then it will block the
+ * subsequent threads that want to locate such object via FID.
+ *
+ * \param[in] sb super block for this file-system
+ * \param[in] open_req pointer to the original open request
+ */
+void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
+{
+ struct mdt_body *body;
+ struct md_op_data *op_data;
+ struct ptlrpc_request *close_req = NULL;
+ struct obd_export *exp = ll_s2sbi(sb)->ll_md_exp;
+ ENTRY;
+
+ body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY);
+ OBD_ALLOC_PTR(op_data);
+ if (op_data == NULL) {
+ CWARN("%s: cannot allocate op_data to release open handle for "
+ DFID"\n",
+ ll_get_fsname(sb, NULL, 0), PFID(&body->mbo_fid1));
+
+ RETURN_EXIT;
+ }
+
+ op_data->op_fid1 = body->mbo_fid1;
+ op_data->op_ioepoch = body->mbo_ioepoch;
+ op_data->op_handle = body->mbo_handle;
+ op_data->op_mod_time = cfs_time_current_sec();
+ md_close(exp, op_data, NULL, &close_req);
+ ptlrpc_req_finished(close_req);
+ ll_finish_md_op_data(op_data);
+
+ EXIT;
+}
+