Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 261741 Details for
Bug 369771
GFS2: bring RHEL gfs2_edit up to date
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Patch to fix the problem
369771.patch (text/plain), 68.78 KB, created by
Robert Peterson
on 2007-11-16 19:41:24 UTC
(
hide
)
Description:
Patch to fix the problem
Filename:
MIME Type:
Creator:
Robert Peterson
Created:
2007-11-16 19:41:24 UTC
Size:
68.78 KB
patch
obsolete
>Index: edit/gfs2hex.c >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/edit/gfs2hex.c,v >retrieving revision 1.5.2.3 >diff -w -u -p -p -u -r1.5.2.3 gfs2hex.c >--- edit/gfs2hex.c 26 Jun 2007 01:40:43 -0000 1.5.2.3 >+++ edit/gfs2hex.c 16 Nov 2007 19:37:02 -0000 >@@ -192,6 +192,7 @@ int indirect_dirent(struct indirect_info > 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 @@ void do_dinode_extended(struct gfs2_dino > (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 @@ void do_dinode_extended(struct gfs2_dino > 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 @@ void do_dinode_extended(struct gfs2_dino > 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_dinode_extended(struct gfs2_dino > ** > ******************************************************************************* > ******************************************************************************/ >-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_indirect_extended(char *buf) > ** > ******************************************************************************* > ******************************************************************************/ >-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 @@ int display_gfs2(void) > 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 @@ int display_gfs2(void) > case GFS2_METATYPE_LH: > print_gfs2("Log Header:"); > eol(0); >+ 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 @@ int display_gfs2(void) > 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); >Index: edit/hexedit.c >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/edit/hexedit.c,v >retrieving revision 1.6.2.3 >diff -w -u -p -p -u -r1.6.2.3 hexedit.c >--- edit/hexedit.c 26 Jun 2007 01:40:43 -0000 1.6.2.3 >+++ edit/hexedit.c 16 Nov 2007 19:37:04 -0000 >@@ -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 @@ void print_usage(void) > 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 @@ int display_block_type(const char *lpBuf > } > else > print_gfs2(" "); >- print_gfs2("of %" PRIu64 " (0x%" PRIX64 ")", max_block, max_block); >+ 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 @@ int display_block_type(const char *lpBuf > 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: >@@ -409,15 +428,29 @@ int display_block_type(const char *lpBuf > break; > case GFS2_METATYPE_LD: > print_gfs2("(log descriptor)"); >- struct_len = sizeof(struct 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 @@ int display_block_type(const char *lpBuf > 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 @@ uint64_t masterblock(const char *fn) > } > > /* ------------------------------------------------------------------------ */ >+/* 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 @@ int parse_rindex(struct gfs2_inode *di, > 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 @@ int print_jindex(struct gfs2_inode *di) > 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,6 +906,7 @@ int print_quota(struct gfs2_inode *di) > int has_indirect_blocks(void) > { > if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB || >+ 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; >@@ -820,51 +950,100 @@ void print_inode_type(__be16 de_type) > } > > /* ------------------------------------------------------------------------ */ >+/* 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; >+ if (!level) > eol(0); >- start_line = line; > 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,36 +1069,46 @@ int display_indirect(void) > for (i = 0; i < di.di_height; i++) > factor[i + 1] = factor[i] * inptrs; > } >+ if (!level) > print_gfs2(" (at height=%d)", cur_height); >- } >- if (indirect_blocks) { > eol(0); >- print_gfs2("Indirect blocks:"); > } >+ if (!level && indblocks) { >+ print_gfs2("Indirect blocks:"); > 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) { >+ int h; >+ >+ for (h = 0; h < level; h++) >+ print_gfs2(" "); >+ } >+ print_gfs2("%d => ", pndx); > if (termlines) > move(line,9); >- print_gfs2("0x%llx / %lld", indirect[print_entry_ndx].block, >- indirect[print_entry_ndx].block); >+ print_gfs2("0x%llx / %lld", ind->ii[pndx].block, >+ ind->ii[pndx].block); > 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]) { > sprintf(estring, "%"PRIx64, >- indirect[print_entry_ndx].block); >+ ind->ii[print_entry_ndx].block); > strcpy(edit_fmt, "%"PRIx64); > edit_size[dmode] = strlen(estring); > COLORS_NORMAL; >@@ -927,14 +1116,14 @@ int display_indirect(void) > } > if (!S_ISDIR(di.di_mode)) { > int hgt; >- uint64_t file_offset = 0ull; >+ 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] = print_entry_ndx; >+ offsets[0] = pndx; > for (hgt = cur_height; hgt >= 0; hgt--) > file_offset += offsets[cur_height - hgt] * > factor[di.di_height - hgt - 1] * bufsize; >@@ -950,52 +1139,43 @@ int display_indirect(void) > 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; >+ >+ 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); > } >- if (indirect[print_entry_ndx].is_dir) { >- int d; >- >- 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; >+ free(tmpbuf); > } >+ free(more_indir); > } >- } /* if isdir */ >+ 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 @@ int display_extended(void) > 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 @@ int display_extended(void) > /* ------------------------------------------------------------------------ */ > /* read_superblock - read the superblock */ > /* ------------------------------------------------------------------------ */ >-void read_superblock(void) >+void read_superblock(int fd) > { > int x; > >@@ -1172,7 +1355,9 @@ void read_superblock(void) > 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_superblock(void) > /* ------------------------------------------------------------------------ */ > 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 @@ int display(int identify_only) > } > 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); >- } >- else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */ >- int x; >- struct gfs2_dirent de; >- >+ do_indirect_extended(buf, indirect); > 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; > } >+ else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */ >+ do_leaf_extended(buf, indirect); > } > last_entry_onscreen[dmode] = 0; > if (dmode == EXTENDED_MODE && !block_has_extended_info()) >@@ -1377,6 +1542,20 @@ uint64_t goto_block(void) > 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 @@ void hex_edit(int *exitch) > 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,10 +1714,12 @@ void jump(void) > unsigned int col2; > uint64_t *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 */ > if (temp_blk < max_block) { /* if the block number is valid */ >@@ -1808,6 +1989,189 @@ void interactive_mode(void) > }/* 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 @@ void usage(void) > 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 @@ void usage(void) > 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 @@ void usage(void) > 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 @@ void process_parameters(int argc, char * > 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 @@ void process_parameters(int argc, char * > 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 @@ void process_parameters(int argc, char * > 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 @@ void process_parameters(int argc, char * > ******************************************************************************/ > 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 @@ int main(int argc, char *argv[]) > } > } > >+ 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,6 +2469,8 @@ int main(int argc, char *argv[]) > 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(); >@@ -2033,5 +2484,7 @@ int main(int argc, char *argv[]) > close(fd); > if (buf) > free(buf); >+ if (indirect) >+ free(indirect); > exit(EXIT_SUCCESS); > } >Index: edit/hexedit.h >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/edit/hexedit.h,v >retrieving revision 1.4.2.5 >diff -w -u -p -p -u -r1.4.2.5 hexedit.h >--- edit/hexedit.h 13 Nov 2007 17:06:32 -0000 1.4.2.5 >+++ edit/hexedit.h 16 Nov 2007 19:37:04 -0000 >@@ -57,8 +57,14 @@ enum dsp_mode { HEX_MODE = 0, GFS2_MODE > #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 gfs1 INIT(0); > 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 indirect_info { > 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 @@ struct gfs_sb { > 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); >Index: edit/savemeta.c >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/edit/savemeta.c,v >retrieving revision 1.1.2.2 >diff -w -u -p -p -u -r1.1.2.2 savemeta.c >--- edit/savemeta.c 11 Oct 2007 20:32:35 -0000 1.1.2.2 >+++ edit/savemeta.c 16 Nov 2007 19:37:04 -0000 >@@ -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 { > 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 @@ int get_gfs_struct_info(char *buf, int * > *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 @@ int get_gfs_struct_info(char *buf, int * > /* 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 @@ void warm_fuzzy_stuff(uint64_t block, in > > seconds = tv.tv_sec; > if (last_fs_block) { >+ printf("\r"); >+ if (save) { > 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("%" 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 @@ void save_block(int fd, int out_fd, uint > 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 @@ void savemeta(const char *in_fn, const c > 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 @@ void savemeta(const char *in_fn, const c > 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 @@ void savemeta(const char *in_fn, const c > } > 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 @@ void savemeta(const char *in_fn, const c > 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; > >+ 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 @@ int restore_data(int fd, int in_fd) > 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 @@ int restore_data(int fd, int in_fd) > 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; >+ if (!printblocksonly) { > last_fs_block = >- lseek(fd, 0, SEEK_END) / bufsize; >+ 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); >+ PRIu64 " bytes in the destination" \ >+ " file system.\n\n", >+ last_fs_block, bufsize); >+ } > first = 0; > } >+ 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) >+ 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); > } >Index: libgfs2/ondisk.c >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/libgfs2/ondisk.c,v >retrieving revision 1.5.2.3 >diff -w -u -p -p -u -r1.5.2.3 ondisk.c >--- libgfs2/ondisk.c 11 Oct 2007 20:32:36 -0000 1.5.2.3 >+++ libgfs2/ondisk.c 16 Nov 2007 19:37:04 -0000 >@@ -386,7 +386,7 @@ void gfs2_dirent_print(struct gfs2_diren > > 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 @@ void gfs2_ea_header_print(struct gfs2_ea > > 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) >Index: libgfs2/ondisk.h >=================================================================== >RCS file: /cvs/cluster/cluster/gfs2/libgfs2/ondisk.h,v >retrieving revision 1.2 >diff -w -u -p -p -u -r1.2 ondisk.h >--- libgfs2/ondisk.h 14 Jun 2006 13:55:11 -0000 1.2 >+++ libgfs2/ondisk.h 16 Nov 2007 19:37:04 -0000 >@@ -35,6 +35,8 @@ extern void gfs2_ea_header_in(struct gfs > 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);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 369771
: 261741