[Cluster-devel] cluster/gfs2 edit/gfs2hex.c edit/hexedit.c edi ...
rpeterso at sourceware.org
rpeterso at sourceware.org
Fri Nov 16 19:42:36 UTC 2007
CVSROOT: /cvs/cluster
Module name: cluster
Branch: RHEL5
Changes by: rpeterso at sourceware.org 2007-11-16 19:42:35
Modified files:
gfs2/edit : gfs2hex.c hexedit.c hexedit.h savemeta.c
gfs2/libgfs2 : ondisk.c ondisk.h
Log message:
Resolves: bz 369771: GFS2: bring RHEL gfs2_edit up to date
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.3&r2=1.5.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.3&r2=1.6.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.5&r2=1.4.2.6
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/savemeta.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.2.2&r2=1.1.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/ondisk.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.3&r2=1.5.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/ondisk.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.2&r2=1.2.2.1
--- cluster/gfs2/edit/gfs2hex.c 2007/06/26 01:40:43 1.5.2.3
+++ cluster/gfs2/edit/gfs2hex.c 2007/11/16 19:42:34 1.5.2.4
@@ -192,6 +192,7 @@
memcpy(&indir->dirent[d].dirent, &de, sizeof(struct gfs2_dirent));
memcpy(&indir->dirent[d].filename,
ptr + sizeof(struct gfs2_dirent), de.de_name_len);
+ indir->dirent[d].filename[de.de_name_len] = '\0';
indir->dirent[d].block = de.de_inum.no_addr;
indir->is_dir = TRUE;
indir->dirents++;
@@ -222,7 +223,7 @@
(gfs1 && di->__pad1 == GFS_FILE_DIR);
indirect_blocks = 0;
- memset(&indirect, 0, sizeof(indirect));
+ memset(indirect, 0, sizeof(indirect));
if (di->di_height > 0) {
/* Indirect pointers */
for (x = sizeof(struct gfs2_dinode), y = 0;
@@ -230,21 +231,23 @@
x += sizeof(uint64_t), y++) {
p = be64_to_cpu(*(uint64_t *)(buf + x));
if (p) {
- indirect[indirect_blocks].block = p;
- indirect[indirect_blocks].is_dir = FALSE;
+ indirect->ii[indirect_blocks].block = p;
+ indirect->ii[indirect_blocks].is_dir = FALSE;
indirect_blocks++;
}
}
}
- else if (isdir &&
- !(di->di_flags & GFS2_DIF_EXHASH)) {
+ else if (isdir && !(di->di_flags & GFS2_DIF_EXHASH)) {
int skip = 0;
+
/* Directory Entries: */
- indirect[0].dirents = 0;
- indirect[0].block = block;
- indirect[0].is_dir = TRUE;
+ indirect->ii[0].dirents = 0;
+ indirect->ii[0].block = block;
+ indirect->ii[0].is_dir = TRUE;
for (x = sizeof(struct gfs2_dinode); x < bufsize; x += skip) {
- skip = indirect_dirent(&indirect[0], buf + x, indirect[0].dirents);
+ skip = indirect_dirent(indirect->ii,
+ buf + x,
+ indirect->ii[0].dirents);
if (skip <= 0)
break;
}
@@ -267,20 +270,22 @@
struct gfs2_leaf leaf;
unsigned int bufoffset;
+ if (last >= max_block)
+ break;
tmp_bh = bread(&sbd, last);
gfs2_leaf_in(&leaf, tmp_bh->b_data);
- indirect[indirect_blocks].dirents = 0;
+ indirect->ii[indirect_blocks].dirents = 0;
for (direntcount = 0, bufoffset = sizeof(struct gfs2_leaf);
bufoffset < bufsize;
direntcount++, bufoffset += skip) {
- skip = indirect_dirent(&indirect[indirect_blocks],
+ skip = indirect_dirent(&indirect->ii[indirect_blocks],
tmp_bh->b_data + bufoffset,
direntcount);
if (skip <= 0)
break;
}
brelse(tmp_bh, not_updated);
- indirect[indirect_blocks].block = last;
+ indirect->ii[indirect_blocks].block = last;
indirect_blocks++;
last = p;
} /* if not duplicate pointer */
@@ -303,24 +308,26 @@
**
*******************************************************************************
******************************************************************************/
-void do_indirect_extended(char *buf)
+int do_indirect_extended(char *buf, struct iinfo *iinf)
{
unsigned int x, y;
uint64_t p;
+ int i_blocks;
- indirect_blocks = 0;
- memset(&indirect, 0, sizeof(indirect));
+ i_blocks = 0;
+ memset(iinf, 0, sizeof(struct iinfo));
for (x = (gfs1 ? sizeof(struct gfs_indirect):
sizeof(struct gfs2_meta_header)), y = 0;
x < bufsize;
x += sizeof(uint64_t), y++) {
p = be64_to_cpu(*(uint64_t *)(buf + x));
if (p) {
- indirect[indirect_blocks].block = p;
- indirect[indirect_blocks].is_dir = FALSE;
- indirect_blocks++;
+ iinf->ii[i_blocks].block = p;
+ iinf->ii[i_blocks].is_dir = FALSE;
+ i_blocks++;
}
}
+ return i_blocks;
}
/******************************************************************************
@@ -338,20 +345,32 @@
**
*******************************************************************************
******************************************************************************/
-void do_leaf_extended(char *buf)
+void do_leaf_extended(char *buf, struct iinfo *indir)
{
+ int x, i;
struct gfs2_dirent de;
- unsigned int x;
- eol(0);
- print_gfs2("Directory Entries:");
- eol(0);
-
- for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) {
- eol(0);
- gfs2_dirent_in(&de, buf + x);
- if (de.de_inum.no_addr)
- gfs2_dirent_print(&de, buf + x + sizeof(struct gfs2_dirent));
+ x = 0;
+ memset(indir, 0, sizeof(indir));
+ /* Directory Entries: */
+ for (i = sizeof(struct gfs2_leaf); i < bufsize;
+ i += de.de_rec_len) {
+ gfs2_dirent_in(&de, buf + i);
+ if (de.de_inum.no_addr) {
+ indir->ii[0].block = de.de_inum.no_addr;
+ indir->ii[0].dirent[x].block = de.de_inum.no_addr;
+ memcpy(&indir->ii[0].dirent[x].dirent,
+ &de, sizeof(struct gfs2_dirent));
+ memcpy(&indir->ii[0].dirent[x].filename,
+ buf + i + sizeof(struct gfs2_dirent),
+ de.de_name_len);
+ indir->ii[0].dirent[x].filename[de.de_name_len] = '\0';
+ indir->ii[0].is_dir = TRUE;
+ indir->ii[0].dirents++;
+ x++;
+ }
+ if (de.de_rec_len <= sizeof(struct gfs2_dirent))
+ break;
}
}
@@ -456,7 +475,10 @@
struct gfs2_meta_header mh;
struct gfs2_rgrp rg;
struct gfs2_leaf lf;
+ struct gfs_log_header lh1;
struct gfs2_log_header lh;
+ struct gfs2_log_descriptor ld;
+ struct gfs2_quota_change qc;
uint32_t magic;
@@ -517,14 +539,26 @@
case GFS2_METATYPE_LH:
print_gfs2("Log Header:");
eol(0);
- gfs2_log_header_in(&lh, buf);
- gfs2_log_header_print(&lh);
+ if (gfs1) {
+ gfs_log_header_in(&lh1, buf);
+ gfs_log_header_print(&lh1);
+ } else {
+ gfs2_log_header_in(&lh, buf);
+ gfs2_log_header_print(&lh);
+ }
break;
+ case GFS2_METATYPE_LD:
+ print_gfs2("Log descriptor");
+ eol(0);
+ gfs2_log_descriptor_in(&ld, buf);
+ gfs2_log_descriptor_print(&ld);
+ break;
+
case GFS2_METATYPE_EA:
print_gfs2("Eattr Block:");
eol(0);
- gfs2_meta_header_print(&mh);
+ do_eattr_extended(buf);
break;
case GFS2_METATYPE_ED:
@@ -533,6 +567,19 @@
gfs2_meta_header_print(&mh);
break;
+ case GFS2_METATYPE_LB:
+ print_gfs2("Log Buffer");
+ eol(0);
+ gfs2_meta_header_print(&mh);
+ break;
+
+ case GFS2_METATYPE_QC:
+ print_gfs2("Quota Change");
+ eol(0);
+ gfs2_quota_change_in(&qc, buf);
+ gfs2_quota_change_print(&qc);
+ break;
+
default:
print_gfs2("Unknown metadata type");
eol(0);
--- cluster/gfs2/edit/hexedit.c 2007/06/26 01:40:43 1.6.2.3
+++ cluster/gfs2/edit/hexedit.c 2007/11/16 19:42:34 1.6.2.4
@@ -46,9 +46,11 @@
int display(int identify_only);
extern void eol(int col);
-extern void do_indirect_extended(char *buf);
-extern void savemeta(const char *in_fn, const char *out_fn, int slow);
-extern void restoremeta(const char *in_fn, const char *out_device);
+extern void do_leaf_extended(char *buf, struct iinfo *indir);
+extern int do_indirect_extended(char *buf, struct iinfo *ii);
+extern void savemeta(const char *out_fn, int slow);
+extern void restoremeta(const char *in_fn, const char *out_device,
+ int printblocksonly);
/* ------------------------------------------------------------------------ */
/* UpdateSize - screen size changed, so update it */
@@ -326,12 +328,31 @@
Erase();
}
+
+
+/* ------------------------------------------------------------------------ */
+/* get_block_type */
+/* returns: metatype if block is a GFS2 structure block type */
+/* 0 if block is not a GFS2 structure */
+/* ------------------------------------------------------------------------ */
+int get_block_type(const char *lpBuffer)
+{
+ int ret_type = 0;
+
+ if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 &&
+ *(lpBuffer+2)==0x19 && *(lpBuffer+3)==0x70 &&
+ *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
+ *(lpBuffer+6)==0x00) /* If magic number appears at the start */
+ ret_type = *(lpBuffer+7);
+ return ret_type;
+}
+
/* ------------------------------------------------------------------------ */
/* display_block_type */
/* returns: metatype if block is a GFS2 structure block type */
/* 0 if block is not a GFS2 structure */
/* ------------------------------------------------------------------------ */
-int display_block_type(const char *lpBuffer)
+int display_block_type(const char *lpBuffer, int from_restore)
{
int ret_type = 0; /* return type */
@@ -356,21 +377,19 @@
}
else
print_gfs2(" ");
- print_gfs2("of %" PRIu64 " (0x%" PRIX64 ")", max_block, max_block);
- if (termlines)
- move(line, 55);
- else
- printf(" ");
-
+ if (!from_restore) {
+ print_gfs2("of %" PRIu64 " (0x%" PRIX64 ")", max_block,
+ max_block);
+ if (termlines)
+ move(line, 55);
+ else
+ printf(" ");
+ }
if (block == RGLIST_DUMMY_BLOCK) {
ret_type = GFS2_METATYPE_RG;
struct_len = sizeof(struct gfs2_rgrp);
}
- else if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 &&
- *(lpBuffer+2)==0x19 && *(lpBuffer+3)==0x70 &&
- *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
- *(lpBuffer+6)==0x00) { /* If magic number appears at the start */
- ret_type = *(lpBuffer+7);
+ else if ((ret_type = get_block_type(lpBuffer))) {
switch (*(lpBuffer+7)) {
case GFS2_METATYPE_SB: /* 1 */
print_gfs2("(superblock)");
@@ -396,7 +415,7 @@
struct_len = sizeof(struct gfs2_meta_header);
break;
case GFS2_METATYPE_LF: /* 6 */
- print_gfs2("(leaf dinode blklst)");
+ print_gfs2("(directory leaf)");
struct_len = sizeof(struct gfs2_leaf);
break;
case GFS2_METATYPE_JD:
@@ -408,16 +427,30 @@
struct_len = sizeof(struct gfs2_log_header);
break;
case GFS2_METATYPE_LD:
- print_gfs2("(log descriptor)");
- struct_len = sizeof(struct gfs2_log_descriptor);
+ print_gfs2("(log descriptor)");
+ if (gfs1)
+ struct_len = sizeof(struct gfs_log_descriptor);
+ else
+ struct_len =
+ sizeof(struct gfs2_log_descriptor);
break;
case GFS2_METATYPE_EA:
print_gfs2("(extended attr hdr)");
- struct_len = sizeof(struct gfs2_ea_header);
+ struct_len = sizeof(struct gfs2_meta_header) +
+ sizeof(struct gfs2_ea_header);
break;
case GFS2_METATYPE_ED:
print_gfs2("(extended attr data)");
- struct_len = 512;
+ struct_len = sizeof(struct gfs2_meta_header) +
+ sizeof(struct gfs2_ea_header);
+ break;
+ case GFS2_METATYPE_LB:
+ print_gfs2("(log buffer)");
+ struct_len = sizeof(struct gfs2_meta_header);
+ break;
+ case GFS2_METATYPE_QC:
+ print_gfs2("(quota change)");
+ struct_len = sizeof(struct gfs2_quota_change);
break;
default:
print_gfs2("(wtf?)");
@@ -428,6 +461,8 @@
else
struct_len = 512;
eol(0);
+ if (from_restore)
+ return ret_type;
if (termlines && dmode == HEX_MODE) {
/* calculate how much of the buffer we can fit on screen */
screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
@@ -583,6 +618,100 @@
}
/* ------------------------------------------------------------------------ */
+/* rgcount - return how many rgrps there are. */
+/* ------------------------------------------------------------------------ */
+void rgcount(void)
+{
+ uint64_t block;
+ struct gfs2_buffer_head *ribh;
+ struct gfs2_inode *riinode;
+
+ if (gfs1)
+ block = sbd1->sb_rindex_di.no_addr;
+ else
+ block = masterblock("rindex");
+ ribh = bread(&sbd, block);
+ riinode = inode_get(&sbd, ribh);
+ printf("%lld RGs in this file system.\n",
+ riinode->i_di.di_size / sizeof(struct gfs2_rindex));
+ inode_put(riinode, not_updated);
+ exit(EXIT_SUCCESS);
+}
+
+/* ------------------------------------------------------------------------ */
+/* find_rgrp_block - locate the block for a given rgrp number */
+/* ------------------------------------------------------------------------ */
+uint64_t find_rgrp_block(struct gfs2_inode *di, int rg)
+{
+ char buf[sizeof(struct gfs2_rindex)];
+ int amt;
+ struct gfs2_rindex ri;
+
+ amt = gfs2_readi(di, (void *)&buf,
+ rg * sizeof(struct gfs2_rindex),
+ sizeof(struct gfs2_rindex));
+ if (!amt) /* end of file */
+ return 0;
+ gfs2_rindex_in(&ri, buf);
+ return ri.ri_addr;
+}
+
+/* ------------------------------------------------------------------------ */
+/* set_rgrp_flags - Set an rgrp's flags to a given value */
+/* rgnum: which rg to print or modify flags for (0 - X) */
+/* new_flags: value to set new rg_flags to (if modify == TRUE) */
+/* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
+/* full: TRUE if the full RG should be printed. */
+/* ------------------------------------------------------------------------ */
+void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
+{
+ struct gfs2_rgrp rg;
+ struct gfs2_buffer_head *bh, *ribh;
+ uint64_t rgblk, block;
+ struct gfs2_inode *riinode;
+
+ if (gfs1)
+ block = sbd1->sb_rindex_di.no_addr;
+ else
+ block = masterblock("rindex");
+ ribh = bread(&sbd, block);
+ riinode = inode_get(&sbd, ribh);
+ if (rgnum >= riinode->i_di.di_size / sizeof(struct gfs2_rindex)) {
+ fprintf(stderr, "Error: File system only has %lld RGs.\n",
+ riinode->i_di.di_size / sizeof(struct gfs2_rindex));
+ inode_put(riinode, not_updated);
+ brelse(ribh, not_updated);
+ return;
+ }
+ rgblk = find_rgrp_block(riinode, rgnum);
+ bh = bread(&sbd, rgblk);
+ gfs2_rgrp_in(&rg, bh->b_data);
+ if (modify) {
+ printf("RG #%d (block %llu / 0x%llx) rg_flags changed from 0x%08x to 0x%08x\n",
+ rgnum, (unsigned long long)rgblk,
+ (unsigned long long)rgblk, rg.rg_flags, new_flags);
+ rg.rg_flags = new_flags;
+ gfs2_rgrp_out(&rg, bh->b_data);
+ brelse(bh, updated);
+ } else {
+ if (full) {
+ print_gfs2("RG #%d", rgnum);
+ print_gfs2(" located at: %llu (0x%llx)", rgblk, rgblk);
+ eol(0);
+ gfs2_rgrp_print(&rg);
+ }
+ else
+ printf("RG #%d (block %llu / 0x%llx) rg_flags = 0x%08x\n",
+ rgnum, (unsigned long long)rgblk,
+ (unsigned long long)rgblk, rg.rg_flags);
+ brelse(bh, not_updated);
+ }
+ inode_put(riinode, not_updated);
+ if (modify)
+ bsync(&sbd);
+}
+
+/* ------------------------------------------------------------------------ */
/* parse_rindex - print the rgindex file. */
/* ------------------------------------------------------------------------ */
int parse_rindex(struct gfs2_inode *di, int print_rindex)
@@ -603,9 +732,9 @@
error = gfs2_readi(di, (void *)&buf,
print_entry_ndx * sizeof(struct gfs2_rindex),
sizeof(struct gfs2_rindex));
- gfs2_rindex_in(&ri, buf);
if (!error) /* end of file */
break;
+ gfs2_rindex_in(&ri, buf);
if (!termlines ||
(print_entry_ndx >= start_row[dmode] &&
((print_entry_ndx - start_row[dmode])+1) * lines_per_row[dmode] <=
@@ -677,7 +806,7 @@
print_gfs2("Journal index entries found: %d.",
di->i_di.di_size / sizeof(struct gfs_jindex));
eol(0);
- lines_per_row[dmode] = 6;
+ lines_per_row[dmode] = 4;
for (print_entry_ndx=0; ; print_entry_ndx++) {
error = gfs2_readi(di, (void *)&buf,
print_entry_ndx*sizeof(struct gfs_jindex),
@@ -777,8 +906,9 @@
int has_indirect_blocks(void)
{
if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB ||
- (gfs2_struct_type == GFS2_METATYPE_DI &&
- (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR))))
+ gfs2_struct_type == GFS2_METATYPE_LF ||
+ (gfs2_struct_type == GFS2_METATYPE_DI &&
+ (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR))))
return TRUE;
return FALSE;
}
@@ -820,51 +950,100 @@
}
/* ------------------------------------------------------------------------ */
+/* display_leaf - display directory leaf */
+/* ------------------------------------------------------------------------ */
+int display_leaf(struct iinfo *ind)
+{
+ int start_line, total_dirents = 0;
+ int d;
+
+ eol(0);
+ if (gfs2_struct_type == GFS2_METATYPE_SB)
+ print_gfs2("The superblock has 2 directories");
+ else
+ print_gfs2("This directory contains %d directory entries.",
+ ind->ii[0].dirents);
+
+ start_line = line;
+ for (d = 0; d < ind->ii[0].dirents; d++) {
+ if (termlines && d >= termlines - start_line - 1
+ + start_row[dmode])
+ break;
+ total_dirents++;
+ if (ind->ii[0].dirents > 1) {
+ eol(5);
+ if (termlines) {
+ if (edit_row[dmode] >=0 &&
+ line - start_line - 1 ==
+ edit_row[dmode] -
+ start_row[dmode]) {
+ COLORS_HIGHLIGHT;
+ sprintf(estring, "%"PRIx64,
+ ind->ii[0].dirent[d].block);
+ strcpy(edit_fmt, "%"PRIx64);
+ }
+ }
+ print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ",
+ total_dirents, d + 1,
+ ind->ii[0].dirent[d].dirent.de_inum.no_formal_ino,
+ ind->ii[0].dirent[d].dirent.de_inum.no_formal_ino,
+ ind->ii[0].dirent[d].block,
+ ind->ii[0].dirent[d].block);
+ }
+ print_inode_type(ind->ii[0].dirent[d].dirent.de_type);
+ print_gfs2(" %s", ind->ii[0].dirent[d].filename);
+ if (termlines) {
+ if (edit_row[dmode] >= 0 &&
+ line - start_line - 1 == edit_row[dmode] -
+ start_row[dmode])
+ COLORS_NORMAL;
+ }
+ }
+ if (line >= 4)
+ last_entry_onscreen[dmode] = line - 4;
+ eol(0);
+ end_row[dmode] = ind->ii[0].dirents;
+ if (end_row[dmode] < last_entry_onscreen[dmode])
+ end_row[dmode] = last_entry_onscreen[dmode];
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
/* display_indirect */
/* ------------------------------------------------------------------------ */
-int display_indirect(void)
+int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff)
{
- int start_line, total_dirents, indir_blocks;
- int i, cur_height = -1;
+ int start_line, total_dirents;
+ int i, cur_height = -1, pndx;
uint64_t factor[5]={0,0,0,0,0};
int offsets[5];
last_entry_onscreen[dmode] = 0;
- eol(0);
- start_line = line;
+ if (!level)
+ eol(0);
if (!has_indirect_blocks())
return -1;
-
- indir_blocks = indirect_blocks;
- if (!indirect_blocks) {
- if (gfs2_struct_type == GFS2_METATYPE_SB)
- print_gfs2("The superblock has 2 directories");
- else
- print_gfs2("This directory contains %d directory entries.",
- indirect[0].dirents);
- indir_blocks = 1; /* not really an indirect block, but treat it as one */
- }
- else {
+ if (!level) {
if (gfs2_struct_type == GFS2_METATYPE_DI) {
if (S_ISDIR(di.di_mode))
print_gfs2("This directory contains %d indirect blocks",
- indirect_blocks);
+ indblocks);
else
print_gfs2("This inode contains %d indirect blocks",
- indirect_blocks);
+ indblocks);
}
else
print_gfs2("This indirect block contains %d indirect blocks",
- indirect_blocks);
+ indblocks);
}
+ eol(0);
total_dirents = 0;
/* Figure out multiplication factors for indirect pointers. */
- if ((indir_blocks == indirect_blocks) && !S_ISDIR(di.di_mode)) {
+ if (!S_ISDIR(di.di_mode)) {
memset(&offsets, 0, sizeof(offsets));
/* See if we are on an inode or have one in history. */
- cur_height = 0;
- if (gfs2_struct_type != GFS2_METATYPE_DI) {
- cur_height = 0;
+ cur_height = level;
+ if (!level && gfs2_struct_type != GFS2_METATYPE_DI) {
for (i = 0; i <= blockhist && i < 5; i++) {
offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode];
if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI)
@@ -890,112 +1069,113 @@
for (i = 0; i < di.di_height; i++)
factor[i + 1] = factor[i] * inptrs;
}
- print_gfs2(" (at height=%d)", cur_height);
- }
- if (indirect_blocks) {
+ if (!level)
+ print_gfs2(" (at height=%d)", cur_height);
eol(0);
+ }
+ if (!level && indblocks) {
print_gfs2("Indirect blocks:");
+ eol(0);
}
- eol(0);
- for (print_entry_ndx = start_row[dmode];
- (!termlines || print_entry_ndx < termlines - start_line - 2
- + start_row[dmode]) && print_entry_ndx < indir_blocks;
- print_entry_ndx++) {
+ start_line = line;
+ for (pndx = start_row[dmode];
+ (!termlines || pndx < termlines - start_line - 1
+ + start_row[dmode]) && pndx < indblocks;
+ pndx++) {
+ uint64_t file_offset;
+
+ print_entry_ndx = pndx;
if (termlines) {
if (edit_row[dmode] >= 0 &&
- line - start_line - 2 == edit_row[dmode] -
- start_row[dmode])
+ line - start_line ==
+ edit_row[dmode] - start_row[dmode])
COLORS_HIGHLIGHT;
move(line, 1);
}
- if (indir_blocks == indirect_blocks) {
- print_gfs2("%d => ", print_entry_ndx);
- if (termlines)
- move(line,9);
- print_gfs2("0x%llx / %lld", indirect[print_entry_ndx].block,
- indirect[print_entry_ndx].block);
- if (termlines) {
- if (edit_row[dmode] >= 0 &&
- line - start_line - 2 == edit_row[dmode] -
- start_row[dmode]) {
- sprintf(estring, "%"PRIx64,
- indirect[print_entry_ndx].block);
- strcpy(edit_fmt, "%"PRIx64);
- edit_size[dmode] = strlen(estring);
- COLORS_NORMAL;
- }
- }
- if (!S_ISDIR(di.di_mode)) {
- int hgt;
- uint64_t file_offset = 0ull;
- float human_off;
- char h;
-
- /* Now divide by how deep we are at the moment. */
- /* This is how much data is represented by each */
- /* indirect pointer for each height we've traversed. */
- offsets[0] = print_entry_ndx;
- for (hgt = cur_height; hgt >= 0; hgt--)
- file_offset += offsets[cur_height - hgt] *
- factor[di.di_height - hgt - 1] * bufsize;
- print_gfs2(" ");
- h = 'K';
- human_off = (file_offset / 1024.0);
- if (human_off > 1024.0) { h = 'M'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'G'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'T'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'P'; human_off /= 1024.0; }
- if (human_off > 1024.0) { h = 'E'; human_off /= 1024.0; }
- print_gfs2("(data offset 0x%llx / %lld / %6.2f%c)",
- file_offset, file_offset, human_off, h);
+ if (!termlines) {
+ int h;
+
+ for (h = 0; h < level; h++)
print_gfs2(" ");
+ }
+ print_gfs2("%d => ", pndx);
+ if (termlines)
+ move(line,9);
+ print_gfs2("0x%llx / %lld", ind->ii[pndx].block,
+ ind->ii[pndx].block);
+ if (termlines) {
+ if (edit_row[dmode] >= 0 &&
+ line - start_line ==
+ edit_row[dmode] - start_row[dmode]) {
+ sprintf(estring, "%"PRIx64,
+ ind->ii[print_entry_ndx].block);
+ strcpy(edit_fmt, "%"PRIx64);
+ edit_size[dmode] = strlen(estring);
+ COLORS_NORMAL;
}
}
- if (indirect[print_entry_ndx].is_dir) {
- int d;
+ if (!S_ISDIR(di.di_mode)) {
+ int hgt;
+ file_offset = startoff;
+ float human_off;
+ char h;
+
+ /* Now divide by how deep we are at the moment. */
+ /* This is how much data is represented by each */
+ /* indirect pointer for each height we've traversed. */
+ offsets[0] = pndx;
+ for (hgt = cur_height; hgt >= 0; hgt--)
+ file_offset += offsets[cur_height - hgt] *
+ factor[di.di_height - hgt - 1] * bufsize;
+ print_gfs2(" ");
+ h = 'K';
+ human_off = (file_offset / 1024.0);
+ if (human_off > 1024.0) { h = 'M'; human_off /= 1024.0; }
+ if (human_off > 1024.0) { h = 'G'; human_off /= 1024.0; }
+ if (human_off > 1024.0) { h = 'T'; human_off /= 1024.0; }
+ if (human_off > 1024.0) { h = 'P'; human_off /= 1024.0; }
+ if (human_off > 1024.0) { h = 'E'; human_off /= 1024.0; }
+ print_gfs2("(data offset 0x%llx / %lld / %6.2f%c)",
+ file_offset, file_offset, human_off, h);
+ print_gfs2(" ");
+ }
+ else
+ file_offset = 0;
+ if (!termlines && ((level + 1 < di.di_height) ||
+ (S_ISDIR(di.di_mode) && !level))) {
+ struct iinfo *more_indir;
+ int more_ind;
+ char *tmpbuf;
- if (indirect[print_entry_ndx].dirents > 1 &&
- indir_blocks == indirect_blocks)
- print_gfs2("(directory leaf with %d entries)",
- indirect[print_entry_ndx].dirents);
- for (d = 0; d < indirect[print_entry_ndx].dirents; d++) {
- total_dirents++;
- if (indirect[print_entry_ndx].dirents > 1) {
- eol(5);
- if (termlines) {
- if (edit_row[dmode] >=0 &&
- line - start_line - 2 ==
- edit_row[dmode] -
- start_row[dmode]) {
- COLORS_HIGHLIGHT;
- sprintf(estring, "%"PRIx64,
- indirect[print_entry_ndx].dirent[d].block);
- strcpy(edit_fmt, "%"PRIx64);
- }
- }
- print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ",
- total_dirents, d + 1,
- indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino,
- indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino,
- indirect[print_entry_ndx].dirent[d].block,
- indirect[print_entry_ndx].dirent[d].block);
- }
- print_inode_type(indirect[print_entry_ndx].dirent[d].dirent.de_type);
- print_gfs2(" %s", indirect[print_entry_ndx].dirent[d].filename);
- if (termlines) {
- if (edit_row[dmode] >= 0 &&
- line - start_line - 2 == edit_row[dmode] -
- start_row[dmode])
- COLORS_NORMAL;
+ more_indir = malloc(sizeof(struct iinfo));
+ tmpbuf = malloc(bufsize);
+ if (tmpbuf) {
+ do_lseek(sbd.device_fd,
+ ind->ii[pndx].block * bufsize);
+ do_read(sbd.device_fd, tmpbuf,
+ bufsize); /* read in the desired block */
+ memset(more_indir, 0, sizeof(struct iinfo));
+ if (S_ISDIR(di.di_mode)) {
+ do_leaf_extended(tmpbuf, more_indir);
+ display_leaf(more_indir);
+ } else {
+ more_ind = do_indirect_extended(tmpbuf,
+ more_indir);
+ display_indirect(more_indir,
+ more_ind, level + 1,
+ file_offset);
}
+ free(tmpbuf);
}
- } /* if isdir */
+ free(more_indir);
+ }
+ print_entry_ndx = pndx; /* restore after recursion */
eol(0);
} /* for each display row */
if (line >= 7) /* 7 because it was bumped at the end */
last_entry_onscreen[dmode] = line - 7;
eol(0);
- end_row[dmode] = (indirect_blocks ? indirect_blocks:indirect[0].dirents);
+ end_row[dmode] = indblocks;
if (end_row[dmode] < last_entry_onscreen[dmode])
end_row[dmode] = last_entry_onscreen[dmode];
lines_per_row[dmode] = 1;
@@ -1091,14 +1271,17 @@
struct gfs2_buffer_head *tmp_bh;
/* Display any indirect pointers that we have. */
- if (display_indirect() == 0)
- return -1;
- else if (block_is_rindex()) {
+ if (block_is_rindex()) {
tmp_bh = bread(&sbd, block);
tmp_inode = inode_get(&sbd, tmp_bh);
parse_rindex(tmp_inode, TRUE);
brelse(tmp_bh, not_updated);
}
+ else if (has_indirect_blocks() && !indirect_blocks &&
+ !display_leaf(indirect))
+ return -1;
+ else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
+ return -1;
else if (block_is_rglist()) {
tmp_bh = bread(&sbd, masterblock("rindex"));
tmp_inode = inode_get(&sbd, tmp_bh);
@@ -1135,7 +1318,7 @@
/* ------------------------------------------------------------------------ */
/* read_superblock - read the superblock */
/* ------------------------------------------------------------------------ */
-void read_superblock(void)
+void read_superblock(int fd)
{
int x;
@@ -1172,7 +1355,9 @@
else
gfs1 = FALSE;
bufsize = sbd.sd_sb.sb_bsize;
- block = 0x10 * (4096 / bufsize);
+ if (!bufsize)
+ bufsize = GFS2_DEFAULT_BSIZE;
+ block = 0x10 * (GFS2_DEFAULT_BSIZE / bufsize);
}
/* ------------------------------------------------------------------------ */
@@ -1180,9 +1365,9 @@
/* ------------------------------------------------------------------------ */
void read_master_dir(void)
{
- ioctl(fd, BLKFLSBUF, 0);
- do_lseek(fd, sbd.sd_sb.sb_master_dir.no_addr * bufsize);
- do_read(fd, buf, bufsize); /* read in the desired block */
+ ioctl(sbd.device_fd, BLKFLSBUF, 0);
+ do_lseek(sbd.device_fd, sbd.sd_sb.sb_master_dir.no_addr * bufsize);
+ do_read(sbd.device_fd, buf, bufsize); /* read in the desired block */
gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
do_dinode_extended(&di, buf); /* get extended data, if any */
memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
@@ -1205,70 +1390,50 @@
}
if (block_in_mem != blk) { /* If we changed blocks from the last read */
dev_offset = blk * bufsize;
- ioctl(fd, BLKFLSBUF, 0);
- do_lseek(fd, dev_offset);
- do_read(fd, buf, bufsize); /* read in the desired block */
+ ioctl(sbd.device_fd, BLKFLSBUF, 0);
+ do_lseek(sbd.device_fd, dev_offset);
+ do_read(sbd.device_fd, buf, bufsize); /* read desired block */
block_in_mem = blk; /* remember which block is in memory */
}
line = 1;
- gfs2_struct_type = display_block_type(buf);
+ gfs2_struct_type = display_block_type(buf, FALSE);
if (identify_only)
return 0;
indirect_blocks = 0;
lines_per_row[dmode] = 1;
if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / bufsize)) {
gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */
- memset(&indirect, 0, sizeof(indirect));
- indirect[0].block = sbd.sd_sb.sb_master_dir.no_addr;
- indirect[0].is_dir = TRUE;
- indirect[0].dirents = 2;
+ memset(indirect, 0, sizeof(indirect));
+ indirect->ii[0].block = sbd.sd_sb.sb_master_dir.no_addr;
+ indirect->ii[0].is_dir = TRUE;
+ indirect->ii[0].dirents = 2;
- memcpy(&indirect[0].dirent[0].filename, "root", 4);
- indirect[0].dirent[0].dirent.de_inum.no_formal_ino =
+ memcpy(&indirect->ii[0].dirent[0].filename, "root", 4);
+ indirect->ii[0].dirent[0].dirent.de_inum.no_formal_ino =
sbd.sd_sb.sb_root_dir.no_formal_ino;
- indirect[0].dirent[0].dirent.de_inum.no_addr =
+ indirect->ii[0].dirent[0].dirent.de_inum.no_addr =
sbd.sd_sb.sb_root_dir.no_addr;
- indirect[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr;
- indirect[0].dirent[0].dirent.de_type = DT_DIR;
+ indirect->ii[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr;
+ indirect->ii[0].dirent[0].dirent.de_type = DT_DIR;
- memcpy(&indirect[0].dirent[1].filename, "master", 7);
- indirect[0].dirent[1].dirent.de_inum.no_formal_ino =
+ memcpy(&indirect->ii[0].dirent[1].filename, "master", 7);
+ indirect->ii[0].dirent[1].dirent.de_inum.no_formal_ino =
sbd.sd_sb.sb_master_dir.no_formal_ino;
- indirect[0].dirent[1].dirent.de_inum.no_addr =
+ indirect->ii[0].dirent[1].dirent.de_inum.no_addr =
sbd.sd_sb.sb_master_dir.no_addr;
- indirect[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr;
- indirect[0].dirent[1].dirent.de_type = DT_DIR;
+ indirect->ii[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr;
+ indirect->ii[0].dirent[1].dirent.de_type = DT_DIR;
}
else if (gfs2_struct_type == GFS2_METATYPE_DI) {
gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
do_dinode_extended(&di, buf); /* get extended data, if any */
}
else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
- do_indirect_extended(buf);
+ do_indirect_extended(buf, indirect);
+ indirect_blocks = 1;
}
else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
- int x;
- struct gfs2_dirent de;
-
- indirect_blocks = 1;
- memset(&indirect, 0, sizeof(indirect));
- /* Directory Entries: */
- for (x = sizeof(struct gfs2_leaf); x < bufsize;
- x += de.de_rec_len) {
- gfs2_dirent_in(&de, buf + x);
- if (de.de_inum.no_addr) {
- indirect[indirect_blocks].block = de.de_inum.no_addr;
- indirect[indirect_blocks].dirent[x].block = de.de_inum.no_addr;
- memcpy(&indirect[indirect_blocks].dirent[x].dirent, &de,
- sizeof(struct gfs2_dirent));
- memcpy(&indirect[indirect_blocks].dirent[x].filename,
- buf + x + sizeof(struct gfs2_dirent), de.de_name_len);
- indirect[indirect_blocks].is_dir = TRUE;
- indirect[indirect_blocks].dirents++;
- }
- if (de.de_rec_len <= sizeof(struct gfs2_dirent))
- break;
- }
+ do_leaf_extended(buf, indirect);
}
last_entry_onscreen[dmode] = 0;
if (dmode == EXTENDED_MODE && !block_has_extended_info())
@@ -1377,6 +1542,20 @@
temp_blk = masterblock(string);
}
}
+ else if (string[0] == '+') {
+ if (string[1] == '0' && string[2] == 'x')
+ sscanf(string, "%"SCNx64, &temp_blk);
+ else
+ sscanf(string, "%" PRIu64, &temp_blk);
+ temp_blk += block;
+ }
+ else if (string[0] == '-') {
+ if (string[1] == '0' && string[2] == 'x')
+ sscanf(string, "%"SCNx64, &temp_blk);
+ else
+ sscanf(string, "%" PRIu64, &temp_blk);
+ temp_blk -= block;
+ }
else if (string[0] == '0' && string[1] == 'x')
sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
else
@@ -1457,9 +1636,9 @@
ch += (estring[i+1] - 'A' + 0x0a);
buf[offset + hexoffset] = ch;
}
- do_lseek(fd, dev_offset);
- do_write(fd, buf, bufsize);
- fsync(fd);
+ do_lseek(sbd.device_fd, dev_offset);
+ do_write(sbd.device_fd, buf, bufsize);
+ fsync(sbd.device_fd);
}
}
}
@@ -1535,9 +1714,11 @@
unsigned int col2;
uint64_t *b;
- col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
- b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2];
- temp_blk=be64_to_cpu(*b);
+ if (edit_row[dmode] >= 0) {
+ col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
+ b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2];
+ temp_blk=be64_to_cpu(*b);
+ }
}
else
sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */
@@ -1808,6 +1989,189 @@
}/* interactive_mode */
/* ------------------------------------------------------------------------ */
+/* gfs_log_header_in - read in a gfs1-style log header */
+/* ------------------------------------------------------------------------ */
+void gfs_log_header_in(struct gfs_log_header *head, char *buf)
+{
+ struct gfs_log_header *str = (struct gfs_log_header *) buf;
+
+ gfs2_meta_header_in(&head->lh_header, buf);
+
+ head->lh_flags = be32_to_cpu(str->lh_flags);
+ head->lh_pad = be32_to_cpu(str->lh_pad);
+
+ head->lh_first = be64_to_cpu(str->lh_first);
+ head->lh_sequence = be64_to_cpu(str->lh_sequence);
+
+ head->lh_tail = be64_to_cpu(str->lh_tail);
+ head->lh_last_dump = be64_to_cpu(str->lh_last_dump);
+
+ memcpy(head->lh_reserved, str->lh_reserved, 64);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* gfs_log_header_print - print a gfs1-style log header */
+/* ------------------------------------------------------------------------ */
+void gfs_log_header_print(struct gfs_log_header *lh)
+{
+ gfs2_meta_header_print(&lh->lh_header);
+ pv(lh, lh_flags, "%u", "0x%.8X");
+ pv(lh, lh_pad, "%u", "%x");
+ pv(lh, lh_first, "%llu", "%llx");
+ pv(lh, lh_sequence, "%llu", "%llx");
+ pv(lh, lh_tail, "%llu", "%llx");
+ pv(lh, lh_last_dump, "%llu", "%llx");
+}
+
+/* ------------------------------------------------------------------------ */
+/* dump_journal - dump a journal file's contents. */
+/* ------------------------------------------------------------------------ */
+void dump_journal(const char *journal)
+{
+ struct gfs2_buffer_head *jindex_bh, *j_bh = NULL;
+ uint64_t jindex_block, jblock, j_size, jb;
+ int error, start_line, journal_num;
+ struct gfs2_dinode jdi;
+ char jbuf[bufsize];
+ struct gfs2_inode *j_inode = NULL;
+
+ start_line = line;
+ lines_per_row[dmode] = 1;
+ error = 0;
+ journal_num = atoi(journal + 7);
+ print_gfs2("Dumping journal #%d.", journal_num);
+ eol(0);
+ /* Figure out the block of the jindex file */
+ if (gfs1)
+ jindex_block = sbd1->sb_jindex_di.no_addr;
+ else
+ jindex_block = masterblock("jindex");
+ /* read in the block */
+ jindex_bh = bread(&sbd, jindex_block);
+ /* get the dinode data from it. */
+ gfs2_dinode_in(&di, jindex_bh->b_data); /* parse disk inode into structure */
+
+ if (!gfs1)
+ do_dinode_extended(&di, jindex_bh->b_data); /* parse dir. */
+ brelse(jindex_bh, not_updated);
+
+ if (gfs1) {
+ struct gfs2_inode *jiinode;
+ struct gfs_jindex ji;
+
+ jiinode = inode_get(&sbd, jindex_bh);
+ error = gfs2_readi(jiinode, (void *)&jbuf,
+ journal_num * sizeof(struct gfs_jindex),
+ sizeof(struct gfs_jindex));
+ if (!error)
+ return;
+ gfs_jindex_in(&ji, jbuf);
+ jblock = ji.ji_addr;
+ j_size = ji.ji_nsegment * 0x10;
+ } else {
+ jblock = indirect->ii[0].dirent[journal_num + 2].block;
+ j_bh = bread(&sbd, jblock);
+ j_inode = inode_get(&sbd, j_bh);
+ gfs2_dinode_in(&jdi, j_bh->b_data);/* parse dinode to struct */
+ j_size = jdi.di_size;
+ }
+
+ for (jb = 0; jb < j_size; jb += (gfs1 ? 1:bufsize)) {
+ if (gfs1) {
+ if (j_bh)
+ brelse(j_bh, not_updated);
+ j_bh = bread(&sbd, jblock + jb);
+ memcpy(jbuf, j_bh->b_data, bufsize);
+ }
+ else
+ error = gfs2_readi(j_inode, (void *)&jbuf, jb,
+ bufsize);
+ if (!error) /* end of file */
+ break;
+ if (get_block_type(jbuf) == GFS2_METATYPE_LD) {
+ uint64_t *b;
+ struct gfs2_log_descriptor ld;
+ int i = 0, ltndx;
+ uint32_t logtypes[2][6] = {
+ {GFS2_LOG_DESC_METADATA,
+ GFS2_LOG_DESC_REVOKE,
+ GFS2_LOG_DESC_JDATA,
+ 0, 0, 0},
+ {GFS_LOG_DESC_METADATA,
+ GFS_LOG_DESC_IUL,
+ GFS_LOG_DESC_IDA,
+ GFS_LOG_DESC_Q,
+ GFS_LOG_DESC_LAST,
+ 0}};
+ const char *logtypestr[2][6] = {
+ {"Metadata", "Revoke", "Jdata",
+ "Unknown", "Unknown", "Unknown"},
+ {"Metadata", "Unlinked inode", "Dealloc inode",
+ "Quota", "Final Entry", "Unknown"}};
+
+ print_gfs2("Block #%4llx: Log descriptor, ",
+ jb / (gfs1 ? 1 : bufsize));
+ gfs2_log_descriptor_in(&ld, jbuf);
+ print_gfs2("type %d ", ld.ld_type);
+
+ for (ltndx = 0;; ltndx++) {
+ if (ld.ld_type == logtypes[gfs1][ltndx] ||
+ logtypes[gfs1][ltndx] == 0)
+ break;
+ }
+ print_gfs2("(%s) ", logtypestr[gfs1][ltndx]);
+ print_gfs2("len:%u, data1: %u",
+ ld.ld_length, ld.ld_data1);
+ eol(0);
+ print_gfs2(" ");
+ if (gfs1)
+ b = (uint64_t *)(jbuf +
+ sizeof(struct gfs_log_descriptor));
+ else
+ b = (uint64_t *)(jbuf +
+ sizeof(struct gfs2_log_descriptor));
+ while (*b && (char *)b < (jbuf + bufsize)) {
+ if (!termlines ||
+ (print_entry_ndx >= start_row[dmode] &&
+ ((print_entry_ndx - start_row[dmode])+1) *
+ lines_per_row[dmode] <= termlines - start_line - 2)) {
+ if (i && i % 4 == 0) {
+ eol(0);
+ print_gfs2(" ");
+ }
+ i++;
+ print_gfs2("0x%08llx ", be64_to_cpu(*b));
+ }
+ b++;
+ }
+ eol(0);
+ } else if (get_block_type(jbuf) == GFS2_METATYPE_LH) {
+ struct gfs2_log_header lh;
+ struct gfs_log_header lh1;
+
+ if (gfs1) {
+ gfs_log_header_in(&lh1, jbuf);
+ print_gfs2("Block #%4llx: Log header: Seq"
+ "= 0x%x, first = 0x%x tail = "
+ "0x%x, last = 0x%x",
+ jb, lh1.lh_sequence, lh1.lh_first,
+ lh1.lh_tail, lh1.lh_last_dump);
+ } else {
+ gfs2_log_header_in(&lh, jbuf);
+ print_gfs2("Block #%4llx: Log header: Seq"
+ "= 0x%x, tail = 0x%x, blk = 0x%x",
+ jb / bufsize, lh.lh_sequence,
+ lh.lh_tail, lh.lh_blkno);
+ }
+ eol(0);
+ }
+ }
+ brelse(j_bh, not_updated);
+ blockhist = -1; /* So we don't print anything else */
+}
+
+/* ------------------------------------------------------------------------ */
/* usage - print command line usage */
/* ------------------------------------------------------------------------ */
void usage(void)
@@ -1815,9 +2179,13 @@
fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-p structures|blocks] /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,"savemeta - save off your metadata for analysis and debugging. The intelligent way (assume bitmap is correct).\n");
+ fprintf(stderr,"printsavedmeta - prints out the saved metadata blocks from a savemeta file.\n");
+ fprintf(stderr,"savemeta <file_system> <file> - save off your metadata for analysis and debugging.\n");
+ fprintf(stderr," (The intelligent way: assume bitmap is correct).\n");
fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging. The SLOW way (block by block).\n");
fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
+ fprintf(stderr,"rgcount - print how many RGs in the file system.\n");
+ fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
fprintf(stderr,"-V prints version number.\n");
fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
fprintf(stderr,"-p prints GFS2 structures or blocks to stdout.\n");
@@ -1830,6 +2198,7 @@
fprintf(stderr," inum - prints the inum file.\n");
fprintf(stderr," statfs - prints the statfs file.\n");
fprintf(stderr," rindex - prints the rindex file.\n");
+ fprintf(stderr," rg X - print resource group X.\n");
fprintf(stderr," rgs - prints all the resource groups (rgs).\n");
fprintf(stderr," quota - prints the quota file.\n");
fprintf(stderr,"-x print in hexmode.\n");
@@ -1843,6 +2212,12 @@
fprintf(stderr," gfs2_edit -x -p master /dev/bobs_vg/lvol0\n");
fprintf(stderr," To print out the block-type for block 0x27381:\n");
fprintf(stderr," gfs2_edit identify -p 0x27381 /dev/bobs_vg/lvol0\n");
+ fprintf(stderr," To print out the fourth Resource Group. (the first R is #0)\n");
+ fprintf(stderr," gfs2_edit -p rg 3 /dev/sdb1\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");
}/* usage */
/* ------------------------------------------------------------------------ */
@@ -1883,12 +2258,21 @@
dmode = GFS2_MODE;
}
else if (!strcasecmp(argv[i], "savemeta"))
- savemeta(argv[i+1], argv[i+2], FALSE);
+ termlines = 0;
else if (!strcasecmp(argv[i], "savemetaslow"))
- savemeta(argv[i+1], argv[i+2], TRUE);
+ termlines = 0;
+ else if (!strcasecmp(argv[i], "printsavedmeta"))
+ restoremeta(argv[i+1], argv[i+2],
+ TRUE);
else if (!strcasecmp(argv[i], "restoremeta"))
- restoremeta(argv[i+1], argv[i+2]);
- else if (strchr(argv[i],'/'))
+ restoremeta(argv[i+1], argv[i+2], FALSE);
+ else if (!strcmp(argv[i], "rgcount"))
+ termlines = 0;
+ else if (!strcmp(argv[i], "rgflags"))
+ termlines = 0;
+ else if (!strcmp(argv[i], "rg"))
+ termlines = 0;
+ else if (!device[0] && strchr(argv[i],'/'))
strcpy(device, argv[i]);
}
else { /* second pass */
@@ -1943,6 +2327,61 @@
else
push_block(masterblock("quota"));
}
+ else if (!strcmp(argv[i], "rgcount"))
+ rgcount();
+ else if (!strcmp(argv[i], "rgflags")) {
+ int rg, set = FALSE;
+ uint32_t new_flags = 0;
+
+ i++;
+ if (i >= argc - 1) {
+ printf("Error: rg # not specified.\n");
+ printf("Format is: %s rgflags rgnum"
+ "[newvalue]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ if (argv[i][0]=='0' && argv[i][1]=='x')
+ sscanf(argv[i], "%"SCNx32,
+ &rg);
+ else
+ rg = atoi(argv[i]);
+ i++;
+ if (i < argc - 1 &&
+ isdigit(argv[i][0])) {
+ set = TRUE;
+ if (argv[i][0]=='0' &&
+ argv[i][1]=='x')
+ sscanf(argv[i],
+ "%"SCNx32,
+ &new_flags);
+ else
+ new_flags =
+ atoi(argv[i]);
+ }
+ set_rgrp_flags(rg, new_flags, set,
+ FALSE);
+ exit(EXIT_SUCCESS);
+ }
+ else if (!strcmp(argv[i], "rg")) {
+ int rg;
+
+ i++;
+ if (i >= argc - 1) {
+ printf("Error: rg # not specified.\n");
+ printf("Format is: %s rg rgnum"
+ "\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ rg = atoi(argv[i]);
+ i++;
+ set_rgrp_flags(rg, 0, FALSE, TRUE);
+ exit(EXIT_SUCCESS);
+ }
+ else if (!strcasecmp(argv[i], "savemeta"))
+ savemeta(argv[i+2], FALSE);
+ else if (!strcasecmp(argv[i], "savemetaslow"))
+ savemeta(argv[i+2], TRUE);
else if (argv[i][0]=='0' && argv[i][1]=='x') { /* hex addr */
sscanf(argv[i], "%"SCNx64, &temp_blk);/* retrieve in hex */
push_block(temp_blk);
@@ -1951,6 +2390,9 @@
sscanf(argv[i], "%"SCNd64, &temp_blk);
push_block(temp_blk);
}
+ else if (!strncmp(argv[i], "journal", 7) && isdigit(argv[i][7])) {
+ dump_journal(argv[i]);
+ }
else {
fprintf(stderr,"I don't know what '%s' means.\n", argv[i]);
usage();
@@ -1973,10 +2415,14 @@
******************************************************************************/
int main(int argc, char *argv[])
{
- int i, j;
+ int i, j, fd;
prog_name = argv[0];
+ indirect = malloc(sizeof(struct iinfo));
+ if (!indirect)
+ die("Out of memory.");
+ memset(indirect, 0, sizeof(struct iinfo));
memset(start_row, 0, sizeof(start_row));
memset(lines_per_row, 0, sizeof(lines_per_row));
memset(end_row, 0, sizeof(end_row));
@@ -1999,16 +2445,19 @@
}
}
+ edit_row[GFS2_MODE] = 10; /* Start off at root inode
+ pointer in superblock */
memset(device, 0, sizeof(device));
termlines = 30; /* assume interactive mode until we find -p */
process_parameters(argc, argv, 0);
fd = open(device, O_RDWR);
if (fd < 0)
- die("can't open %s: %s\n", argv[1], strerror(errno));
+ die("can't open %s: %s\n", device, strerror(errno));
max_block = lseek(fd, 0, SEEK_END) / bufsize;
- read_superblock();
+ read_superblock(fd);
+ strcpy(sbd.device_name, device);
if (!gfs1)
read_master_dir();
block_in_mem = -1;
@@ -2020,11 +2469,13 @@
else { /* print all the structures requested */
for (i = 0; i <= blockhist; i++) {
block = blockstack[i + 1].block;
+ if (!block)
+ break;
display(identify);
if (!identify) {
display_extended();
printf("-------------------------------------" \
- "-----------------");
+ "-----------------");
eol(0);
}
block = pop_block();
@@ -2033,5 +2484,7 @@
close(fd);
if (buf)
free(buf);
+ if (indirect)
+ free(indirect);
exit(EXIT_SUCCESS);
}
--- cluster/gfs2/edit/hexedit.h 2007/11/13 17:06:32 1.4.2.5
+++ cluster/gfs2/edit/hexedit.h 2007/11/16 19:42:34 1.4.2.6
@@ -57,8 +57,14 @@
#define GFS_FILE_FIFO (101) /* fifo/pipe */
#define GFS_FILE_SOCK (102) /* socket */
+/* GFS 1 journal block types: */
+#define GFS_LOG_DESC_METADATA (300) /* metadata */
+#define GFS_LOG_DESC_IUL (400) /* unlinked inode */
+#define GFS_LOG_DESC_IDA (401) /* de-allocated inode */
+#define GFS_LOG_DESC_Q (402) /* quota */
+#define GFS_LOG_DESC_LAST (500) /* final in a logged transaction */
+
EXTERN char *prog_name;
-EXTERN int fd;
EXTERN uint64_t block INIT(0);
EXTERN int blockhist INIT(0);
EXTERN int edit_mode INIT(0);
@@ -96,6 +102,48 @@
EXTERN int editing INIT(0);
EXTERN uint64_t temp_blk;
+struct gfs_jindex {
+ uint64_t ji_addr; /* starting block of the journal */
+ uint32_t ji_nsegment; /* number (quantity) of segments in journal */
+ uint32_t ji_pad;
+
+ char ji_reserved[64];
+};
+
+struct gfs_log_descriptor {
+ struct gfs2_meta_header ld_header;
+
+ uint32_t ld_type; /* GFS_LOG_DESC_... Type of this log chunk */
+ uint32_t ld_length; /* Number of buffers in this chunk */
+ uint32_t ld_data1; /* descriptor-specific field */
+ uint32_t ld_data2; /* descriptor-specific field */
+ char ld_reserved[64];
+};
+
+struct gfs_log_header {
+ struct gfs2_meta_header lh_header;
+
+ uint32_t lh_flags; /* GFS_LOG_HEAD_... */
+ uint32_t lh_pad;
+
+ uint64_t lh_first; /* Block number of first header in this trans */
+ uint64_t lh_sequence; /* Sequence number of this transaction */
+
+ uint64_t lh_tail; /* Block number of log tail */
+ uint64_t lh_last_dump; /* Block number of last dump */
+
+ char lh_reserved[64];
+};
+
+EXTERN int block_is_jindex(void);
+EXTERN int block_is_inum_file(void);
+EXTERN int block_is_statfs_file(void);
+EXTERN int block_is_quota_file(void);
+EXTERN int display_block_type(const char *lpBuffer, int from_restore);
+EXTERN void gfs_jindex_in(struct gfs_jindex *jindex, char *buf);
+EXTERN void gfs_log_header_in(struct gfs_log_header *head, char *buf);
+EXTERN void gfs_log_header_print(struct gfs_log_header *lh);
+
struct gfs2_dirents {
uint64_t block;
struct gfs2_dirent dirent;
@@ -109,6 +157,10 @@
struct gfs2_dirents dirent[64];
};
+struct iinfo {
+ struct indirect_info ii[512];
+};
+
struct gfs_indirect {
struct gfs2_meta_header in_header;
@@ -159,18 +211,9 @@
char sb_reserved[96];
};
-struct gfs_jindex {
- uint64_t ji_addr; /* starting block of the journal */
- uint32_t ji_nsegment; /* number (quantity) of segments in journal */
- uint32_t ji_pad;
-
- char ji_reserved[64];
-};
-
EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
-EXTERN struct indirect_info indirect[512]; /* more than the most indirect
- pointers possible for any given
- 4K block */
+EXTERN struct iinfo *indirect; /* more than the most indirect
+ pointers possible for any given 4K block */
EXTERN struct indirect_info masterdir; /* Master directory info */
EXTERN int indirect_blocks INIT(0); /* count of indirect blocks */
EXTERN enum dsp_mode dmode INIT(HEX_MODE);
--- cluster/gfs2/edit/savemeta.c 2007/10/11 20:32:35 1.1.2.2
+++ cluster/gfs2/edit/savemeta.c 2007/11/16 19:42:34 1.1.2.3
@@ -31,11 +31,13 @@
#include <linux/gfs2_ondisk.h>
#include "osi_list.h"
+#include "gfs2hex.h"
#include "hexedit.h"
#include "libgfs2.h"
#define BUFSIZE (4096)
#define DFT_SAVE_FILE "/tmp/gfsmeta"
+#define MAX_JOURNALS_SAVED 256
struct saved_metablock {
uint64_t blk;
@@ -46,6 +48,8 @@
struct saved_metablock *savedata;
uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
struct gfs2_block_list *blocklist = NULL;
+uint64_t journal_blocks[MAX_JOURNALS_SAVED];
+int journals_found = 0;
extern void read_superblock(void);
uint64_t masterblock(const char *fn);
@@ -413,13 +417,13 @@
*struct_len = sizeof(struct gfs2_log_header);
break;
case GFS2_METATYPE_LD: /* 9 (log descriptor) */
- *struct_len = sizeof(struct gfs2_log_descriptor);
+ *struct_len = bufsize;
break;
case GFS2_METATYPE_EA: /* 10 (extended attr hdr) */
- *struct_len = sizeof(struct gfs2_ea_header);
+ *struct_len = bufsize;
break;
case GFS2_METATYPE_ED: /* 11 (extended attr data) */
- *struct_len = 512;
+ *struct_len = bufsize;
break;
default:
*struct_len = bufsize;
@@ -434,7 +438,7 @@
/* 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)
+void warm_fuzzy_stuff(uint64_t block, int force, int save)
{
static struct timeval tv;
static uint32_t seconds = 0;
@@ -448,29 +452,67 @@
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));
+ printf("\r");
+ if (save) {
+ percent = (block * 100) / last_fs_block;
+ printf("%" PRIu64 " metadata blocks (%"
+ PRIu64 "%%) processed, ", block,
+ percent);
+ }
+ if (total_out < 1024 * 1024)
+ printf("%" PRIu64 " metadata blocks (%"
+ PRIu64 "KB) %s. ",
+ blks_saved, total_out / 1024,
+ save?"saved":"restored");
+ else
+ printf("%" PRIu64 " metadata blocks (%"
+ PRIu64 "MB) %s. ",
+ blks_saved, total_out / (1024*1024),
+ save?"saved":"restored");
+ if (force)
+ printf("\n");
fflush(stdout);
}
}
}
-void save_block(int fd, int out_fd, uint64_t blk)
+int block_is_a_journal(void)
+{
+ int j;
+
+ for (j = 0; j < journals_found; j++)
+ if (block == journal_blocks[j])
+ return TRUE;
+ return FALSE;
+}
+
+int block_is_systemfile(void)
+{
+ return block_is_jindex() ||
+ block_is_inum_file() ||
+ block_is_statfs_file() ||
+ block_is_quota_file() ||
+ block_is_a_journal();
+}
+
+int 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 */
+ /* If this isn't metadata and isn't a system file, we don't want it.
+ Note that we're checking "block" here rather than blk. That's
+ because we want to know if the source inode's "block" is a system
+ inode, not the block within the inode "blk". They may or may not
+ be the same thing. */
+ if (get_gfs_struct_info(savedata->buf, &blktype, &blklen) &&
+ !block_is_systemfile())
+ return 0; /* Not metadata, and not system file, so skip it */
trailing0 = 0;
p = &savedata->buf[blklen - 1];
while (*p=='\0' && trailing0 < bufsize) {
@@ -485,26 +527,198 @@
do_write(out_fd, savedata->buf, outsz);
total_out += sizeof(savedata->blk) + sizeof(savedata->siglen) + outsz;
blks_saved++;
+ return blktype;
+}
+
+/*
+ * save_indirect_blocks - save all indirect blocks for the given buffer
+ */
+void save_indirect_blocks(int out_fd, osi_list_t *cur_list,
+ struct gfs2_buffer_head *mybh, int height, int hgt)
+{
+ uint64_t old_block = 0, starting_block;
+ uint64_t *ptr;
+ int head_size;
+ struct gfs2_buffer_head *nbh;
+
+ starting_block = block; /* remember where we started */
+ head_size = (hgt > 1 ?
+ sizeof(struct gfs2_meta_header) :
+ sizeof(struct gfs2_dinode));
+
+ for (ptr = (uint64_t *)(mybh->b_data + head_size);
+ (char *)ptr < (mybh->b_data + mybh->b_size); ptr++) {
+ if (!*ptr)
+ continue;
+ block = be64_to_cpu(*ptr);
+ if (block == old_block)
+ continue;
+ old_block = block;
+ save_block(sbd.device_fd, out_fd, block);
+ if (height != hgt) { /* If not at max height */
+ nbh = bread(&sbd, block);
+ osi_list_add_prev(&nbh->b_altlist,
+ cur_list);
+ brelse(nbh, not_updated);
+ }
+ } /* for all data on the indirect block */
+ block = starting_block; /* go back to where we started */
+}
+
+/*
+ * save_inode_data - save off important data associated with an inode
+ *
+ * out_fd - 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
+ * pointers that reside on blocks on all but the highest height.
+ *
+ * For system files like statfs and inum, we want everything because they
+ * may contain important clues and no user data.
+ *
+ * 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.
+ */
+void save_inode_data(int out_fd)
+{
+ uint32_t height;
+ struct gfs2_inode *inode;
+ osi_list_t metalist[GFS2_MAX_META_HEIGHT];
+ osi_list_t *prev_list, *cur_list, *tmp;
+ struct gfs2_buffer_head *metabh, *mybh;
+ int i;
+ char *buf;
+
+ for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
+ osi_list_init(&metalist[i]);
+ buf = malloc(bufsize);
+ metabh = bread(&sbd, block);
+ inode = inode_get(&sbd, metabh);
+ height = inode->i_di.di_height;
+ /* If this is a user inode, we don't follow to the file height.
+ We stop one level less. That way we save off the indirect
+ pointer blocks but not the actual file contents. */
+ if (height && !block_is_systemfile())
+ height--;
+ osi_list_add(&metabh->b_altlist, &metalist[0]);
+ for (i = 1; i <= height; i++){
+ prev_list = &metalist[i - 1];
+ cur_list = &metalist[i];
+
+ 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,
+ height, i);
+ } /* for blocks at that height */
+ } /* for height */
+ /* free metalists */
+ for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
+ cur_list = &metalist[i];
+ while (!osi_list_empty(cur_list)) {
+ mybh = osi_list_entry(cur_list->next,
+ struct gfs2_buffer_head,
+ b_altlist);
+ osi_list_del(&mybh->b_altlist);
+ }
+ }
+ /* Process directory exhash inodes */
+ if (S_ISDIR(inode->i_di.di_mode)) {
+ if (inode->i_di.di_flags & GFS2_DIF_EXHASH) {
+ save_indirect_blocks(out_fd, cur_list, mybh,
+ height, 0);
+ }
+ }
+ if (inode->i_di.di_eattr) { /* if this inode has extended attributes */
+ struct gfs2_ea_header ea;
+ int e;
+
+ metabh = bread(&sbd, inode->i_di.di_eattr);
+ save_block(sbd.device_fd, out_fd, inode->i_di.di_eattr);
+ for (e = sizeof(struct gfs2_meta_header);
+ e < bufsize; e += ea.ea_rec_len) {
+ uint64_t blk, *b;
+ int charoff;
+
+ gfs2_ea_header_in(&ea, metabh->b_data + e);
+ for (i = 0; i < ea.ea_num_ptrs; i++) {
+ charoff = e + ea.ea_name_len +
+ sizeof(struct gfs2_ea_header) +
+ sizeof(uint64_t) - 1;
+ charoff /= sizeof(uint64_t);
+ b = (uint64_t *)(metabh->b_data);
+ b += charoff + i;
+ blk = be64_to_cpu(*b);
+ save_block(sbd.device_fd, out_fd, blk);
+ }
+ if (!ea.ea_rec_len)
+ break;
+ }
+ brelse(metabh, not_updated);
+ }
+ inode_put(inode, not_updated);
+ free(buf);
+}
+
+void get_journal_inode_blocks(void)
+{
+ int journal;
+ struct gfs2_buffer_head *bh;
+
+ journals_found = 0;
+ memset(journal_blocks, 0, sizeof(journal_blocks));
+ /* Save off all the journals--but only the metadata.
+ * This is confusing so I'll explain. The journals contain important
+ * metadata. However, in gfs2 the journals are regular files within
+ * the system directory. Since they're regular files, the blocks
+ * within the journals are considered data, not metadata. Therefore,
+ * they won't have been saved by the code above. We want to dump
+ * these blocks, but we have to be careful. We only care about the
+ * journal blocks that look like metadata, and we need to not save
+ * journaled user data that may exist there as well. */
+ for (journal = 0; ; journal++) { /* while journals exist */
+ uint64_t jblock;
+ int amt;
+ struct gfs2_dinode jdi;
+ struct gfs2_inode *j_inode = NULL;
+
+ if (gfs1) {
+ struct gfs_jindex ji;
+ char jbuf[sizeof(struct gfs_jindex)];
+
+ j_inode = inode_get(&sbd, bh);
+ amt = gfs2_readi(j_inode, (void *)&jbuf,
+ journal * sizeof(struct gfs_jindex),
+ sizeof(struct gfs_jindex));
+ if (!amt)
+ break;
+ gfs_jindex_in(&ji, jbuf);
+ jblock = ji.ji_addr;
+ inode_put(j_inode, not_updated);
+ } else {
+ if (journal > indirect->ii[0].dirents - 3)
+ break;
+ jblock = indirect->ii[0].dirent[journal + 2].block;
+ bh = bread(&sbd, jblock);
+ j_inode = inode_get(&sbd, bh);
+ gfs2_dinode_in(&jdi, bh->b_data);
+ inode_put(j_inode, not_updated);
+ }
+ journal_blocks[journals_found++] = jblock;
+ }
}
-void savemeta(const char *in_fn, const char *out_fn, int slow)
+void savemeta(const char *out_fn, int slow)
{
int out_fd;
osi_list_t *tmp;
- uint64_t blk;
uint64_t memreq;
int rgcount;
+ uint64_t jindex_block;
+ struct gfs2_buffer_head *bh;
- 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;
@@ -512,6 +726,8 @@
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));
savedata = malloc(sizeof(struct saved_metablock));
if (!savedata)
die("Can't allocate memory for the operation.\n");
@@ -536,35 +752,49 @@
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",
+ printf("There are %" PRIu64 " blocks of %" PRIu64 " bytes.\n",
last_fs_block, bufsize);
if (!slow) {
- if (gfs1)
+ if (gfs1) {
sbd.md.riinode =
gfs2_load_inode(&sbd,
sbd1->sb_rindex_di.no_addr);
- else {
+ jindex_block = sbd1->sb_jindex_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);
+ jindex_block = masterblock("jindex");
}
+ bh = bread(&sbd, jindex_block);
+ gfs2_dinode_in(&di, bh->b_data);
+ if (!gfs1)
+ do_dinode_extended(&di, bh->b_data);
+ brelse(bh, not_updated);
}
if (!slow) {
+ printf("Reading resource groups...");
+ fflush(stdout);
if (gfs1)
slow = gfs1_ri_update(&sbd, 0, &rgcount);
else
slow = ri_update(&sbd, 0, &rgcount);
+ printf("Done.\n\n");
+ fflush(stdout);
}
if (!slow) {
blocklist = gfs2_block_list_create(last_fs_block + 1, &memreq);
if (!blocklist)
slow = TRUE;
}
+ get_journal_inode_blocks();
if (!slow) {
+ /* Save off the superblock */
save_block(sbd.device_fd, out_fd, 0x10 * (4096 / bufsize));
+ /* Walk through the resource groups saving everything within */
for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
tmp = tmp->next){
struct rgrp_list *rgd;
@@ -584,28 +814,37 @@
}
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);
+ for (block = rgd->ri.ri_addr;
+ block < rgd->ri.ri_data0; block++) {
+ warm_fuzzy_stuff(block, FALSE, TRUE);
+ save_block(sbd.device_fd, out_fd, block);
+ }
/* Save off the other metadata: inodes, etc. */
- while (!gfs2_next_rg_meta(rgd, &blk, first)) {
- save_block(sbd.device_fd, out_fd, blk);
+ while (!gfs2_next_rg_meta(rgd, &block, first)) {
+ int blktype;
+
+ warm_fuzzy_stuff(block, FALSE, TRUE);
+ blktype = save_block(sbd.device_fd, out_fd,
+ block);
+ if (blktype == GFS2_METATYPE_DI)
+ save_inode_data(out_fd);
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);
+ for (block = 0; block < last_fs_block; block++) {
+ save_block(sbd.device_fd, out_fd, block);
}
}
+ /* Clean up */
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);
+ block = last_fs_block;
+ warm_fuzzy_stuff(block, TRUE, TRUE);
printf("\nMetadata saved to file %s.\n", out_fn);
free(savedata);
close(out_fd);
@@ -613,15 +852,17 @@
exit(0);
}
-int restore_data(int fd, int in_fd)
+int restore_data(int fd, int in_fd, int printblocksonly)
{
size_t rs;
uint64_t buf64, writes = 0;
uint16_t buf16;
int first = 1;
- uint64_t max_fs_size;
- do_lseek(fd, 0);
+ if (!printblocksonly)
+ do_lseek(fd, 0);
+ blks_saved = total_out = 0;
+ last_fs_block = 0;
while (TRUE) {
memset(savedata, 0, sizeof(struct saved_metablock));
rs = read(in_fd, &buf64, sizeof(uint64_t));
@@ -631,12 +872,14 @@
fprintf(stderr, "Error reading from file.\n");
return -1;
}
+ total_out += bufsize;
savedata->blk = be64_to_cpu(buf64);
- if (savedata->blk >= max_fs_size) {
+ if (!printblocksonly &&
+ last_fs_block && savedata->blk >= last_fs_block) {
fprintf(stderr, "Error: File system is too small to "
"restore this metadata.\n");
fprintf(stderr, "File system is %" PRIu64 " blocks, ",
- max_fs_size);
+ last_fs_block);
fprintf(stderr, "Restore block = %" PRIu64 "\n",
savedata->blk);
return -1;
@@ -648,64 +891,100 @@
do_read(in_fd, savedata->buf, savedata->siglen);
if (first) {
gfs2_sb_in(&sbd.sd_sb, savedata->buf);
- if (check_sb(&sbd.sd_sb)) {
+ sbd1 = (struct gfs_sb *)&sbd.sd_sb;
+ if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
+ sbd1->sb_header.mh_type ==
+ GFS_METATYPE_SB &&
+ sbd1->sb_header.mh_format ==
+ GFS_FORMAT_SB &&
+ sbd1->sb_multihost_format ==
+ GFS_FORMAT_MULTI)
+ ;
+ else 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);
+ if (!printblocksonly) {
+ 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++;
+ if (printblocksonly) {
+ print_gfs2("%d (l=0x%x): ", blks_saved,
+ savedata->siglen);
+ block = savedata->blk;
+ display_block_type(savedata->buf, TRUE);
+ } else {
+ warm_fuzzy_stuff(savedata->blk, FALSE, FALSE);
+ if (savedata->blk >= last_fs_block) {
+ printf("Out of space on the destination "
+ "device; quitting.\n");
+ break;
+ }
+ do_lseek(fd, savedata->blk * bufsize);
+ do_write(fd, savedata->buf, bufsize);
+ writes++;
+ }
+ blks_saved++;
} else {
fprintf(stderr, "Bad record length: %d for #%"
PRIu64".\n", savedata->siglen, savedata->blk);
return -1;
}
}
- printf("%" PRIu64 " blocks restored.\n", writes);
+ if (!printblocksonly)
+ warm_fuzzy_stuff(savedata->blk, TRUE, FALSE);
return 0;
}
-void restoremeta(const char *in_fn, const char *out_device)
+void complain(const char *complaint)
{
- int in_fd;
+ fprintf(stderr, "%s\n", complaint);
+ die("Format is: \ngfs2_edit restoremeta <file to restore> "
+ "<dest file system>\n");
+}
+
+void restoremeta(const char *in_fn, const char *out_device,
+ int printblocksonly)
+{
+ int in_fd, error;
+ termlines = 0;
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");
+ 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)
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));
-
+ if (!printblocksonly) {
+ sbd.device_fd = open(out_device, O_RDWR);
+ if (sbd.device_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);
+ blks_saved = 0;
+ error = restore_data(sbd.device_fd, in_fd, printblocksonly);
+ printf("File %s %s %s.\n", in_fn,
+ (printblocksonly ? "print" : "restore"),
+ (error ? "error" : "successful"));
free(savedata);
close(in_fd);
- close(fd);
+ if (!printblocksonly)
+ close(sbd.device_fd);
exit(0);
}
--- cluster/gfs2/libgfs2/ondisk.c 2007/10/11 20:32:36 1.5.2.3
+++ cluster/gfs2/libgfs2/ondisk.c 2007/11/16 19:42:35 1.5.2.4
@@ -386,7 +386,7 @@
memset(buf, 0, GFS2_FNAMESIZE + 1);
memcpy(buf, name, de->de_name_len);
- printf(" name = %s\n", buf);
+ print_it(" name", "%s", NULL, buf);
}
void gfs2_leaf_in(struct gfs2_leaf *lf, char *buf)
@@ -462,7 +462,7 @@
memset(buf, 0, GFS2_EA_MAX_NAME_LEN + 1);
memcpy(buf, name, ea->ea_name_len);
- printf(" name = %s\n", buf);
+ print_it(" name", "%s", NULL, buf);
}
void gfs2_log_header_in(struct gfs2_log_header *lh, char *buf)
--- cluster/gfs2/libgfs2/ondisk.h 2006/06/14 13:55:11 1.2
+++ cluster/gfs2/libgfs2/ondisk.h 2007/11/16 19:42:35 1.2.2.1
@@ -35,6 +35,8 @@
extern void gfs2_ea_header_out(struct gfs2_ea_header *ea, char *buf);
extern void gfs2_log_header_in(struct gfs2_log_header *lh, char *buf);
extern void gfs2_log_header_out(struct gfs2_log_header *lh, char *buf);
+extern void gfs2_log_descriptor_in(struct gfs2_log_descriptor *ld, char *buf);
+extern void gfs2_log_descriptor_out(struct gfs2_log_descriptor *ld, char *buf);
extern void gfs2_inum_range_in(struct gfs2_inum_range *ir, char *buf);
extern void gfs2_inum_range_out(struct gfs2_inum_range *ir, char *buf);
extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, char *buf);
More information about the Cluster-devel
mailing list