From: Eric Sandeen <sandeen@sandeen.net>
To: xfs@oss.sgi.com
Subject: Re: [PATCH 2/2 v2] xfs_repair: new secondary superblock search method] xfs_repair: new secondary superblock search method
Date: Tue, 9 Feb 2016 22:49:20 -0600 [thread overview]
Message-ID: <56BAC150.7070808@sandeen.net> (raw)
In-Reply-To: <1455068099-26992-1-git-send-email-billodo@redhat.com>
On 2/9/16 7:34 PM, Bill O'Donnell wrote:
> 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@redhat.com>
> ---
> Makefile | 2 +-
> include/libxcmd.h | 4 +++-
> libxcmd/topology.c | 35 ++++++++++++++++++++++++++++----
> repair/Makefile | 4 ++--
> repair/sb.c | 58 ++++++++++++++++++++++++++++++++++++++++++++----------
> 5 files changed, 85 insertions(+), 18 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..b98d9b9 100644
> --- a/libxcmd/topology.c
> +++ b/libxcmd/topology.c
> @@ -192,7 +192,8 @@ out:
> return ret;
> }
>
> -static void blkid_get_topology(
> +static void
> +blkid_get_topology(
> const char *device,
> int *sunit,
> int *swidth,
> @@ -284,7 +285,8 @@ check_overwrite(
> return 1;
> }
>
> -static void blkid_get_topology(
> +static void
> +blkid_get_topology(
> const char *device,
> int *sunit,
> int *swidth,
> @@ -302,8 +304,8 @@ static void blkid_get_topology(
>
> #endif /* ENABLE_BLKID */
>
> -
> -void get_topology(
> +void
> +get_topology(
> libxfs_init_t *xi,
> struct fs_topology *ft,
> int force_overwrite)
> @@ -346,3 +348,28 @@ void 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;
When in Rome: :)
int
guess_default_geometry(
__uint64_t *agsize,
__uint64_t *agcount,
libxfs_init_t x)
{
...
(sorry, forgot to mention that last time, but other functions in the
file are laid out this way; it is easier to read)
> + __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..8bc246e 100644
> --- a/repair/sb.c
> +++ b/repair/sb.c
> @@ -22,6 +22,7 @@
> #include "globals.h"
> #include "protos.h"
> #include "err_protos.h"
> +#include "libxcmd.h"
Nitpick, we usually include that right after libxfs.h.
> #define BSIZE (1024 * 1024)
>
> @@ -85,10 +86,11 @@ 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.
> + * skipsize units is bytes, it contains either the agsize in bytes
> + * (if known), or the minimum agsize in bytes if agsize unknown.
> */
Ok, so this is a little confused. There are actually 3 relevant
parameters here:
1) The place to start reading
2) The number of bytes to read at that point
3) How far to seek forward for the next read
In the old world, it's:
1) XFS_MIN_AG_BYTES
2) BSIZE (1MB)
3) BSIZE (i.e. it does sequential reads)
In the new world, it's:
1) the guessed AG size (skipsize?)
2) BSIZE (more than we need, but not expensive, so leave it)
3) the guessed AG size (skipsize)
You really have 2 different pieces of info: Where to do the first read,
and how far forward to skip for the next read. I don't think you
can convey that with a single argument, "skipsize."
> -int
> -find_secondary_sb(xfs_sb_t *rsb)
> +static int __find_secondary_sb(xfs_sb_t *rsb, __uint64_t skipsize)
better to format as:
static int
__find_secondary_sb(
xfs_sb_t *rsb,
__uint64_t skipsize)
{
but ...
> {
> xfs_off_t off;
> xfs_sb_t *sb;
> @@ -99,9 +101,9 @@ find_secondary_sb(xfs_sb_t *rsb)
> int dirty;
> int retval;
> int bsize;
> + int readsize;
>
> do_warn(_("\nattempting to find secondary superblock...\n"));
> -
> sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE);
> if (!sb) {
> do_error(
> @@ -113,13 +115,16 @@ find_secondary_sb(xfs_sb_t *rsb)
> retval = 0;
> dirty = 0;
> bsize = 0;
> + readsize = 0;
>
> /*
> * 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 += readsize) {
> /*
> - * read disk 1 MByte at a time.
we are actually still doing that, read(x.dfd, sb, BSIZE), so I'd
leave the comment...
> + * read disk using readsize interval
> + * (either the bytecount of actual agsize or bsize if
> + * agsize undetermined.)
> */
> if (lseek64(x.dfd, off, SEEK_SET) != off) {
> done = 1;
> @@ -128,9 +133,13 @@ find_secondary_sb(xfs_sb_t *rsb)
> if (!done && (bsize = read(x.dfd, sb, BSIZE)) <= 0) {
> done = 1;
> }
> -
> + if (skipsize == XFS_AG_MIN_BYTES) {
> + readsize = bsize;
> + }
> + else {
better as:
} else {
> + readsize = skipsize;
> + }
I wouldn't call this "readsize" - we are only ever reading BSIZE at a time.
This is how much we advance each loop, so skipsize is a bit better.
But the _functional_ problem here is that it is possible and permissible
to have a filesystem with an AG size of XFS_AG_MIN_BYTES (16MB).
So if you guessed a default geometry with an agsize of XFS_AG_MIN_BYTES,
you've gone back to the fine-grained scanning. The fs probably isn't
very big as a result, so it's not the end of the world, but ...
see below.
> do_warn(".");
> -
> /*
> * check the buffer 512 bytes at a time since
> * we don't know how big the sectors really are.
> @@ -164,9 +173,38 @@ 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 skipsize;
> + __uint64_t agcount;
> + __uint64_t agsize;
> + int blocklog;
> +
> + /*
> + * 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.
> + */
> + blocklog = guess_default_geometry(&agsize, &agcount, x);
> +
> + /*
> + * use found ag geometry to quickly find secondary sb
> + */
> + skipsize = agsize << blocklog;
> + 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;
> }
I'd make __find_secondary_sb() take (sb, start, skip) i.e. send in
this:
> + retval = __find_secondary_sb(rsb, agsize, agsize);
> + if (!retval) {
> + /*
> + * fallback: use minimum agsize for skipsize
> + */
> + retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES, BSIZE);
> + }
and the function is something like:
static int
__find_secondary_sb(
xfs_sb_t *rsb,
xfs_off_t start,
xfs_off_t skip)
{
...
for (done = 0, off = start; !done ; off += skip) {
...
if (lseek64(x.dfd, off, SEEK_SET) != off)
done = 1;
if (!done && (read(x.dfd, sb, BSIZE)) <= 0)
done = 1;
because you really can't deduce both the starting point and the skip-ahead
size from just one parameter.
-Eric
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2016-02-10 4:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-10 1:34 [[PATCH 2/2 v2] xfs_repair: new secondary superblock search method] xfs_repair: new secondary superblock search method Bill O'Donnell
2016-02-10 4:49 ` Eric Sandeen [this message]
2016-02-10 15:43 ` [PATCH " Bill O'Donnell
2016-02-10 15:51 ` Eric Sandeen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56BAC150.7070808@sandeen.net \
--to=sandeen@sandeen.net \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.