示例#1
0
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);
    }
}
示例#2
0
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);
	}
    }
}
示例#3
0
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);
    }
}
示例#4
0
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);
	}
    }
}
示例#5
0
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;
}
示例#6
0
/*
 * 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);
}
示例#7
0
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);
}
示例#8
0
/*
 * 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);
	    }
	}
    }
}
示例#9
0
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++;
	    }
	}
    }
}