⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e2fsck.c

📁 busybox最新版的源码:学习和应用的好东东,多的不说了,大家看后再说吧
💻 C
📖 第 1 页 / 共 5 页
字号:
 * follows.  We keep a sorted array of first EA blocks and its * reference counts.  Once the refcount has dropped to zero, it is * removed from the array to save memory space.  Once the EA block is * checked, its bit is set in the block_ea_map bitmap. */static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret){	ext2_refcount_t refcount;	errcode_t       retval;	size_t          bytes;	retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);	if (retval)		return retval;	memset(refcount, 0, sizeof(struct ea_refcount));	if (!size)		size = 500;	refcount->size = size;	bytes = (size_t) (size * sizeof(struct ea_refcount_el));#ifdef DEBUG	printf("Refcount allocated %d entries, %d bytes.\n",	       refcount->size, bytes);#endif	retval = ext2fs_get_mem(bytes, &refcount->list);	if (retval)		goto errout;	memset(refcount->list, 0, bytes);	refcount->count = 0;	refcount->cursor = 0;	*ret = refcount;	return 0;errout:	ea_refcount_free(refcount);	return retval;}/* * collapse_refcount() --- go through the refcount array, and get rid * of any count == zero entries */static void refcount_collapse(ext2_refcount_t refcount){	unsigned int    i, j;	struct ea_refcount_el   *list;	list = refcount->list;	for (i = 0, j = 0; i < refcount->count; i++) {		if (list[i].ea_count) {			if (i != j)				list[j] = list[i];			j++;		}	}#if defined(DEBUG) || defined(TEST_PROGRAM)	printf("Refcount_collapse: size was %d, now %d\n",	       refcount->count, j);#endif	refcount->count = j;}/* * insert_refcount_el() --- Insert a new entry into the sorted list at a *      specified position. */static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,						 blk_t blk, int pos){	struct ea_refcount_el   *el;	errcode_t               retval;	blk_t                   new_size = 0;	int                     num;	if (refcount->count >= refcount->size) {		new_size = refcount->size + 100;#ifdef DEBUG		printf("Reallocating refcount %d entries...\n", new_size);#endif		retval = ext2fs_resize_mem((size_t) refcount->size *					   sizeof(struct ea_refcount_el),					   (size_t) new_size *					   sizeof(struct ea_refcount_el),					   &refcount->list);		if (retval)			return 0;		refcount->size = new_size;	}	num = (int) refcount->count - pos;	if (num < 0)		return 0;       /* should never happen */	if (num) {		memmove(&refcount->list[pos+1], &refcount->list[pos],			sizeof(struct ea_refcount_el) * num);	}	refcount->count++;	el = &refcount->list[pos];	el->ea_count = 0;	el->ea_blk = blk;	return el;}/* * get_refcount_el() --- given an block number, try to find refcount *      information in the sorted list.  If the create flag is set, *      and we can't find an entry, create one in the sorted list. */static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,					      blk_t blk, int create){	float   range;	int     low, high, mid;	blk_t   lowval, highval;	if (!refcount || !refcount->list)		return 0;retry:	low = 0;	high = (int) refcount->count-1;	if (create && ((refcount->count == 0) ||		       (blk > refcount->list[high].ea_blk))) {		if (refcount->count >= refcount->size)			refcount_collapse(refcount);		return insert_refcount_el(refcount, blk,					  (unsigned) refcount->count);	}	if (refcount->count == 0)		return 0;	if (refcount->cursor >= refcount->count)		refcount->cursor = 0;	if (blk == refcount->list[refcount->cursor].ea_blk)		return &refcount->list[refcount->cursor++];#ifdef DEBUG	printf("Non-cursor get_refcount_el: %u\n", blk);#endif	while (low <= high) {		if (low == high)			mid = low;		else {			/* Interpolate for efficiency */			lowval = refcount->list[low].ea_blk;			highval = refcount->list[high].ea_blk;			if (blk < lowval)				range = 0;			else if (blk > highval)				range = 1;			else				range = ((float) (blk - lowval)) /					(highval - lowval);			mid = low + ((int) (range * (high-low)));		}		if (blk == refcount->list[mid].ea_blk) {			refcount->cursor = mid+1;			return &refcount->list[mid];		}		if (blk < refcount->list[mid].ea_blk)			high = mid-1;		else			low = mid+1;	}	/*	 * If we need to create a new entry, it should be right at	 * low (where high will be left at low-1).	 */	if (create) {		if (refcount->count >= refcount->size) {			refcount_collapse(refcount);			if (refcount->count < refcount->size)				goto retry;		}		return insert_refcount_el(refcount, blk, low);	}	return 0;}static errcode_tea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret){	struct ea_refcount_el   *el;	el = get_refcount_el(refcount, blk, 1);	if (!el)		return EXT2_ET_NO_MEMORY;	el->ea_count++;	if (ret)		*ret = el->ea_count;	return 0;}static errcode_tea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret){	struct ea_refcount_el   *el;	el = get_refcount_el(refcount, blk, 0);	if (!el || el->ea_count == 0)		return EXT2_ET_INVALID_ARGUMENT;	el->ea_count--;	if (ret)		*ret = el->ea_count;	return 0;}static errcode_tea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count){	struct ea_refcount_el   *el;	/*	 * Get the refcount element	 */	el = get_refcount_el(refcount, blk, count ? 1 : 0);	if (!el)		return count ? EXT2_ET_NO_MEMORY : 0;	el->ea_count = count;	return 0;}static inline void ea_refcount_intr_begin(ext2_refcount_t refcount){	refcount->cursor = 0;}static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret){	struct ea_refcount_el   *list;	while (1) {		if (refcount->cursor >= refcount->count)			return 0;		list = refcount->list;		if (list[refcount->cursor].ea_count) {			if (ret)				*ret = list[refcount->cursor].ea_count;			return list[refcount->cursor++].ea_blk;		}		refcount->cursor++;	}}/* * ehandler.c --- handle bad block errors which come up during the *      course of an e2fsck session. */static const char *operation;static errcode_te2fsck_handle_read_error(io_channel channel, unsigned long block, int count,			 void *data, size_t size FSCK_ATTR((unused)),			 int actual FSCK_ATTR((unused)), errcode_t error){	int     i;	char    *p;	ext2_filsys fs = (ext2_filsys) channel->app_data;	e2fsck_t ctx;	ctx = (e2fsck_t) fs->priv_data;	/*	 * If more than one block was read, try reading each block	 * separately.  We could use the actual bytes read to figure	 * out where to start, but we don't bother.	 */	if (count > 1) {		p = (char *) data;		for (i=0; i < count; i++, p += channel->block_size, block++) {			error = io_channel_read_blk(channel, block,						    1, p);			if (error)				return error;		}		return 0;	}	if (operation)		printf(_("Error reading block %lu (%s) while %s.  "), block,		       error_message(error), operation);	else		printf(_("Error reading block %lu (%s).  "), block,		       error_message(error));	preenhalt(ctx);	if (ask(ctx, _("Ignore error"), 1)) {		if (ask(ctx, _("Force rewrite"), 1))			io_channel_write_blk(channel, block, 1, data);		return 0;	}	return error;}static errcode_te2fsck_handle_write_error(io_channel channel, unsigned long block, int count,			const void *data, size_t size FSCK_ATTR((unused)),			int actual FSCK_ATTR((unused)), errcode_t error){	int             i;	const char      *p;	ext2_filsys fs = (ext2_filsys) channel->app_data;	e2fsck_t ctx;	ctx = (e2fsck_t) fs->priv_data;	/*	 * If more than one block was written, try writing each block	 * separately.  We could use the actual bytes read to figure	 * out where to start, but we don't bother.	 */	if (count > 1) {		p = (const char *) data;		for (i=0; i < count; i++, p += channel->block_size, block++) {			error = io_channel_write_blk(channel, block,						     1, p);			if (error)				return error;		}		return 0;	}	if (operation)		printf(_("Error writing block %lu (%s) while %s.  "), block,		       error_message(error), operation);	else		printf(_("Error writing block %lu (%s).  "), block,		       error_message(error));	preenhalt(ctx);	if (ask(ctx, _("Ignore error"), 1))		return 0;	return error;}static const char *ehandler_operation(const char *op){	const char *ret = operation;	operation = op;	return ret;}static void ehandler_init(io_channel channel){	channel->read_error = e2fsck_handle_read_error;	channel->write_error = e2fsck_handle_write_error;}/* * journal.c --- code for handling the "ext3" journal * * Copyright (C) 2000 Andreas Dilger * Copyright (C) 2000 Theodore Ts'o * * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie * Copyright (C) 1999 Red Hat Software * * This file may be redistributed under the terms of the * GNU General Public License version 2 or at your discretion * any later version. *//* * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths. * This creates a larger static binary, and a smaller binary using * shared libraries.  It's also probably slightly less CPU-efficient, * which is why it's not on by default.  But, it's a good way of * testing the functions in inode_io.c and fileio.c. */#undef USE_INODE_IO/* Kernel compatibility functions for handling the journal.  These allow us * to use the recovery.c file virtually unchanged from the kernel, so we * don't have to do much to keep kernel and user recovery in sync. */static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys){#ifdef USE_INODE_IO	*phys = block;	return 0;#else	struct inode    *inode = journal->j_inode;	errcode_t       retval;	blk_t           pblk;	if (!inode) {		*phys = block;		return 0;	}	retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,			    &inode->i_ext2, NULL, 0, block, &pblk);	*phys = pblk;	return retval;#endif}static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize){	struct buffer_head *bh;	bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");	if (!bh)		return NULL;	bh->b_ctx = kdev->k_ctx;	if (kdev->k_dev == K_DEV_FS)		bh->b_io = kdev->k_ctx->fs->io;	else		bh->b_io = kdev->k_ctx->journal_io;	bh->b_size = blocksize;	bh->b_blocknr = blocknr;	return bh;}static void sync_blockdev(kdev_t kdev){	io_channel      io;	if (kdev->k_dev == K_DEV_FS)		io = kdev->k_ctx->fs->io;	else		io = kdev->k_ctx->journal_io;	io_channel_flush(io);}static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[]){	int retval;	struct buffer_head *bh;	for (; nr > 0; --nr) {		bh = *bhp++;		if (rw == READ && !bh->b_uptodate) {			retval = io_channel_read_blk(bh->b_io,						     bh->b_blocknr,						     1, bh->b_data);			if (retval) {				bb_error_msg("while reading block %lu",					(unsigned long) bh->b_blocknr);				bh->b_err = retval;				continue;			}			bh->b_uptodate = 1;		} else if (rw == WRITE && bh->b_dirty) {			retval = io_channel_write_blk(bh->b_io,						      bh->b_blocknr,						      1, bh->b_data);			if (retval) {				bb_error_msg("while writing block %lu",					(unsigned long) bh->b_blocknr);				bh->b_err = retval;				continue;			}			bh->b_dirty = 0;			bh->b_uptodate = 1;		}	}}static void mark_buffer_dirty(struct buffer_head *bh){	bh->b_dirty = 1;}static inline void mark_buffer_clean(struct buffer_head * bh){	bh->b_dirty = 0;}static void brelse(struct buffer_head *bh){	if (bh->b_dirty)		ll_rw_block(WRITE, 1, &bh);	ext2fs_free_mem(&bh);}static int buffer_uptodate(struct buffer_head *bh){	return bh->b_uptodate;}static inline void mark_buffer_uptodate(struct buffer_head *bh, int val){	bh->b_uptodate = val;}static void wait_on_buffer(struct buffer_head *bh){	if (!bh->b_uptodate)		ll_rw_block(READ, 1, &bh);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -