Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 397632e4 authored by Yang Sheng's avatar Yang Sheng Committed by Greg Kroah-Hartman
Browse files

staging/lustre/lov: don't crash accessing LOV object with FID{0, 0}



Some object maybe has a corrupted LOV EA or a hole in
LOV EA. We should not crash client in such case.

Signed-off-by: default avatarFan Yong <fan.yong@intel.com>
Signed-off-by: default avatarYang Sheng <yang.sheng@intel.com>
Reviewed-on: http://review.whamcloud.com/12740
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4958


Reviewed-by: default avatarJian Yu <jian.yu@intel.com>
Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Signed-off-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4345abb2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -227,6 +227,9 @@ static int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
		ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
		loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
		loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
		if (lov_oinfo_is_dummy(loi))
			continue;

		if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) {
			CERROR("OST index %d more than OST count %d\n",
			       loi->loi_ost_idx, lov->desc.ld_tgt_count);
@@ -314,6 +317,9 @@ static int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm,
		ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi);
		loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
		loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
		if (lov_oinfo_is_dummy(loi))
			continue;

		if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) {
			CERROR("OST index %d more than OST count %d\n",
			       loi->loi_ost_idx, lov->desc.ld_tgt_count);
+12 −0
Original line number Diff line number Diff line
@@ -304,4 +304,16 @@ static inline struct lov_stripe_md *lsm_addref(struct lov_stripe_md *lsm)
	return lsm;
}

static inline bool lov_oinfo_is_dummy(const struct lov_oinfo *loi)
{
	if (unlikely(loi->loi_oi.oi.oi_id == 0 &&
		     loi->loi_oi.oi.oi_seq == 0 &&
		     loi->loi_ost_idx == 0 &&
		     loi->loi_ost_gen == 0))
		return true;

	return false;
}


#endif
+12 −0
Original line number Diff line number Diff line
@@ -148,6 +148,9 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
	LASSERT(sub->sub_env == NULL);
	LASSERT(sub->sub_stripe < lio->lis_stripe_count);

	if (unlikely(lov_r0(lov)->lo_sub[stripe] == NULL))
		return -EIO;

	result = 0;
	sub->sub_io_initialized = 0;
	sub->sub_borrowed = 0;
