Optimize secondary sb search, using similar method to find fs geometry as that of xfs_mkfs. If this faster method fails in finding a secondary sb, fall back to original brute force slower search. Signed-off-by: Bill O'Donnell <billodo@xxxxxxxxxx> --- Makefile | 2 +- include/libxcmd.h | 4 +++- libxcmd/topology.c | 28 +++++++++++++++++++++++++++- repair/Makefile | 4 ++-- repair/phase1.c | 25 +++++++++++++++++++++++-- repair/protos.h | 2 +- repair/sb.c | 27 +++++++++++++++++++++------ 7 files changed, 78 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index fca0a42..1d60d9c 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ fsr: libhandle growfs: libxcmd io: libxcmd libhandle quota: libxcmd -repair: libxlog +repair: libxlog libxcmd copy: libxlog ifeq ($(HAVE_BUILDDEFS), yes) diff --git a/include/libxcmd.h b/include/libxcmd.h index df7046e..b140adb 100644 --- a/include/libxcmd.h +++ b/include/libxcmd.h @@ -50,6 +50,8 @@ extern int check_overwrite( char *device); - +extern int guess_default_geometry(__uint64_t *agsize, + __uint64_t *agcount, + libxfs_init_t x); #endif /* __LIBXCMD_H__ */ diff --git a/libxcmd/topology.c b/libxcmd/topology.c index 0eeea28..4a8ab8b 100644 --- a/libxcmd/topology.c +++ b/libxcmd/topology.c @@ -302,7 +302,6 @@ static void blkid_get_topology( #endif /* ENABLE_BLKID */ - void get_topology( libxfs_init_t *xi, struct fs_topology *ft, @@ -346,3 +345,30 @@ void get_topology( &lsectorsize, &psectorsize, force_overwrite); } } + +/* + * Use this macro before we have superblock and mount structure + */ +#define DTOBT(d) ((xfs_rfsblock_t)((d) >> (blocklog - BBSHIFT))) + +int guess_default_geometry(__uint64_t *agsize, __uint64_t *agcount, libxfs_init_t x) { + struct fs_topology ft; + int blocklog; + __uint64_t dblocks; + int multidisk; + memset(&ft, 0, sizeof(ft)); + get_topology(&x, &ft, 1); + + /* + * get geometry from get_topology result. + * Use default block size (2^12) + */ + blocklog = 12; + multidisk = ft.dswidth | ft.dsunit; + printf("x.dsize = %lu\n",(long unsigned int)x.dsize); + dblocks = DTOBT(x.dsize); + calc_default_ag_geometry(blocklog, dblocks, multidisk, + agsize, agcount); + + return(blocklog); +} diff --git a/repair/Makefile b/repair/Makefile index 251722b..d24ab1f 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -20,8 +20,8 @@ CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c btree.c \ progress.c prefetch.c rt.c sb.c scan.c threads.c \ versions.c xfs_repair.c -LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) -LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) +LLDLIBS = $(LIBBLKID) $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) $(LIBXCMD) +LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBXCMD) LLDFLAGS = -static-libtool-libs default: depend $(LTCOMMAND) diff --git a/repair/phase1.c b/repair/phase1.c index 126d0b3..c27033d 100644 --- a/repair/phase1.c +++ b/repair/phase1.c @@ -21,6 +21,7 @@ #include "agheader.h" #include "protos.h" #include "err_protos.h" +#include "libxcmd.h" static void no_sb(void) @@ -47,6 +48,9 @@ alloc_ag_buf(int size) */ #define MAX_SECTSIZE (512 * 1024) +extern libxfs_init_t x; + + /* ARGSUSED */ void phase1(xfs_mount_t *mp) @@ -54,6 +58,10 @@ phase1(xfs_mount_t *mp) xfs_sb_t *sb; char *ag_bp; int rval; + int blocklog; + __uint64_t agcount; + __uint64_t agsize; + __uint64_t skipsize; do_log(_("Phase 1 - find and verify superblock...\n")); @@ -65,6 +73,18 @@ phase1(xfs_mount_t *mp) lost_quotas = 0; /* + * divine the geometry ;) + */ + blocklog = guess_default_geometry(&agsize, &agcount, x); + + /* + * use found ag geometry to quickly find secondary sb + */ + skipsize = agsize << blocklog; + do_log("agsize = %d agcount = %d skipsize = %d\n", + (int)agsize, (int)agcount, (int)skipsize); + + /* * get AG 0 into ag header buf */ ag_bp = alloc_ag_buf(MAX_SECTSIZE); @@ -80,14 +100,15 @@ phase1(xfs_mount_t *mp) if (rval != XR_OK) { do_warn(_("bad primary superblock - %s !!!\n"), err_string(rval)); - if (!find_secondary_sb(sb)) + + if (!find_secondary_sb(sb, skipsize)) no_sb(); primary_sb_modified = 1; } else if ((rval = verify_set_primary_sb(sb, 0, &primary_sb_modified)) != XR_OK) { do_warn(_("couldn't verify primary superblock - %s !!!\n"), err_string(rval)); - if (!find_secondary_sb(sb)) + if (!find_secondary_sb(sb, skipsize)) no_sb(); primary_sb_modified = 1; } diff --git a/repair/protos.h b/repair/protos.h index 9d5a2a6..d96373e 100644 --- a/repair/protos.h +++ b/repair/protos.h @@ -31,7 +31,7 @@ int get_sb(xfs_sb_t *sbp, void write_primary_sb(xfs_sb_t *sbp, int size); -int find_secondary_sb(xfs_sb_t *sb); +int find_secondary_sb(xfs_sb_t *sb, __uint64_t skipsize); struct fs_geometry; void get_sb_geometry(struct fs_geometry *geo, diff --git a/repair/sb.c b/repair/sb.c index 4eef14a..4386479 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -87,8 +87,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest) /* * find a secondary superblock, copy it into the sb buffer */ -int -find_secondary_sb(xfs_sb_t *rsb) +static int __find_secondary_sb(xfs_sb_t *rsb, __uint64_t skipsize ) { xfs_off_t off; xfs_sb_t *sb; @@ -101,7 +100,6 @@ find_secondary_sb(xfs_sb_t *rsb) int bsize; do_warn(_("\nattempting to find secondary superblock...\n")); - sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE); if (!sb) { do_error( @@ -117,7 +115,7 @@ find_secondary_sb(xfs_sb_t *rsb) /* * skip first sector since we know that's bad */ - for (done = 0, off = XFS_AG_MIN_BYTES; !done ; off += bsize) { + for (done = 0, off = skipsize; !done ; off += bsize) { /* * read disk 1 MByte at a time. */ @@ -130,7 +128,6 @@ find_secondary_sb(xfs_sb_t *rsb) } do_warn("."); - /* * check the buffer 512 bytes at a time since * we don't know how big the sectors really are. @@ -164,11 +161,29 @@ find_secondary_sb(xfs_sb_t *rsb) } } } - free(sb); return(retval); } +int +find_secondary_sb(xfs_sb_t *rsb, __uint64_t skipsize) +{ + int retval; + + /* + * Attempt to find secondary sb with a coarse approach, + * using a large skipsize (agsize in bytes). Failing that, + * fallback to the fine-grained approach using min agsize. + */ + retval = __find_secondary_sb(rsb, skipsize); + if (!retval) + /* + * fallback: use minimum agsize for skipsize + */ + retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES); + return(retval); +} + /* * Calculate what the inode alignment field ought to be based on internal * superblock info and determine if it is valid. -- 2.5.0 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs