From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Price Date: Thu, 23 Jan 2020 15:55:51 +0000 Subject: [Cluster-devel] [PATCH 12/13] restoremeta: Add bzip2 support In-Reply-To: <20200123155552.1080247-1-anprice@redhat.com> References: <20200123155552.1080247-1-anprice@redhat.com> Message-ID: <20200123155552.1080247-13-anprice@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Implement the required functions for adding bzip2 support and add functions for reading the initial chunk so that we can try each compression method. gzip has to be tried last as zlib's read function doesn't report if the file is not in gzip format, it just returns the data as-is. Adds a dependency on libbzip2. Signed-off-by: Andrew Price --- configure.ac | 1 + gfs2/edit/Makefile.am | 2 + gfs2/edit/savemeta.c | 136 +++++++++++++++++++++++++++++++----------- 3 files changed, 105 insertions(+), 34 deletions(-) diff --git a/configure.ac b/configure.ac index 0c1b0192..de9d5264 100644 --- a/configure.ac +++ b/configure.ac @@ -104,6 +104,7 @@ PKG_CHECK_MODULES([check], [check >= 0.9.8], AM_CONDITIONAL([HAVE_CHECK], [test "x$have_check" = "xyes"]) PKG_CHECK_MODULES([zlib],[zlib]) +PKG_CHECK_MODULES([bzip2],[bzip2]) PKG_CHECK_MODULES([blkid],[blkid]) PKG_CHECK_MODULES([uuid],[uuid], [have_uuid=yes], diff --git a/gfs2/edit/Makefile.am b/gfs2/edit/Makefile.am index 4a89502c..53a7dea6 100644 --- a/gfs2/edit/Makefile.am +++ b/gfs2/edit/Makefile.am @@ -23,11 +23,13 @@ gfs2_edit_CPPFLAGS = \ gfs2_edit_CFLAGS = \ $(ncurses_CFLAGS) \ $(zlib_CFLAGS) \ + $(bzip2_CFLAGS) \ $(uuid_CFLAGS) gfs2_edit_LDADD = \ $(top_builddir)/gfs2/libgfs2/libgfs2.la \ $(ncurses_LIBS) \ $(zlib_LIBS) \ + $(bzip2_LIBS) \ $(uuid_LIBS) diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 7e47b810..e20b405d 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,7 @@ struct saved_metablock { struct metafd { int fd; gzFile gzfd; + BZFILE *bzfd; const char *filename; int gziplevel; int eof; @@ -60,6 +62,31 @@ struct metafd { const char* (*strerr)(struct metafd *mfd); }; +char *restore_buf; +ssize_t restore_left; +off_t restore_off; +#define RESTORE_BUF_SIZE (2 * 1024 * 1024) + +static char *restore_buf_next(struct metafd *mfd, size_t required_len) +{ + if (restore_left < required_len) { + char *tail = restore_buf + restore_off; + int ret; + + memmove(restore_buf, tail, restore_left); + ret = mfd->read(mfd, restore_buf + restore_left, RESTORE_BUF_SIZE - restore_left); + if (ret < (int)required_len - restore_left) + return NULL; + restore_left += ret; + restore_off = 0; + } + restore_left -= required_len; + restore_off += required_len; + return &restore_buf[restore_off - required_len]; +} + +/* gzip compression method */ + static const char *gz_strerr(struct metafd *mfd) { int err; @@ -83,6 +110,76 @@ static void gz_close(struct metafd *mfd) gzclose(mfd->gzfd); } +/* This should be tried last because gzip doesn't distinguish between + decompressing a gzip file and reading an uncompressed file */ +static int restore_try_gzip(struct metafd *mfd) +{ + mfd->read = gz_read; + mfd->close = gz_close; + mfd->strerr = gz_strerr; + lseek(mfd->fd, 0, SEEK_SET); + mfd->gzfd = gzdopen(mfd->fd, "rb"); + if (!mfd->gzfd) + return 1; + restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE); + if (restore_left < 512) + return -1; + return 0; +} + +/* bzip2 compression method */ + +static const char *bz_strerr(struct metafd *mfd) +{ + int err; + const char *errstr = BZ2_bzerror(mfd->bzfd, &err); + + if (err == BZ_IO_ERROR) + return strerror(errno); + return errstr; +} + +static int bz_read(struct metafd *mfd, void *buf, unsigned len) +{ + int bzerr = BZ_OK; + int ret; + + ret = BZ2_bzRead(&bzerr, mfd->bzfd, buf, len); + if (bzerr == BZ_OK) + return ret; + if (bzerr == BZ_STREAM_END) { + mfd->eof = 1; + return ret; + } + return -1; +} + +static void bz_close(struct metafd *mfd) +{ + BZ2_bzclose(mfd->bzfd); +} + +static int restore_try_bzip(struct metafd *mfd) +{ + int bzerr; + FILE *f; + + f = fdopen(mfd->fd, "r"); + if (f == NULL) + return 1; + + mfd->read = bz_read; + mfd->close = bz_close; + mfd->strerr = bz_strerr; + mfd->bzfd = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0); + if (!mfd->bzfd) + return 1; + restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE); + if (restore_left < 512) + return -1; + return 0; +} + static uint64_t blks_saved; static uint64_t journal_blocks[MAX_JOURNALS_SAVED]; static uint64_t gfs1_journal_size = 0; /* in blocks */ @@ -345,11 +442,13 @@ static void warm_fuzzy_stuff(uint64_t wfsblock, int force) */ static struct metafd savemetaopen(char *out_fn, int gziplevel) { - struct metafd mfd = {-1, NULL, NULL, gziplevel}; + struct metafd mfd = {0}; char gzmode[3] = "w9"; char dft_fn[] = DFT_SAVE_FILE; mode_t mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); + mfd.gziplevel = gziplevel; + if (!out_fn) { out_fn = dft_fn; mfd.fd = mkstemp(out_fn); @@ -959,29 +1058,6 @@ void savemeta(char *out_fn, int saveoption, int gziplevel) exit(0); } -char *restore_buf; -ssize_t restore_left; -off_t restore_off; -#define RESTORE_BUF_SIZE (2 * 1024 * 1024) - -static char *restore_buf_next(struct metafd *mfd, size_t required_len) -{ - if (restore_left < required_len) { - char *tail = restore_buf + restore_off; - int ret; - - memmove(restore_buf, tail, restore_left); - ret = mfd->read(mfd, restore_buf + restore_left, RESTORE_BUF_SIZE - restore_left); - if (ret < required_len - restore_left) - return NULL; - restore_left += ret; - restore_off = 0; - } - restore_left -= required_len; - restore_off += required_len; - return &restore_buf[restore_off - required_len]; -} - static int restore_block(struct metafd *mfd, struct saved_metablock *svb, char **buf, uint16_t maxlen) { struct saved_metablock *svb_be; @@ -1140,16 +1216,8 @@ static int restore_init(const char *path, struct metafd *mfd, struct savemeta_he perror("Could not open metadata file"); return 1; } - mfd->read = gz_read; - mfd->close = gz_close; - mfd->strerr = gz_strerr; - mfd->gzfd = gzdopen(mfd->fd, "rb"); - if (!mfd->gzfd) { - perror("gzdopen"); - return 1; - } - restore_left = mfd->read(mfd, restore_buf, RESTORE_BUF_SIZE); - if (restore_left < 512) { + if (restore_try_bzip(mfd) != 0 && + restore_try_gzip(mfd) != 0) { fprintf(stderr, "Failed to read metadata file header and superblock\n"); return -1; } -- 2.24.1