Whamcloud - gitweb
LU-13974 llog: check stale osp object
[fs/lustre-release.git] / lustre / obdclass / llog_osd.c
index fc0b16f..92d7186 100644 (file)
@@ -126,8 +126,7 @@ static int llog_osd_create_new_object(const struct lu_env *env,
 static int llog_osd_exist(struct llog_handle *handle)
 {
        LASSERT(handle->lgh_obj);
-       return dt_object_exists(handle->lgh_obj) &&
-               !lu_object_is_dying(handle->lgh_obj->do_lu.lo_header);
+       return dt_object_exists(handle->lgh_obj) && !handle->lgh_destroyed;
 }
 
 static void *rec_tail(struct llog_rec_hdr *rec)
@@ -413,6 +412,9 @@ static int llog_osd_write_rec(const struct lu_env *env,
                LASSERT(llh->llh_size == reclen);
        }
 
+       /* return error if osp object is stale */
+       if (idx != LLOG_HEADER_IDX && dt_object_stale(o))
+               RETURN(-ESTALE);
        rc = dt_attr_get(env, o, &lgi->lgi_attr);
        if (rc)
                RETURN(rc);
@@ -438,7 +440,7 @@ static int llog_osd_write_rec(const struct lu_env *env,
                /* llog can be empty only when first record is being written */
                LASSERT(ergo(idx > 0, lgi->lgi_attr.la_size > 0));
 
-               if (!ext2_test_bit(idx, LLOG_HDR_BITMAP(llh))) {
+               if (!test_bit_le(idx, LLOG_HDR_BITMAP(llh))) {
                        CERROR("%s: modify unset record %u\n",
                               o->do_lu.lo_dev->ld_obd->obd_name, idx);
                        RETURN(-ENOENT);
@@ -612,9 +614,10 @@ static int llog_osd_write_rec(const struct lu_env *env,
        /* the lgh_hdr_mutex protects llog header data from concurrent
         * update/cancel, the llh_count and llh_bitmap are protected */
        mutex_lock(&loghandle->lgh_hdr_mutex);
-       if (ext2_set_bit(index, LLOG_HDR_BITMAP(llh))) {
-               CERROR("%s: index %u already set in log bitmap\n",
-                      o->do_lu.lo_dev->ld_obd->obd_name, index);
+       if (__test_and_set_bit_le(index, LLOG_HDR_BITMAP(llh))) {
+               CERROR("%s: index %u already set in llog bitmap "DFID"\n",
+                      o->do_lu.lo_dev->ld_obd->obd_name, index,
+                      PFID(lu_object_fid(&o->do_lu)));
                mutex_unlock(&loghandle->lgh_hdr_mutex);
                LBUG(); /* should never happen */
        }
@@ -723,7 +726,7 @@ out_unlock:
 out:
        /* cleanup llog for error case */
        mutex_lock(&loghandle->lgh_hdr_mutex);
-       ext2_clear_bit(index, LLOG_HDR_BITMAP(llh));
+       clear_bit_le(index, LLOG_HDR_BITMAP(llh));
        llh->llh_count--;
        mutex_unlock(&loghandle->lgh_hdr_mutex);
 
@@ -903,7 +906,7 @@ static int llog_osd_next_block(const struct lu_env *env,
 
        o = loghandle->lgh_obj;
        LASSERT(o);
-       LASSERT(dt_object_exists(o));
+       LASSERT(llog_osd_exist(loghandle));
        dt = lu2dt_dev(o->do_lu.lo_dev);
        LASSERT(dt);
 
@@ -911,8 +914,9 @@ static int llog_osd_next_block(const struct lu_env *env,
        if (rc)
                GOTO(out, rc);
 
-       CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off"
-              "%llu), size %llu\n", next_idx, *cur_idx,
+       CDEBUG(D_OTHER,
+              "looking for log index %u (cur idx %u off %llu), size %llu\n",
+              next_idx, *cur_idx,
               *cur_offset, lgi->lgi_attr.la_size);
 
        while (*cur_offset < lgi->lgi_attr.la_size) {
@@ -967,9 +971,25 @@ static int llog_osd_next_block(const struct lu_env *env,
                rec = buf;
                if (LLOG_REC_HDR_NEEDS_SWABBING(rec))
                        lustre_swab_llog_rec(rec);
-
                tail = (struct llog_rec_tail *)((char *)buf + rc -
                                                sizeof(struct llog_rec_tail));
+
+               if (llog_verify_record(loghandle, rec)) {
+                       /*
+                        * the block seems corrupted. make a pad record so the
+                        * caller can skip the block and try with the next one
+                        */
+                       rec->lrh_len = rc;
+                       rec->lrh_index = next_idx;
+                       rec->lrh_type = LLOG_PAD_MAGIC;
+
+                       tail = rec_tail(rec);
+                       tail->lrt_len = rc;
+                       tail->lrt_index = next_idx;
+
+                       GOTO(out, rc = 0);
+               }
+
                /* get the last record in block */
                last_rec = (struct llog_rec_hdr *)((char *)buf + rc -
                                                   tail->lrt_len);
@@ -978,9 +998,7 @@ static int llog_osd_next_block(const struct lu_env *env,
                        lustre_swab_llog_rec(last_rec);
 
                if (last_rec->lrh_index != tail->lrt_index) {
-                       CERROR("%s: invalid llog tail at log id "DFID":%x "
-                              "offset %llu last_rec idx %u tail idx %u"
-                              "lrt len %u read_size %d\n",
+                       CERROR("%s: invalid llog tail at log id "DFID":%x offset %llu last_rec idx %u tail idx %u lrt len %u read_size %d\n",
                               o->do_lu.lo_dev->ld_obd->obd_name,
                               PFID(&loghandle->lgh_id.lgl_oi.oi_fid),
                               loghandle->lgh_id.lgl_ogen, *cur_offset,
@@ -1008,7 +1026,7 @@ static int llog_osd_next_block(const struct lu_env *env,
 
                /* sanity check that the start of the new buffer is no farther
                 * than the record that we wanted.  This shouldn't happen. */
-               if (rec->lrh_index > next_idx) {
+               if (next_idx && rec->lrh_index > next_idx) {
                        if (!force_mini_rec && next_idx > last_idx)
                                goto retry;
 
@@ -1077,7 +1095,7 @@ static int llog_osd_prev_block(const struct lu_env *env,
 
        o = loghandle->lgh_obj;
        LASSERT(o);
-       LASSERT(dt_object_exists(o));
+       LASSERT(llog_osd_exist(loghandle));
        dt = lu2dt_dev(o->do_lu.lo_dev);
        LASSERT(dt);
 
@@ -1249,8 +1267,7 @@ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle,
                } else {
                        /* If logid == NULL, then it means the caller needs
                         * to allocate new FID (llog_cat_declare_add_rec()). */
-                       rc = obd_fid_alloc(env, ctxt->loc_exp,
-                                          &lgi->lgi_fid, NULL);
+                       rc = dt_fid_alloc(env, dt, &lgi->lgi_fid, NULL, NULL);
                        if (rc < 0)
                                RETURN(rc);
                        rc = 0;
@@ -1311,7 +1328,12 @@ generate:
                        GOTO(out, rc);
                new_id = true;
        }
-
+       if (OBD_FAIL_PRECHECK(OBD_FAIL_MDS_LLOG_UMOUNT_RACE) &&
+           cfs_fail_val == 1) {
+               cfs_fail_val = 2;
+               OBD_RACE(OBD_FAIL_MDS_LLOG_UMOUNT_RACE);
+               msleep(MSEC_PER_SEC);
+       }
        o = ls_locate(env, ls, &lgi->lgi_fid, NULL);
        if (IS_ERR(o))
                GOTO(out_name, rc = PTR_ERR(o));
@@ -1800,7 +1822,7 @@ static int llog_osd_destroy(const struct lu_env *env,
        LASSERT(o != NULL);
 
        dt_write_lock(env, o, 0);
-       if (!dt_object_exists(o))
+       if (!llog_osd_exist(loghandle))
                GOTO(out_unlock, rc = 0);
 
        if (loghandle->lgh_name) {
@@ -1826,6 +1848,7 @@ static int llog_osd_destroy(const struct lu_env *env,
        if (rc < 0)
                GOTO(out_unlock, rc);
 
+       loghandle->lgh_destroyed = true;
        if (loghandle->lgh_ctxt->loc_flags & LLOG_CTXT_FLAG_NORMAL_FID) {
                rc = llog_osd_regular_fid_del_name_entry(env, o, th, false);
                if (rc < 0)
@@ -2011,7 +2034,7 @@ int llog_osd_get_cat_list(const struct lu_env *env, struct dt_device *d,
                if (IS_ERR(th))
                        GOTO(out, rc = PTR_ERR(th));
 
-               lgi->lgi_attr.la_valid = LA_MODE;
+               lgi->lgi_attr.la_valid = LA_MODE | LA_TYPE;
                lgi->lgi_attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
                lgi->lgi_dof.dof_type = dt_mode_to_dft(S_IFREG);