#define OBD_FAIL_MDS_DQACQ_NET 0x187
/* OI scrub */
-#define OBD_FAIL_OSD_SCRUB_DELAY 0x190
-#define OBD_FAIL_OSD_SCRUB_CRASH 0x191
-#define OBD_FAIL_OSD_SCRUB_FATAL 0x192
+#define OBD_FAIL_OSD_SCRUB_DELAY 0x190
+#define OBD_FAIL_OSD_SCRUB_CRASH 0x191
+#define OBD_FAIL_OSD_SCRUB_FATAL 0x192
+#define OBD_FAIL_OSD_FID_MAPPING 0x193
#define OBD_FAIL_OST 0x200
#define OBD_FAIL_OST_CONNECT_NET 0x201
#define OBD_FAIL_LOV_INIT 0x1403
#define OBD_FAIL_GLIMPSE_DELAY 0x1404
-#define OBD_FAIL_UPDATE_OBJ_NET 0x1500
+#define OBD_FAIL_UPDATE_OBJ_NET 0x1500
+
/* Assign references to moved code to reduce code changes */
#define OBD_FAIL_PRECHECK(id) CFS_FAIL_PRECHECK(id)
#define OBD_FAIL_CHECK(id) CFS_FAIL_CHECK(id)
struct mdd_device *m, struct lustre_cfg *cfg)
{
ENTRY;
- mdd_changelog_fini(env, m);
if (m->mdd_dot_lustre_objs.mdd_obf)
mdd_object_put(env, m->mdd_dot_lustre_objs.mdd_obf);
if (m->mdd_dot_lustre)
break;
case LCFG_CLEANUP:
mdd_lfsck_cleanup(env, m);
+ mdd_changelog_fini(env, m);
rc = next->ld_ops->ldo_process_config(env, next, cfg);
lu_dev_del_linkage(d->ld_site, d);
mdd_device_shutdown(env, m, cfg);
mdd->mdd_capa = root;
+ rc = mdd_changelog_init(env, mdd);
+ if (rc != 0)
+ GOTO(out, rc);
+
rc = mdd_lfsck_setup(env, mdd);
- if (rc) {
+ if (rc != 0)
CERROR("%s: failed to initialize lfsck: rc = %d\n",
mdd2obd_dev(mdd)->obd_name, rc);
- GOTO(out, rc);
- }
- rc = mdd_changelog_init(env, mdd);
GOTO(out, rc);
if (rc)
RETURN(rc);
- lustre_lma_init(&dti->dti_lma, lu_object_fid(&o->do_lu));
- lustre_lma_swab(&dti->dti_lma);
- dti->dti_lb.lb_buf = &dti->dti_lma;
- dti->dti_lb.lb_len = sizeof(dti->dti_lma);
- rc = dt_xattr_set(env, o, &dti->dti_lb, XATTR_NAME_LMA, 0, th,
- BYPASS_CAPA);
-
if (los == NULL)
RETURN(rc);
if (rc) {
lu_object_put_nocache(env, &dto->do_lu);
dto = ERR_PTR(rc);
- } else {
- struct lu_fid dti_fid;
- /* since local files FIDs are not in OI the directory entry
- * is used to get inode number/generation, we need to do lookup
- * again to cache this data after create */
- rc = dt_lookup_dir(env, parent, name, &dti_fid);
- LASSERT(rc == 0);
}
RETURN(dto);
}
GOTO(out_trans, rc);
LASSERT(dt_object_exists(o));
- lustre_lma_init(&dti->dti_lma, lu_object_fid(&o->do_lu));
- lustre_lma_swab(&dti->dti_lma);
- dti->dti_lb.lb_buf = &dti->dti_lma;
- dti->dti_lb.lb_len = sizeof(dti->dti_lma);
- rc = dt_xattr_set(env, o, &dti->dti_lb, XATTR_NAME_LMA, 0,
- th, BYPASS_CAPA);
- if (rc)
- GOTO(out_trans, rc);
-
losd.lso_magic = cpu_to_le32(LOS_MAGIC);
losd.lso_next_oid = cpu_to_le32(fid_oid(first_fid) + 1);
* unexpected reason, we should be able to detect it later by calling
* do_create->osd_oi_insert()
*/
- if (conf != NULL && (conf->loc_flags & LOC_F_NEW) != 0)
+ if (conf != NULL && conf->loc_flags & LOC_F_NEW)
GOTO(out, result = 0);
/* Search order: 3. OI files. */
result = osd_oi_lookup(info, dev, fid, id, true);
if (result == -ENOENT) {
- if (!fid_is_norm(fid) ||
+ if (!fid_is_norm(fid) || fid_is_on_ost(info, dev, fid) ||
!ldiskfs_test_bit(osd_oi_fid2idx(dev,fid),
sf->sf_oi_bitmap))
GOTO(out, result = 0);
osd_trans_exec_op(env, handle, OSD_OT_ATTR_SET);
+ if (OBD_FAIL_CHECK(OBD_FAIL_OSD_FID_MAPPING)) {
+ struct osd_thread_info *oti = osd_oti_get(env);
+ const struct lu_fid *fid0 = lu_object_fid(&dt->do_lu);
+ struct lu_fid *fid1 = &oti->oti_fid;
+ struct osd_inode_id *id = &oti->oti_id;
+ struct iam_path_descr *ipd;
+ struct iam_container *bag;
+ struct osd_thandle *oh;
+ int rc;
+
+ fid_cpu_to_be(fid1, fid0);
+ memset(id, 1, sizeof(*id));
+ bag = &osd_fid2oi(osd_dev(dt->do_lu.lo_dev),
+ fid0)->oi_dir.od_container;
+ ipd = osd_idx_ipd_get(env, bag);
+ if (unlikely(ipd == NULL))
+ RETURN(-ENOMEM);
+
+ oh = container_of0(handle, struct osd_thandle, ot_super);
+ rc = iam_update(oh->ot_handle, bag, (const struct iam_key *)fid1,
+ (const struct iam_rec *)id, ipd);
+ osd_ipd_put(env, bag, ipd);
+ return(rc > 0 ? 0 : rc);
+ }
+
inode = obj->oo_inode;
ll_vfs_dq_init(inode);
osd_trans_declare_op(env, oh, OSD_OT_CREATE,
osd_dto_credits_noquota[DTO_OBJECT_CREATE]);
- /* XXX: So far, only normal fid needs be inserted into the oi,
- * things could be changed later. Revise following code then. */
- if (fid_is_norm(lu_object_fid(&dt->do_lu)) &&
- !fid_is_on_ost(osd_oti_get(env), osd_dt_dev(handle->th_dev),
- lu_object_fid(&dt->do_lu))) {
+ if (!fid_is_on_ost(osd_oti_get(env), osd_dt_dev(handle->th_dev),
+ lu_object_fid(&dt->do_lu)))
/* Reuse idle OI block may cause additional one OI block
* to be changed. */
osd_trans_declare_op(env, oh, OSD_OT_INSERT,
osd_dto_credits_noquota[DTO_INDEX_INSERT] + 1);
- }
+
/* If this is directory, then we expect . and .. to be inserted as
* well. The one directory block always needs to be created for the
* directory, so we could use DTO_WRITE_BASE here (GDT, block bitmap,
osd_trans_declare_op(env, oh, OSD_OT_DELETE,
osd_dto_credits_noquota[DTO_OBJECT_DELETE]);
- /* XXX: So far, only normal fid needs to be inserted into the OI,
- * so only normal fid needs to be removed from the OI also.
- * Recycle idle OI leaf may cause additional three OI blocks
+ /* Recycle idle OI leaf may cause additional three OI blocks
* to be changed. */
osd_trans_declare_op(env, oh, OSD_OT_DESTROY,
- fid_is_norm(lu_object_fid(&dt->do_lu)) ?
- osd_dto_credits_noquota[DTO_INDEX_DELETE] + 3 : 0);
+ osd_dto_credits_noquota[DTO_INDEX_DELETE] + 3);
/* one less inode */
rc = osd_declare_inode_qid(env, inode->i_uid, inode->i_gid, -1, oh,
void osd_get_ldiskfs_dirent_param(struct ldiskfs_dentry_param *param,
const struct dt_rec *fid)
{
- /* XXX: replace the check with "!fid_is_client_mdt_visible()"
- * when FID in OI file introduced for local object. */
- if (!fid_is_norm((const struct lu_fid *)fid) &&
- !fid_is_igif((const struct lu_fid *)fid)) {
+ if (!fid_is_client_mdt_visible((const struct lu_fid *)fid)) {
param->edp_magic = 0;
return;
}
}
/**
- * Try to read the fid from inode ea into dt_rec, if return value
- * i.e. rc is +ve, then we got fid, otherwise we will have to form igif
+ * Try to read the fid from inode ea into dt_rec.
*
* \param fid object fid.
*
osd_trans_declare_rb(env, th, OSD_OT_REF_ADD);
result = __osd_object_create(info, obj, attr, hint, dof, th);
- /* objects under osd root shld have igif fid, so dont add fid EA */
- /* For ost object, the fid will be stored during first write */
- if (result == 0 && fid_seq(fid) >= FID_SEQ_NORMAL &&
- !fid_is_on_ost(info, osd_dt_dev(th->th_dev), fid))
+ if ((result == 0) &&
+ (fid_is_last_id(fid) ||
+ !fid_is_on_ost(info, osd_dt_dev(th->th_dev), fid)))
result = osd_ea_fid_set(info, obj->oo_inode, fid);
if (result == 0)
oic->oic_lid = *id;
oic->oic_fid = *fid;
if ((scrub->os_pos_current <= ino) &&
- (sf->sf_flags & SF_INCONSISTENT ||
+ ((sf->sf_flags & SF_INCONSISTENT) ||
+ (sf->sf_flags & SF_UPGRADE && fid_is_igif(fid)) ||
ldiskfs_test_bit(osd_oi_fid2idx(dev, fid),
sf->sf_oi_bitmap)))
osd_consistency_check(oti, dev, oic);
oic->oic_lid = *id;
oic->oic_fid = *fid;
if ((scrub->os_pos_current <= ino) &&
- (sf->sf_flags & SF_INCONSISTENT ||
+ ((sf->sf_flags & SF_INCONSISTENT) ||
+ (sf->sf_flags & SF_UPGRADE && fid_is_igif(fid)) ||
ldiskfs_test_bit(osd_oi_fid2idx(dev, fid), sf->sf_oi_bitmap)))
osd_consistency_check(oti, dev, oic);
spinlock_t od_osfs_lock;
unsigned int od_noscrub:1,
- od_init_scrub:1,
od_handle_nolma:1;
struct fsfilt_operations *od_fsops;
* Author: Nikita Danilov <nikita@clusterfs.com>
*/
-/*
- * oi uses two mechanisms to implement fid->cookie mapping:
- *
- * - persistent index, where cookie is a record and fid is a key, and
- *
- * - algorithmic mapping for "igif" fids.
- *
- */
-
#define DEBUG_SUBSYSTEM S_MDS
#include <linux/module.h>
int rc;
ENTRY;
+ if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
+ RETURN(0);
+
if (fid_is_idif(fid) || fid_is_last_id(fid))
RETURN(1);
const struct lu_fid *fid, struct osd_inode_id *id,
bool check_fld)
{
- int rc = 0;
+ if (unlikely(fid_is_last_id(fid)))
+ return osd_obj_spec_lookup(info, osd, fid, id);
- if ((!fid_is_last_id(fid) && check_fld &&
- fid_is_on_ost(info, osd, fid)) ||
- fid_is_llog(fid)) {
+ if ((check_fld && fid_is_on_ost(info, osd, fid)) || fid_is_llog(fid))
/* old OSD obj id */
/* FIXME: actually for all of the OST object */
- rc = osd_obj_map_lookup(info, osd, fid, id);
- } else if (fid_is_igif(fid)) {
- osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid));
- } else if (fid_is_fs_root(fid)) {
+ return osd_obj_map_lookup(info, osd, fid, id);
+
+ if (fid_is_fs_root(fid)) {
osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino,
osd_sb(osd)->s_root->d_inode->i_generation);
- } else {
- if (unlikely(fid_is_acct(fid)))
- return osd_acct_obj_lookup(info, osd, fid, id);
- else if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE) ||
- fid_is_last_id(fid))
- return osd_obj_spec_lookup(info, osd, fid, id);
-
- rc = __osd_oi_lookup(info, osd, fid, id);
+ return 0;
}
- return rc;
+
+ if (unlikely(fid_is_acct(fid)))
+ return osd_acct_obj_lookup(info, osd, fid, id);
+
+ return __osd_oi_lookup(info, osd, fid, id);
}
-static int osd_oi_iam_insert(struct osd_thread_info *oti, struct osd_oi *oi,
+static int osd_oi_iam_refresh(struct osd_thread_info *oti, struct osd_oi *oi,
const struct dt_rec *rec, const struct dt_key *key,
- struct thandle *th)
+ struct thandle *th, bool insert)
{
- struct iam_container *bag;
- struct iam_rec *iam_rec = (struct iam_rec *)oti->oti_ldp;
- struct iam_path_descr *ipd;
- struct osd_thandle *oh;
- int rc;
- ENTRY;
+ struct iam_container *bag;
+ struct iam_path_descr *ipd;
+ struct osd_thandle *oh;
+ int rc;
+ ENTRY;
- LASSERT(oi);
- LASSERT(oi->oi_inode);
+ LASSERT(oi);
+ LASSERT(oi->oi_inode);
ll_vfs_dq_init(oi->oi_inode);
- bag = &oi->oi_dir.od_container;
- ipd = osd_idx_ipd_get(oti->oti_env, bag);
- if (unlikely(ipd == NULL))
- RETURN(-ENOMEM);
+ bag = &oi->oi_dir.od_container;
+ ipd = osd_idx_ipd_get(oti->oti_env, bag);
+ if (unlikely(ipd == NULL))
+ RETURN(-ENOMEM);
- oh = container_of0(th, struct osd_thandle, ot_super);
- LASSERT(oh->ot_handle != NULL);
- LASSERT(oh->ot_handle->h_transaction != NULL);
- if (S_ISDIR(oi->oi_inode->i_mode))
- osd_fid_pack((struct osd_fid_pack *)iam_rec, rec,
- &oti->oti_fid);
- else
- iam_rec = (struct iam_rec *) rec;
- rc = iam_insert(oh->ot_handle, bag, (const struct iam_key *)key,
- iam_rec, ipd);
- osd_ipd_put(oti->oti_env, bag, ipd);
- LINVRNT(osd_invariant(obj));
- RETURN(rc);
+ oh = container_of0(th, struct osd_thandle, ot_super);
+ LASSERT(oh->ot_handle != NULL);
+ LASSERT(oh->ot_handle->h_transaction != NULL);
+ if (insert)
+ rc = iam_insert(oh->ot_handle, bag, (const struct iam_key *)key,
+ (const struct iam_rec *)rec, ipd);
+ else
+ rc = iam_update(oh->ot_handle, bag, (const struct iam_key *)key,
+ (const struct iam_rec *)rec, ipd);
+ osd_ipd_put(oti->oti_env, bag, ipd);
+ LINVRNT(osd_invariant(obj));
+ RETURN(rc);
}
int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
struct thandle *th)
{
struct lu_fid *oi_fid = &info->oti_fid2;
- struct osd_inode_id *oi_id = &info->oti_id2;
+ struct osd_inode_id *oi_id = &info->oti_id2;
+ int rc = 0;
- if (fid_is_igif(fid) || unlikely(fid_seq(fid) == FID_SEQ_DOT_LUSTRE))
- return 0;
+ if (unlikely(fid_is_last_id(fid)))
+ return osd_obj_spec_insert(info, osd, fid, id, th);
- if ((fid_is_on_ost(info, osd, fid) && !fid_is_last_id(fid)) ||
- fid_is_llog(fid))
+ if (fid_is_on_ost(info, osd, fid) || fid_is_llog(fid))
return osd_obj_map_insert(info, osd, fid, id, th);
- /* Server mount should not depends on OI files */
- if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE) ||
- fid_is_last_id(fid))
- return osd_obj_spec_insert(info, osd, fid, id, th);
-
fid_cpu_to_be(oi_fid, fid);
osd_id_pack(oi_id, id);
- return osd_oi_iam_insert(info, osd_fid2oi(osd, fid),
- (const struct dt_rec *)oi_id,
- (const struct dt_key *)oi_fid, th);
+ rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
+ (const struct dt_rec *)oi_id,
+ (const struct dt_key *)oi_fid, th, true);
+ if (rc != 0) {
+ struct inode *inode;
+ struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs;
+
+ if (rc != -EEXIST)
+ return rc;
+
+ rc = osd_oi_lookup(info, osd, fid, oi_id, false);
+ if (unlikely(rc != 0))
+ return rc;
+
+ if (osd_id_eq(id, oi_id)) {
+ CERROR("%.16s: the FID "DFID" is there already:%u/%u\n",
+ LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
+ PFID(fid), id->oii_ino, id->oii_gen);
+ return -EEXIST;
+ }
+
+ /* Check whether the mapping for oi_id is valid or not. */
+ inode = osd_iget(info, osd, oi_id);
+ if (IS_ERR(inode)) {
+ rc = PTR_ERR(inode);
+ if (rc == -ENOENT || rc == -ESTALE)
+ goto update;
+ return rc;
+ }
+
+ rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma);
+ iput(inode);
+ if (rc == -ENODATA)
+ goto update;
+
+ if (rc != 0)
+ return rc;
+
+ if (lu_fid_eq(fid, &lma->lma_self_fid)) {
+ CERROR("%.16s: the FID "DFID" is used by two objects: "
+ "%u/%u %u/%u\n",
+ LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
+ PFID(fid), oi_id->oii_ino, oi_id->oii_gen,
+ id->oii_ino, id->oii_gen);
+ return -EEXIST;
+ }
+
+update:
+ osd_id_pack(oi_id, id);
+ rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
+ (const struct dt_rec *)oi_id,
+ (const struct dt_key *)oi_fid, th, false);
+ if (rc != 0)
+ return rc;
+ }
+
+ if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
+ rc = osd_obj_spec_insert(info, osd, fid, id, th);
+ return rc;
}
static int osd_oi_iam_delete(struct osd_thread_info *oti, struct osd_oi *oi,
{
struct lu_fid *oi_fid = &info->oti_fid2;
- if (fid_is_igif(fid) || fid_is_last_id(fid))
+ if (fid_is_last_id(fid))
return 0;
- LASSERT(fid_seq(fid) != FID_SEQ_LOCAL_FILE);
-
if (fid_is_on_ost(info, osd, fid) || fid_is_llog(fid))
return osd_obj_map_delete(info, osd, fid, th);
int rc;
ENTRY;
- /* XXX: This is a temporary flag to disable initial OI scrub until
- * the patcp for handling special FIDs in the OI files ready.
- * We do not want to merge the two patches together, because
- * it makes the patch too large to be reviewed. */
- if (!dev->od_init_scrub)
- RETURN(0);
-
while (1) {
rc = scandir(info, dev, dentry, filldir);
if (item != NULL) {
test_1a() {
scrub_prep 0
+ echo "start $SINGLEMDS without disabling OI scrub"
+ start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null ||
+ error "(1) Fail to start MDS!"
+
+ local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }')
+ [ "$STATUS" == "init" ] ||
+ error "(2) Expect 'init', but got '$STATUS'"
+
+ local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
+ [ -z "$FLAGS" ] || error "(3) Expect empty flags, but got '$FLAGS'"
+
+ mount_client $MOUNT || error "(4) Fail to start client!"
+
+ #define OBD_FAIL_OSD_FID_MAPPING 0x193
+ do_facet $SINGLEMDS $LCTL set_param fail_loc=0x193
+ # update .lustre OI mapping
+ touch $MOUNT/.lustre
+ do_facet $SINGLEMDS $LCTL set_param fail_loc=0
+
+ umount_client $MOUNT || error "(5) Fail to stop client!"
+
+ echo "stop $SINGLEMDS"
+ stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!"
+
+ echo "start $SINGLEMDS with disabling OI scrub"
+ start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null ||
+ error "(7) Fail to start MDS!"
+
+ local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }')
+ [ "$STATUS" == "init" ] ||
+ error "(8) Expect 'init', but got '$STATUS'"
+
+ local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
+ [ "$FLAGS" == "inconsistent" ] ||
+ error "(9) Expect 'inconsistent', but got '$FLAGS'"
+}
+run_test 1a "Auto trigger initial OI scrub when server mounts"
+
+test_1b() {
+ scrub_prep 0
mds_remove_ois || error "(1) Fail to remove/recreate!"
echo "start $SINGLEMDS without disabling OI scrub"
diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh ||
error "(5) File diff failed unexpected!"
}
-run_test 1a "Trigger OI scrub when MDT mounts for OI files remove/recreate case"
+run_test 1b "Trigger OI scrub when MDT mounts for OI files remove/recreate case"
-test_1b() {
+test_1c() {
local index
# OI files to be removed:
error "(6) Expect empty flags, but got '$FLAGS'"
done
}
-run_test 1b "Auto detect kinds of OI file(s) removed/recreated cases"
+run_test 1c "Auto detect kinds of OI file(s) removed/recreated cases"
test_2() {
scrub_prep 0