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 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs