#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
GOTO(out, rc);
}
+ 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) {
struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram;
struct dt_object *parent = NULL;
struct linkea_data ldata_new = { 0 };
- int count = 0;
+ int dirent_count = 0;
+ int linkea_count = 0;
int rc = 0;
bool once = true;
ENTRY;
/* Drop invalid linkEA entry. */
if (!fid_is_sane(tfid)) {
linkea_del_buf(ldata, cname);
+ linkea_count++;
continue;
}
* child to be visible via other parent, then
* remove this linkEA entry. */
linkea_del_buf(ldata, cname);
+ linkea_count++;
continue;
}
if (unlikely(!dt_try_as_dir(env, parent))) {
lfsck_object_put(env, parent);
linkea_del_buf(ldata, cname);
+ linkea_count++;
continue;
}
RETURN(rc);
linkea_del_buf(ldata, cname);
+ linkea_count++;
linkea_first_entry(ldata);
/* There may be some invalid dangling name entries under
* other parent directories, remove all of them. */
goto next;
}
- count += rc;
+ dirent_count += rc;
next:
linkea_del_buf(ldata, cname);
}
- ns->ln_dirent_repaired += count;
+ ns->ln_dirent_repaired += dirent_count;
RETURN(rc);
}
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 (rc == 0 && fid_is_zero(pfid) && linkea_count > 0)
+ rc = lfsck_namespace_rebuild_linkea(env, com, child,
+ ldata);
+
RETURN(rc);
}
RETURN(rc);
}
- 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. */
} 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);
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--;
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 osd_object *obj = osd_dt_obj(dt);
struct osd_thandle *oh;
+ uint64_t object;
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);
RETURN(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);
+
GOTO(out, rc);
}
}
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);
out:
if (child != NULL)
RETURN(rc);
}
-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,
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,
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);
[[ $(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
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 "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 "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
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"
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"