@@ -42,6 +42,17 @@ OPTIONS
Perform metadata repairs if possible. Without this option,
the raw namespace contents will not be touched.
+-L::
+--rewrite-log::
+ Regenerate the BTT log and write it to media. This can be used to
+ convert from the old (pre 4.15) padding format that was incompatible
+ with other BTT implementations to the updated format. This requires
+ the --repair option to be provided.
+
+ WARNING: Do not interrupt this operation as it can potentially cause
+ unrecoverable metadata corruption. It is highly recommended to create
+ a backup of the raw namespace before attempting this.
+
-f::
--force::
Unless this option is specified, a check-namespace operation
@@ -46,6 +46,7 @@ struct check_opts {
bool verbose;
bool force;
bool repair;
+ bool logfix;
};
struct btt_chk {
@@ -246,6 +247,12 @@ static void btt_log_group_read(struct arena_info *a, u32 lane,
memcpy(log, &a->map.log[lane], LOG_GRP_SIZE);
}
+static void btt_log_group_write(struct arena_info *a, u32 lane,
+ struct log_group *log)
+{
+ memcpy(&a->map.log[lane], log, LOG_GRP_SIZE);
+}
+
static u32 log_seq(struct log_group *log, int log_idx)
{
return le32_to_cpu(log->ent[log_idx].seq);
@@ -358,6 +365,7 @@ enum btt_errcodes {
BTT_LOG_MAP_ERR,
BTT_MAP_OOB,
BTT_BITMAP_ERROR,
+ BTT_LOGFIX_ERR,
};
static void btt_xlat_status(struct arena_info *a, int errcode)
@@ -405,6 +413,11 @@ static void btt_xlat_status(struct arena_info *a, int errcode)
"arena %d: bitmap error: internal blocks are incorrectly referenced\n",
a->num);
break;
+ case BTT_LOGFIX_ERR:
+ err(a->bttc,
+ "arena %d: rewrite-log error: log may be in an unknown/unrecoverable state\n",
+ a->num);
+ break;
default:
err(a->bttc, "arena %d: unknown error: %d\n",
a->num, errcode);
@@ -563,6 +576,44 @@ static int btt_check_bitmap(struct arena_info *a)
return rc;
}
+static int btt_rewrite_log(struct arena_info *a)
+{
+ struct log_group log;
+ int rc;
+ u32 i;
+
+ info(a->bttc, "arena %d: rewriting log\n", a->num);
+ /*
+ * To rewrite the log, we implicitly use the 'new' padding scheme of
+ * (0, 1) but resetting the log to a completely initial state (i.e.
+ * slot-0 contains a made-up entry containing the 'free' block from
+ * the existing current log entry, and a sequence number of '1'. All
+ * other slots are zeroed.
+ *
+ * This way of rewriting the log is the most flexible as it can be
+ * (ab)used to convert a new padding format back to the old one.
+ * Since it only recreates slot-0, which is common between both
+ * existing formats, an older kernel will simply initialize the free
+ * list using those slot-0 entries, and run with it as though slot-2
+ * is the other valid slot.
+ */
+ memset(&log, 0, LOG_GRP_SIZE);
+ for (i = 0; i < a->nfree; i++) {
+ struct log_entry ent;
+
+ rc = btt_log_read(a, i, &ent);
+ if (rc)
+ return BTT_LOGFIX_ERR;
+
+ log.ent[0].lba = ent.lba;
+ log.ent[0].old_map = ent.old_map;
+ log.ent[0].new_map = ent.new_map;
+ log.ent[0].seq = 1;
+ btt_log_group_write(a, i, &log);
+ }
+ return 0;
+}
+
static int btt_check_arenas(struct btt_chk *bttc)
{
struct arena_info *a = NULL;
@@ -591,6 +642,12 @@ static int btt_check_arenas(struct btt_chk *bttc)
rc = btt_check_bitmap(a);
if (rc)
break;
+
+ if (bttc->opts->logfix) {
+ rc = btt_rewrite_log(a);
+ if (rc)
+ break;
+ }
}
if (a && rc != BTT_OK) {
@@ -1094,13 +1151,14 @@ static int btt_recover_first_sb(struct btt_chk *bttc)
}
int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
- bool repair)
+ bool repair, bool logfix)
{
const char *devname = ndctl_namespace_get_devname(ndns);
struct check_opts __opts = {
.verbose = verbose,
.force = force,
.repair = repair,
+ .logfix = logfix,
}, *opts = &__opts;
int raw_mode, rc, disabled_flag = 0, open_flags;
struct btt_sb *btt_sb;
@@ -1127,6 +1185,16 @@ int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
goto out_bttc;
}
+ if (opts->logfix) {
+ if (!opts->repair) {
+ err(bttc, "--rewrite-log also requires --repair\n");
+ rc = -EINVAL;
+ goto out_bttc;
+ }
+ info(bttc,
+ "WARNING: interruption may cause unrecoverable metadata corruption\n");
+ }
+
bttc->opts = opts;
bttc->sys_page_size = sysconf(_SC_PAGESIZE);
bttc->rawsize = ndctl_namespace_get_size(ndns);
@@ -39,6 +39,7 @@
static bool verbose;
static bool force;
static bool repair;
+static bool logfix;
static struct parameters {
bool do_scan;
bool mode_default;
@@ -121,6 +122,7 @@ OPT_BOOLEAN('L', "autolabel", ¶m.autolabel, "automatically initialize labels
#define CHECK_OPTIONS() \
OPT_BOOLEAN('R', "repair", &repair, "perform metadata repairs"), \
+OPT_BOOLEAN('L', "rewrite-log", &logfix, "regenerate the log"), \
OPT_BOOLEAN('f', "force", &force, "check namespace even if currently active")
static const struct option base_options[] = {
@@ -985,7 +987,7 @@ static int namespace_reconfig(struct ndctl_region *region,
}
int namespace_check(struct ndctl_namespace *ndns, bool verbose, bool force,
- bool repair);
+ bool repair, bool logfix);
static int do_xaction_namespace(const char *namespace,
enum device_action action, struct ndctl_ctx *ctx)
@@ -1049,7 +1051,7 @@ static int do_xaction_namespace(const char *namespace,
break;
case ACTION_CHECK:
rc = namespace_check(ndns, verbose,
- force, repair);
+ force, repair, logfix);
if (rc < 0)
return rc;
break;
@@ -193,6 +193,15 @@ do_tests()
cycle_ns "$dev"
verify_idx 0 2
+ # rewrite log using ndctl, verify conversion to new format
+ ndctl check-namespace --rewrite-log --repair --force --verbose $dev
+ do_random_io "/dev/$blockdev"
+ cycle_ns "$dev"
+ verify_idx 0 1
+
+ # check-namespace again to make sure everything is ok
+ ndctl check-namespace --force --verbose $dev
+
# the old format btt metadata was created with a null parent uuid,
# making it 'stickier' than a normally created btt. Be sure to clean
# it up by wiping the info block
Add a --rewrite-log option to ndctl check-namespace which reads the active log entries, and rewrites them as though initializing a new BTT. This allows us to convert an old (pre 4.15) format of log/padding layout to a new one that is compatible with other BTT implementations. In the btt-pad-compat unit test, add testing for the format conversion operation. Cc: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com> --- Documentation/ndctl/ndctl-check-namespace.txt | 11 +++++ ndctl/check.c | 70 ++++++++++++++++++++++++++- ndctl/namespace.c | 6 ++- test/btt-pad-compat.sh | 9 ++++ 4 files changed, 93 insertions(+), 3 deletions(-)