@@ -391,6 +394,15 @@ static int lov_io_iter_init(const struct lu_env *env,
					   endpos, &start, &end))
			continue;

		if (unlikely(lov_r0(lio->lis_object)->lo_sub[stripe] == NULL)) {
			if (ios->cis_io->ci_type == CIT_READ ||
			    ios->cis_io->ci_type == CIT_WRITE ||
			    ios->cis_io->ci_type == CIT_FAULT)
				return -EIO;

			continue;
		}

		end = lov_offset_mod(end, +1);
		sub = lov_sub_get(env, lio, stripe);
		if (!IS_ERR(sub)) {
+20 −6
Original line number Diff line number Diff line
@@ -308,7 +308,8 @@ static int lov_lock_sub_init(const struct lu_env *env,
		 * XXX for wide striping smarter algorithm is desirable,
		 * breaking out of the loop, early.
		 */
		if (lov_stripe_intersects(loo->lo_lsm, i,
		if (likely(r0->lo_sub[i] != NULL) &&
		    lov_stripe_intersects(loo->lo_lsm, i,
					  file_start, file_end, &start, &end))
			nr++;
	}
@@ -326,7 +327,8 @@ static int lov_lock_sub_init(const struct lu_env *env,
	 * top-lock.
	 */
	for (i = 0, nr = 0; i < r0->lo_nr; ++i) {
		if (lov_stripe_intersects(loo->lo_lsm, i,
		if (likely(r0->lo_sub[i] != NULL) &&
		    lov_stripe_intersects(loo->lo_lsm, i,
					  file_start, file_end, &start, &end)) {
			struct cl_lock_descr *descr;

@@ -914,10 +916,22 @@ static int lov_lock_stripe_is_matching(const struct lu_env *env,
	 */
	start = cl_offset(&lov->lo_cl, descr->cld_start);
	end   = cl_offset(&lov->lo_cl, descr->cld_end + 1) - 1;
	result = end - start <= lsm->lsm_stripe_size &&
		 stripe == lov_stripe_number(lsm, start) &&
		 stripe == lov_stripe_number(lsm, end);
	if (result) {
	result = 0;
	/* glimpse should work on the object with LOV EA hole. */
	if (end - start <= lsm->lsm_stripe_size) {
		int idx;

		idx = lov_stripe_number(lsm, start);
		if (idx == stripe ||
		    unlikely(lov_r0(lov)->lo_sub[idx] == NULL)) {
			idx = lov_stripe_number(lsm, end);
			if (idx == stripe ||
			    unlikely(lov_r0(lov)->lo_sub[idx] == NULL))
				result = 1;
		}
	}

	if (result != 0) {
		struct cl_lock_descr *subd = &lov_env_info(env)->lti_ldescr;
		u64 sub_start;
		u64 sub_end;
+26 −6
Original line number Diff line number Diff line
@@ -1011,9 +1011,13 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
	}

	for (i = 0; i < lsm->lsm_stripe_count; i++) {
		if (lsm->lsm_oinfo[i]->loi_ost_idx == ost_idx) {
			if (ostid_id(&lsm->lsm_oinfo[i]->loi_oi) !=
					ostid_id(&src_oa->o_oi)) {
		struct lov_oinfo *loi = lsm->lsm_oinfo[i];

		if (lov_oinfo_is_dummy(loi))
			continue;

		if (loi->loi_ost_idx == ost_idx) {
			if (ostid_id(&loi->loi_oi) != ostid_id(&src_oa->o_oi)) {
				rc = -EINVAL;
				goto out;
			}
@@ -1305,10 +1309,14 @@ static int lov_find_cbdata(struct obd_export *exp,
		struct lov_stripe_md submd;
		struct lov_oinfo *loi = lsm->lsm_oinfo[i];

		if (lov_oinfo_is_dummy(loi))
			continue;

		if (!lov->lov_tgts[loi->loi_ost_idx]) {
			CDEBUG(D_HA, "lov idx %d NULL\n", loi->loi_ost_idx);
			continue;
		}

		submd.lsm_oi = loi->loi_oi;
		submd.lsm_stripe_count = 0;
		rc = obd_find_cbdata(lov->lov_tgts[loi->loi_ost_idx]->ltd_exp,
@@ -1616,8 +1624,12 @@ static u64 fiemap_calc_fm_end_offset(struct ll_user_fiemap *fiemap,

	/* Find out stripe_no from ost_index saved in the fe_device */
	for (i = 0; i < lsm->lsm_stripe_count; i++) {
		if (lsm->lsm_oinfo[i]->loi_ost_idx ==
					fiemap->fm_extents[0].fe_device) {
		struct lov_oinfo *oinfo = lsm->lsm_oinfo[i];

		if (lov_oinfo_is_dummy(oinfo))
			continue;

		if (oinfo->loi_ost_idx == fiemap->fm_extents[0].fe_device) {
			stripe_no = i;
			break;
		}
@@ -1795,6 +1807,11 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key,
					   &lun_start, &obd_object_end)) == 0)
			continue;

		if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe])) {
			rc = -EIO;
			goto out;
		}

		/* If this is a continuation FIEMAP call and we are on
		 * starting stripe then lun_start needs to be set to
		 * fm_end_offset */
@@ -1985,6 +2002,9 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp,
		 * be NULL and won't match the lock's export. */
		for (i = 0; i < lsm->lsm_stripe_count; i++) {
			loi = lsm->lsm_oinfo[i];
			if (lov_oinfo_is_dummy(loi))
				continue;

			if (!lov->lov_tgts[loi->loi_ost_idx])
				continue;
			if (lov->lov_tgts[loi->loi_ost_idx]->ltd_exp ==
Loading