[PATCH v4 2/2] xfs_repair: new secondary superblock search method
Bill O'Donnell
billodo at redhat.com
Fri Feb 12 13:03:31 CST 2016
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 at redhat.com>
---
Makefile | 2 +-
include/libxcmd.h | 6 +++++-
libxcmd/topology.c | 27 +++++++++++++++++++++++++++
repair/Makefile | 4 ++--
repair/sb.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
5 files changed, 76 insertions(+), 12 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 a912534..eb16cd5 100644
--- a/include/libxcmd.h
+++ b/include/libxcmd.h
@@ -51,6 +51,10 @@ 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 4cbe4b1..ec9695c 100644
--- a/libxcmd/topology.c
+++ b/libxcmd/topology.c
@@ -339,3 +339,30 @@ get_topology(
&lsectorsize, &psectorsize, force_overwrite);
}
}
+
+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;
+ dblocks = x.dsize >> (blocklog - BBSHIFT);
+ 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/sb.c b/repair/sb.c
index 4eef14a..8dcad5f 100644
--- a/repair/sb.c
+++ b/repair/sb.c
@@ -17,6 +17,7 @@
*/
#include "libxfs.h"
+#include "libxcmd.h"
#include "libxlog.h"
#include "agheader.h"
#include "globals.h"
@@ -85,10 +86,15 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest)
}
/*
- * find a secondary superblock, copy it into the sb buffer
+ * find a secondary superblock, copy it into the sb buffer.
+ * start is the point to begin reading BSIZE bytes.
+ * skip contains a byte-count of how far to advance for next read.
*/
-int
-find_secondary_sb(xfs_sb_t *rsb)
+static int
+__find_secondary_sb(
+ xfs_sb_t *rsb,
+ __uint64_t start,
+ __uint64_t skip)
{
xfs_off_t off;
xfs_sb_t *sb;
@@ -101,7 +107,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 +122,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 = start; !done ; off += skip) {
/*
* read disk 1 MByte at a time.
*/
@@ -128,9 +133,7 @@ find_secondary_sb(xfs_sb_t *rsb)
if (!done && (bsize = read(x.dfd, sb, BSIZE)) <= 0) {
done = 1;
}
-
do_warn(".");
-
/*
* check the buffer 512 bytes at a time since
* we don't know how big the sectors really are.
@@ -166,7 +169,37 @@ find_secondary_sb(xfs_sb_t *rsb)
}
free(sb);
- return(retval);
+ return retval;
+}
+
+int
+find_secondary_sb(xfs_sb_t *rsb)
+{
+ int retval;
+ __uint64_t agcount;
+ __uint64_t agsize;
+ __uint64_t skip;
+ int blocklog;
+
+ /*
+ * Attempt to find secondary sb with a coarse approach,
+ * using a large skip (agsize in bytes). Failing that,
+ * fallback to the fine-grained approach using min agsize.
+ */
+ blocklog = guess_default_geometry(&agsize, &agcount, x);
+
+ /*
+ * use found ag geometry to quickly find secondary sb
+ */
+ skip = agsize << blocklog;
+ retval = __find_secondary_sb(rsb, skip, skip);
+ if (!retval) {
+ /*
+ * fallback: use minimum agsize for skipsize
+ */
+ retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES, BSIZE);
+ }
+ return retval;
}
/*
--
2.5.0
More information about the xfs
mailing list