All of lore.kernel.org
 help / color / mirror / Atom feed
From: rpeterso@sourceware.org <rpeterso@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/gfs2/edit savemeta.c
Date: 26 Jun 2007 01:53:19 -0000	[thread overview]
Message-ID: <20070626015319.10677.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	rpeterso at sourceware.org	2007-06-26 01:53:19

Added files:
	gfs2/edit      : savemeta.c 

Log message:
	Resolves: bz 245635: Bring gfs2_edit up to date

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/savemeta.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1

/cvs/cluster/cluster/gfs2/edit/savemeta.c,v  -->  standard output
revision 1.1.2.1
--- cluster/gfs2/edit/savemeta.c
+++ -	2007-06-26 01:53:19.678210000 +0000
@@ -0,0 +1,711 @@
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
+**
+**  This copyrighted material is made available to anyone wishing to use,
+**  modify, copy, or redistribute it subject to the terms and conditions
+**  of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <curses.h>
+#include <term.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <linux_endian.h>
+#include <sys/time.h>
+#include <linux/gfs2_ondisk.h>
+
+#include "osi_list.h"
+#include "hexedit.h"
+#include "libgfs2.h"
+
+#define BUFSIZE (4096)
+#define DFT_SAVE_FILE "/tmp/gfsmeta"
+
+struct saved_metablock {
+	uint64_t blk;
+	uint16_t siglen; /* significant data length */
+	char buf[BUFSIZE];
+};
+
+struct saved_metablock *savedata;
+uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
+struct gfs2_block_list *blocklist = NULL;
+
+extern void read_superblock(void);
+uint64_t masterblock(const char *fn);
+
+static __inline__ int fs_is_jdata(struct gfs2_inode *ip)
+{
+        return ip->i_di.di_flags & GFS2_DIF_JDATA;
+}
+
+static struct metapath *find_metapath(struct gfs2_inode *ip, uint64_t block)
+{
+	struct gfs2_sbd *sdp = ip->i_sbd;
+	struct metapath *mp;
+	uint64_t b = block;
+	unsigned int i;
+
+	zalloc(mp, sizeof(struct metapath));
+
+	for (i = ip->i_di.di_height; i--;)
+		mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
+
+	return mp;
+}
+
+static __inline__ uint64_t *
+metapointer(struct gfs2_buffer_head *bh, unsigned int height,
+			struct metapath *mp)
+{
+	unsigned int head_size = (height > 0) ?
+		sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
+
+	return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height];
+}
+
+static void lookup_block(struct gfs2_inode *ip,
+	     struct gfs2_buffer_head *bh, unsigned int height, struct metapath *mp,
+	     int create, int *new, uint64_t *block)
+{
+	uint64_t *ptr = metapointer(bh, height, mp);
+
+	if (*ptr) {
+		*block = be64_to_cpu(*ptr);
+		return;
+	}
+
+	*block = 0;
+
+	if (!create)
+		return;
+
+	if (height == ip->i_di.di_height - 1&&
+	    !(S_ISDIR(ip->i_di.di_mode)))
+		*block = data_alloc(ip);
+	else
+		*block = meta_alloc(ip);
+
+	*ptr = cpu_to_be64(*block);
+	ip->i_di.di_blocks++;
+
+	*new = 1;
+}
+
+void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
+		    uint64_t *dblock, uint32_t *extlen, int prealloc)
+{
+	struct gfs2_sbd *sdp = ip->i_sbd;
+	struct gfs2_buffer_head *bh;
+	struct metapath *mp;
+	int create = *new;
+	unsigned int bsize;
+	unsigned int height;
+	unsigned int end_of_metadata;
+	unsigned int x;
+	enum update_flags f;
+
+	f = not_updated;
+	*new = 0;
+	*dblock = 0;
+	if (extlen)
+		*extlen = 0;
+
+	if (!ip->i_di.di_height) { /* stuffed */
+		if (!lblock) {
+			*dblock = ip->i_di.di_num.no_addr;
+			if (extlen)
+				*extlen = 1;
+		}
+		return;
+	}
+
+	bsize = (fs_is_jdata(ip)) ? sdp->sd_jbsize : sdp->bsize;
+
+	height = calc_tree_height(ip, (lblock + 1) * bsize);
+	if (ip->i_di.di_height < height) {
+		if (!create)
+			return;
+
+		build_height(ip, height);
+	}
+
+	mp = find_metapath(ip, lblock);
+	end_of_metadata = ip->i_di.di_height - 1;
+
+	bh = bhold(ip->i_bh);
+
+	for (x = 0; x < end_of_metadata; x++) {
+		lookup_block(ip, bh, x, mp, create, new, dblock);
+		brelse(bh, not_updated);
+		if (!*dblock)
+			goto out;
+
+		if (*new) {
+			struct gfs2_meta_header mh;
+
+			bh = bget(sdp, *dblock);
+			mh.mh_magic = GFS2_MAGIC;
+			mh.mh_type = GFS2_METATYPE_IN;
+			mh.mh_format = GFS2_FORMAT_IN;
+			gfs2_meta_header_out(&mh, bh->b_data);
+			f = updated;
+		} else
+			bh = bread(sdp, *dblock);
+	}
+
+	if (!prealloc)
+		lookup_block(ip, bh, end_of_metadata, mp, create, new, dblock);
+
+	if (extlen && *dblock) {
+		*extlen = 1;
+
+		if (!*new) {
+			uint64_t tmp_dblock;
+			int tmp_new;
+			unsigned int nptrs;
+
+			nptrs = (end_of_metadata) ? sdp->sd_inptrs : sdp->sd_diptrs;
+
+			while (++mp->mp_list[end_of_metadata] < nptrs) {
+				lookup_block(ip, bh, end_of_metadata, mp, FALSE, &tmp_new,
+							 &tmp_dblock);
+
+				if (*dblock + *extlen != tmp_dblock)
+					break;
+
+				(*extlen)++;
+			}
+		}
+	}
+
+	brelse(bh, f);
+
+ out:
+	free(mp);
+}
+
+int gfs1_readi(struct gfs2_inode *ip, void *buf,
+	       uint64_t offset, unsigned int size)
+{
+	struct gfs2_sbd *sdp = ip->i_sbd;
+	struct gfs2_buffer_head *bh;
+	uint64_t lblock, dblock;
+	uint32_t extlen = 0;
+	unsigned int amount;
+	int not_new = 0;
+	int journaled = fs_is_jdata(ip);
+	int copied = 0;
+
+	if (offset >= ip->i_di.di_size)
+		return 0;
+
+	if ((offset + size) > ip->i_di.di_size)
+		size = ip->i_di.di_size - offset;
+
+	if (!size)
+		return 0;
+
+	if (journaled) {
+		lblock = offset / sdp->sd_jbsize;
+		offset %= sdp->sd_jbsize;
+	} else {
+		lblock = offset >> sdp->sd_sb.sb_bsize_shift;
+		offset &= sdp->sd_sb.sb_bsize - 1;
+	}
+
+	if (!ip->i_di.di_height) /* stuffed */
+		offset += sizeof(struct gfs2_dinode);
+	else if (journaled)
+		offset += sizeof(struct gfs2_meta_header);
+
+	while (copied < size) {
+		amount = size - copied;
+		if (amount > sdp->bsize - offset)
+			amount = sdp->bsize - offset;
+
+		if (!extlen)
+			gfs1_block_map(ip, lblock, &not_new, &dblock,
+				       &extlen, FALSE);
+
+		if (dblock) {
+			bh = bread(sdp, dblock);
+			dblock++;
+			extlen--;
+		} else
+			bh = NULL;
+
+
+		if (bh) {
+			memcpy(buf+copied, bh->b_data + offset, amount);
+			brelse(bh, not_updated);
+		} else
+			memset(buf+copied, 0, amount);
+		copied += amount;
+		lblock++;
+
+		offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
+	}
+
+	return copied;
+}
+
+/**
+ * gfs1_rindex_read - read in the rg index file
+ *                  Stolen from libgfs2/super.c, but modified to handle gfs1.
+ * @sdp: the incore superblock pointer
+ * fd: optional file handle for rindex file (if meta_fs file system is mounted)
+ *     (if fd is <= zero, it will read from raw device)
+ * @count1: return count of the rgs.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
+{
+	unsigned int rg;
+	int error;
+	struct gfs2_rindex buf;
+	struct rgrp_list *rgd, *prev_rgd;
+	uint64_t prev_length;
+
+	*count1 = 0;
+	prev_rgd = NULL;
+	for (rg = 0; ; rg++) {
+		if (fd > 0)
+			error = read(fd, &buf, sizeof(struct gfs2_rindex));
+		else
+			error = gfs1_readi(sdp->md.riinode, (char *)&buf,
+					   (rg * sizeof(struct gfs2_rindex)),
+					   sizeof(struct gfs2_rindex));
+		if (!error)
+			break;
+		if (error != sizeof(struct gfs2_rindex))
+			return -1;
+
+		rgd = (struct rgrp_list *)malloc(sizeof(struct rgrp_list));
+		memset(rgd, 0, sizeof(struct rgrp_list));
+		osi_list_add_prev(&rgd->list, &sdp->rglist);
+
+		gfs2_rindex_in(&rgd->ri, (char *)&buf);
+
+		rgd->start = rgd->ri.ri_addr;
+		if (prev_rgd) {
+			prev_length = rgd->start - prev_rgd->start;
+			prev_rgd->length = prev_length;
+		}
+
+		if(gfs2_compute_bitstructs(sdp, rgd))
+			return -1;
+
+		(*count1)++;
+		prev_rgd = rgd;
+	}
+	if (prev_rgd)
+		prev_rgd->length = prev_length;
+	return 0;
+}
+
+/**
+ * gfs1_ri_update - attach rgrps to the super block
+ *                  Stolen from libgfs2/super.c, but modified to handle gfs1.
+ * @sdp:
+ *
+ * Given the rgrp index inode, link in all rgrps into the super block
+ * and be sure that they can be read.
+ *
+ * Returns: 0 on success, -1 on failure.
+ */
+int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount)
+{
+	struct rgrp_list *rgd;
+	osi_list_t *tmp;
+	int count1 = 0, count2 = 0;
+	uint64_t errblock = 0;
+
+	if (gfs1_rindex_read(sdp, fd, &count1))
+	    goto fail;
+	for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
+		enum update_flags f;
+
+		f = not_updated;
+		rgd = osi_list_entry(tmp, struct rgrp_list, list);
+		errblock = gfs2_rgrp_read(sdp, rgd);
+		if (errblock)
+			return errblock;
+		else
+			gfs2_rgrp_relse(rgd, f);
+		count2++;
+	}
+
+	*rgcount = count1;
+	if (count1 != count2)
+		goto fail;
+
+	return 0;
+
+ fail:
+	gfs2_rgrp_free(&sdp->rglist, not_updated);
+	return -1;
+}
+
+
+/*
+ * get_gfs_struct_info - get block type and structure length
+ *
+ * @block_type - pointer to integer to hold the block type
+ * @struct_length - pointer to integet to hold the structure length
+ *
+ * returns: 0 if successful
+ *          -1 if this isn't gfs metadata.
+ */
+int get_gfs_struct_info(char *buf, int *block_type, int *struct_len)
+{
+	struct gfs2_meta_header mh;
+
+	*block_type = 0;
+	*struct_len = 0;
+
+	gfs2_meta_header_in(&mh, buf);
+	if (mh.mh_magic != GFS2_MAGIC)
+		return -1;
+
+	*block_type = mh.mh_type;
+
+	switch (mh.mh_type) {
+	case GFS2_METATYPE_SB:   /* 1 (superblock) */
+		*struct_len = sizeof(struct gfs_sb);
+		break;
+	case GFS2_METATYPE_RG:   /* 2 (rsrc grp hdr) */
+		*struct_len = bufsize; /*sizeof(struct gfs_rgrp);*/
+		break;
+	case GFS2_METATYPE_RB:   /* 3 (rsrc grp bitblk) */
+		*struct_len = bufsize;
+		break;
+	case GFS2_METATYPE_DI:   /* 4 (disk inode) */
+		*struct_len = bufsize; /*sizeof(struct gfs_dinode);*/
+		break;
+	case GFS2_METATYPE_IN:   /* 5 (indir inode blklst) */
+		*struct_len = bufsize; /*sizeof(struct gfs_indirect);*/
+		break;
+	case GFS2_METATYPE_LF:   /* 6 (leaf dinode blklst) */
+		*struct_len = bufsize; /*sizeof(struct gfs_leaf);*/
+		break;
+	case GFS2_METATYPE_JD:   /* 7 (journal data) */
+		*struct_len = sizeof(struct gfs2_meta_header);
+		break;
+	case GFS2_METATYPE_LH:   /* 8 (log header) */
+		*struct_len = sizeof(struct gfs2_log_header);
+		break;
+	case GFS2_METATYPE_LD:   /* 9 (log descriptor) */
+		*struct_len = sizeof(struct gfs2_log_descriptor);
+		break;
+	case GFS2_METATYPE_EA:   /* 10 (extended attr hdr) */
+		*struct_len = sizeof(struct gfs2_ea_header);
+		break;
+	case GFS2_METATYPE_ED:   /* 11 (extended attr data) */
+		*struct_len = 512;
+		break;
+	default:
+		*struct_len = bufsize;
+		break;
+	}
+	return 0;
+}
+
+/* Put out a warm, fuzzy message every second so the user     */
+/* doesn't think we hung.  (This may take a long time).       */
+/* We only check whether to report every one percent because  */
+/* checking every block kills performance.  We only report    */
+/* every second because we don't need 100 extra messages in   */
+/* logs made from verbose mode.                               */
+void warm_fuzzy_stuff(uint64_t block, int force)
+{
+        static struct timeval tv;
+        static uint32_t seconds = 0;
+        
+	last_reported_block = block;
+	gettimeofday(&tv, NULL);
+	if (!seconds)
+		seconds = tv.tv_sec;
+	if (force || tv.tv_sec - seconds) {
+		static uint64_t percent;
+
+		seconds = tv.tv_sec;
+		if (last_fs_block) {
+			percent = (block * 100) / last_fs_block;
+			printf("\r%" PRIu64 " blocks (%"
+			       PRIu64 "%%) processed, ", block, percent);
+			printf("%" PRIu64 " blocks (%" PRIu64 "MB) saved    ",
+			       blks_saved, total_out / (1024*1024));
+			fflush(stdout);
+		}
+	}
+}
+
+void save_block(int fd, int out_fd, uint64_t blk)
+{
+	int blktype, blklen, outsz;
+	uint16_t trailing0;
+	char *p;
+
+	warm_fuzzy_stuff(blk, FALSE);
+	memset(savedata, 0, sizeof(struct saved_metablock));
+	do_lseek(fd, blk * bufsize);
+	do_read(fd, savedata->buf, bufsize); /* read in the block */
+
+	if (get_gfs_struct_info(savedata->buf, &blktype, &blklen))
+		return; /* Not metadata, so skip it */
+	trailing0 = 0;
+	p = &savedata->buf[blklen - 1];
+	while (*p=='\0' && trailing0 < bufsize) {
+		trailing0++;
+		p--;
+	}
+	savedata->blk = cpu_to_be64(blk);
+	do_write(out_fd, &savedata->blk, sizeof(savedata->blk));
+	outsz = blklen - trailing0;
+	savedata->siglen = cpu_to_be16(outsz);
+	do_write(out_fd, &savedata->siglen, sizeof(savedata->siglen));
+	do_write(out_fd, savedata->buf, outsz);
+	total_out += sizeof(savedata->blk) + sizeof(savedata->siglen) + outsz;
+	blks_saved++;
+}
+
+void savemeta(const char *in_fn, const char *out_fn, int slow)
+{
+	int out_fd;
+	osi_list_t *tmp;
+	uint64_t blk;
+	uint64_t memreq;
+	int rgcount;
+
+	memset(&sbd, 0, sizeof(struct gfs2_sbd));
+	strcpy(sbd.device_name, in_fn);
+	sbd.bsize = GFS2_DEFAULT_BSIZE;
+	sbd.rgsize = -1;
+	sbd.jsize = GFS2_DEFAULT_JSIZE;
+	sbd.qcsize = GFS2_DEFAULT_QCSIZE;
+	sbd.md.journals = 1;
+	sbd.device_fd = open(in_fn, O_RDONLY);
+	if (sbd.device_fd < 0)
+		die("Can't open %s: %s\n", in_fn, strerror(errno));
+
+	if (!out_fn)
+		out_fn = DFT_SAVE_FILE;
+	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));
+
+	savedata = malloc(sizeof(struct saved_metablock));
+	if (!savedata)
+		die("Can't allocate memory for the operation.\n");
+
+	do_lseek(sbd.device_fd, 0);
+	blks_saved = total_out = last_reported_block = 0;
+	bufsize = BUFSIZE;
+	if (!slow) {
+		int i;
+
+		device_geometry(&sbd);
+		fix_device_geometry(&sbd);
+		osi_list_init(&sbd.rglist);
+		osi_list_init(&sbd.buf_list);
+		for(i = 0; i < BUF_HASH_SIZE; i++)
+			osi_list_init(&sbd.buf_hash[i]);
+		sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
+		compute_constants(&sbd);
+		if(read_sb(&sbd) < 0)
+			slow = TRUE;
+		else
+			bufsize = sbd.bsize = sbd.sd_sb.sb_bsize;
+	}
+	last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / bufsize;
+	printf("There are %" PRIu64 " blocks of %" PRIu64 " bytes.\n\n",
+	       last_fs_block, bufsize);
+	if (!slow) {
+		if (gfs1)
+			sbd.md.riinode =
+				gfs2_load_inode(&sbd,
+						sbd1->sb_rindex_di.no_addr);
+		else {
+			sbd.master_dir =
+				gfs2_load_inode(&sbd,
+						sbd.sd_sb.sb_master_dir.no_addr);
+
+			slow = gfs2_lookupi(sbd.master_dir, "rindex", 6, 
+					    &sbd.md.riinode);
+		}
+	}
+	if (!slow) {
+		if (gfs1)
+			slow = gfs1_ri_update(&sbd, 0, &rgcount);
+		else
+			slow = ri_update(&sbd, 0, &rgcount);
+	}
+	if (!slow) {
+		blocklist = gfs2_block_list_create(last_fs_block + 1, &memreq);
+		if (!blocklist)
+			slow = TRUE;
+	}
+	if (!slow) {
+		save_block(sbd.device_fd, out_fd, 0x10 * (4096 / bufsize));
+		for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
+		     tmp = tmp->next){
+			struct rgrp_list *rgd;
+			int i, first;
+
+			rgd = osi_list_entry(tmp, struct rgrp_list, list);
+			slow = gfs2_rgrp_read(&sbd, rgd);
+			if (slow)
+				continue;
+			log_debug("RG at %"PRIu64" is %u long\n",
+				  rgd->ri.ri_addr, rgd->ri.ri_length);
+			for (i = 0; i < rgd->ri.ri_length; i++) {
+				if(gfs2_block_set(blocklist,
+						  rgd->ri.ri_addr + i,
+						  gfs2_meta_other))
+					break;
+			}
+			first = 1;
+			/* Save off the rg and bitmaps */
+			for (blk = rgd->ri.ri_addr;
+			     blk < rgd->ri.ri_data0; blk++)
+				save_block(sbd.device_fd, out_fd, blk);
+			/* Save off the other metadata: inodes, etc. */
+			while (!gfs2_next_rg_meta(rgd, &blk, first)) {
+				save_block(sbd.device_fd, out_fd, blk);
+				first = 0;
+			}
+			gfs2_rgrp_relse(rgd, not_updated);
+		}
+	}
+	if (slow) {
+		for (blk = 0; blk < last_fs_block; blk++) {
+			save_block(sbd.device_fd, out_fd, blk);
+		}
+	}
+	if (blocklist)
+		gfs2_block_list_destroy(blocklist);
+	/* There may be a gap between end of file system and end of device */
+	/* so we tell the user that we've processed everything. */
+	blk = last_fs_block;
+	warm_fuzzy_stuff(blk, TRUE);
+	printf("\nMetadata saved to file %s.\n", out_fn);
+	free(savedata);
+	close(out_fd);
+	close(sbd.device_fd);
+	exit(0);
+}
+
+int restore_data(int fd, int in_fd)
+{
+	size_t rs;
+	uint64_t buf64, writes = 0;
+	uint16_t buf16;
+	int first = 1;
+	uint64_t max_fs_size;
+
+	do_lseek(fd, 0);
+	while (TRUE) {
+		memset(savedata, 0, sizeof(struct saved_metablock));
+		rs = read(in_fd, &buf64, sizeof(uint64_t));
+		if (!rs)
+			break;
+		if (rs != sizeof(uint64_t)) {
+			fprintf(stderr, "Error reading from file.\n");
+			return -1;
+		}
+		savedata->blk = be64_to_cpu(buf64);
+		if (savedata->blk >= max_fs_size) {
+			fprintf(stderr, "Error: File system is too small to "
+				"restore this metadata.\n");
+			fprintf(stderr, "File system is %" PRIu64 " blocks, ",
+				max_fs_size);
+			fprintf(stderr, "Restore block = %" PRIu64 "\n",
+				savedata->blk);
+			return -1;
+		}
+		rs = read(in_fd, &buf16, sizeof(uint16_t));
+		savedata->siglen = be16_to_cpu(buf16);
+		if (savedata->siglen > 0 &&
+		    savedata->siglen <= sizeof(savedata->buf)) {
+			do_read(in_fd, savedata->buf, savedata->siglen);
+			if (first) {
+				gfs2_sb_in(&sbd.sd_sb, savedata->buf);
+				if (check_sb(&sbd.sd_sb)) {
+					fprintf(stderr,"Error: Invalid superblock data.\n");
+					return -1;
+				}
+				bufsize = sbd.sd_sb.sb_bsize;
+				last_fs_block =
+					lseek(fd, 0, SEEK_END) / bufsize;
+				printf("There are %" PRIu64 " blocks of %" \
+				       PRIu64 "bytes in the destination file" \
+				       " system.\n\n", last_fs_block, bufsize);
+				first = 0;
+			}
+			do_lseek(fd, savedata->blk * bufsize);
+			do_write(fd, savedata->buf, bufsize);
+			writes++;
+		} else {
+			fprintf(stderr, "Bad record length: %d for #%"
+				PRIu64".\n", savedata->siglen, savedata->blk);
+			return -1;
+		}
+	}
+	printf("%" PRIu64 " blocks restored.\n", writes);
+	return 0;
+}
+
+void restoremeta(const char *in_fn, const char *out_device)
+{
+	int in_fd;
+
+	if (!in_fn)
+		die("No source file specified.  Format is: \ngfs2_edit "
+		    "restoremeta <file to restore> <dest file system>\n");
+	if (!out_device)
+		die("No destination file system specified.  Format is: \n"
+		    "gfs2_edit restoremeta <file to restore> <dest file "
+		    "system>\n");
+	in_fd = open(in_fn, O_RDONLY);
+	if (in_fd < 0)
+		die("Can't open source file %s: %s\n",
+		    in_fn, strerror(errno));
+
+	fd = open(out_device, O_RDWR);
+	if (fd < 0)
+		die("Can't open destination file system %s: %s\n",
+		    out_device, strerror(errno));
+
+	savedata = malloc(sizeof(struct saved_metablock));
+	if (!savedata)
+		die("Can't allocate memory for the restore operation.\n");
+
+	blks_saved = total_out = 0;
+	if (restore_data(fd, in_fd) == 0)
+		printf("File %s restore successful.\n", in_fn);
+	else
+		printf("File %s restore error.\n", in_fn);
+	free(savedata);
+	close(in_fd);
+	close(fd);
+
+	exit(0);
+}



             reply	other threads:[~2007-06-26  1:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-26  1:53 rpeterso [this message]
  -- strict thread matches above, loose matches on Subject: below --
2007-10-19  3:22 [Cluster-devel] cluster/gfs2/edit savemeta.c rpeterso

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=20070626015319.10677.qmail@sourceware.org \
    --to=rpeterso@sourceware.org \
    /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.