* into structure @lrd
*/
static int tgt_reply_data_read(const struct lu_env *env, struct lu_target *tgt,
- struct lsd_reply_data *lrd, loff_t off)
+ struct lsd_reply_data *lrd, loff_t off,
+ __u32 magic)
{
- int rc;
- struct tgt_thread_info *tti = tgt_th_info(env);
- struct lsd_reply_data *buf = &tti->tti_lrd;
+ struct tgt_thread_info *tti = tgt_th_info(env);
+ struct lsd_reply_data *buf = &tti->tti_lrd;
+ int rc;
tti->tti_off = off;
tti->tti_buf.lb_buf = buf;
- tti->tti_buf.lb_len = sizeof(*buf);
+
+ if (magic == LRH_MAGIC)
+ tti->tti_buf.lb_len = sizeof(*buf);
+ else if (magic == LRH_MAGIC_V1)
+ tti->tti_buf.lb_len = sizeof(struct lsd_reply_data_v1);
+ else
+ return -EINVAL;
rc = dt_record_read(env, tgt->lut_reply_data, &tti->tti_buf,
&tti->tti_off);
if (rc != 0)
return rc;
- lrd->lrd_transno = le64_to_cpu(buf->lrd_transno);
- lrd->lrd_xid = le64_to_cpu(buf->lrd_xid);
- lrd->lrd_data = le64_to_cpu(buf->lrd_data);
- lrd->lrd_result = le32_to_cpu(buf->lrd_result);
- lrd->lrd_client_gen = le32_to_cpu(buf->lrd_client_gen);
- lrd->lrd_batch_idx = le32_to_cpu(buf->lrd_batch_idx);
+ lrd->lrd_transno = le64_to_cpu(buf->lrd_transno);
+ lrd->lrd_xid = le64_to_cpu(buf->lrd_xid);
+ lrd->lrd_data = le64_to_cpu(buf->lrd_data);
+ lrd->lrd_result = le32_to_cpu(buf->lrd_result);
+ lrd->lrd_client_gen = le32_to_cpu(buf->lrd_client_gen);
+
+ if (magic == LRH_MAGIC)
+ lrd->lrd_batch_idx = le32_to_cpu(buf->lrd_batch_idx);
+ else
+ lrd->lrd_batch_idx = 0;
+
return 0;
}
-
/* Free the in-memory reply data structure @trd and release
* the corresponding slot in the reply_data file of target @lut
* Called with ted_lcd_lock held
}
EXPORT_SYMBOL(tgt_server_data_update);
-static int tgt_truncate_last_rcvd(const struct lu_env *env,
- struct lu_target *tgt, loff_t size)
+static int tgt_truncate_object(const struct lu_env *env, struct lu_target *tgt,
+ struct dt_object *dt, loff_t size)
{
- struct dt_object *dt = tgt->lut_last_rcvd;
struct thandle *th;
struct lu_attr attr;
int rc;
tgt_client_data_update(env, exp);
}
+static int tgt_reply_data_upgrade_check(const struct lu_env *env,
+ struct lu_target *tgt)
+{
+ struct lsd_reply_header lrh;
+ int rc;
+
+ /*
+ * Reply data is supported by MDT targets only for now.
+ * When reply data object @lut_reply_data is NULL, it indicates the
+ * target type is OST and it should skip the upgrade check.
+ */
+ if (tgt->lut_reply_data == NULL)
+ RETURN(0);
+
+ rc = tgt_reply_header_read(env, tgt, &lrh);
+ if (rc) {
+ CERROR("%s: failed to read %s: rc = %d\n",
+ tgt_name(tgt), REPLY_DATA, rc);
+ RETURN(rc);
+ }
+
+ if (lrh.lrh_magic == LRH_MAGIC)
+ RETURN(0);
+
+ rc = tgt_truncate_object(env, tgt, tgt->lut_reply_data, 0);
+ if (rc) {
+ CERROR("%s: failed to truncate %s: rc = %d\n",
+ tgt_name(tgt), REPLY_DATA, rc);
+ RETURN(rc);
+ }
+
+ lrh.lrh_magic = LRH_MAGIC;
+ lrh.lrh_header_size = sizeof(struct lsd_reply_header);
+ lrh.lrh_reply_size = sizeof(struct lsd_reply_data);
+ rc = tgt_reply_header_write(env, tgt, &lrh);
+ if (rc)
+ CERROR("%s: failed to write header for %s: rc = %d\n",
+ tgt_name(tgt), REPLY_DATA, rc);
+
+ RETURN(rc);
+}
+
/**
* Update boot epoch when recovery ends
*/
/** update server epoch */
tgt_server_data_update(&env, tgt, 1);
+ tgt_reply_data_upgrade_check(&env, tgt);
lu_env_fini(&env);
}
LCONSOLE_WARN("%s: mounting at first time on 1.8 FS, "
"remove all clients for interop needs\n",
tgt_name(tgt));
- rc = tgt_truncate_last_rcvd(env, tgt,
- lsd->lsd_client_start);
+ rc = tgt_truncate_object(env, tgt, tgt->lut_last_rcvd,
+ lsd->lsd_client_start);
if (rc)
RETURN(rc);
last_rcvd_size = lsd->lsd_client_start;
GOTO(out, rc);
}
} else {
+ __u32 recsz = sizeof(struct lsd_reply_data);
+
rc = tgt_reply_header_read(env, tgt, lrh);
if (rc) {
CERROR("%s: error reading %s: rc = %d\n",
tgt_name(tgt), REPLY_DATA, rc);
GOTO(out, rc);
}
- if (lrh->lrh_magic != LRH_MAGIC ||
- lrh->lrh_header_size != sizeof(struct lsd_reply_header) ||
- lrh->lrh_reply_size != sizeof(struct lsd_reply_data)) {
+ if (!(lrh->lrh_magic == LRH_MAGIC &&
+ lrh->lrh_reply_size == sizeof(struct lsd_reply_data) &&
+ lrh->lrh_header_size == sizeof(struct lsd_reply_header)) &&
+ !(lrh->lrh_magic == LRH_MAGIC_V1 &&
+ lrh->lrh_reply_size == sizeof(struct lsd_reply_data_v1) &&
+ lrh->lrh_header_size == sizeof(struct lsd_reply_header))) {
CERROR("%s: invalid header in %s\n",
tgt_name(tgt), REPLY_DATA);
GOTO(out, rc = -EINVAL);
}
+ if (lrh->lrh_magic == LRH_MAGIC_V1)
+ recsz = sizeof(struct lsd_reply_data_v1);
+
hash = cfs_hash_getref(tgt->lut_obd->obd_gen_hash);
if (hash == NULL)
GOTO(out, rc = -ENODEV);
/* Load reply_data from disk */
for (idx = 0, off = sizeof(struct lsd_reply_header);
- off < reply_data_size;
- idx++, off += sizeof(struct lsd_reply_data)) {
- rc = tgt_reply_data_read(env, tgt, lrd, off);
+ off < reply_data_size; idx++, off += recsz) {
+ rc = tgt_reply_data_read(env, tgt, lrd, off,
+ lrh->lrh_magic);
if (rc) {
CERROR("%s: error reading %s: rc = %d\n",
tgt_name(tgt), REPLY_DATA, rc);
{
struct lsd_reply_header lrh = {};
unsigned long long slot;
+ __u32 recsz;
int rc = 0;
int n;
lrh.lrh_magic = __le32_to_cpu(lrh.lrh_magic);
lrh.lrh_header_size = __le32_to_cpu(lrh.lrh_header_size);
lrh.lrh_reply_size = __le32_to_cpu(lrh.lrh_reply_size);
- if (lrh.lrh_magic != LRH_MAGIC) {
- fprintf(stderr,
- "%s: invalid %s header: lrh_magic=0x%08x expected 0x%08x\n",
- progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC);
- rc = EINVAL;
- }
if (lrh.lrh_header_size != sizeof(struct lsd_reply_header)) {
fprintf(stderr,
"%s: invalid %s header: lrh_header_size=0x%08x expected 0x%08x\n",
(unsigned int)sizeof(struct lsd_reply_header));
rc = EINVAL;
}
- if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) {
+ if (lrh.lrh_magic == LRH_MAGIC) {
+ if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) {
+ fprintf(stderr,
+ "%s: invalid %s header: lrh_reply_size=0x%08x expected 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_reply_size,
+ (unsigned int)sizeof(struct lsd_reply_data));
+ rc = EINVAL;
+ } else {
+ recsz = sizeof(struct lsd_reply_data);
+ }
+ } else if (lrh.lrh_magic == LRH_MAGIC_V1) {
+ if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data_v1)) {
+ fprintf(stderr,
+ "%s: invalid %s header: lrh_reply_size=0x%08x expected 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_reply_size,
+ (unsigned int)sizeof(struct lsd_reply_data));
+ rc = EINVAL;
+ } else {
+ recsz = sizeof(struct lsd_reply_data_v1);
+ }
+ } else {
fprintf(stderr,
- "%s: invalid %s header: lrh_reply_size=0x%08x expected 0x%08x\n",
- progname, REPLY_DATA, lrh.lrh_reply_size,
- (unsigned int)sizeof(struct lsd_reply_data));
+ "%s: invalid %s header: lrh_magic=0x%08x expected 0x%08x or 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC,
+ LRH_MAGIC_V1);
rc = EINVAL;
}
struct lsd_reply_data lrd;
/* read a reply data */
- n = fread(&lrd, 1, sizeof(lrd), fp);
- if (n < sizeof(lrd)) {
+ n = fread(&lrd, 1, recsz, fp);
+ if (n < recsz) {
if (feof(fp))
break;
fprintf(stderr, "%s: Short read (%d of %d)\n",
lrd.lrd_result = __le32_to_cpu(lrd.lrd_result);
lrd.lrd_client_gen = __le32_to_cpu(lrd.lrd_client_gen);
+ if (lrh.lrh_magic == LRH_MAGIC)
+ lrd.lrd_batch_idx = __le32_to_cpu(lrd.lrd_batch_idx);
+
printf(" %lld:\n", slot);
printf(" client_generation: %u\n",
lrd.lrd_client_gen);
printf(" last_result: %u\n", lrd.lrd_result);
printf(" last_data: %llu\n\n",
(unsigned long long)lrd.lrd_data);
+ if (lrh.lrh_magic == LRH_MAGIC)
+ printf(" batch_idx: %u\n", lrd.lrd_batch_idx);
}
return 0;