void walk_dtree( int device, uint64 block, uint32 length, int64 *total_nblocks) { int rc; dtpage_t dtree_buffer; uint8 *stbl; idtentry_t *cur_entry; uint64 first_block, cur_block, last_block; uint32 cur_length; int32 lastindex, index; int32 thisindex; /* * Read the page from disk */ rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize, length << sb.s_l2bsize, &dtree_buffer, GET ); if( dtree_buffer.header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Mark blocks for each entry and visit that page */ lastindex = dtree_buffer.header.nextindex; stbl = (uint8 *)&(dtree_buffer.slot[dtree_buffer.header.stblindex]); for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ thisindex = stbl[index]; cur_entry = (idtentry_t *)&(dtree_buffer.slot[thisindex]); first_block = addressPXD( &(cur_entry->xd) ); cur_length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += cur_length; last_block = first_block + cur_length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, cur_length, total_nblocks); } }
void walk_internal_page(int device, uint64 block, uint32 length, int64 *total_nblocks, int32 flag) { int rc; xtpage_t xtree_page; int32 lastindex, index; uint64 first_block, cur_block, last_block; uint32 cur_length; int32 leafbad; /* * Read the internal page */ rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize, length << sb.s_l2bsize, &xtree_page, GET ); /* * Mark the blocks for the page; if internal page walk down page */ leafbad = (xtree_page.header.flag & BT_LEAF) ? flag : 0; lastindex = xtree_page.header.nextindex; for( index = XTENTRYSTART; index < lastindex; index++ ) { /* * This is actual data of the inode, mark these blocks */ first_block = addressXAD( &(xtree_page.xad[index]) ); cur_length = lengthXAD( &(xtree_page.xad[index]) ); *total_nblocks += cur_length; last_block = first_block + cur_length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, leafbad ); } if( xtree_page.header.flag & BT_INTERNAL ) { /* * This is an internal page of the b-tree. Walk the page. */ walk_internal_page(device, first_block, cur_length, total_nblocks, flag); } } }
void walk_dir( int device, dtroot_t *root_header, int64 *total_nblocks) { int32 index, lastindex; uint64 first_block, cur_block, last_block; idtentry_t *cur_entry; uint32 length; if( root_header->header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Have root of directory inode btree. * Walk tree marking all blocks allocated. */ lastindex = root_header->header.nextindex; for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ cur_entry = (idtentry_t *)&(root_header->slot[root_header->header.stbl[index]]); first_block = addressPXD( &(cur_entry->xd) ); length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += length; last_block = first_block + length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, length, total_nblocks); } }
void walk_inode_tree(int device, xtpage_t *inode_root, int64 *total_nblocks, int32 flag) { int32 index, lastindex; uint64 first_block, cur_block, last_block; uint32 length; int32 leafbad; /* * Have root of inode btree. Walk tree marking all blocks allocated. */ leafbad = (inode_root->header.flag & BT_LEAF) ? flag : 0; lastindex = inode_root->header.nextindex; for( index = XTENTRYSTART; index < lastindex; index++ ) { /* * This is actual data of the inode, mark these blocks */ first_block = addressXAD( &(inode_root->xad[index]) ); length = lengthXAD( &(inode_root->xad[index]) ); *total_nblocks += length; last_block = first_block + length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, leafbad ); } if( inode_root->header.flag & BT_INTERNAL ) { /* * This is an internal page of the b-tree. Walk the page. */ walk_internal_page(device, first_block, length, total_nblocks, flag); } } }
void operate(int c, int cnt) { register int i; void (*moveop)(), (*deleteop)(); void (*opf)(); bool subop = 0; char *oglobp, *ocurs; register line *addr; static char lastFKND, lastFCHR; char d; moveop = vmove, deleteop = vdelete; wcursor = cursor; wdot = NOLINE; notecnt = 0; dir = 1; switch (c) { /* * d delete operator. */ case 'd': moveop = vdelete; deleteop = beep; break; /* * s substitute characters, like c\040, i.e. change space. */ case 's': ungetkey(' '); subop++; /* fall into ... */ /* * c Change operator. */ case 'c': if ((c == 'c' && workcmd[0] == 'C') || workcmd[0] == 'S') subop++; moveop = vchange; deleteop = beep; break; /* * ! Filter through a UNIX command. */ case '!': moveop = vfilter; deleteop = beep; break; /* * y Yank operator. Place specified text so that it * can be put back with p/P. Also yanks to named buffers. */ case 'y': moveop = vyankit; deleteop = beep; break; /* * = Reformat operator (for LISP). */ #ifdef LISP case '=': forbid(!value(LISP)); /* fall into ... */ #endif /* * > Right shift operator. * < Left shift operator. */ case '<': case '>': moveop = vshftop; deleteop = beep; break; /* * r Replace character under cursor with single following * character. */ case 'r': vrep(cnt); return; default: goto nocount; } /* * Had an operator, so accept another count. * Multiply counts together. */ if (isdigit(peekkey()) && peekkey() != '0') { cnt *= vgetcnt(); Xcnt = cnt; forbid (cnt <= 0); } /* * Get next character, mapping it and saving as * part of command for repeat. */ c = map(getesc()); if (c == 0) return; if (!subop) *lastcp++ = c; nocount: opf = moveop; switch (c) { /* * b Back up a word. * B Back up a word, liberal definition. */ case 'b': case 'B': dir = -1; /* fall into ... */ /* * w Forward a word. * W Forward a word, liberal definition. */ case 'W': case 'w': wdkind = c & ' '; if (edge()) { forbid (opf == vmove); wcursor = dir == -1 ? linebuf : strend(linebuf); } else while (cnt > 0 && !edge()) word(opf, cnt), cnt--; vmoving = 0; break; /* * E to end of following blank/nonblank word */ case 'E': wdkind = 0; goto ein; /* * e To end of following word. */ case 'e': wdkind = 1; ein: if (edge()) { forbid(opf == vmove); wcursor = dir == -1 ? linebuf : strend(linebuf); } else { while (cnt > 1 && !edge()) { word(opf, cnt); cnt--; } eend(opf, cnt); } vmoving = 0; break; /* * ( Back an s-expression. */ case '(': dir = -1; /* fall into... */ /* * ) Forward an s-expression. */ case ')': forbid(lfind(0, cnt, opf, (line *) 0) < 0); if (wdot) markpr(wdot); break; /* * { Back an s-expression, but don't stop on atoms. * In text mode, a paragraph. For C, a balanced set * of {}'s. */ case '{': dir = -1; /* fall into... */ /* * } Forward an s-expression, but don't stop on atoms. * In text mode, back paragraph. For C, back a balanced * set of {}'s. */ case '}': forbid(lfind(1, cnt, opf, (line *) 0) < 0); if (wdot) markpr(wdot); break; /* * % To matching () or {}. If not at ( or { scan for * first such after cursor on this line. */ case '%': vsave(); i = lmatchp((line *) 0); getDOT(); forbid(!i); if (opf != vmove) if (dir > 0) wcursor++; else cursor++; else if (wdot) markpr(wdot); break; /* * [ Back to beginning of defun, i.e. an ( in column 1. * For text, back to a section macro. * For C, back to a { in column 1 (~~ beg of function.) */ case '[': dir = -1; /* fall into ... */ /* * ] Forward to next defun, i.e. a ( in column 1. * For text, forward section. * For C, forward to a } in column 1 (if delete or such) * or if a move to a { in column 1. */ case ']': if (!vglobp) forbid(getkey() != c); if (Xhadcnt) vsetsiz(Xcnt); vsave(); i = lbrack(c, opf); getDOT(); forbid(!i); if (wdot) markpr(wdot); if (ex_ospeed > B300) hold |= HOLDWIG; break; /* * , Invert last find with f F t or T, like inverse * of ;. */ case ',': forbid (lastFKND == 0); c = isupper((int)lastFKND) ? tolower((int)lastFKND) : toupper((int)lastFKND); ungetkey(lastFCHR); if (vglobp == 0) vglobp = ""; subop++; goto nocount; /* * 0 To beginning of real line. */ case '0': wcursor = linebuf; vmoving = 0; break; /* * ; Repeat last find with f F t or T. */ case ';': forbid (lastFKND == 0); c = lastFKND; ungetkey(lastFCHR); subop++; goto nocount; /* * F Find single character before cursor in current line. * T Like F, but stops before character. */ case 'F': /* inverted find */ case 'T': dir = -1; /* fall into ... */ /* * f Find single character following cursor in current line. * t Like f, but stope before character. */ case 'f': /* find */ case 't': i = getesc(); if (i == 0) return; if (!subop) *lastcp++ = i; if (vglobp == 0) lastFKND = c, lastFCHR = i; for (; cnt > 0; cnt--) forbid (find(i) == 0); switch (c) { case 'T': wcursor++; break; case 't': wcursor--; case 'f': fixup: if (moveop != vmove) wcursor++; break; } vmoving = 0; break; /* * | Find specified print column in current line. */ case '|': if (Pline == numbline) cnt += 8; vmovcol = cnt; vmoving = 1; wcursor = vfindcol(cnt); break; /* * ^ To beginning of non-white space on line. */ case '^': wcursor = vskipwh(linebuf); vmoving = 0; break; /* * $ To end of line. */ case '$': if (cnt > 1) { if (opf == vmove) { wcursor = 0; vmoving = 1; vmovcol = 20000; cnt--; } else wcursor = linebuf; wdot = dot + cnt; break; } if (linebuf[0]) { wcursor = strend(linebuf) - 1; goto fixup; } wcursor = linebuf; vmoving = 0; break; /* * h Back a character. * ^H Back a character. */ case 'h': case CTRL('h'): dir = -1; /* fall into ... */ /* * space Forward a character. */ case ' ': forbid (margin() || (opf == vmove && edge())); while (cnt > 0 && !margin()) wcursor += dir, cnt--; if ((margin() && opf == vmove) || wcursor < linebuf) wcursor -= dir; vmoving = 0; break; /* * D Delete to end of line, short for d$. */ case 'D': cnt = INF; goto deleteit; /* * X Delete character before cursor. */ case 'X': dir = -1; /* fall into ... */ deleteit: /* * x Delete character at cursor, leaving cursor where it is. */ case 'x': if (margin()) goto errlab; while (cnt > 0 && !margin()) wcursor += dir, cnt--; opf = deleteop; vmoving = 0; break; default: /* * Stuttered operators are equivalent to the operator on * a line, thus turn dd into d_. */ if (opf == vmove || c != workcmd[0]) { errlab: beep(); return; } /* fall into ... */ /* * _ Target for a line or group of lines. * Stuttering is more convenient; this is mostly * for aesthetics. */ case '_': wdot = dot + cnt - 1; vmoving = 0; wcursor = 0; break; /* * H To first, home line on screen. * Count is for count'th line rather than first. */ case 'H': wdot = (dot - vcline) + cnt - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * - Backwards lines, to first non-white character. */ case '-': wdot = dot - cnt; vmoving = 0; wcursor = 0; break; /* * ^P To previous line same column. Ridiculous on the * console of the VAX since it puts console in LSI mode. */ case CTRL('p'): wdot = dot - cnt; if (vmoving == 0) vmoving = 1, vmovcol = column(cursor); wcursor = 0; break; /* * L To last line on screen, or count'th line from the * bottom. */ case 'L': wdot = dot + vcnt - vcline - cnt; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * M To the middle of the screen. */ case 'M': wdot = dot + ((vcnt + 1) / 2) - vcline - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * + Forward line, to first non-white. * * CR Convenient synonym for +. */ case '+': case CR: wdot = dot + cnt; vmoving = 0; wcursor = 0; break; /* * ^N To next line, same column if possible. * * LF Linefeed is a convenient synonym for ^N. */ case CTRL('n'): case NL: wdot = dot + cnt; if (vmoving == 0) vmoving = 1, vmovcol = column(cursor); wcursor = 0; break; /* * n Search to next match of current pattern. */ case 'n': vglobp = vscandir; c = *vglobp++; goto nocount; /* * N Like n but in reverse direction. */ case 'N': vglobp = vscandir[0] == '/' ? "?" : "/"; c = *vglobp++; goto nocount; /* * ' Return to line specified by following mark, * first white position on line. * * ` Return to marked line at remembered column. */ case '\'': case '`': d = c; c = getesc(); if (c == 0) return; c = markreg(c); forbid (c == 0); wdot = getmark(c); forbid (wdot == NOLINE); if (Xhadcnt) vsetsiz(Xcnt); if (opf == vmove) markit(wdot); vmoving = 0; wcursor = d == '`' ? ncols[c - 'a'] : 0; if (wcursor) { vsave(); ex_getline(*wdot); if (wcursor > strend(linebuf)) wcursor = 0; getDOT(); } if (ex_ospeed > B300) hold |= HOLDWIG; break; /* * G Goto count'th line, or last line if no count * given. */ case 'G': if (!Xhadcnt) cnt = lineDOL(); wdot = zero + cnt; forbid (wdot < one || wdot > dol); if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * / Scan forward for following re. * ? Scan backward for following re. */ case '/': case '?': if (Xhadcnt) vsetsiz(Xcnt); vsave(); ocurs = cursor; wcursor = 0; if (readecho(c)) return; if (!vglobp) vscandir[0] = genbuf[0]; oglobp = globp; CP(vutmp, genbuf); globp = vutmp; d = peekc; ungetchar(0); fixech(); CATCH #ifdef V6 /* * Lose typeahead (ick). */ vcook(); #endif addr = address(); #ifdef V6 vraw(); #endif ONERR #ifdef V6 vraw(); #endif globp = oglobp; ungetchar(d); splitw = 0; vclean(); vjumpto(dot, ocurs, 0); return; ENDCATCH if (globp == 0) globp = ""; else if (peekc) --globp; ungetchar(d); c = 0; if (*globp == 'z') globp++, c = '\n'; if (any(*globp, "^+-.")) c = *globp++; i = 0; while (isdigit((int)*globp)) i = i * 10 + *globp++ - '0'; if (*globp) c = *globp++; globp = oglobp; splitw = 0; vmoving = 0; if (i != 0) vsetsiz(i); if (opf == vmove) { if (state == ONEOPEN || state == HARDOPEN) outline = destline = WBOT; markit(addr); if (loc1 > linebuf && *loc1 == 0) loc1--; if (c) vjumpto(addr, loc1, c); else { vmoving = 0; if (loc1) { vmoving++; vmovcol = column(loc1); } getDOT(); if (state == CRTOPEN && addr != dot) vup1(); vupdown(addr - dot, NOSTR); } return; } lastcp[-1] = 'n'; getDOT(); wdot = addr; break; } /* * Apply. */ if (vreg && wdot == 0) wdot = dot; (*opf)(c); wdot = NOLINE; }
/* * Do a z operation. * Code here is rather long, and very uninteresting. */ void vzop(int hadcnt, int cnt, register int c) { register line *addr; if (state != VISUAL) { /* * Z from open; always like a z=. * This code is a mess and should be cleaned up. */ vmoveitup(1, 1); vgoto(outline, 0); ostop(normf); setoutt(); addr2 = dot; vclear(); destline = WECHO; zop2(Xhadcnt ? Xcnt : value(WINDOW) - 1, '='); if (state == CRTOPEN) putnl(); putNFL(); termreset(); Outchar = vputchar; ignore(ostart()); vcnt = 0; outline = destline = 0; vjumpto(dot, cursor, 0); return; } if (hadcnt) { addr = zero + cnt; if (addr < one) addr = one; if (addr > dol) addr = dol; markit(addr); } else switch (c) { case '+': addr = dot + vcnt - vcline; break; case '^': addr = dot - vcline - 1; forbid (addr < one); c = '-'; break; default: addr = dot; break; } switch (c) { case '.': case '-': break; case '^': forbid (addr <= one); break; case '+': forbid (addr >= dol); /* fall into ... */ case CR: case NL: c = CR; break; default: beep(); return; } vmoving = 0; vjumpto(addr, NOSTR, c); }
int32 validfs( HFILE device ) { uint64 num_log_blocks; int32 rc; uint64 first_block, last_block; uint32 length, inode_address; uint64 index; struct dinode inode_buffer; int64 total_nblocks; /* * Initialize internal block map */ num_log_blocks = sb.s_size >> sb.s_l2bfactor; rc = calc_map_size( num_log_blocks, sb.s_bsize, sb.s_agsize ); if( rc != 0 ) { printf("Failure creating internal block map.\n"); } /* * Mark fixed items allocated; these are only the items which aren't mapped * by one of the inode tables. */ /* * Reserved blocks */ length = AGGR_RSVD_BYTES >> sb.s_l2bsize; first_block = 0; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Primary superblock */ length = SIZE_OF_SUPER >> sb.s_l2bsize; first_block = SUPER1_OFF >> sb.s_l2bsize; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Secondary superblock */ first_block = SUPER2_OFF >> sb.s_l2bsize; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Walk aggregate inode table; marking blocks seen */ rc = ujfs_rwinode( device, &inode_buffer, AGGREGATE_I, GET, sb.s_bsize, AGGREGATE_I ); if( rc != 0 ) return(rc); rc = walk_ait( device, &inode_buffer, TRUE ); if( rc != 0 ) { printf( "Failed walking aggregate inode table, or difference in inode maps.\n"); } /* * Walk secondary aggregate inode table; marking blocks seen */ inode_address = (AGGREGATE_I * sizeof(struct dinode)) + ( addressPXD(&(sb.s_ait2)) << sb.s_l2bsize ); rc = ujfs_rw_diskblocks( device, inode_address, sizeof(struct dinode), &inode_buffer, GET ); if( rc != 0 ) return(rc); rc = walk_ait( device, &inode_buffer, FALSE ); if( rc != 0 ) { printf( "Failed walking secondary inode table, or difference in inode maps.\n"); } /* * Since we don't walk the inodes of the secondary inode table we need to * be sure and mark the blocks for the map's addressing structure */ total_nblocks = 0; walk_inode_tree(device, (xtpage_t *)&inode_buffer.di_btroot, &total_nblocks, 0); if( inode_buffer.di_nblocks != total_nblocks ) { error++; printf( "Secondary AIT Inode %d (fileset: %d) nblocks bad, disk: %lld, actual: %lld\n", inode_buffer.di_number, inode_buffer.di_fileset, inode_buffer.di_nblocks, total_nblocks); } /* * Now the bitmaps are marked, fill in the rest of the maps and compare * with the maps on disk */ rc = compare_maps( device, num_log_blocks, sb.s_bsize ); return(rc); }
/* * Read the specified extent as an extent of IAG's * If its offset is 0 skip the first page since this is a control page. * For all other IAGs need to mark blocks: * - mark the blocks for any allocated extents for the IAG * - read the extent and mark blocks for any allocated inodes * Note: the blocks owned by the table itself will be marked when the inode for * the table is seen. */ void walk_iag_extent( int device, xad_t *extent, boolean_t is_primary, dinomap_t *control_page, dinomap_t *disk_cp, struct list_item **top_iagfree, struct list_item **top_inofree, struct list_item **top_extfree, int32 inostamp ) { uint64 offset, address, count, end; uint32 length, page_length; iag_t iag_buffer; int32 index, rc, extdx; pxd_t *inoext_ptr; uint32 map, found_map; uint32 agno; ino_t start_inum; uint32 mymap[EXTSPERIAG]; int16 seen_extent = 0, free_inodes = 0; offset = offsetXAD( extent ); address = addressXAD( extent ); length = lengthXAD( extent ); page_length = PSIZE >> sb.s_l2bsize; if( offset == 0 ) { /* * Read in the disk control page now. We will compare it after all the * other pages of the map have been processed. */ rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize, sizeof(dinomap_t), disk_cp, GET ); if( rc != 0 ) exit(rc); address += page_length; length -= page_length; } while( length > 0 ) { /* * Clear map to use for tracking inodes seen */ memset( mymap, 0, EXTSPERIAG * sizeof(uint32)); /* * Read next IAG */ rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize, PSIZE, &iag_buffer, GET ); if( rc != 0 ) exit(rc); length -= page_length; address += page_length; control_page->in_nextiag = iag_buffer.iagnum + 1; if( iag_buffer.iagfree != -1 ) { /* * We have an item on the iagfree list following this one. */ rc = search_and_add(top_iagfree, iag_buffer.iagfree, DISK_LIST); if( rc != 0 ) { printf("Bad iagfree item on-disk: %d\n", iag_buffer.iagfree); } } agno = iag_buffer.agstart / sb.s_agsize; if( iag_buffer.extfreefwd != -1 ) { /* * We have an item on the extfree list following this one. */ rc = search_and_add(&(top_extfree[agno]), iag_buffer.extfreefwd, DISK_LIST); if( rc != 0 ) { printf("Bad extfree[%d] item on-disk: %d\n", agno, iag_buffer.extfreefwd); } } if( iag_buffer.inofreefwd != -1 ) { /* * We have an item on the inofree list following this one. */ rc = search_and_add(&(top_inofree[agno]), iag_buffer.inofreefwd, DISK_LIST); if( rc != 0 ) { printf("Bad inofree[%d] item on-disk: %d\n", agno, iag_buffer.inofreefwd); } } /* * Mark blocks for any allocated inode extents */ for( index = 0; index < SMAPSZ; index++ ) { map = iag_buffer.extsmap[index]; inoext_ptr = iag_buffer.inoext + (index * EXTSPERSUM); for( extdx = 0; extdx < EXTSPERSUM, map != 0; extdx++, map <<= 1) { if( (map & HIGHORDER) != 0 ) { seen_extent++; /* * Count inodes for allocated inode extents */ control_page->in_numinos += NUM_INODE_PER_EXTENT; control_page->in_agctl[agno].numinos += NUM_INODE_PER_EXTENT; address = count = addressPXD(inoext_ptr + extdx); end = count + inoext_ptr[extdx].len; for( ; count < end; count++) { markit( count, 0 ); } if( is_primary == TRUE ) { /* * Now need to read inodes and mark blocks for them * Only do this for the primary inode table */ start_inum = (iag_buffer.iagnum << L2INOSPERIAG) + (index << (L2EXTSPERSUM + L2INOSPEREXT)) + (extdx << L2INOSPEREXT); walk_inoext( device, address, inoext_ptr[extdx].len, iag_buffer.wmap[(index * EXTSPERSUM) + extdx], control_page, agno, start_inum, &found_map, inostamp ); mymap[(index * EXTSPERSUM) + extdx] = found_map; if( ~found_map != 0 ) free_inodes = 1; } } } } if( seen_extent == 0 ) { /* * No extents for this IAG, add it to iagfree list */ rc = search_and_add(top_iagfree, iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad iagfree item found: %d\n", iag_buffer.iagnum); } } else if( seen_extent != EXTSPERIAG ) { /* * Have free extents in this IAG, add to AG free extent list */ rc = search_and_add(&(top_extfree[agno]), iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad extfree[%d] item found: %d\n", agno, iag_buffer.iagnum); } } if( free_inodes != 0 ) { /* * We have some free inodes in the extent */ rc = search_and_add(&(top_inofree[agno]), iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad inofree[%d] item found: %d\n", agno, iag_buffer.iagnum); } } if( is_primary ) { /* * Compare map found by walking extents to the on-disk version */ rc = memcmp( mymap, iag_buffer.wmap, EXTSPERIAG * sizeof(uint32)); if( rc != 0 ) { error++; printf("Miscompare of inode wmap of IAG %d.\n", iag_buffer.iagnum); print_uint_array ("Found map:", mymap, EXTSPERIAG); print_uint_array ("Disk wmap:", iag_buffer.wmap, EXTSPERIAG); } rc = memcmp( mymap, iag_buffer.pmap, EXTSPERIAG * sizeof(uint32)); if( rc != 0 ) { error++; printf("Miscompare of inode pmap of IAG %d.\n", iag_buffer.iagnum); print_uint_array ("Found map:", mymap, EXTSPERIAG); print_uint_array ("Disk pmap:", iag_buffer.pmap, EXTSPERIAG); } } } }
void walk_inoext( int device, uint64 address, uint32 length, uint32 wmap, dinomap_t *control_page, uint32 agno, ino_t start_inum, uint32 *found_map, int32 inostamp ) { dinode_t *next_inode; uint32 left_to_read = length << sb.s_l2bsize; uint64 cur_address = address << sb.s_l2bsize; int32 index, rc; uint32 map = wmap; char page_buffer[PSIZE]; ino_t cur_inum = start_inum; uint32 mask = HIGHORDER; uint64 first_block, cur_block, last_block; uint32 num_blocks; int64 total_nblocks; *found_map = 0; while( (left_to_read > 0) ) { /* * Read next page of inodes for this extent */ rc = ujfs_rw_diskblocks( device, cur_address, PSIZE, page_buffer, GET ); cur_address += PSIZE; left_to_read -= PSIZE; next_inode = (dinode_t *)page_buffer; for( index = 0; index < INOSPERPAGE; index++, next_inode++, cur_inum++, map <<= 1, mask >>= 1 ) { /* * Initialize count for this inode's number of blocks */ total_nblocks = 0; /* * If this inode is allocated, mark blocks for its b-tree */ if( (map & HIGHORDER) != 0 ) { if( next_inode->di_nlink <= 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); } else { *found_map |= mask; } /* * Account for any blocks used by EA for this inode */ if( next_inode->di_ea.flag & DXD_EXTENT ) { first_block = addressDXD(&(next_inode->di_ea)); num_blocks = lengthDXD(&(next_inode->di_ea)); total_nblocks += num_blocks; last_block = first_block + num_blocks; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } } if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == FILESYSTEM_I) ) { /* * Need to account for inode map's blocks */ walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); /* * Need to walk this tree of inodes */ rc = walk_ait( device, next_inode, TRUE ); if( rc != 0 ) { error++; printf("Problem with Fileset Inode Allocation Map.\n"); } } else if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == BADBLOCK_I) ) { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, BADBLOCK); } else if( next_inode->di_mode & IFDIR ) { /* * Need to walk the extents as directory extents */ walk_dir( device, (dtroot_t *)&(next_inode->di_btroot), &total_nblocks); } else { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); } /* * Now total_nblocks contains the total number of blocks * actually allocated for this inode. Compare this to the * on-disk information. */ if( next_inode->di_nblocks != total_nblocks ) { error++; printf( "Inode %d (fileset: %d) nblocks bad, disk: %lld, actual: %lld\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nblocks, total_nblocks); } } else { if( next_inode->di_number == cur_inum && next_inode->di_inostamp == inostamp && addressPXD(&(next_inode->di_ixpxd)) == address && lengthPXD(&(next_inode->di_ixpxd)) == length && next_inode->di_nlink > 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); *found_map |= mask; } control_page->in_numfree++; control_page->in_agctl[agno].numfree++; } } } }