From: Steven Whitehouse <swhiteho@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [PATCH v2] gfs2_edit: Add compression to savemeta and restoremeta
Date: Wed, 04 May 2011 18:56:42 +0100 [thread overview]
Message-ID: <1304531802.15937.0.camel@menhir> (raw)
In-Reply-To: <1304531482-14029-1-git-send-email-anprice@redhat.com>
Hi,
Looks good to me,
Steve.
On Wed, 2011-05-04 at 18:51 +0100, Andrew Price wrote:
> This patch adds the ability to output gzip-compressed data with savemeta and
> makes it the default behaviour. It also adds a -z <0-9> option to allow the
> level of compression to be controlled, 0 meaning no compression and 9 being the
> default. restoremeta can now restore from a gzip-compressed or raw metadata
> file without any extra options.
>
> The file opening, closing and writing code from savemeta has been moved into
> savemeta{open,close,write} functions to abstract away compressed and
> non-compressed file output.
>
> Adds a dependency on zlib.
>
> Signed-off-by: Andrew Price <anprice@redhat.com>
> ---
>
> This revision of the patch replaces the -nocompress option with the -z <0-9>
> option and removes the unnecessary strdup() mentioned in the previous email.
>
> configure.ac | 1 +
> gfs2/edit/Makefile.am | 4 +-
> gfs2/edit/hexedit.c | 49 +++++++++--
> gfs2/edit/hexedit.h | 2 +-
> gfs2/edit/savemeta.c | 218 ++++++++++++++++++++++++++++++++++++-------------
> gfs2/man/gfs2_edit.8 | 42 +++++-----
> 6 files changed, 225 insertions(+), 91 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 10bcc95..3fc02d0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -119,6 +119,7 @@ PKG_CHECK_MODULES([cfg],[libcfg])
> PKG_CHECK_MODULES([fenced],[libfenced])
> PKG_CHECK_MODULES([dlmcontrol],[libdlmcontrol])
> PKG_CHECK_MODULES([quorum],[libquorum])
> +PKG_CHECK_MODULES([zlib],[zlib])
>
> # old versions of ncurses don't ship pkg-config files
> PKG_CHECK_MODULES([ncurses],[ncurses],,
> diff --git a/gfs2/edit/Makefile.am b/gfs2/edit/Makefile.am
> index 9701c91..c4814dc 100644
> --- a/gfs2/edit/Makefile.am
> +++ b/gfs2/edit/Makefile.am
> @@ -10,8 +10,8 @@ gfs2_edit_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM \
> -I$(top_srcdir)/gfs2/include \
> -I$(top_srcdir)/gfs2/libgfs2
>
> -gfs2_edit_CFLAGS = $(ncurses_CFLAGS)
> +gfs2_edit_CFLAGS = $(ncurses_CFLAGS) $(zlib_CFLAGS)
>
> -gfs2_edit_LDFLAGS = $(ncurses_LIBS)
> +gfs2_edit_LDFLAGS = $(ncurses_LIBS) $(zlib_LIBS)
>
> gfs2_edit_LDADD = $(top_builddir)/gfs2/libgfs2/libgfs2.la
> diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
> index d8f8841..b15ed28 100644
> --- a/gfs2/edit/hexedit.c
> +++ b/gfs2/edit/hexedit.c
> @@ -41,6 +41,7 @@ struct gfs2_log_header *llh;
> struct gfs2_log_descriptor *lld;
> int pgnum;
> int details = 0;
> +long int gziplevel = 9;
>
> int display(int identify_only);
>
> @@ -3294,7 +3295,7 @@ static void dump_journal(const char *journal)
> /* ------------------------------------------------------------------------ */
> static void usage(void)
> {
> - fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-p structures|blocks][blocktype][blockalloc [val]][blockbits][blockrg][find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|13|qc][field <f>[val]] /dev/device\n\n");
> + fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-z <0-9>] [-p structures|blocks][blocktype][blockalloc [val]][blockbits][blockrg][find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|13|qc][field <f>[val]] /dev/device\n\n");
> fprintf(stderr,"If only the device is specified, it enters into hexedit mode.\n");
> fprintf(stderr,"identify - prints out only the block type, not the details.\n");
> fprintf(stderr,"printsavedmeta - prints out the saved metadata blocks from a savemeta file.\n");
> @@ -3335,6 +3336,8 @@ static void usage(void)
> fprintf(stderr,"-p <b> find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|"
> "13|qc - find block of given type after block <b>\n");
> fprintf(stderr," <b> specifies the starting block for search\n");
> + fprintf(stderr,"-z 1 use gzip compression level 1 for savemeta (default 9)\n");
> + fprintf(stderr,"-z 0 do not use compression\n");
> fprintf(stderr,"-s specifies a starting block such as root, rindex, quota, inum.\n");
> fprintf(stderr,"-x print in hexmode.\n");
> fprintf(stderr,"-h prints this help.\n\n");
> @@ -3361,10 +3364,33 @@ static void usage(void)
> fprintf(stderr," gfs2_edit -p quota find di /dev/x/y\n");
> fprintf(stderr," To set the Resource Group flags for rg #7 to 3.\n");
> fprintf(stderr," gfs2_edit rgflags 7 3 /dev/sdc2\n");
> - fprintf(stderr," To save off all metadata for /dev/vg/lv:\n");
> - fprintf(stderr," gfs2_edit savemeta /dev/vg/lv /tmp/metasave\n");
> + fprintf(stderr," To save off all metadata for /dev/vg/lv without compression:\n");
> + fprintf(stderr," gfs2_edit savemeta -z 0 /dev/vg/lv /tmp/metasave\n");
> }/* usage */
>
> +/**
> + * getgziplevel - Process the -z parameter to savemeta operations
> + * argv - argv
> + * i - a pointer to the argv index at which to begin processing
> + * The index pointed to by i will be incremented past the -z option if found
> + */
> +static void getgziplevel(char *argv[], int *i)
> +{
> + char *endptr;
> + (*i)++;
> + if (!strcasecmp(argv[*i], "-z")) {
> + (*i)++;
> + errno = 0;
> + gziplevel = strtol(argv[*i], &endptr, 10);
> + if (errno || endptr == argv[*i] || gziplevel < 0 || gziplevel > 9) {
> + fprintf(stderr, "Compression level out of range: %s\n", argv[*i]);
> + exit(-1);
> + }
> + } else {
> + (*i)--;
> + }
> +}
> +
> /* ------------------------------------------------------------------------ */
> /* parameterpass1 - pre-processing for command-line parameters */
> /* ------------------------------------------------------------------------ */
> @@ -3558,13 +3584,16 @@ static void process_parameters(int argc, char *argv[], int pass)
> exit(EXIT_SUCCESS);
> }
> }
> - else if (!strcasecmp(argv[i], "savemeta"))
> - savemeta(argv[i+2], 0);
> - else if (!strcasecmp(argv[i], "savemetaslow"))
> - savemeta(argv[i+2], 1);
> - else if (!strcasecmp(argv[i], "savergs"))
> - savemeta(argv[i+2], 2);
> - else if (isdigit(argv[i][0])) { /* decimal addr */
> + else if (!strcasecmp(argv[i], "savemeta")) {
> + getgziplevel(argv, &i);
> + savemeta(argv[i+2], 0, gziplevel);
> + } else if (!strcasecmp(argv[i], "savemetaslow")) {
> + getgziplevel(argv, &i);
> + savemeta(argv[i+2], 1, gziplevel);
> + } else if (!strcasecmp(argv[i], "savergs")) {
> + getgziplevel(argv, &i);
> + savemeta(argv[i+2], 2, gziplevel);
> + } else if (isdigit(argv[i][0])) { /* decimal addr */
> sscanf(argv[i], "%"SCNd64, &temp_blk);
> push_block(temp_blk);
> } else {
> diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
> index a7a3109..cc87925 100644
> --- a/gfs2/edit/hexedit.h
> +++ b/gfs2/edit/hexedit.h
> @@ -341,7 +341,7 @@ extern void gfs_log_header_in(struct gfs_log_header *head,
> struct gfs2_buffer_head *bh);
> extern void gfs_log_header_print(struct gfs_log_header *lh);
> extern void gfs_dinode_in(struct gfs_dinode *di, struct gfs2_buffer_head *bh);
> -extern void savemeta(char *out_fn, int saveoption);
> +extern void savemeta(char *out_fn, int saveoption, int gziplevel);
> extern void restoremeta(const char *in_fn, const char *out_device,
> uint64_t printblocksonly);
> extern int display(int identify_only);
> diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
> index 4d9f591..1797568 100644
> --- a/gfs2/edit/savemeta.c
> +++ b/gfs2/edit/savemeta.c
> @@ -18,6 +18,7 @@
> #include <limits.h>
> #include <sys/time.h>
> #include <linux/gfs2_ondisk.h>
> +#include <zlib.h>
>
> #include "osi_list.h"
> #include "gfs2hex.h"
> @@ -34,6 +35,13 @@ struct saved_metablock {
> char buf[BUFSIZE];
> };
>
> +struct metafd {
> + int fd;
> + gzFile gzfd;
> + const char *filename;
> + int gziplevel;
> +};
> +
> struct saved_metablock *savedata;
> uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
> uint64_t journal_blocks[MAX_JOURNALS_SAVED];
> @@ -193,7 +201,98 @@ static void warm_fuzzy_stuff(uint64_t wfsblock, int force)
> }
> }
>
> -static int save_block(int fd, int out_fd, uint64_t blk)
> +/**
> + * Open a file and prepare it for writing by savemeta()
> + * out_fn: the path to the file, which will be truncated if it exists
> + * gziplevel: 0 - do not compress the file,
> + * 1-9 - use gzip compression level 1-9
> + * Returns a struct metafd containing the opened file descriptor
> + */
> +static struct metafd savemetaopen(char *out_fn, int gziplevel)
> +{
> + struct metafd mfd;
> + char gzmode[5] = "rwb9";
> + char dft_fn[] = DFT_SAVE_FILE;
> +
> + if (!out_fn) {
> + out_fn = dft_fn;
> + mfd.fd = mkstemp(out_fn);
> + } else {
> + mfd.fd = open(out_fn, O_RDWR | O_CREAT, 0644);
> + }
> + mfd.filename = out_fn;
> +
> + if (mfd.fd < 0) {
> + fprintf(stderr, "Can't open %s: %s\n", out_fn, strerror(errno));
> + exit(1);
> + }
> +
> + if (ftruncate(mfd.fd, 0)) {
> + fprintf(stderr, "Can't truncate %s: %s\n", out_fn, strerror(errno));
> + exit(1);
> + }
> +
> + mfd.gziplevel = gziplevel;
> + if (gziplevel > 0) {
> + gzmode[3] = '0' + gziplevel;
> + mfd.gzfd = gzdopen(mfd.fd, gzmode);
> + if (!mfd.gzfd) {
> + fprintf(stderr, "gzdopen error: %s\n", strerror(errno));
> + exit(1);
> + }
> + }
> +
> + return mfd;
> +}
> +
> +/**
> + * Write nbyte bytes from buf to a file opened with savemetaopen()
> + * mfd: the file descriptor opened using savemetaopen()
> + * buf: the buffer to write data from
> + * nbyte: the number of bytes to write
> + * Returns the number of bytes written from buf or -1 on error
> + */
> +static ssize_t savemetawrite(struct metafd *mfd, const void *buf, size_t nbyte)
> +{
> + ssize_t ret;
> + int gzerr;
> + const char *gzerrmsg;
> +
> + if (mfd->gziplevel == 0) {
> + return write(mfd->fd, buf, nbyte);
> + }
> +
> + ret = gzwrite(mfd->gzfd, buf, nbyte);
> + if (ret != nbyte) {
> + gzerrmsg = gzerror(mfd->gzfd, &gzerr);
> + if (gzerr != Z_ERRNO) {
> + fprintf(stderr, "Error: zlib: %s\n", gzerrmsg);
> + }
> + }
> + return ret;
> +}
> +
> +/**
> + * Closes a file descriptor previously opened using savemetaopen()
> + * mfd: the file descriptor previously opened using savemetaopen()
> + * Returns 0 on success or -1 on error
> + */
> +static int savemetaclose(struct metafd *mfd)
> +{
> + int gzret;
> + if (mfd->gziplevel > 0) {
> + gzret = gzclose(mfd->gzfd);
> + if (gzret == Z_STREAM_ERROR) {
> + fprintf(stderr, "gzclose: file is not valid\n");
> + return -1;
> + } else if (gzret == Z_ERRNO) {
> + return -1;
> + }
> + }
> + return close(mfd->fd);
> +}
> +
> +static int save_block(int fd, struct metafd *mfd, uint64_t blk)
> {
> int blktype, blklen, outsz;
> uint16_t trailing0;
> @@ -228,7 +327,7 @@ static int save_block(int fd, int out_fd, uint64_t blk)
> p--;
> }
> savedata->blk = cpu_to_be64(blk);
> - if (write(out_fd, &savedata->blk, sizeof(savedata->blk)) !=
> + if (savemetawrite(mfd, &savedata->blk, sizeof(savedata->blk)) !=
> sizeof(savedata->blk)) {
> fprintf(stderr, "write error: %s from %s:%d: "
> "block %lld (0x%llx)\n", strerror(errno),
> @@ -239,7 +338,7 @@ static int save_block(int fd, int out_fd, uint64_t blk)
> }
> outsz = blklen - trailing0;
> savedata->siglen = cpu_to_be16(outsz);
> - if (write(out_fd, &savedata->siglen, sizeof(savedata->siglen)) !=
> + if (savemetawrite(mfd, &savedata->siglen, sizeof(savedata->siglen)) !=
> sizeof(savedata->siglen)) {
> fprintf(stderr, "write error: %s from %s:%d: "
> "block %lld (0x%llx)\n", strerror(errno),
> @@ -248,7 +347,7 @@ static int save_block(int fd, int out_fd, uint64_t blk)
> (unsigned long long)savedata->blk);
> exit(-1);
> }
> - if (write(out_fd, savedata->buf, outsz) != outsz) {
> + if (savemetawrite(mfd, savedata->buf, outsz) != outsz) {
> fprintf(stderr, "write error: %s from %s:%d: "
> "block %lld (0x%llx)\n", strerror(errno),
> __FUNCTION__, __LINE__,
> @@ -265,7 +364,7 @@ static int save_block(int fd, int out_fd, uint64_t blk)
> /*
> * save_ea_block - save off an extended attribute block
> */
> -static void save_ea_block(int out_fd, struct gfs2_buffer_head *metabh)
> +static void save_ea_block(struct metafd *mfd, struct gfs2_buffer_head *metabh)
> {
> int i, e, ea_len = sbd.bsize;
> struct gfs2_ea_header ea;
> @@ -283,7 +382,7 @@ static void save_ea_block(int out_fd, struct gfs2_buffer_head *metabh)
> b = (uint64_t *)(metabh->b_data);
> b += charoff + i;
> blk = be64_to_cpu(*b);
> - save_block(sbd.device_fd, out_fd, blk);
> + save_block(sbd.device_fd, mfd, blk);
> }
> if (!ea.ea_rec_len)
> break;
> @@ -294,7 +393,7 @@ static void save_ea_block(int out_fd, struct gfs2_buffer_head *metabh)
> /*
> * save_indirect_blocks - save all indirect blocks for the given buffer
> */
> -static void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
> +static void save_indirect_blocks(struct metafd *mfd, osi_list_t *cur_list,
> struct gfs2_buffer_head *mybh, int height, int hgt)
> {
> uint64_t old_block = 0, indir_block;
> @@ -314,10 +413,10 @@ static void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
> if (indir_block == old_block)
> continue;
> old_block = indir_block;
> - blktype = save_block(sbd.device_fd, out_fd, indir_block);
> + blktype = save_block(sbd.device_fd, mfd, indir_block);
> if (blktype == GFS2_METATYPE_EA) {
> nbh = bread(&sbd, indir_block);
> - save_ea_block(out_fd, nbh);
> + save_ea_block(mfd, nbh);
> brelse(nbh);
> }
> if (height != hgt) { /* If not at max height */
> @@ -333,7 +432,7 @@ static void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
> /*
> * save_inode_data - save off important data associated with an inode
> *
> - * out_fd - destination file descriptor
> + * mfd - destination file descriptor
> * block - block number of the inode to save the data for
> *
> * For user files, we don't want anything except all the indirect block
> @@ -345,7 +444,7 @@ static void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
> * For file system journals, the "data" is a mixture of metadata and
> * journaled data. We want all the metadata and none of the user data.
> */
> -static void save_inode_data(int out_fd)
> +static void save_inode_data(struct metafd *mfd)
> {
> uint32_t height;
> struct gfs2_inode *inode;
> @@ -382,7 +481,7 @@ static void save_inode_data(int out_fd)
> for (tmp = prev_list->next; tmp != prev_list; tmp = tmp->next){
> mybh = osi_list_entry(tmp, struct gfs2_buffer_head,
> b_altlist);
> - save_indirect_blocks(out_fd, cur_list, mybh,
> + save_indirect_blocks(mfd, cur_list, mybh,
> height, i);
> } /* for blocks at that height */
> } /* for height */
> @@ -410,7 +509,7 @@ static void save_inode_data(int out_fd)
> old_leaf = leaf_no;
> mybh = bread(&sbd, leaf_no);
> if (gfs2_check_meta(mybh, GFS2_METATYPE_LF) == 0)
> - save_block(sbd.device_fd, out_fd, leaf_no);
> + save_block(sbd.device_fd, mfd, leaf_no);
> brelse(mybh);
> }
> }
> @@ -419,17 +518,17 @@ static void save_inode_data(int out_fd)
> struct gfs2_buffer_head *lbh;
>
> lbh = bread(&sbd, inode->i_di.di_eattr);
> - save_block(sbd.device_fd, out_fd, inode->i_di.di_eattr);
> + save_block(sbd.device_fd, mfd, inode->i_di.di_eattr);
> gfs2_meta_header_in(&mh, lbh);
> if (mh.mh_magic == GFS2_MAGIC &&
> mh.mh_type == GFS2_METATYPE_EA)
> - save_ea_block(out_fd, lbh);
> + save_ea_block(mfd, lbh);
> else if (mh.mh_magic == GFS2_MAGIC &&
> mh.mh_type == GFS2_METATYPE_IN)
> - save_indirect_blocks(out_fd, cur_list, lbh, 2, 2);
> + save_indirect_blocks(mfd, cur_list, lbh, 2, 2);
> else {
> if (mh.mh_magic == GFS2_MAGIC) /* if it's metadata */
> - save_block(sbd.device_fd, out_fd,
> + save_block(sbd.device_fd, mfd,
> inode->i_di.di_eattr);
> fprintf(stderr,
> "\nWarning: corrupt extended "
> @@ -529,32 +628,21 @@ static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
> return 0;
> }
>
> -void savemeta(char *out_fn, int saveoption)
> +void savemeta(char *out_fn, int saveoption, int gziplevel)
> {
> - int out_fd;
> int slow;
> osi_list_t *tmp;
> int rgcount;
> uint64_t jindex_block;
> struct gfs2_buffer_head *lbh;
> struct rgrp_list *last_rgd, *prev_rgd;
> + struct metafd mfd;
>
> slow = (saveoption == 1);
> sbd.md.journals = 1;
>
> - if (!out_fn) {
> - out_fn = strdup(DFT_SAVE_FILE);
> - if (!out_fn)
> - die("Can't allocate memory for the operation.\n");
> - out_fd = mkstemp(out_fn);
> - } else
> - out_fd = open(out_fn, O_RDWR | O_CREAT, 0644);
> -
> - if (out_fd < 0)
> - die("Can't open %s: %s\n", out_fn, strerror(errno));
> -
> - if (ftruncate(out_fd, 0))
> - die("Can't truncate %s: %s\n", out_fn, strerror(errno));
> + mfd = savemetaopen(out_fn, gziplevel);
> +
> savedata = malloc(sizeof(struct saved_metablock));
> if (!savedata)
> die("Can't allocate memory for the operation.\n");
> @@ -649,15 +737,15 @@ void savemeta(char *out_fn, int saveoption)
> get_journal_inode_blocks();
> if (!slow) {
> /* Save off the superblock */
> - save_block(sbd.device_fd, out_fd, 0x10 * (4096 / sbd.bsize));
> + save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
> /* If this is gfs1, save off the rindex because it's not
> part of the file system as it is in gfs2. */
> if (gfs1) {
> int j;
>
> block = sbd1->sb_rindex_di.no_addr;
> - save_block(sbd.device_fd, out_fd, block);
> - save_inode_data(out_fd);
> + save_block(sbd.device_fd, &mfd, block);
> + save_inode_data(&mfd);
> /* In GFS1, journals aren't part of the RG space */
> for (j = 0; j < journals_found; j++) {
> log_debug("Saving journal #%d\n", j + 1);
> @@ -665,7 +753,7 @@ void savemeta(char *out_fn, int saveoption)
> block < journal_blocks[j] +
> gfs1_journal_size;
> block++)
> - save_block(sbd.device_fd, out_fd, block);
> + save_block(sbd.device_fd, &mfd, block);
> }
> }
> /* Walk through the resource groups saving everything within */
> @@ -687,7 +775,7 @@ void savemeta(char *out_fn, int saveoption)
> for (block = rgd->ri.ri_addr;
> block < rgd->ri.ri_data0; block++) {
> warm_fuzzy_stuff(block, FALSE);
> - save_block(sbd.device_fd, out_fd, block);
> + save_block(sbd.device_fd, &mfd, block);
> }
> /* Save off the other metadata: inodes, etc. */
> if (saveoption != 2) {
> @@ -696,9 +784,9 @@ void savemeta(char *out_fn, int saveoption)
> while (!gfs2_next_rg_meta(rgd, &block, first)){
> warm_fuzzy_stuff(block, FALSE);
> blktype = save_block(sbd.device_fd,
> - out_fd, block);
> + &mfd, block);
> if (blktype == GFS2_METATYPE_DI)
> - save_inode_data(out_fd);
> + save_inode_data(&mfd);
> first = 0;
> }
> /* Save off the free/unlinked meta blocks too.
> @@ -707,7 +795,7 @@ void savemeta(char *out_fn, int saveoption)
> while (!next_rg_freemeta(&sbd, rgd, &block,
> first)) {
> blktype = save_block(sbd.device_fd,
> - out_fd, block);
> + &mfd, block);
> first = 0;
> }
> }
> @@ -716,7 +804,7 @@ void savemeta(char *out_fn, int saveoption)
> }
> if (slow) {
> for (block = 0; block < last_fs_block; block++) {
> - save_block(sbd.device_fd, out_fd, block);
> + save_block(sbd.device_fd, &mfd, block);
> }
> }
> /* Clean up */
> @@ -724,28 +812,33 @@ void savemeta(char *out_fn, int saveoption)
> /* so we tell the user that we've processed everything. */
> block = last_fs_block;
> warm_fuzzy_stuff(block, TRUE);
> - printf("\nMetadata saved to file %s.\n", out_fn);
> + printf("\nMetadata saved to file %s ", mfd.filename);
> + if (mfd.gziplevel) {
> + printf("(gzipped, level %d).\n", mfd.gziplevel);
> + } else {
> + printf("(uncompressed).\n");
> + }
> free(savedata);
> - close(out_fd);
> + savemetaclose(&mfd);
> close(sbd.device_fd);
> exit(0);
> }
>
> -static int restore_data(int fd, int in_fd, int printblocksonly,
> +static int restore_data(int fd, gzFile *gzin_fd, int printblocksonly,
> int find_highblk)
> {
> size_t rs;
> uint64_t buf64, writes = 0, highest_valid_block = 0;
> uint16_t buf16;
> - int first = 1, pos;
> + int first = 1, pos, gzerr;
> char rdbuf[256];
> char gfs_superblock_id[8] = {0x01, 0x16, 0x19, 0x70,
> 0x00, 0x00, 0x00, 0x01};
>
> if (!printblocksonly)
> lseek(fd, 0, SEEK_SET);
> - lseek(in_fd, 0, SEEK_SET);
> - rs = read(in_fd, rdbuf, sizeof(rdbuf));
> + gzseek(gzin_fd, 0, SEEK_SET);
> + rs = gzread(gzin_fd, rdbuf, sizeof(rdbuf));
> if (rs != sizeof(rdbuf)) {
> fprintf(stderr, "Error: File is too small.\n");
> return -1;
> @@ -759,7 +852,7 @@ static int restore_data(int fd, int in_fd, int printblocksonly,
> }
> if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
> pos = 0;
> - if (lseek(in_fd, pos, SEEK_SET) != pos) {
> + if (gzseek(gzin_fd, pos, SEEK_SET) != pos) {
> fprintf(stderr, "bad seek: %s from %s:%d: "
> "offset %lld (0x%llx)\n", strerror(errno),
> __FUNCTION__, __LINE__, (unsigned long long)pos,
> @@ -772,7 +865,7 @@ static int restore_data(int fd, int in_fd, int printblocksonly,
> struct gfs2_buffer_head dummy_bh;
>
> memset(savedata, 0, sizeof(struct saved_metablock));
> - rs = read(in_fd, &buf64, sizeof(uint64_t));
> + rs = gzread(gzin_fd, &buf64, sizeof(uint64_t));
> if (!rs)
> break;
> if (rs != sizeof(uint64_t)) {
> @@ -791,7 +884,15 @@ static int restore_data(int fd, int in_fd, int printblocksonly,
> (unsigned long long)savedata->blk);
> return -1;
> }
> - rs = read(in_fd, &buf16, sizeof(uint16_t));
> + if (gzread(gzin_fd, &buf16, sizeof(uint16_t)) !=
> + sizeof(uint16_t)) {
> + fprintf(stderr, "read error: %s from %s:%d: "
> + "block %lld (0x%llx)\n",
> + gzerror(gzin_fd, &gzerr), __FUNCTION__, __LINE__,
> + (unsigned long long)savedata->blk,
> + (unsigned long long)savedata->blk);
> + exit(-1);
> + }
> savedata->siglen = be16_to_cpu(buf16);
> if (savedata->siglen > sizeof(savedata->buf)) {
> fprintf(stderr, "\nBad record length: %d for block #%llu"
> @@ -801,11 +902,11 @@ static int restore_data(int fd, int in_fd, int printblocksonly,
> return -1;
> }
> if (savedata->siglen &&
> - read(in_fd, savedata->buf, savedata->siglen) !=
> + gzread(gzin_fd, savedata->buf, savedata->siglen) !=
> savedata->siglen) {
> fprintf(stderr, "read error: %s from %s:%d: "
> "block %lld (0x%llx)\n",
> - strerror(errno), __FUNCTION__, __LINE__,
> + gzerror(gzin_fd, &gzerr), __FUNCTION__, __LINE__,
> (unsigned long long)savedata->blk,
> (unsigned long long)savedata->blk);
> exit(-1);
> @@ -910,15 +1011,16 @@ static void complain(const char *complaint)
> void restoremeta(const char *in_fn, const char *out_device,
> uint64_t printblocksonly)
> {
> - int in_fd, error;
> + int error;
> + gzFile gzfd;
>
> termlines = 0;
> if (!in_fn)
> complain("No source file specified.");
> if (!printblocksonly && !out_device)
> complain("No destination file system specified.");
> - in_fd = open(in_fn, O_RDONLY);
> - if (in_fd < 0)
> + gzfd = gzopen(in_fn, "rb");
> + if (!gzfd)
> die("Can't open source file %s: %s\n",
> in_fn, strerror(errno));
>
> @@ -935,13 +1037,13 @@ void restoremeta(const char *in_fn, const char *out_device,
> die("Can't allocate memory for the restore operation.\n");
>
> blks_saved = 0;
> - restore_data(sbd.device_fd, in_fd, printblocksonly, 1);
> - error = restore_data(sbd.device_fd, in_fd, printblocksonly, 0);
> + restore_data(sbd.device_fd, gzfd, printblocksonly, 1);
> + error = restore_data(sbd.device_fd, gzfd, printblocksonly, 0);
> printf("File %s %s %s.\n", in_fn,
> (printblocksonly ? "print" : "restore"),
> (error ? "error" : "successful"));
> free(savedata);
> - close(in_fd);
> + gzclose(gzfd);
> if (!printblocksonly)
> close(sbd.device_fd);
>
> diff --git a/gfs2/man/gfs2_edit.8 b/gfs2/man/gfs2_edit.8
> index 2546c7b..a48a38c 100644
> --- a/gfs2/man/gfs2_edit.8
> +++ b/gfs2/man/gfs2_edit.8
> @@ -138,7 +138,9 @@ Print program version information only.
> .TP
> \fB-x\fP
> Print in hex mode.
> -
> +.TP
> +\fB-z <0-9>\fP
> +Compress metadata with gzip compression level 1 to 9 (default 9). 0 means no compression at all.
> .TP
> \fBrg\fP \fI<rg>\fR \fI<device>\fR
> Print the contents of Resource Group \fI<rg>\fR on \fI<device>\fR.
> @@ -169,35 +171,35 @@ that may be contained in the files. This option works quickly by
> using the system bitmap blocks in the resource groups to determine the
> location of all the metadata. If there is corruption
> in the bitmaps, resource groups or rindex file, this method may fail and
> -you may need to use the savemetaslow option.
> -The destination file is not compressed. You may want to compress it
> -with a program such as bzip2 before sending it for analysis.
> +you may need to use the savemetaslow option. The destination file is
> +compressed using gzip unless -z 0 is specified.
> .TP
> \fBsavemetaslow\fP \fI<device>\fR \fI<filename>\fR
> Save off GFS2 metadata, as with the savemeta option, examining every
> block in the file system for metadata. This option is less prone to failure
> due to file system corruption than the savemeta option, but it is
> -extremely slow.
> +extremely slow. The destination file is compressed using gzip unless
> +-z 0 is specified.
> .TP
> \fBsavergs\fP \fI<device>\fR \fI<filename>\fR
> Save off only the GFS2 resource group metadata for the file system on the
> -specified device to a file given by <filename>.
> +specified device to a file given by <filename>. The destination file is
> +compressed using gzip unless -z 0 is specified.
> .TP
> \fBrestoremeta\fP \fI<filename>\fR \fI<dest device>\fR
> -Take a file created with the savemeta option and restores its
> -contents on top of the specified destination device. \fBWARNING\fP:
> -When you use this option, the file system and all data on the
> -destination device is destroyed. Since only metadata (but no data)
> -is restored, every file in the resulting file system is likely to be
> -corrupt. The ONLY purpose of this option is to examine and debug file
> -system problems by restoring and examining the state of the saved metadata.
> -If the destination file system is the same size or larger than the source
> -file system where the metadata was saved, the resulting file system
> -will be the same size as the source. If the destination device is
> -smaller than the source file system, gfs2_edit will restore as much as
> -it can, then quit, leaving you with a file system that probably will not
> -mount, but from which you might still be able to figure out what is
> -wrong with the source file system.
> +Take a compressed or uncompressed file created with the savemeta option and
> +restores its contents on top of the specified destination device.
> +\fBWARNING\fP: When you use this option, the file system and all data on the
> +destination device is destroyed. Since only metadata (but no data) is
> +restored, every file in the resulting file system is likely to be corrupt. The
> +ONLY purpose of this option is to examine and debug file system problems by
> +restoring and examining the state of the saved metadata. If the destination
> +file system is the same size or larger than the source file system where the
> +metadata was saved, the resulting file system will be the same size as the
> +source. If the destination device is smaller than the source file system,
> +gfs2_edit will restore as much as it can, then quit, leaving you with a file
> +system that probably will not mount, but from which you might still be able to
> +figure out what is wrong with the source file system.
>
> .SH INTERACTIVE MODE
> If you specify a device on the gfs2_edit command line and you specify
prev parent reply other threads:[~2011-05-04 17:56 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-14 17:08 [Cluster-devel] [PATCH] gfs2_edit: Add compression to savemeta and restoremeta Andrew Price
2011-04-28 14:55 ` Steven Whitehouse
2011-04-28 16:40 ` Andrew Price
2011-05-04 17:51 ` [Cluster-devel] [PATCH v2] " Andrew Price
2011-05-04 17:56 ` Steven Whitehouse [this message]
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=1304531802.15937.0.camel@menhir \
--to=swhiteho@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).