staging/lustre/lov: don't crash accessing LOV object with FID{0, 0}
authorYang Sheng <yang.sheng@intel.com>
Thu, 26 Mar 2015 01:53:22 +0000 (21:53 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Mar 2015 10:10:25 +0000 (11:10 +0100)
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: Fan Yong <fan.yong@intel.com>
Signed-off-by: Yang 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: Jian Yu <jian.yu@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/lov/lov_ea.c
drivers/staging/lustre/lustre/lov/lov_internal.h
drivers/staging/lustre/lustre/lov/lov_io.c
drivers/staging/lustre/lustre/lov/lov_lock.c
drivers/staging/lustre/lustre/lov/lov_obd.c
drivers/staging/lustre/lustre/lov/lov_object.c
drivers/staging/lustre/lustre/lov/lov_request.c

index d1b0417d50583a2b2d3a99c049020ae6d6de5f87..2bcfaeaff6fa586efe924ed1edf182d0c980177b 100644 (file)
@@ -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);
index 8c8508bbbb808750b36411841683f0583cc0de8e..b644acc9b034c0c36cf726aecfbd65e33f8d995e 100644 (file)
@@ -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
index f1f6db3f664a06952f73992f23c0bc62ce335aa3..80c2ef6d0fb5d92fd8568166782994d98c36dd22 100644 (file)
@@ -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)) {
index 49e694222ac839416327779de74d25de31b9e38c..f2eca565bddab0130ea80f470458e71c349b8245 100644 (file)
@@ -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;
index b2ed52f20afbf9cadf9e563164a094bdf7d94654..02781576637edd64657486d548fc8364a75550d5 100644 (file)
@@ -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);
+                       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 ==
index d69a0354baf51a4875b1cb0dfeebc830c4ed8928..1fb1dfae6f72542dcea8f3b0fe5408768b7d78cb 100644 (file)
@@ -230,6 +230,9 @@ static int lov_init_raid0(const struct lu_env *env,
                        struct lov_oinfo *oinfo = lsm->lsm_oinfo[i];
                        int ost_idx = oinfo->loi_ost_idx;
 
+                       if (lov_oinfo_is_dummy(oinfo))
+                               continue;
+
                        result = ostid_to_fid(ofid, &oinfo->loi_oi,
                                              oinfo->loi_ost_idx);
                        if (result != 0)
@@ -973,6 +976,10 @@ int lov_read_and_clear_async_rc(struct cl_object *clob)
                        LASSERT(lsm != NULL);
                        for (i = 0; i < lsm->lsm_stripe_count; i++) {
                                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
+
+                               if (lov_oinfo_is_dummy(loi))
+                                       continue;
+
                                if (loi->loi_ar.ar_rc && !rc)
                                        rc = loi->loi_ar.ar_rc;
                                loi->loi_ar.ar_rc = 0;
index 7358b9d29103c89dbff7719e69c92186c4bde1db..933e2d1f8127e13a37c116b3737a61bd188635e1 100644 (file)
@@ -299,6 +299,9 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_request *req;
 
                loi = oinfo->oi_md->lsm_oinfo[i];
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        if (oinfo->oi_oa->o_valid & OBD_MD_FLEPOCH) {
@@ -384,6 +387,9 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_request *req;
 
                loi = lsm->lsm_oinfo[i];
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        continue;
@@ -497,6 +503,9 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
                struct lov_oinfo *loi = oinfo->oi_md->lsm_oinfo[i];
                struct lov_request *req;
 
+               if (lov_oinfo_is_dummy(loi))
+                       continue;
+
                if (!lov_check_and_wait_active(lov, loi->loi_ost_idx)) {
                        CDEBUG(D_HA, "lov idx %d inactive\n", loi->loi_ost_idx);
                        continue;