On Fri, Aug 12, 2016 at 06:30:03PM -0500, Eric Sandeen wrote:
> This adds a new "crc" command to xfs_db for CRC-enabled filesystems.
>
> If a structure has a CRC field, we can validate it, invalidate/corrupt
> it, or revalidate/rewrite it:
>
> xfs_db> sb 0
> xfs_db> crc -v
> crc = 0x796c814f (correct)
> xfs_db> crc -i
> Metadata CRC error detected at block 0x0/0x200
> crc = 0x796c8150 (bad)
> xfs_db> crc -r
> crc = 0x796c814f (correct)
>
> (-i and -r require "expert" write-capable mode)
>
> This requires temporarily replacing the write verifier with
> a dummy which won't recalculate the CRC on the way to disk.
>
> It also required me to write a new flist function, which is
> totally foreign to me, so hopefully done right - but it seems
> to work here.
>
> Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
> ---
>
> I found this very useful when working with a filesystem image
> which was consistent except for a corrupt CRC; the ability to
> rewrite the correct CRCs and run repair to validate the fs was
> very handy...
Hi Eric,
I agree that this feature is very useful when some hardware or
software problems make a bad CRC value. But is this patch a completed
patch?
For example, flist_find_ftyp is created by this patch, by I can't find
where is it called in this patch.
I checked your original V1 patch:
https://www.marc.info/?l=linux-xfs&m=142662442506252&w=3
It has more content than this. Should I read/merge this patch with
other patches together?
Thanks,
Zorro
>
> V2: Fix whitespace damage, clarify write_cur() changes
> a bit w/ code & comments.
>
> V3: Be a bit more verbose with command output
>
> V4: Rebase patch to current tree
>
> diff --git a/db/Makefile b/db/Makefile
> index 8260da3..ba4b1a8 100644
> --- a/db/Makefile
> +++ b/db/Makefile
> @@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
> LTCOMMAND = xfs_db
>
> HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
> - btblock.h bmroot.h check.h command.h convert.h debug.h \
> + btblock.h bmroot.h check.h command.h convert.h crc.h debug.h \
> dir2.h dir2sf.h dquot.h echo.h faddr.h field.h \
> flist.h fprint.h frag.h freesp.h hash.h help.h init.h inode.h input.h \
> io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \
> diff --git a/db/command.c b/db/command.c
> index 3c17a1e..1848d64 100644
> --- a/db/command.c
> +++ b/db/command.c
> @@ -49,6 +49,7 @@
> #include "write.h"
> #include "malloc.h"
> #include "dquot.h"
> +#include "crc.h"
>
> cmdinfo_t *cmdtab;
> int ncmds;
> @@ -124,6 +125,7 @@ init_commands(void)
> bmap_init();
> check_init();
> convert_init();
> + crc_init();
> debug_init();
> echo_init();
> frag_init();
> diff --git a/db/flist.c b/db/flist.c
> index 84065a2..2530baf 100644
> --- a/db/flist.c
> +++ b/db/flist.c
> @@ -411,6 +411,40 @@ flist_split(
> return v;
> }
>
> +/*
> + * Given a set of fields, scan for a field of the given type.
> + * Return an flist leading to the first found field
> + * of that type.
> + * Return NULL if no field of the given type is found.
> + */
> +flist_t *
> +flist_find_ftyp(
> + const field_t *fields,
> + fldt_t type)
> +{
> + flist_t *fl;
> + const field_t *f;
> + const ftattr_t *fa;
> +
> + for (f = fields; f->name; f++) {
> + fl = flist_make(f->name);
> + fl->fld = f;
> + if (f->ftyp == type)
> + return fl;
> + fa = &ftattrtab[f->ftyp];
> + if (fa->subfld) {
> + flist_t *nfl;
> + nfl = flist_find_ftyp(fa->subfld, type);
> + if (nfl) {
> + fl->child = nfl;
> + return fl;
> + }
> + }
> + flist_free(fl);
> + }
> + return NULL;
> +}
> +
> static void
> ftok_free(
> ftok_t *ft)
> diff --git a/db/flist.h b/db/flist.h
> index 5c9fba0..3f4b312 100644
> --- a/db/flist.h
> +++ b/db/flist.h
> @@ -37,3 +37,4 @@ extern int flist_parse(const struct field *fields, flist_t
> *fl, void *obj,
> int startoff);
> extern void flist_print(flist_t *fl);
> extern flist_t *flist_scan(char *name);
> +extern flist_t *flist_find_ftyp(const field_t *fields, fldt_t type);
> diff --git a/db/io.c b/db/io.c
> index 91cab12..56b4414 100644
> --- a/db/io.c
> +++ b/db/io.c
> @@ -27,6 +27,7 @@
> #include "output.h"
> #include "init.h"
> #include "malloc.h"
> +#include "crc.h"
>
> static int pop_f(int argc, char **argv);
> static void pop_help(void);
> @@ -473,12 +474,14 @@ xfs_verify_recalc_crc(
> void
> write_cur(void)
> {
> + int skip_crc = (iocur_top->bp->b_ops->verify_write == xfs_dummy_verify);
> +
> if (iocur_sp < 0) {
> dbprintf(_("nothing to write\n"));
> return;
> }
>
> - if (xfs_sb_version_hascrc(&mp->m_sb) && iocur_top->ino_buf) {
> + if (xfs_sb_version_hascrc(&mp->m_sb) && iocur_top->ino_buf &&
> !skip_crc) {
> libxfs_dinode_calc_crc(mp, iocur_top->data);
> iocur_top->ino_crc_ok = 1;
> }
> @@ -489,6 +492,19 @@ write_cur(void)
> write_cur_bbs();
> else
> write_cur_buf();
> +
> + /* If we didn't write the crc automatically, re-check validity */
> + if (iocur_top->ino_buf && skip_crc) {
> + xfs_dinode_t *dip;
> + xfs_ino_t ino;
> +
> + dip = iocur_top->data;
> + ino = iocur_top->ino;
> + iocur_top->ino_crc_ok = xfs_verify_cksum((char *)dip,
> + mp->m_sb.sb_inodesize,
> + XFS_DINODE_CRC_OFF);
> + }
> +
> }
>
> void
> diff --git a/db/write.h b/db/write.h
> index 31e2665..664ddcc 100644
> --- a/db/write.h
> +++ b/db/write.h
> @@ -20,5 +20,5 @@ struct field;
>
> extern void write_init(void);
> extern void write_block(const field_t *fields, int argc, char **argv);
> -extern void write_string(const field_t *fields, int argc, char **argv);
> extern void write_struct(const field_t *fields, int argc, char **argv);
> +extern void write_string(const field_t *fields, int argc, char **argv);
> diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
> index ff8f862..894a94e 100644
> --- a/man/man8/xfs_db.8
> +++ b/man/man8/xfs_db.8
> @@ -87,16 +87,14 @@ or
> .I filename
> read-only. This option is required if the filesystem is mounted.
> It is only necessary to omit this flag if a command that changes data
> -.RB ( write ", " blocktrash )
> +.RB ( write ", " blocktrash ", " crc )
> is to be used.
> .TP
> .B \-x
> Specifies expert mode.
> This enables the
> -.B write
> -and
> -.B blocktrash
> -commands.
> +.RB ( write ", " blocktrash ", " crc
> +invalidate/revalidate) commands.
> .TP
> .B \-V
> Prints the version number and exits.
> @@ -422,6 +420,25 @@ conversions such as
> .I agb
> .BR fsblock .
> .TP
> +.B crc [\-i|\-r|\-v]
> +Invalidates, revalidates, or validates the CRC (checksum)
> +field of the current structure, if it has one.
> +This command is available only on CRC-enabled filesystems.
> +With no argument, validation is performed.
> +Each command will display the resulting CRC value and state.
> +.RS 1.0i
> +.TP 0.4i
> +.B \-i
> +Invalidate the structure's CRC value (incrementing it by one),
> +and write it to disk.
> +.TP
> +.B \-r
> +Recalculate the current structure's correct CRC value, and write it to disk.
> +.TP
> +.B \-v
> +Validate and display the current value and state of the structure's CRC.
> +.RE
> +.TP
> .BI "daddr [" d ]
> Set current address to the daddr (512 byte block) given by
> .IR d .
>
> _______________________________________________
> xfs mailing list
> xfs@xxxxxxxxxxx
> http://oss.sgi.com/mailman/listinfo/xfs
|