/* Slab for MDT object allocation */
static struct kmem_cache *mdt_object_kmem;
+/* For HSM restore handles */
+struct kmem_cache *mdt_hsm_cdt_kmem;
+
+/* For HSM request handles */
+struct kmem_cache *mdt_hsm_car_kmem;
+
static struct lu_kmem_descr mdt_caches[] = {
{
.ckd_cache = &mdt_object_kmem,
.ckd_size = sizeof(struct mdt_object)
},
{
+ .ckd_cache = &mdt_hsm_cdt_kmem,
+ .ckd_name = "mdt_cdt_restore_handle",
+ .ckd_size = sizeof(struct cdt_restore_handle)
+ },
+ {
+ .ckd_cache = &mdt_hsm_car_kmem,
+ .ckd_name = "mdt_cdt_agent_req",
+ .ckd_size = sizeof(struct cdt_agent_req)
+ },
+ {
.ckd_cache = NULL
}
};
b->blocks = 0;
/* if no object is allocated on osts, the size on mds is valid. b=22272 */
b->valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
- } else if ((ma->ma_valid & MA_LOV) && ma->ma_lmm &&
- (ma->ma_lmm->lmm_pattern & LOV_PATTERN_F_RELEASED)) {
+ } else if ((ma->ma_valid & MA_LOV) && ma->ma_lmm != NULL &&
+ ma->ma_lmm->lmm_pattern & LOV_PATTERN_F_RELEASED) {
/* A released file stores its size on MDS. */
b->blocks = 0;
b->valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
/* the Lustre protocol supposes to return default striping
* on the user-visible root if explicitly requested */
if ((ma->ma_valid & MA_LOV) == 0 && S_ISDIR(la->la_mode) &&
- (ma->ma_need & MA_LOV_DEF && is_root) && (ma->ma_need & MA_LOV)) {
+ (ma->ma_need & MA_LOV_DEF && is_root) && ma->ma_need & MA_LOV) {
struct lu_fid rootfid;
struct mdt_object *root;
struct mdt_device *mdt = info->mti_mdt;
LASSERT(mdt_object_remote(o));
- LASSERT((ibits & MDS_INODELOCK_UPDATE));
+ LASSERT(ibits & MDS_INODELOCK_UPDATE);
memset(einfo, 0, sizeof(*einfo));
einfo->ei_type = LDLM_IBITS;
},
[MDT_IT_OCREAT] = {
.it_fmt = &RQF_LDLM_INTENT,
- .it_flags = MUTABOR,
+ /*
+ * OCREAT is not a MUTABOR request as if the file
+ * already exists.
+ * We do the extra check of OBD_CONNECT_RDONLY in
+ * mdt_reint_open() when we really need to create
+ * the object.
+ */
+ .it_flags = 0,
.it_act = mdt_intent_reint,
.it_reint = REINT_OPEN
},
},
[MDT_IT_GETXATTR] = {
.it_fmt = &RQF_LDLM_INTENT_GETXATTR,
- .it_flags = 0,
+ .it_flags = HABEO_CORPUS,
.it_act = mdt_intent_getxattr
},
[MDT_IT_LAYOUT] = {
const char *identity_upcall = "NONE";
struct md_device *next;
int rc;
- int node_id;
+ long node_id;
mntopt_t mntopts;
ENTRY;
cfs_timer_init(&m->mdt_ck_timer, mdt_ck_timer_callback, m);
rc = mdt_hsm_cdt_init(m);
- if (rc != 0)
- CERROR("%s: Cannot init coordinator, rc %d\n",
+ if (rc != 0) {
+ CERROR("%s: error initializing coordinator, rc %d\n",
mdt_obd_name(m), rc);
+ GOTO(err_free_ns, rc);
+ }
rc = mdt_ck_thread_start(m);
if (rc)
- GOTO(err_free_ns, rc);
+ GOTO(err_free_hsm, rc);
rc = tgt_init(env, &m->mdt_lut, obd, m->mdt_bottom, mdt_common_slice,
OBD_FAIL_MDS_ALL_REQUEST_NET,
err_capa:
cfs_timer_disarm(&m->mdt_ck_timer);
mdt_ck_thread_stop(m);
+err_free_hsm:
+ mdt_hsm_cdt_fini(m);
err_free_ns:
ldlm_namespace_free(m->mdt_namespace, NULL, 0);
obd->obd_namespace = m->mdt_namespace = NULL;
RETURN(rc);
}
+static int mdt_ctxt_add_dirty_flag(struct lu_env *env,
+ struct mdt_thread_info *info,
+ struct mdt_file_data *mfd)
+{
+ struct lu_context ses;
+ int rc;
+ ENTRY;
+
+ rc = lu_context_init(&ses, LCT_SESSION);
+ if (rc)
+ RETURN(rc);
+
+ env->le_ses = &ses;
+ lu_context_enter(&ses);
+
+ mdt_ucred(info)->uc_valid = UCRED_OLD;
+ rc = mdt_add_dirty_flag(info, mfd->mfd_object, &info->mti_attr);
+
+ lu_context_exit(&ses);
+ lu_context_fini(&ses);
+ env->le_ses = NULL;
+
+ RETURN(rc);
+}
+
static int mdt_export_cleanup(struct obd_export *exp)
{
struct mdt_export_data *med = &exp->exp_mdt_data;
cfs_list_for_each_entry_safe(mfd, n, &closing_list, mfd_list) {
cfs_list_del_init(&mfd->mfd_list);
ma->ma_need = ma->ma_valid = 0;
+
+ /* This file is being closed due to an eviction, it
+ * could have been modified and now dirty regarding to
+ * HSM archive, check this!
+ * The logic here is to mark a file dirty if there's a
+ * chance it was dirtied before the client was evicted,
+ * so that we don't have to wait for a release attempt
+ * before finding out the file was actually dirty and
+ * fail the release. Aggressively marking it dirty here
+ * will cause the policy engine to attempt to
+ * re-archive it; when rearchiving, we can compare the
+ * current version to the HSM data_version and make the
+ * archive request into a noop if it's not actually
+ * dirty.
+ */
+ if (mfd->mfd_mode & (FMODE_WRITE|MDS_FMODE_TRUNC))
+ rc = mdt_ctxt_add_dirty_flag(&env, info, mfd);
+
/* Don't unlink orphan on failover umount, LU-184 */
if (exp->exp_flags & OBD_OPT_FAILOVER) {
ma->ma_valid = MA_FLAGS;
linkea_entry_unpack(lee, &reclen, tmpname, tmpfid);
/* If set, use link #linkno for path lookup, otherwise use
link #0. Only do this for the final path element. */
- if ((pli->pli_fidcount == 0) &&
- (pli->pli_linkno < leh->leh_reccount)) {
+ if (pli->pli_fidcount == 0 &&
+ pli->pli_linkno < leh->leh_reccount) {
int count;
for (count = 0; count < pli->pli_linkno; count++) {
lee = (struct link_ea_entry *)