It contains several fixes to make the LFSCK to work under DNE mode
for zfs-based backend.
Test-Parameters: mdsfilesystemtype=zfs mdtfilesystemtype=zfs ostfilesystemtype=zfs mdscount=2 mdtcount=2 testlist=sanity-lfsck
Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I8e8758336d4ce67667f7e3586475ddd72db2d419
Reviewed-on: http://review.whamcloud.com/12552
Tested-by: Jenkins
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: wangdi <di.wang@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
#define OBD_FAIL_LFSCK_BAD_NETWORK 0x161c
#define OBD_FAIL_LFSCK_NO_LINKEA 0x161d
#define OBD_FAIL_LFSCK_BAD_PARENT 0x161e
#define OBD_FAIL_LFSCK_BAD_NETWORK 0x161c
#define OBD_FAIL_LFSCK_NO_LINKEA 0x161d
#define OBD_FAIL_LFSCK_BAD_PARENT 0x161e
-#define OBD_FAIL_LFSCK_BAD_PARENT2 0x161f
#define OBD_FAIL_LFSCK_DANGLING2 0x1620
#define OBD_FAIL_LFSCK_DANGLING3 0x1621
#define OBD_FAIL_LFSCK_MUL_REF 0x1622
#define OBD_FAIL_LFSCK_DANGLING2 0x1620
#define OBD_FAIL_LFSCK_DANGLING3 0x1621
#define OBD_FAIL_LFSCK_MUL_REF 0x1622
+ if (fid_is_zero(pfid))
+ GOTO(out, rc = 0);
+
/* The ".." name entry is wrong, update it. */
if (!lu_fid_eq(pfid, lfsck_dto2fid(parent))) {
if (!lustre_handle_is_used(lh) && retry != NULL) {
/* The ".." name entry is wrong, update it. */
if (!lu_fid_eq(pfid, lfsck_dto2fid(parent))) {
if (!lustre_handle_is_used(lh) && retry != NULL) {
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct dt_object *parent = NULL;
struct linkea_data ldata_new = { 0 };
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct dt_object *parent = NULL;
struct linkea_data ldata_new = { 0 };
+ int dirent_count = 0;
+ int linkea_count = 0;
int rc = 0;
bool once = true;
ENTRY;
int rc = 0;
bool once = true;
ENTRY;
/* Drop invalid linkEA entry. */
if (!fid_is_sane(tfid)) {
linkea_del_buf(ldata, cname);
/* Drop invalid linkEA entry. */
if (!fid_is_sane(tfid)) {
linkea_del_buf(ldata, cname);
* child to be visible via other parent, then
* remove this linkEA entry. */
linkea_del_buf(ldata, cname);
* child to be visible via other parent, then
* remove this linkEA entry. */
linkea_del_buf(ldata, cname);
if (unlikely(!dt_try_as_dir(env, parent))) {
lfsck_object_put(env, parent);
linkea_del_buf(ldata, cname);
if (unlikely(!dt_try_as_dir(env, parent))) {
lfsck_object_put(env, parent);
linkea_del_buf(ldata, cname);
RETURN(rc);
linkea_del_buf(ldata, cname);
RETURN(rc);
linkea_del_buf(ldata, cname);
linkea_first_entry(ldata);
/* There may be some invalid dangling name entries under
* other parent directories, remove all of them. */
linkea_first_entry(ldata);
/* There may be some invalid dangling name entries under
* other parent directories, remove all of them. */
next:
linkea_del_buf(ldata, cname);
}
next:
linkea_del_buf(ldata, cname);
}
- ns->ln_dirent_repaired += count;
+ ns->ln_dirent_repaired += dirent_count;
linkea_del_buf(ldata, cname);
}
linkea_del_buf(ldata, cname);
}
+ linkea_first_entry(ldata);
if (ldata->ld_leh->leh_reccount == 1) {
rc = lfsck_namespace_dsd_single(env, com, child, pfid, ldata,
lh, type, NULL);
if (ldata->ld_leh->leh_reccount == 1) {
rc = lfsck_namespace_dsd_single(env, com, child, pfid, ldata,
lh, type, NULL);
+ if (rc == 0 && fid_is_zero(pfid) && linkea_count > 0)
+ rc = lfsck_namespace_rebuild_linkea(env, com, child,
+ ldata);
+
- linkea_first_entry(ldata);
/* If the dangling name entry for the orphan directory object has
* been remvoed, then just check whether the directory object is
* still under the .lustre/lost+found/MDTxxxx/ or not. */
/* If the dangling name entry for the orphan directory object has
* been remvoed, then just check whether the directory object is
* still under the .lustre/lost+found/MDTxxxx/ or not. */
} else if (lfsck->li_lpf_obj != NULL &&
lu_fid_eq(pfid, lfsck_dto2fid(lfsck->li_lpf_obj))) {
lpf = true;
} else if (lfsck->li_lpf_obj != NULL &&
lu_fid_eq(pfid, lfsck_dto2fid(lfsck->li_lpf_obj))) {
lpf = true;
+ } else if (unlikely(!fid_is_sane(pfid))) {
+ fid_zero(pfid);
}
rc = lfsck_links_read(env, child, &ldata);
}
rc = lfsck_links_read(env, child, &ldata);
mdd_object_make_hint(env, mdd_pobj, son, attr, spec, hint);
memset(ldata, 0, sizeof(*ldata));
mdd_object_make_hint(env, mdd_pobj, son, attr, spec, hint);
memset(ldata, 0, sizeof(*ldata));
- if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT2)) {
+ if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT)) {
struct lu_fid tfid = *mdd_object_fid(mdd_pobj);
tfid.f_oid--;
struct lu_fid tfid = *mdd_object_fid(mdd_pobj);
tfid.f_oid--;
dot_dot_fid, NULL, th);
}
dot_dot_fid, NULL, th);
}
- if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT) ||
- OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT2)) {
+ if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT)) {
struct lu_fid tfid = *dot_dot_fid;
tfid.f_oid--;
struct lu_fid tfid = *dot_dot_fid;
tfid.f_oid--;
{
struct osd_object *obj = osd_dt_obj(dt);
struct osd_thandle *oh;
{
struct osd_object *obj = osd_dt_obj(dt);
struct osd_thandle *oh;
ENTRY;
LASSERT(th != NULL);
oh = container_of0(th, struct osd_thandle, ot_super);
ENTRY;
LASSERT(th != NULL);
oh = container_of0(th, struct osd_thandle, ot_super);
- LASSERT(obj->oo_db);
- LASSERT(osd_object_is_zap(obj->oo_db));
+ /* This is for inserting dot/dotdot for new created dir. */
+ if (obj->oo_db == NULL)
+ object = DMU_NEW_OBJECT;
+ else
+ object = obj->oo_db->db_object;
- dmu_tx_hold_bonus(oh->ot_tx, obj->oo_db->db_object);
- dmu_tx_hold_zap(oh->ot_tx, obj->oo_db->db_object, TRUE, (char *)key);
+ dmu_tx_hold_bonus(oh->ot_tx, object);
+ dmu_tx_hold_zap(oh->ot_tx, object, TRUE, (char *)key);
* during iteration */
GOTO(out, rc = 0);
} else if (name[1] == '.' && name[2] == 0) {
* during iteration */
GOTO(out, rc = 0);
} else if (name[1] == '.' && name[2] == 0) {
+ if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT)) {
+ struct lu_fid tfid = *fid;
+
+ osd_object_put(env, child);
+ tfid.f_oid--;
+ child = osd_object_find(env, dt, &tfid);
+ if (IS_ERR(child))
+ RETURN(PTR_ERR(child));
+
+ LASSERT(child->oo_db);
+ }
+
/* update parent dnode in the child.
* later it will be used to generate ".." */
rc = osd_object_sa_update(parent,
SA_ZPL_PARENT(osd),
&child->oo_db->db_object,
8, oh);
/* update parent dnode in the child.
* later it will be used to generate ".." */
rc = osd_object_sa_update(parent,
SA_ZPL_PARENT(osd),
&child->oo_db->db_object,
8, oh);
rc = -zap_add(osd->od_os, parent->oo_db->db_object,
(char *)key, 8, sizeof(oti->oti_zde) / 8,
(void *)&oti->oti_zde, oh->ot_tx);
rc = -zap_add(osd->od_os, parent->oo_db->db_object,
(char *)key, 8, sizeof(oti->oti_zde) / 8,
(void *)&oti->oti_zde, oh->ot_tx);
+ if (unlikely(rc == -EEXIST &&
+ name[0] == '.' && name[1] == '.' && name[2] == 0))
+ /* Update (key,oid) in ZAP */
+ rc = -zap_update(osd->od_os, parent->oo_db->db_object,
+ (char *)key, 8, sizeof(oti->oti_zde) / 8,
+ (void *)&oti->oti_zde, oh->ot_tx);
-static struct dt_index_operations osd_dir_ops = {
+struct dt_index_operations osd_dir_ops = {
.dio_lookup = osd_dir_lookup,
.dio_declare_insert = osd_declare_dir_insert,
.dio_insert = osd_dir_insert,
.dio_lookup = osd_dir_lookup,
.dio_declare_insert = osd_declare_dir_insert,
.dio_insert = osd_dir_insert,
extern const struct dt_index_operations osd_acct_index_ops;
uint64_t osd_quota_fid2dmu(const struct lu_fid *fid);
extern struct lu_device_operations osd_lu_ops;
extern const struct dt_index_operations osd_acct_index_ops;
uint64_t osd_quota_fid2dmu(const struct lu_fid *fid);
extern struct lu_device_operations osd_lu_ops;
+extern struct dt_index_operations osd_dir_ops;
int osd_declare_quota(const struct lu_env *env, struct osd_device *osd,
qid_t uid, qid_t gid, long long space,
struct osd_thandle *oh, bool is_blk, int *flags,
int osd_declare_quota(const struct lu_env *env, struct osd_device *osd,
qid_t uid, qid_t gid, long long space,
struct osd_thandle *oh, bool is_blk, int *flags,
switch (dof->dof_type) {
case DFT_DIR:
switch (dof->dof_type) {
case DFT_DIR:
+ dt->do_index_ops = &osd_dir_ops;
case DFT_INDEX:
/* for zap create */
dmu_tx_hold_zap(oh->ot_tx, DMU_NEW_OBJECT, 1, NULL);
case DFT_INDEX:
/* for zap create */
dmu_tx_hold_zap(oh->ot_tx, DMU_NEW_OBJECT, 1, NULL);
[[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.50) ]] &&
ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2d 2e 3 22 23 24 25 26 27 28 29 30 31"
[[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.6.50) ]] &&
ALWAYS_EXCEPT="$ALWAYS_EXCEPT 2d 2e 3 22 23 24 25 26 27 28 29 30 31"
+# DNE does not support striped directory on zfs-based backend yet.
+[ $(facet_fstype $SINGLEMDS) != ldiskfs ] &&
+ ALWAYS_EXCEPT="$ALWAYS_EXCEPT 31"
+
build_test_filter
$LCTL set_param debug=+lfsck > /dev/null || true
build_test_filter
$LCTL set_param debug=+lfsck > /dev/null || true
echo "#####"
echo "The parent_A references the child directory via some name entry,"
echo "but the child directory back references another parent_B via its"
echo "#####"
echo "The parent_A references the child directory via some name entry,"
echo "but the child directory back references another parent_B via its"
- echo "".." name entry. The parent_A does not exist. Then the namesapce"
+ echo "".." name entry. The parent_B does not exist. Then the namesapce"
echo "LFSCK will repair the child directory's ".." name entry."
echo "#####"
echo "LFSCK will repair the child directory's ".." name entry."
echo "#####"
echo "The parent_A references the child directory via the name entry_B,"
echo "but the child directory back references another parent_C via its"
echo "".." name entry. The parent_C exists, but there is no the name"
echo "The parent_A references the child directory via the name entry_B,"
echo "but the child directory back references another parent_C via its"
echo "".." name entry. The parent_C exists, but there is no the name"
- echo "entry_B under the parent_B. Then the namesapce LFSCK will repair"
+ echo "entry_B under the parent_C. Then the namesapce LFSCK will repair"
echo "the child directory's ".." name entry and its linkEA."
echo "#####"
echo "the child directory's ".." name entry and its linkEA."
echo "#####"
echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
echo "and bad linkEA. The dummy's dotdot name entry references the"
echo "guard. The dummy's linkEA references n non-exist name entry."
echo "Inject failure stub on MDT0 to simulate bad dotdot name entry"
echo "and bad linkEA. The dummy's dotdot name entry references the"
echo "guard. The dummy's linkEA references n non-exist name entry."
- #define OBD_FAIL_LFSCK_BAD_PARENT2 0x161f
- do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161f
+ #define OBD_FAIL_LFSCK_BAD_PARENT 0x161e
+ do_facet $SINGLEMDS $LCTL set_param fail_loc=0x161e
$LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
error "(3) Fail to mkdir on MDT0"
do_facet $SINGLEMDS $LCTL set_param fail_loc=0
$LFS mkdir -i 0 $DIR/$tdir/foo/dummy ||
error "(3) Fail to mkdir on MDT0"
do_facet $SINGLEMDS $LCTL set_param fail_loc=0
mkdir $DIR/$tdir/d0/dummy || error "(2) Fail to mkdir dummy"
$LFS path2fid $DIR/$tdir/d0/dummy
mkdir $DIR/$tdir/d0/dummy || error "(2) Fail to mkdir dummy"
$LFS path2fid $DIR/$tdir/d0/dummy
- local pfid=$($LFS path2fid $DIR/$tdir/d0/dummy)
+
+ local pfid
+ if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then
+ pfid=$($LFS path2fid $DIR/$tdir/d0/guard)
+ else
+ pfid=$($LFS path2fid $DIR/$tdir/d0/dummy)
+ fi
touch $DIR/$tdir/d0/guard/foo ||
error "(3) Fail to touch $DIR/$tdir/d0/guard/foo"
touch $DIR/$tdir/d0/guard/foo ||
error "(3) Fail to touch $DIR/$tdir/d0/guard/foo"
do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1622
$LFS mkdir -i 0 $DIR/$tdir/d0/dummy/foo ||
error "(4) Fail to mkdir $DIR/$tdir/d0/dummy/foo"
do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1622
$LFS mkdir -i 0 $DIR/$tdir/d0/dummy/foo ||
error "(4) Fail to mkdir $DIR/$tdir/d0/dummy/foo"
+ $LFS path2fid $DIR/$tdir/d0/dummy/foo
local cfid=$($LFS path2fid $DIR/$tdir/d0/dummy/foo)
rmdir $DIR/$tdir/d0/dummy/foo ||
error "(5) Fail to remove $DIR/$tdir/d0/dummy/foo name entry"
local cfid=$($LFS path2fid $DIR/$tdir/d0/dummy/foo)
rmdir $DIR/$tdir/d0/dummy/foo ||
error "(5) Fail to remove $DIR/$tdir/d0/dummy/foo name entry"