📄 e2fsck.c
字号:
* 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 + -