#include <lustre_acl.h>
#include <lustre_mds.h>
+#include <lustre_swab.h>
#include "mdt_internal.h"
#include <lustre_nodemap.h>
return rc;
}
+static int mdt_close_resync_done(struct mdt_thread_info *info,
+ struct mdt_object *o, struct md_attr *ma)
+{
+ struct close_data *data;
+ struct ldlm_lock *lease;
+ struct md_layout_change layout = { 0 };
+ __u32 *resync_ids = NULL;
+ size_t resync_count = 0;
+ bool lease_broken;
+ int rc;
+ ENTRY;
+
+ if (exp_connect_flags(info->mti_exp) & OBD_CONNECT_RDONLY)
+ RETURN(-EROFS);
+
+ if (!S_ISREG(lu_object_attr(&o->mot_obj)))
+ RETURN(-EINVAL);
+
+ data = req_capsule_client_get(info->mti_pill, &RMF_CLOSE_DATA);
+ if (data == NULL)
+ RETURN(-EPROTO);
+
+ if (ptlrpc_req_need_swab(mdt_info_req(info)))
+ lustre_swab_close_data_resync_done(&data->cd_resync);
+
+ if (!fid_is_zero(&data->cd_fid))
+ RETURN(-EPROTO);
+
+ lease = ldlm_handle2lock(&data->cd_handle);
+ if (lease == NULL)
+ RETURN(-ESTALE);
+
+ /* try to hold open_sem so that nobody else can open the file */
+ if (!down_write_trylock(&o->mot_open_sem)) {
+ ldlm_lock_cancel(lease);
+ GOTO(out_reprocess, rc = -EBUSY);
+ }
+
+ /* Check if the lease open lease has already canceled */
+ lock_res_and_lock(lease);
+ lease_broken = ldlm_is_cancel(lease);
+ unlock_res_and_lock(lease);
+
+ LDLM_DEBUG(lease, DFID " lease broken? %d\n",
+ PFID(mdt_object_fid(o)), lease_broken);
+
+ /* Cancel server side lease. Client side counterpart should
+ * have been cancelled. It's okay to cancel it now as we've
+ * held mot_open_sem. */
+ ldlm_lock_cancel(lease);
+
+ if (lease_broken) /* don't perform release task */
+ GOTO(out_unlock, rc = -ESTALE);
+
+ resync_count = data->cd_resync.resync_count;
+ if (!resync_count)
+ GOTO(out_unlock, rc = 0);
+
+ if (resync_count > INLINE_RESYNC_ARRAY_SIZE) {
+ void *data;
+
+ if (!req_capsule_has_field(info->mti_pill, &RMF_U32,
+ RCL_CLIENT))
+ GOTO(out_unlock, rc = -EPROTO);
+
+ OBD_ALLOC(resync_ids, resync_count * sizeof(__u32));
+ if (!resync_ids)
+ GOTO(out_unlock, rc = -ENOMEM);
+
+ data = req_capsule_client_get(info->mti_pill, &RMF_U32);
+ memcpy(resync_ids, data, resync_count * sizeof(__u32));
+
+ layout.mlc_resync_ids = resync_ids;
+ } else {
+ layout.mlc_resync_ids = data->cd_resync.resync_ids_inline;
+ }
+
+ layout.mlc_opc = MD_LAYOUT_RESYNC_DONE;
+ layout.mlc_resync_count = resync_count;
+ if (ma->ma_attr.la_valid & (LA_SIZE | LA_BLOCKS)) {
+ layout.mlc_som.lsa_valid = LSOM_FL_VALID;
+ layout.mlc_som.lsa_size = ma->ma_attr.la_size;
+ layout.mlc_som.lsa_blocks = ma->ma_attr.la_blocks;
+ }
+ rc = mdt_layout_change(info, o, &layout);
+ if (rc)
+ GOTO(out_unlock, rc);
+
+ EXIT;
+
+out_unlock:
+ up_write(&o->mot_open_sem);
+
+ /* already released */
+ if (rc == 0) {
+ struct mdt_body *repbody;
+
+ repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+ LASSERT(repbody != NULL);
+ repbody->mbo_valid |= OBD_MD_CLOSE_INTENT_EXECED;
+ }
+
+ if (resync_ids)
+ OBD_FREE(resync_ids, resync_count * sizeof(__u32));
+
+out_reprocess:
+ ldlm_reprocess_all(lease->l_resource);
+ LDLM_LOCK_PUT(lease);
+
+ ma->ma_valid = 0;
+ ma->ma_need = 0;
+
+ return rc;
+}
+
#define MFD_CLOSED(mode) ((mode) == MDS_FMODE_CLOSED)
static int mdt_mfd_closed(struct mdt_file_data *mfd)
{
mode = mfd->mfd_mode;
intent = ma->ma_attr_flags & MDS_CLOSE_INTENT;
+
+ CDEBUG(D_INODE, "%s: close file "DFID" with intent: %llx\n",
+ mdt_obd_name(info->mti_mdt), PFID(mdt_object_fid(o)), intent);
+
switch (intent) {
case MDS_HSM_RELEASE: {
rc = mdt_hsm_release(info, o, ma);
}
break;
}
+ case MDS_CLOSE_RESYNC_DONE:
+ rc = mdt_close_resync_done(info, o, ma);
+ break;
default:
/* nothing */
break;