From mboxrd@z Thu Jan 1 00:00:00 1970 From: rpeterso@sourceware.org Date: 26 Jun 2007 01:40:44 -0000 Subject: [Cluster-devel] cluster/gfs2 edit/Makefile edit/gfs2hex.c edit ... Message-ID: <20070626014044.897.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Branch: RHEL5 Changes by: rpeterso at sourceware.org 2007-06-26 01:40:43 Modified files: gfs2/edit : Makefile gfs2hex.c hexedit.c hexedit.h gfs2/libgfs2 : super.c Log message: Resolves: bz 245635: Bring gfs2_edit up to date Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.2&r2=1.5.2.3 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.2&r2=1.6.2.3 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.2&r2=1.4.2.3 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/super.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3.2.1&r2=1.3.2.2 --- cluster/gfs2/edit/Makefile 2006/08/11 15:18:12 1.4 +++ cluster/gfs2/edit/Makefile 2007/06/26 01:40:43 1.4.2.1 @@ -15,6 +15,7 @@ SOURCE= \ gfs2hex.c \ + savemeta.c \ hexedit.c top_srcdir=.. --- cluster/gfs2/edit/gfs2hex.c 2006/11/14 20:13:36 1.5.2.2 +++ cluster/gfs2/edit/gfs2hex.c 2007/06/26 01:40:43 1.5.2.3 @@ -41,12 +41,12 @@ extern uint64_t bufsize; extern int line, termlines; extern char edit_fmt[80]; -extern char edit_string[1024]; +extern char estring[1024]; extern int edit_mode INIT(0); -extern int edit_row[DISPLAY_MODES], edit_col[DISPLAY_MODES]; -extern int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES]; -extern char edit_string[1024], edit_fmt[80]; -extern enum dsp_mode display_mode INIT(HEX_MODE); +extern int edit_row[DMODES], edit_col[DMODES]; +extern int edit_size[DMODES], last_entry_onscreen[DMODES]; +extern char edit_fmt[80]; +extern enum dsp_mode dmode INIT(HEX_MODE); /* display mode */ void eol(int col) /* end of line */ { @@ -76,6 +76,33 @@ va_end(args); } +void check_highlight(int highlight) +{ + if (!termlines || line >= termlines) /* If printing or out of bounds */ + return; + if (dmode == HEX_MODE) { + if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) { + if (highlight) { + COLORS_HIGHLIGHT; + last_entry_onscreen[dmode] = print_entry_ndx; + } + else + COLORS_NORMAL; + } + } + else { + if ((line * lines_per_row[dmode]) - 4 == + (edit_row[dmode] - start_row[dmode]) * lines_per_row[dmode]) { + if (highlight) { + COLORS_HIGHLIGHT; + last_entry_onscreen[dmode] = print_entry_ndx; + } + else + COLORS_NORMAL; + } + } +} + void print_it(const char *label, const char *fmt, const char *fmt2, ...) { va_list args; @@ -85,13 +112,10 @@ if (!termlines || line < termlines) { va_start(args, fmt2); + check_highlight(TRUE); if (termlines) { - if (line == edit_row[display_mode] + 4) - COLORS_HIGHLIGHT; move(line,0); printw("%s", label); - if (line == edit_row[display_mode] + 4) - COLORS_NORMAL; move(line,24); } else { @@ -102,28 +126,21 @@ } vsprintf(tmp_string, fmt, args); - if (termlines) { - if (line == edit_row[display_mode] + 4) - COLORS_HIGHLIGHT; + if (termlines) printw(tmp_string); - if (line == edit_row[display_mode] + 4) - COLORS_NORMAL; - } else printf(tmp_string); + check_highlight(FALSE); if (fmt2) { decimalsize = strlen(tmp_string); va_end(args); va_start(args, fmt2); vsprintf(tmp_string, fmt2, args); + check_highlight(TRUE); if (termlines) { move(line, 50); - if (line == edit_row[display_mode] + 4) - COLORS_HIGHLIGHT; printw("%s", tmp_string); - if (line == edit_row[display_mode] + 4) - COLORS_NORMAL; } else { int i; @@ -131,6 +148,7 @@ printf(" "); printf("%s", tmp_string); } + check_highlight(FALSE); } else { if (strstr(fmt,"X") || strstr(fmt,"x")) @@ -148,14 +166,13 @@ } if (termlines) { refresh(); - if (line == edit_row[display_mode] + 4) { - strcpy(edit_string, tmp_string); + if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) { + strcpy(estring, tmp_string); strcpy(edit_fmt, fmt); - edit_size[display_mode] = strlen(edit_string); + edit_size[dmode] = strlen(estring); COLORS_NORMAL; } - if (line - 3 > edit_last[display_mode]) - edit_last[display_mode] = line - 4; + last_entry_onscreen[dmode] = (line / lines_per_row[dmode]) - 4; } eol(0); va_end(args); @@ -293,7 +310,8 @@ indirect_blocks = 0; memset(&indirect, 0, sizeof(indirect)); - for (x = sizeof(struct gfs_indirect), y = 0; + 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)); @@ -326,7 +344,7 @@ unsigned int x; eol(0); - printf("Directory Entries:"); + print_gfs2("Directory Entries:"); eol(0); for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) { @@ -360,7 +378,7 @@ unsigned int x; eol(0); - printf("Eattr Entries:"); + print_gfs2("Eattr Entries:"); eol(0); for (x = sizeof(struct gfs2_meta_header); x < bufsize; x += ea.ea_rec_len) @@ -374,8 +392,10 @@ void gfs2_inum_print2(const char *title,struct gfs2_inum *no) { if (termlines) { + check_highlight(TRUE); move(line,2); printw(title); + check_highlight(FALSE); } else printf(" %s:",title); --- cluster/gfs2/edit/hexedit.c 2006/11/14 20:13:36 1.6.2.2 +++ cluster/gfs2/edit/hexedit.c 2007/06/26 01:40:43 1.6.2.3 @@ -42,9 +42,13 @@ #include -int display(enum dsp_mode display_mode, int identify_only); +#define RGLIST_DUMMY_BLOCK -2 + +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); /* ------------------------------------------------------------------------ */ /* UpdateSize - screen size changed, so update it */ @@ -70,7 +74,7 @@ else perror("Error: tgetent failed."); termlines--; /* last line is number of lines -1 */ - display(display_mode, FALSE); + display(FALSE); signal(SIGWINCH, UpdateSize); } @@ -112,9 +116,9 @@ /* returns: 1 if user exited by hitting enter */ /* 0 if user exited by hitting escape */ /* ------------------------------------------------------------------------- */ -int bobgets(char string[],int x,int y,int sz) +int bobgets(char string[],int x,int y,int sz,int *ch) { - int done,ch,runningy,rc; + int done,runningy,rc; move(x,y); done=FALSE; @@ -127,23 +131,29 @@ runningy=y; rc=0; while (!done) { - ch=getch(); + *ch = getch(); - if(ch < 0x0100 && isprint(ch)) { + if(*ch < 0x0100 && isprint(*ch)) { char *p=string+strlen(string); // end of the string + *(p+1)='\0'; while (insert && p > &string[runningy-y]) { *p=*(p-1); p--; } - string[runningy-y]=ch; + string[runningy-y]=*ch; runningy++; move(x,y); addstr(string); + if (runningy-y >= sz) { + rc=1; + *ch = KEY_RIGHT; + done = TRUE; + } } else { // special character, is it one we recognize? - switch(ch) + switch(*ch) { case(KEY_ENTER): case('\n'): @@ -157,11 +167,20 @@ done=TRUE; break; case(KEY_LEFT): - if (runningy>y) + if (dmode == HEX_MODE) { + done = TRUE; + rc = 1; + } + else runningy--; break; case(KEY_RIGHT): - runningy++; + if (dmode == HEX_MODE) { + done = TRUE; + rc = 1; + } + else + runningy++; break; case(KEY_DC): case(0x07F): @@ -220,7 +239,7 @@ break; default: move(0,70); - printw("%08X",ch); + printw("%08X",*ch); // ignore all other characters break; } // end switch on non-printable character @@ -323,12 +342,15 @@ } print_gfs2("Block #"); if (termlines) { - if (edit_row[display_mode] == -1) + if (edit_row[dmode] == -1) COLORS_HIGHLIGHT; } - print_gfs2("%lld (0x%"PRIx64")", block, block); + if (block == RGLIST_DUMMY_BLOCK) + print_gfs2("RG List "); + else + print_gfs2("%lld (0x%"PRIx64")", block, block); if (termlines) { - if (edit_row[display_mode] == -1) + if (edit_row[dmode] == -1) COLORS_NORMAL; move(line,30); } @@ -340,9 +362,14 @@ else printf(" "); - 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 */ + 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); switch (*(lpBuffer+7)) { case GFS2_METATYPE_SB: /* 1 */ @@ -401,7 +428,7 @@ else struct_len = 512; eol(0); - if (termlines && display_mode == HEX_MODE) { + if (termlines && dmode == HEX_MODE) { /* calculate how much of the buffer we can fit on screen */ screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8; if (!screen_chunk_size) @@ -413,9 +440,11 @@ /*eol(9);*/ } if (block == sbd.sd_sb.sb_root_dir.no_addr) - print_gfs2("-------------------- Root direcory -------------------"); + print_gfs2("-------------------- Root directory ------------------"); else if (!gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr) print_gfs2("------------------- Master directory -----------------"); + else if (!gfs1 && block == RGLIST_DUMMY_BLOCK) + print_gfs2("----------------------- RG List ----------------------"); else { if (gfs1) { if (block == sbd1->sb_rindex_di.no_addr) @@ -465,6 +494,7 @@ pointer = (unsigned char *)lpBuffer + offset; ptr2 = (unsigned char *)lpBuffer + offset; l = offset; + print_entry_ndx = 0; while (((termlines && line < termlines && line <= ((screen_chunk_size / 16) + 2)) || @@ -499,15 +529,15 @@ } if (i%4 == 0) print_gfs2(" "); - if (termlines && line == edit_row[display_mode] + 3 && - i == edit_col[display_mode]) { + if (termlines && line == edit_row[dmode] + 3 && + i == edit_col[dmode]) { COLORS_HIGHLIGHT; /* normal part of the structure */ - memset(edit_string,0,3); - sprintf(edit_string,"%02X",*pointer); + memset(estring,0,3); + sprintf(estring,"%02X",*pointer); } print_gfs2("%02X",*pointer); - if (termlines && line == edit_row[display_mode] + 3 && - i == edit_col[display_mode]) { + if (termlines && line == edit_row[dmode] + 3 && + i == edit_col[dmode]) { if (l < struct_len + offset) COLORS_NORMAL; /* normal part of the structure */ else @@ -524,10 +554,11 @@ ptr2++; } print_gfs2("] "); - if (line - 3 > edit_last[display_mode]) - edit_last[display_mode] = line - 3; + if (line - 3 > last_entry_onscreen[dmode]) + last_entry_onscreen[dmode] = line - 3; eol(0); l+=16; + print_entry_ndx++; } /* while */ if (gfs1) { COLORS_NORMAL; @@ -552,28 +583,125 @@ } /* ------------------------------------------------------------------------ */ -/* print_rindex - print the rgindex file. */ +/* parse_rindex - print the rgindex file. */ /* ------------------------------------------------------------------------ */ -int print_rindex(struct gfs2_inode *di) +int parse_rindex(struct gfs2_inode *di, int print_rindex) { - int rgs, error; + int error, start_line; struct gfs2_rindex ri; char buf[sizeof(struct gfs2_rindex)]; + char highlighted_addr[32]; + start_line = line; error = 0; print_gfs2("RG index entries found: %d.", di->i_di.di_size / sizeof(struct gfs2_rindex)); eol(0); - for (rgs=0; ; rgs++) { - error = gfs2_readi(di, (void *)&buf, rgs * sizeof(struct gfs2_rindex), - sizeof(struct gfs2_rindex)); + lines_per_row[dmode] = 6; + memset(highlighted_addr, 0, sizeof(highlighted_addr)); + for (print_entry_ndx=0; ; print_entry_ndx++) { + 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; - print_gfs2("RG #%d", rgs + 1); - eol(0); - gfs2_rindex_print(&ri); + if (!termlines || + (print_entry_ndx >= start_row[dmode] && + ((print_entry_ndx - start_row[dmode])+1) * lines_per_row[dmode] <= + termlines - start_line - 2)) { + if (edit_row[dmode] == print_entry_ndx) { + COLORS_HIGHLIGHT; + sprintf(highlighted_addr, "%llx", (unsigned long long)ri.ri_addr); + } + print_gfs2("RG #%d", print_entry_ndx); + if (!print_rindex) + print_gfs2(" located at: %llu (0x%llx)", + ri.ri_addr, ri.ri_addr); + eol(0); + if (edit_row[dmode] == print_entry_ndx) + COLORS_NORMAL; + if(print_rindex) + gfs2_rindex_print(&ri); + else { + struct gfs2_rgrp rg; + struct gfs2_buffer_head *tmp_bh; + + tmp_bh = bread(&sbd, ri.ri_addr); + gfs2_rgrp_in(&rg, tmp_bh->b_data); + gfs2_rgrp_print(&rg); + brelse(tmp_bh, not_updated); + } + last_entry_onscreen[dmode] = print_entry_ndx; + } + } + strcpy(estring, highlighted_addr); + end_row[dmode] = print_entry_ndx; + return error; +} + +/* ------------------------------------------------------------------------ */ +/* gfs_jindex_in - read in a gfs1 jindex structure. */ +/* ------------------------------------------------------------------------ */ +void gfs_jindex_in(struct gfs_jindex *jindex, char *buf) +{ + struct gfs_jindex *str = (struct gfs_jindex *) buf; + + jindex->ji_addr = be64_to_cpu(str->ji_addr); + jindex->ji_nsegment = be32_to_cpu(str->ji_nsegment); + jindex->ji_pad = be32_to_cpu(str->ji_pad); + memcpy(jindex->ji_reserved, str->ji_reserved, 64); +} + +/* ------------------------------------------------------------------------ */ +/* gfs_jindex_print - print an jindex entry. */ +/* ------------------------------------------------------------------------ */ +void gfs_jindex_print(struct gfs_jindex *ji) +{ + pv(ji, ji_addr, "%llu", "0x%llx"); + pv(ji, ji_nsegment, "%u", "0x%x"); + pv(ji, ji_pad, "%u", "0x%x"); +} + +/* ------------------------------------------------------------------------ */ +/* print_jindex - print the jindex file. */ +/* ------------------------------------------------------------------------ */ +int print_jindex(struct gfs2_inode *di) +{ + int error, start_line; + struct gfs_jindex ji; + char buf[sizeof(struct gfs_jindex)]; + + start_line = line; + error = 0; + print_gfs2("Journal index entries found: %d.", + di->i_di.di_size / sizeof(struct gfs_jindex)); + eol(0); + lines_per_row[dmode] = 6; + for (print_entry_ndx=0; ; print_entry_ndx++) { + error = gfs2_readi(di, (void *)&buf, + print_entry_ndx*sizeof(struct gfs_jindex), + sizeof(struct gfs_jindex)); + gfs_jindex_in(&ji, buf); + if (!error) /* end of file */ + break; + if (!termlines || + (print_entry_ndx >= start_row[dmode] && + ((print_entry_ndx - start_row[dmode])+1) * + lines_per_row[dmode] <= termlines - start_line - 2)) { + if (edit_row[dmode] == print_entry_ndx) { + COLORS_HIGHLIGHT; + sprintf(estring, "%" PRIx64, ji.ji_addr); + } + print_gfs2("Journal #%d", print_entry_ndx); + eol(0); + if (edit_row[dmode] == print_entry_ndx) + COLORS_NORMAL; + gfs_jindex_print(&ji); + last_entry_onscreen[dmode] = print_entry_ndx; + } } + end_row[dmode] = print_entry_ndx; return error; } @@ -644,168 +772,358 @@ } /* ------------------------------------------------------------------------ */ -/* display_extended */ +/* has_indirect_blocks */ /* ------------------------------------------------------------------------ */ -int display_extended(void) +int has_indirect_blocks(void) { - int e, start_line, total_dirents, indir_blocks; - struct gfs2_inode *tmp_inode; + 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)))) + return TRUE; + return FALSE; +} - edit_last[display_mode] = 0; +/* ------------------------------------------------------------------------ */ +/* print_inode_type */ +/* ------------------------------------------------------------------------ */ +void print_inode_type(__be16 de_type) +{ + switch(de_type) { + case DT_UNKNOWN: + print_gfs2("Unknown"); + break; + case DT_REG: + print_gfs2("File "); + break; + case DT_DIR: + print_gfs2("Dir "); + break; + case DT_LNK: + print_gfs2("Symlink"); + break; + case DT_BLK: + print_gfs2("BlkDev "); + break; + case DT_CHR: + print_gfs2("ChrDev "); + break; + case DT_FIFO: + print_gfs2("Fifo "); + break; + case DT_SOCK: + print_gfs2("Socket "); + break; + default: + print_gfs2("%04x ", de_type); + break; + } +} + +/* ------------------------------------------------------------------------ */ +/* display_indirect */ +/* ------------------------------------------------------------------------ */ +int display_indirect(void) +{ + int start_line, total_dirents, indir_blocks; + int i, cur_height = -1; + uint64_t factor[5]={0,0,0,0,0}; + int offsets[5]; + + last_entry_onscreen[dmode] = 0; eol(0); start_line = line; - if (indirect_blocks || - (gfs2_struct_type == GFS2_METATYPE_DI && - (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR)))) { - indir_blocks = indirect_blocks; - if (!indirect_blocks) { + 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); - eol(0); - indir_blocks = 1; /* not really an indirect block, but treat it as one */ - } - else { - if (gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode)) + indir_blocks = 1; /* not really an indirect block, but treat it as one */ + } + else { + if (gfs2_struct_type == GFS2_METATYPE_DI) { + if (S_ISDIR(di.di_mode)) print_gfs2("This directory contains %d indirect blocks", indirect_blocks); else print_gfs2("This inode contains %d indirect blocks", indirect_blocks); - eol(0); - print_gfs2("Indirect blocks for this inode:"); - eol(0); } - total_dirents = 0; - for (e = 0; (!termlines || e < termlines - start_line - 2) && - e < indir_blocks; e++) { + else + print_gfs2("This indirect block contains %d indirect blocks", + indirect_blocks); + } + total_dirents = 0; + /* Figure out multiplication factors for indirect pointers. */ + if ((indir_blocks == indirect_blocks) && !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; + 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) + break; + cur_height++; + } + } + if (cur_height >= 0) { + int diptrs, inptrs; + + if (gfs1) { + diptrs = 483; + inptrs = 501; + } else { + diptrs = (bufsize - sizeof(sizeof(struct gfs2_dinode))) / sizeof(uint64_t); + inptrs = (bufsize - sizeof(sizeof(struct gfs2_meta_header))) / + sizeof(uint64_t); + } + /* Multiply out the max factor based on inode height.*/ + /* This is how much data is represented by each */ + /* indirect pointer at each height. */ + factor[0] = 1ull; + for (i = 0; i < di.di_height; i++) + factor[i + 1] = factor[i] * inptrs; + } + print_gfs2(" (at height=%d)", cur_height); + } + if (indirect_blocks) { + eol(0); + 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++) { + if (termlines) { + if (edit_row[dmode] >= 0 && + line - start_line - 2 == 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[display_mode] >= 0 && - line - start_line - 2 == edit_row[display_mode]) - COLORS_HIGHLIGHT; - move(line, 1); - } - if (indir_blocks == indirect_blocks) { - print_gfs2("%d => ", e); - if (termlines) - move(line,9); - print_gfs2("0x%llx / %lld", indirect[e].block, - indirect[e].block); - if (termlines) { - if (edit_row[display_mode] >= 0 && - line - start_line - 2 == edit_row[display_mode]) { - sprintf(edit_string, "%"PRIx64, indirect[e].block); - strcpy(edit_fmt, "%"PRIx64); - edit_size[display_mode] = strlen(edit_string); - COLORS_NORMAL; - } + 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 (indir_blocks == indirect_blocks) + 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); print_gfs2(" "); - if (indirect[e].is_dir) { - int d; - - if (indirect[e].dirents > 1 && indir_blocks == indirect_blocks) - print_gfs2("(directory leaf with %d entries)", - indirect[e].dirents); - for (d = 0; d < indirect[e].dirents; d++) { - total_dirents++; - if (indirect[e].dirents > 1) { - eol(5); - if (termlines) { - if (edit_row[display_mode] >=0 && - line - start_line - 2 == edit_row[display_mode]) { - COLORS_HIGHLIGHT; - sprintf(edit_string, "%"PRIx64, - indirect[e].dirent[d].block); - strcpy(edit_fmt, "%"PRIx64); - } - } - print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ", - total_dirents, d + 1, - indirect[e].dirent[d].dirent.de_inum.no_formal_ino, - indirect[e].dirent[d].dirent.de_inum.no_formal_ino, - indirect[e].dirent[d].block, - indirect[e].dirent[d].block); - } - switch(indirect[e].dirent[d].dirent.de_type) { - case DT_UNKNOWN: - print_gfs2("Unknown"); - break; - case DT_REG: - print_gfs2("File "); - break; - case DT_DIR: - print_gfs2("Dir "); - break; - case DT_LNK: - print_gfs2("Symlink"); - break; - case DT_BLK: - print_gfs2("BlkDev "); - break; - case DT_CHR: - print_gfs2("ChrDev "); - break; - case DT_FIFO: - print_gfs2("Fifo "); - break; - case DT_SOCK: - print_gfs2("Socket "); - break; - default: - print_gfs2("%04x ", - indirect[e].dirent[d].dirent.de_type); - break; - } - - print_gfs2(" %s", indirect[e].dirent[d].filename); + } + } + 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[display_mode] >= 0 && - line - start_line - 2 == edit_row[display_mode]) - COLORS_NORMAL; + 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); } - } /* if isdir */ - else - print_gfs2("indirect block"); - eol(0); - } /* for termlines */ - if (line >= 7) /* 7 because it was bumped at the end */ - edit_last[display_mode] = line - 7; - } /* if (indirect_blocks) */ - else - print_gfs2("This block does not have indirect blocks."); + 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; + } + } + } /* if isdir */ + 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); + if (end_row[dmode] < last_entry_onscreen[dmode]) + end_row[dmode] = last_entry_onscreen[dmode]; + lines_per_row[dmode] = 1; + return 0; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_rindex */ +/* ------------------------------------------------------------------------ */ +int block_is_rindex(void) +{ if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) || - (block == masterblock("rindex"))) { - struct gfs2_buffer_head *tmp_bh; + (block == masterblock("rindex"))) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_rglist - there's no such block as the rglist. This is a */ +/* special case meant to parse the rindex and follow the */ +/* blocks to the real rgs. */ +/* ------------------------------------------------------------------------ */ +int block_is_rglist(void) +{ + if (block == RGLIST_DUMMY_BLOCK) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_jindex */ +/* ------------------------------------------------------------------------ */ +int block_is_jindex(void) +{ + if ((gfs1 && block == sbd1->sb_jindex_di.no_addr)) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_inum_file */ +/* ------------------------------------------------------------------------ */ +int block_is_inum_file(void) +{ + if (!gfs1 && block == masterblock("inum")) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_statfs_file */ +/* ------------------------------------------------------------------------ */ +int block_is_statfs_file(void) +{ + if (!gfs1 && block == masterblock("statfs")) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_is_quota_file */ +/* ------------------------------------------------------------------------ */ +int block_is_quota_file(void) +{ + if ((gfs1 && block == gfs1_quota_di.no_addr) || + (block == masterblock("quota"))) + return TRUE; + return FALSE; +} + +/* ------------------------------------------------------------------------ */ +/* block_has_extended_info */ +/* ------------------------------------------------------------------------ */ +int block_has_extended_info(void) +{ + if (has_indirect_blocks() || + block_is_rindex() || + block_is_rglist() || + block_is_jindex() || + block_is_inum_file() || + block_is_statfs_file() || + block_is_quota_file()) + return TRUE; + return FALSE; +} +/* ------------------------------------------------------------------------ */ +/* display_extended */ +/* ------------------------------------------------------------------------ */ +int display_extended(void) +{ + struct gfs2_inode *tmp_inode; + struct gfs2_buffer_head *tmp_bh; + + /* Display any indirect pointers that we have. */ + if (display_indirect() == 0) + return -1; + else if (block_is_rindex()) { tmp_bh = bread(&sbd, block); tmp_inode = inode_get(&sbd, tmp_bh); - print_rindex(tmp_inode); + parse_rindex(tmp_inode, TRUE); brelse(tmp_bh, not_updated); } - else if (!gfs1 && block == masterblock("inum")) { - struct gfs2_buffer_head *tmp_bh; - + else if (block_is_rglist()) { + tmp_bh = bread(&sbd, masterblock("rindex")); + tmp_inode = inode_get(&sbd, tmp_bh); + parse_rindex(tmp_inode, FALSE); + brelse(tmp_bh, not_updated); + } + else if (block_is_jindex()) { + tmp_bh = bread(&sbd, block); + tmp_inode = inode_get(&sbd, tmp_bh); + print_jindex(tmp_inode); + brelse(tmp_bh, not_updated); + } + else if (block_is_inum_file()) { tmp_bh = bread(&sbd, block); tmp_inode = inode_get(&sbd, tmp_bh); print_inum(tmp_inode); brelse(tmp_bh, not_updated); } - else if (!gfs1 && block == masterblock("statfs")) { - struct gfs2_buffer_head *tmp_bh; - + else if (block_is_statfs_file()) { tmp_bh = bread(&sbd, block); tmp_inode = inode_get(&sbd, tmp_bh); print_statfs(tmp_inode); brelse(tmp_bh, not_updated); } - else if ((gfs1 && block == gfs1_quota_di.no_addr) || - (block == masterblock("quota"))) { - struct gfs2_buffer_head *tmp_bh; - + else if (block_is_quota_file()) { tmp_bh = bread(&sbd, block); tmp_inode = inode_get(&sbd, tmp_bh); print_quota(tmp_inode); @@ -823,7 +1141,7 @@ sbd1 = (struct gfs_sb *)&sbd.sd_sb; ioctl(fd, BLKFLSBUF, 0); - do_lseek(fd, 0x10 * bufsize); + do_lseek(fd, 0x10 * 4096); do_read(fd, buf, bufsize); /* read in the desired block */ memset(&sbd, 0, sizeof(struct gfs2_sbd)); sbd.device_fd = fd; @@ -853,6 +1171,8 @@ } else gfs1 = FALSE; + bufsize = sbd.sd_sb.sb_bsize; + block = 0x10 * (4096 / bufsize); } /* ------------------------------------------------------------------------ */ @@ -871,26 +1191,54 @@ /* ------------------------------------------------------------------------ */ /* display */ /* ------------------------------------------------------------------------ */ -int display(enum dsp_mode display_mode, int identify_only) +int display(int identify_only) { + uint64_t blk; + + if (block == RGLIST_DUMMY_BLOCK) + blk = masterblock("rindex"); + else + blk = block; if (termlines) { display_title_lines(); move(2,0); } - if (block_in_mem != block) { /* If we changed blocks from the last read */ - dev_offset = block * bufsize; + 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 */ - block_in_mem = block; /* remember which block is in memory */ + block_in_mem = blk; /* remember which block is in memory */ } line = 1; gfs2_struct_type = display_block_type(buf); if (identify_only) return 0; indirect_blocks = 0; - if (gfs2_struct_type == GFS2_METATYPE_SB || block == 0x10) + 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; + + memcpy(&indirect[0].dirent[0].filename, "root", 4); + indirect[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 = + 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; + + memcpy(&indirect[0].dirent[1].filename, "master", 7); + indirect[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 = + 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; + } 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 */ @@ -905,7 +1253,8 @@ indirect_blocks = 1; memset(&indirect, 0, sizeof(indirect)); /* Directory Entries: */ - for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) { + 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; @@ -917,16 +1266,31 @@ indirect[indirect_blocks].is_dir = TRUE; indirect[indirect_blocks].dirents++; } + if (de.de_rec_len <= sizeof(struct gfs2_dirent)) + break; } } - edit_last[display_mode] = 0; - if (display_mode == HEX_MODE) /* if hex display mode */ - hexdump(dev_offset, buf, (gfs2_struct_type == GFS2_METATYPE_DI)? - struct_len + di.di_size:bufsize); /* show block in hex */ - else if (display_mode == GFS2_MODE) /* if structure display */ - display_gfs2(); /* display the gfs2 structure */ - else /* otherwise */ - display_extended(); /* display extended blocks */ + last_entry_onscreen[dmode] = 0; + if (dmode == EXTENDED_MODE && !block_has_extended_info()) + dmode = HEX_MODE; + if (termlines) { + move(termlines, 63); + if (dmode==HEX_MODE) + printw("Mode: Hex %s", (editing?"edit ":"view ")); + else + printw("Mode: %s", (dmode==GFS2_MODE?"Structure": + "Pointers ")); + move(line, 0); + } + if (dmode == HEX_MODE) /* if hex display mode */ + hexdump(dev_offset, buf, + (gfs2_struct_type == GFS2_METATYPE_DI)? + struct_len + di.di_size:bufsize); + else if (dmode == GFS2_MODE) /* if structure display */ + display_gfs2(); /* display the gfs2 structure */ + else + display_extended(); /* display extended blocks */ + /* No else here because display_extended can switch back to hex mode */ if (termlines) refresh(); return(0); @@ -937,14 +1301,19 @@ /* ------------------------------------------------------------------------ */ void push_block(uint64_t blk) { - int i; + int i, bhst; + bhst = blockhist % BLOCK_STACK_SIZE; if (blk) { - blockstack[blockhist % BLOCK_STACK_SIZE].display_mode = display_mode; - for (i = 0; i < DISPLAY_MODES; i++) { - blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i] = edit_row[i]; - blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i] = edit_col[i]; + blockstack[bhst].dmode = dmode; + for (i = 0; i < DMODES; i++) { + blockstack[bhst].start_row[i] = start_row[i]; + blockstack[bhst].end_row[i] = end_row[i]; + blockstack[bhst].edit_row[i] = edit_row[i]; + blockstack[bhst].edit_col[i] = edit_col[i]; + blockstack[bhst].lines_per_row[i] = lines_per_row[i]; } + blockstack[bhst].gfs2_struct_type = gfs2_struct_type; blockhist++; blockstack[blockhist % BLOCK_STACK_SIZE].block = blk; } @@ -955,17 +1324,22 @@ /* ------------------------------------------------------------------------ */ uint64_t pop_block(void) { - int i; + int i, bhst; if (!blockhist) return block; blockhist--; - display_mode = blockstack[blockhist % BLOCK_STACK_SIZE].display_mode; - for (i = 0; i < DISPLAY_MODES; i++) { - edit_row[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i]; - edit_col[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i]; + bhst = blockhist % BLOCK_STACK_SIZE; + dmode = blockstack[bhst].dmode; + for (i = 0; i < DMODES; i++) { + start_row[i] = blockstack[bhst].start_row[i]; + end_row[i] = blockstack[bhst].end_row[i]; + edit_row[i] = blockstack[bhst].edit_row[i]; + edit_col[i] = blockstack[bhst].edit_col[i]; + lines_per_row[i] = blockstack[bhst].lines_per_row[i]; } - return blockstack[blockhist % BLOCK_STACK_SIZE].block; + gfs2_struct_type = blockstack[bhst].gfs2_struct_type; + return blockstack[bhst].block; } /* ------------------------------------------------------------------------ */ @@ -973,16 +1347,20 @@ /* ------------------------------------------------------------------------ */ uint64_t goto_block(void) { - uint64_t temp_blk; char string[256]; + int ch; memset(string, 0, sizeof(string)); sprintf(string,"%"PRId64, block); - if (bobgets(string, 1, 7, 16)) { + if (bobgets(string, 1, 7, 16, &ch)) { if (!strcmp(string,"root")) temp_blk = sbd.sd_sb.sb_root_dir.no_addr; - else if (!gfs1 && !strcmp(string,"master")) - temp_blk = sbd.sd_sb.sb_master_dir.no_addr; + else if (!strcmp(string,"master")) { + if (!gfs1) + temp_blk = sbd.sd_sb.sb_master_dir.no_addr; + else + ; /* maybe put out an error message@some point */ + } else if (isalpha(string[0])) { if (gfs1) { if (!strcmp(string, "jindex")) @@ -992,15 +1370,19 @@ else if (!strcmp(string, "quota")) temp_blk = gfs1_quota_di.no_addr; } - else - temp_blk = masterblock(string); + else { + if (!strcmp(string, "rgs")) + temp_blk = RGLIST_DUMMY_BLOCK; + else + temp_blk = masterblock(string); + } } else if (string[0] == '0' && string[1] == 'x') sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */ else sscanf(string, "%" PRIu64, &temp_blk); /* retrieve decimal */ - if (temp_blk < max_block) { + if (temp_blk == RGLIST_DUMMY_BLOCK || temp_blk < max_block) { offset = 0; block = temp_blk; push_block(block); @@ -1016,22 +1398,159 @@ { if (color_scheme) { - init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN); /* title lines */ - init_pair(COLOR_NORMAL, COLOR_WHITE, COLOR_BLACK); /* normal text */ - init_pair(COLOR_INVERSE, COLOR_BLACK, COLOR_WHITE); /* inverse text */ - init_pair(COLOR_SPECIAL, COLOR_RED, COLOR_BLACK); /* special text */ - init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */ - init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_BLACK); /* offsets */ - init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */ + init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN); + init_pair(COLOR_NORMAL, COLOR_WHITE, COLOR_BLACK); + init_pair(COLOR_INVERSE, COLOR_BLACK, COLOR_WHITE); + init_pair(COLOR_SPECIAL, COLOR_RED, COLOR_BLACK); + init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); + init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_BLACK); + init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); } else { - init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN); /* title lines */ - init_pair(COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE); /* normal text */ - init_pair(COLOR_INVERSE, COLOR_WHITE, COLOR_BLACK); /* inverse text */ - init_pair(COLOR_SPECIAL, COLOR_RED, COLOR_WHITE); /* special text */ - init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */ - init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_WHITE); /* offsets */ - init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */ + init_pair(COLOR_TITLE, COLOR_BLACK, COLOR_CYAN); + init_pair(COLOR_NORMAL, COLOR_BLACK, COLOR_WHITE); + init_pair(COLOR_INVERSE, COLOR_WHITE, COLOR_BLACK); + init_pair(COLOR_SPECIAL, COLOR_RED, COLOR_WHITE); + init_pair(COLOR_HIGHLIGHT, COLOR_MAGENTA, COLOR_WHITE); + init_pair(COLOR_OFFSETS, COLOR_CYAN, COLOR_WHITE); + init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); + } +} + +/* ------------------------------------------------------------------------ */ +/* hex_edit - Allow the user to edit the page by entering hex digits */ +/* ------------------------------------------------------------------------ */ +void hex_edit(int *exitch) +{ + int left_off; + int ch; + + left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17; + /* 8 and 16 char addresses on screen */ + + if (bobgets(estring, edit_row[dmode] + 3, + (edit_col[dmode] * 2) + (edit_col[dmode] / 4) + left_off, + 2, exitch)) { + if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) { + int hexoffset; + int i, sl = strlen(estring); + + for (i = 0; i < sl; i+=2) { + hexoffset = (edit_row[dmode] * 16) + + edit_col[dmode] + (i / 2); + ch = 0x00; + if (isdigit(estring[i])) + ch = (estring[i] - '0') * 0x10; + else if (estring[i] >= 'a' && + estring[i] <= 'f') + ch = (estring[i]-'a' + 0x0a)*0x10; + else if (estring[i] >= 'A' && + estring[i] <= 'F') + ch = (estring[i] - 'A' + 0x0a) * 0x10; + if (isdigit(estring[i+1])) + ch += (estring[i+1] - '0'); + else if (estring[i+1] >= 'a' && + estring[i+1] <= 'f') + ch += (estring[i+1] - 'a' + 0x0a); + else if (estring[i+1] >= 'A' && + estring[i+1] <= 'F') + ch += (estring[i+1] - 'A' + 0x0a); + buf[offset + hexoffset] = ch; + } + do_lseek(fd, dev_offset); + do_write(fd, buf, bufsize); + fsync(fd); + } + } +} + +/* ------------------------------------------------------------------------ */ +/* page up */ +/* ------------------------------------------------------------------------ */ +void pageup(void) +{ + if (dmode == EXTENDED_MODE) { + int dsplines = termlines - 6; + + if (edit_row[dmode] - (dsplines / lines_per_row[dmode]) > 0) { + start_row[dmode] -= (dsplines / lines_per_row[dmode]); + edit_row[dmode] -= (dsplines / lines_per_row[dmode]); + } + else { + start_row[dmode] = 0; + edit_row[dmode] = 0; + } + } + else { + start_row[dmode] = edit_row[dmode] = 0; + if (dmode == GFS2_MODE || offset==0) { + block--; + if (dmode == HEX_MODE) + offset = (bufsize % screen_chunk_size) > 0 ? + screen_chunk_size * + (bufsize / screen_chunk_size) : + bufsize - screen_chunk_size; + else + offset = 0; + } + else + offset -= screen_chunk_size; + } +} + +/* ------------------------------------------------------------------------ */ +/* page down */ +/* ------------------------------------------------------------------------ */ +void pagedn(void) +{ + if (dmode == EXTENDED_MODE) { + int dsplines = termlines - 6; + + if ((edit_row[dmode] + dsplines) / lines_per_row[dmode] + 1 < + end_row[dmode]) { + start_row[dmode] += dsplines / lines_per_row[dmode]; + edit_row[dmode] += dsplines / lines_per_row[dmode]; + } + else + edit_row[dmode] = end_row[dmode] - 1; + } + else { + start_row[dmode] = edit_row[dmode] = 0; + if (dmode == GFS2_MODE || + offset + screen_chunk_size >= bufsize) { + block++; + offset = 0; + } + else + offset += screen_chunk_size; + } +} + +/* ------------------------------------------------------------------------ */ +/* jump - jump to the address the cursor is on */ +/* ------------------------------------------------------------------------ */ +void jump(void) +{ + if (dmode == HEX_MODE) { + 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); + } + else + sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */ + if (temp_blk < max_block) { /* if the block number is valid */ + int i; + + offset = 0; + block = temp_blk; + push_block(block); + for (i = 0; i < DMODES; i++) { + start_row[i] = end_row[i] = edit_row[i] = 0; + edit_col[i] = 0; + } } } @@ -1041,8 +1560,6 @@ void interactive_mode(void) { int ch, Quit; - int64_t temp_blk; - int left_off; if ((wind = initscr()) == NULL) { fprintf(stderr, "Error: unable to initialize screen."); @@ -1062,240 +1579,223 @@ init_colors(); /* Accept keystrokes and act on them accordingly */ Quit = FALSE; + editing = FALSE; while (!Quit) { - display(display_mode, FALSE); - while ((ch=getch()) == 0); // wait for input + display(FALSE); + if (editing) { + if (edit_row[dmode] == -1) + block = goto_block(); + else { + if (dmode == HEX_MODE) + hex_edit(&ch); + else if (dmode == GFS2_MODE) + bobgets(estring, edit_row[dmode]+4, 24, + edit_size[dmode], &ch); + else + bobgets(estring, edit_row[dmode]+6, 14, + edit_size[dmode], &ch); + } + } + else + while ((ch=getch()) == 0); // wait for input + switch (ch) { - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* escape or 'q' */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 0x1b: case 0x03: case 'q': - Quit=TRUE; + if (editing) + editing = FALSE; + else + Quit=TRUE; break; - /* -------------------------------------------------------------- */ - /* home - return to the superblock */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ + /* home - return to the superblock */ + /* --------------------------------------------------------- */ case KEY_HOME: - block = 0x10; - push_block(block); - offset = 0; + if (dmode == EXTENDED_MODE) { + start_row[dmode] = end_row[dmode] = 0; + edit_row[dmode] = 0; + } + else { + block = 0x10 * (4096 / bufsize); + push_block(block); + offset = 0; + } break; - /* -------------------------------------------------------------- */ - /* backspace - return to the previous block on the stack */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ + /* backspace - return to the previous block on the stack */ + /* --------------------------------------------------------- */ case KEY_BACKSPACE: case 0x7f: block = pop_block(); offset = 0; break; - /* -------------------------------------------------------------- */ - /* space - go down the block stack (opposite of backspace) */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ + /* space - go down the block stack (opposite of backspace) */ + /* --------------------------------------------------------- */ case ' ': blockhist++; block = blockstack[blockhist % BLOCK_STACK_SIZE].block; offset = 0; break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* arrow up */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case KEY_UP: - if (edit_row[display_mode] >= 0) /* -1 means change block number */ - edit_row[display_mode]--; + if (dmode == EXTENDED_MODE) { + if (edit_row[dmode] > 0) + edit_row[dmode]--; + if (edit_row[dmode] < start_row[dmode]) + start_row[dmode] = edit_row[dmode]; + } + else { + if (edit_row[dmode] >= 0) + edit_row[dmode]--; + } break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* arrow down */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case KEY_DOWN: - if (edit_row[display_mode] < edit_last[display_mode]) - edit_row[display_mode]++; + if (dmode == EXTENDED_MODE) { + if (edit_row[dmode] + 1 < end_row[dmode]) { + if (edit_row[dmode] >= last_entry_onscreen[dmode]) + start_row[dmode]++; + edit_row[dmode]++; + } + } + else { + if (edit_row[dmode] < last_entry_onscreen[dmode]) + edit_row[dmode]++; + } break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* arrow left */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case KEY_LEFT: - if (display_mode == HEX_MODE) { - if (edit_col[display_mode] > 0) - edit_col[display_mode]--; + if (dmode == HEX_MODE) { + if (edit_col[dmode] > 0) + edit_col[dmode]--; else - edit_col[display_mode] = 15; + edit_col[dmode] = 15; } break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* arrow right */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case KEY_RIGHT: - if (display_mode == HEX_MODE) { - if (edit_col[display_mode] < 15) - edit_col[display_mode]++; + if (dmode == HEX_MODE) { + if (edit_col[dmode] < 15) + edit_col[dmode]++; else - edit_col[display_mode] = 0; + edit_col[dmode] = 0; } break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* m - change display mode key */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'm': - display_mode = ((display_mode + 1) % DISPLAY_MODES); + dmode = ((dmode + 1) % DMODES); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* J - Jump to highlighted block number */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'j': - if (display_mode == HEX_MODE) { - unsigned int col2; - uint64_t *b; - - col2 = edit_col[display_mode] & 0x08;/* thus 0-7->0, 8-15->8 */ - b = (uint64_t *)&buf[edit_row[display_mode]*16 + offset + col2]; - temp_blk=be64_to_cpu(*b); - } - else - sscanf(edit_string, "%"SCNx64, &temp_blk);/* retrieve in hex */ - if (temp_blk < max_block) { /* if the block number is valid */ - int i; - - offset = 0; - block = temp_blk; - push_block(block); - for (i = 0; i < DISPLAY_MODES; i++) { - edit_row[i] = 0; - edit_col[i] = 0; - } - } + jump(); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* g - goto block */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'g': block = goto_block(); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* h - help key */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'h': print_usage(); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ + /* e - change to extended mode */ + /* --------------------------------------------------------- */ + case 'e': + dmode = EXTENDED_MODE; + break; + /* --------------------------------------------------------- */ /* b - Back one 4K block */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'b': - edit_row[display_mode] = 0; - if (block > 0) { + start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0; + if (block > 0) block--; - } offset = 0; break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* c - Change color scheme */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'c': color_scheme = !color_scheme; init_colors(); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* page up key */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 0x19: // ctrl-y for vt100 case KEY_PPAGE: // PgUp case 0x15: // ctrl-u for vi compat. case 0x02: // ctrl-b for less compat. - edit_row[display_mode] = 0; - if (display_mode == GFS2_MODE || offset==0) { - block--; - if (display_mode == HEX_MODE) - offset = (bufsize % screen_chunk_size) > 0 ? - screen_chunk_size * (bufsize / screen_chunk_size) : - bufsize - screen_chunk_size; + pageup(); + break; + /* --------------------------------------------------------- */ + /* end - Jump to the end of the list */ + /* --------------------------------------------------------- */ + case 0x168: + if (dmode == EXTENDED_MODE) { + int dsplines = termlines - 6; + int ents_per_screen = dsplines / + lines_per_row[dmode]; + + edit_row[dmode] = end_row[dmode] - 1; + if ((edit_row[dmode] - ents_per_screen)+1 > 0) + start_row[dmode] = edit_row[dmode] - + ents_per_screen + 1; else - offset = 0; + start_row[dmode] = 0; } - else - offset -= screen_chunk_size; + /* TODO: Make end key work for other display modes. */ break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* f - Forward one 4K block */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 'f': - edit_row[display_mode] = 0; + start_row[dmode]=end_row[dmode]=edit_row[dmode] = 0; + lines_per_row[dmode] = 1; block++; offset = 0; break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* page down key */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case 0x16: // ctrl-v for vt100 case KEY_NPAGE: // PgDown case 0x04: // ctrl-d for vi compat. - edit_row[display_mode] = 0; - if (display_mode == GFS2_MODE || - offset + screen_chunk_size >= bufsize) { - block++; - offset = 0; - } - else - offset += screen_chunk_size; + pagedn(); break; - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ /* enter key - change a value */ - /* -------------------------------------------------------------- */ + /* --------------------------------------------------------- */ case(KEY_ENTER): case('\n'): case('\r'): - if (edit_row[display_mode] == -1) - block = goto_block(); - else { - if (display_mode == HEX_MODE) { - left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17; - /* 8 and 16 char addresses on screen */ - - if (bobgets(edit_string, edit_row[display_mode] + 3, - (edit_col[display_mode] * 2) + - (edit_col[display_mode] / 4) + left_off, 2)) { - if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) { - int hexoffset; - unsigned char ch; - - hexoffset = (edit_row[display_mode] * 16) + - edit_col[display_mode]; - ch = 0x00; - if (isdigit(edit_string[0])) - ch = (edit_string[0] - '0') * 0x10; - else if (edit_string[0] >= 'a' && - edit_string[0] <= 'f') - ch = (edit_string[0] - 'a' + 0x0a) * 0x10; - else if (edit_string[0] >= 'A' && - edit_string[0] <= 'F') - ch = (edit_string[0] - 'A' + 0x0a) * 0x10; - if (isdigit(edit_string[1])) - ch += (edit_string[1] - '0'); - else if (edit_string[1] >= 'a' && - edit_string[1] <= 'f') - ch += (edit_string[1] - 'a' + 0x0a); - else if (edit_string[1] >= 'A' && - edit_string[1] <= 'F') - ch += (edit_string[1] - 'A' + 0x0a); - buf[offset + hexoffset] = ch; - do_lseek(fd, dev_offset); - do_write(fd, buf, bufsize); - fsync(fd); - } - } - } - else if (display_mode == GFS2_MODE) - bobgets(edit_string, edit_row[display_mode] + 4, 24, - edit_size[display_mode]); - else - bobgets(edit_string, edit_row[display_mode] + 6, 14, - edit_size[display_mode]); - } + editing = !editing; break; default: move(termlines - 1, 0); - printw("Keystroke not understood: %02X",ch); + printw("Keystroke not understood: 0x%03X",ch); refresh(); sleep(1); break; @@ -1315,6 +1815,9 @@ 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,"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,"-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"); @@ -1327,6 +1830,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," rgs - prints all the resource groups (rgs).\n"); fprintf(stderr," quota - prints the quota file.\n"); fprintf(stderr,"-x print in hexmode.\n"); fprintf(stderr,"-h prints this help.\n\n"); @@ -1376,17 +1880,21 @@ else if (!strcasecmp(argv[i], "-p") || !strcasecmp(argv[i], "-print")) { termlines = 0; /* initial value--we'll figure it out later */ - display_mode = GFS2_MODE; + dmode = GFS2_MODE; } + else if (!strcasecmp(argv[i], "savemeta")) + savemeta(argv[i+1], argv[i+2], FALSE); + else if (!strcasecmp(argv[i], "savemetaslow")) + savemeta(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],'/')) strcpy(device, argv[i]); } else { /* second pass */ if (!termlines && !strchr(argv[i],'/')) { /* if print, no slash */ - uint64_t temp_blk; - if (!strcasecmp(argv[i], "-x")) - display_mode = HEX_MODE; + dmode = HEX_MODE; else if (argv[i][0] == '-') /* if it starts with a dash */ ; /* ignore it--meant for pass == 0 */ else if (!strcmp(argv[i], "identify")) @@ -1396,12 +1904,16 @@ max_block, max_block); else if (!strcmp(argv[i], "sb") || !strcmp(argv[i], "superblock")) - push_block(0x10); /* superblock */ + push_block(0x10 * (4096 / bufsize)); /* superblock */ else if (!strcmp(argv[i], "root") || !strcmp(argv[i], "rootdir")) push_block(sbd.sd_sb.sb_root_dir.no_addr); - else if (!gfs1 && !strcmp(argv[i], "master")) - push_block(sbd.sd_sb.sb_master_dir.no_addr); + else if (!strcmp(argv[i], "master")) { + if (!gfs1) + push_block(sbd.sd_sb.sb_master_dir.no_addr); + else + fprintf(stderr, "This is GFS1; there's no master directory.\n"); + } else if (!strcmp(argv[i], "jindex")) { if (gfs1) push_block(sbd1->sb_jindex_di.no_addr); @@ -1421,6 +1933,10 @@ else push_block(masterblock("rindex")); } + else if (!strcmp(argv[i], "rgs")) { + if (!gfs1) + push_block(RGLIST_DUMMY_BLOCK); + } else if (!strcmp(argv[i], "quota")) { if (gfs1) push_block(gfs1_quota_di.no_addr); @@ -1461,19 +1977,25 @@ prog_name = argv[0]; + memset(start_row, 0, sizeof(start_row)); + memset(lines_per_row, 0, sizeof(lines_per_row)); + memset(end_row, 0, sizeof(end_row)); memset(edit_row, 0, sizeof(edit_row)); memset(edit_col, 0, sizeof(edit_col)); memset(edit_size, 0, sizeof(edit_size)); - memset(edit_last, 0, sizeof(edit_last)); - display_mode = HEX_MODE; + memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen)); + dmode = HEX_MODE; type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */ block = 0x10; for (i = 0; i < BLOCK_STACK_SIZE; i++) { - blockstack[i].display_mode = display_mode; + blockstack[i].dmode = dmode; blockstack[i].block = block; - for (j = 0; j < DISPLAY_MODES; j++) { + for (j = 0; j < DMODES; j++) { + blockstack[i].start_row[j] = 0; + blockstack[i].end_row[j] = 0; blockstack[i].edit_row[j] = 0; blockstack[i].edit_col[j] = 0; + blockstack[i].lines_per_row[j] = 0; } } @@ -1498,7 +2020,7 @@ else { /* print all the structures requested */ for (i = 0; i <= blockhist; i++) { block = blockstack[i + 1].block; - display(display_mode, identify); + display(identify); if (!identify) { display_extended(); printf("-------------------------------------" \ --- cluster/gfs2/edit/hexedit.h 2006/11/14 20:13:36 1.4.2.2 +++ cluster/gfs2/edit/hexedit.h 2007/06/26 01:40:43 1.4.2.3 @@ -39,7 +39,7 @@ #define INIT(X) =X #endif -#define DISPLAY_MODES 3 +#define DMODES 3 enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2 }; #define BLOCK_STACK_SIZE 256 @@ -64,7 +64,7 @@ EXTERN int edit_mode INIT(0); EXTERN int line; EXTERN char edit_fmt[80]; -EXTERN char edit_string[1024]; +EXTERN char estring[1024]; /* edit string */ EXTERN uint64_t dev_offset INIT(0); EXTERN uint64_t max_block INIT(0); EXTERN char *buf INIT(NULL); @@ -76,9 +76,10 @@ EXTERN int line INIT(1); EXTERN int struct_len INIT(0); EXTERN unsigned int offset; -EXTERN int edit_row[DISPLAY_MODES], edit_col[DISPLAY_MODES]; -EXTERN int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES]; -EXTERN char edit_string[1024], edit_fmt[80]; +EXTERN int edit_row[DMODES], edit_col[DMODES], print_entry_ndx; +EXTERN int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES]; +EXTERN int edit_size[DMODES], last_entry_onscreen[DMODES]; +EXTERN char edit_fmt[80]; EXTERN struct gfs2_sbd sbd; EXTERN struct gfs_sb *sbd1; EXTERN struct gfs2_inum gfs1_quota_di; /* kludge because gfs2 sb too small */ @@ -92,6 +93,8 @@ EXTERN int color_scheme INIT(0); EXTERN WINDOW *wind; EXTERN int gfs1 INIT(0); +EXTERN int editing INIT(0); +EXTERN uint64_t temp_blk; struct gfs2_dirents { uint64_t block; @@ -114,9 +117,17 @@ struct blkstack_info { uint64_t block; - int edit_row[DISPLAY_MODES]; - int edit_col[DISPLAY_MODES]; - enum dsp_mode display_mode; + int start_row[DMODES]; + int end_row[DMODES]; + int lines_per_row[DMODES]; + int edit_row[DMODES]; + int edit_col[DMODES]; + enum dsp_mode dmode; + int gfs2_struct_type; +}; + +struct metapath { + uint64_t mp_list[GFS2_MAX_META_HEIGHT]; }; struct gfs_sb { @@ -148,13 +159,21 @@ 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 indirect_info masterdir; /* Master directory info */ EXTERN int indirect_blocks INIT(0); /* count of indirect blocks */ -EXTERN enum dsp_mode display_mode INIT(HEX_MODE); +EXTERN enum dsp_mode dmode INIT(HEX_MODE); #define SCREEN_HEIGHT (16) #define SCREEN_WIDTH (16) @@ -221,12 +240,54 @@ #define COLOR_OFFSETS 6 #define COLOR_CONTENTS 7 -#define COLORS_TITLE do { attrset(COLOR_PAIR(COLOR_TITLE));attron(A_BOLD); } while (0) -#define COLORS_NORMAL do { attrset(COLOR_PAIR(COLOR_NORMAL));attron(A_BOLD); } while (0) -#define COLORS_INVERSE do { attrset(COLOR_PAIR(COLOR_INVERSE));attron(A_BOLD); } while (0) -#define COLORS_SPECIAL do { attrset(COLOR_PAIR(COLOR_SPECIAL));attron(A_BOLD); } while (0) -#define COLORS_HIGHLIGHT do { attrset(COLOR_PAIR(COLOR_HIGHLIGHT));attron(A_BOLD); } while (0) -#define COLORS_OFFSETS do { attrset(COLOR_PAIR(COLOR_OFFSETS));attron(A_BOLD); } while (0) -#define COLORS_CONTENTS do { attrset(COLOR_PAIR(COLOR_CONTENTS));attron(A_BOLD); } while (0) +#define COLORS_TITLE \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_TITLE)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_NORMAL \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_NORMAL)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_INVERSE \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_INVERSE)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_SPECIAL \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_SPECIAL)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_HIGHLIGHT \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_HIGHLIGHT)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_OFFSETS \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_OFFSETS)); \ + attron(A_BOLD); \ + } \ + } while (0) +#define COLORS_CONTENTS \ + do { \ + if (termlines) { \ + attrset(COLOR_PAIR(COLOR_CONTENTS)); \ + attron(A_BOLD); \ + } \ + } while (0) #endif /* __HEXVIEW_DOT_H__ */ --- cluster/gfs2/libgfs2/super.c 2007/05/01 18:20:50 1.3.2.1 +++ cluster/gfs2/libgfs2/super.c 2007/06/26 01:40:43 1.3.2.2 @@ -33,7 +33,7 @@ * * Returns: 0 on success, -1 on failure */ -static int check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb) +int check_sb(struct gfs2_sb *sb) { if (sb->sb_header.mh_magic != GFS2_MAGIC || sb->sb_header.mh_type != GFS2_METATYPE_SB) { @@ -75,7 +75,7 @@ gfs2_sb_in(&sdp->sd_sb, bh->b_data); brelse(bh, not_updated); - error = check_sb(sdp, &sdp->sd_sb); + error = check_sb(&sdp->sd_sb); if (error) goto out;