Files
reiserfsprogs/resize_reiserfs/do_shrink.c
T
Jeff Mahoney 47cff72748 cleanup: run indent with the Linux Kernel style across all code
Over the years, the reiserfs kernel code has been gradually cleaned up
to be more readable. This patch does the same to the progs code.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
2013-08-26 17:14:42 -04:00

312 lines
7.8 KiB
C

/*
* Copyright 2000-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
#include "resize.h"
#include <time.h>
static unsigned long int_node_cnt = 0, int_moved_cnt = 0;
static unsigned long leaf_node_cnt = 0, leaf_moved_cnt = 0;
static unsigned long unfm_node_cnt = 0, unfm_moved_cnt = 0;
static unsigned long total_node_cnt = 0;
static unsigned long total_moved_cnt = 0;
static unsigned long unused_block;
static unsigned long blocks_used;
static int block_count_mismatch = 0;
static reiserfs_bitmap_t *bmp;
static struct reiserfs_super_block *ondisk_sb;
/* abnornal exit from block reallocation process */
static void quit_resizer(reiserfs_filsys_t *fs)
{
/* save changes to bitmap blocks */
reiserfs_close(fs);
/* leave fs in ERROR state */
reiserfs_exit(1, "fs shrinking was not completed successfully, "
"run reiserfsck.");
}
/* block moving */
static unsigned long move_generic_block(reiserfs_filsys_t *fs,
unsigned long block,
unsigned long bnd, int h)
{
struct buffer_head *bh, *bh2;
/* primitive fsck */
if (block > get_sb_block_count(ondisk_sb)) {
fprintf(stderr, "resize_reiserfs: invalid block number "
"(%lu) found.\n", block);
quit_resizer(fs);
}
/* progress bar, 3D style :) */
if (opt_verbose)
print_how_far(stderr, &total_node_cnt, blocks_used, 1, 0);
else
total_node_cnt++;
/* infinite loop check */
if (total_node_cnt > blocks_used && !block_count_mismatch) {
fputs("resize_reiserfs: warning: block count exeeded\n",
stderr);
block_count_mismatch = 1;
}
if (block < bnd) /* block will not be moved */
return 0;
/* move wrong block */
bh = bread(fs->fs_dev, block, fs->fs_blocksize);
if (!bh)
reiserfs_exit(1, "move_generic_block: bread failed.\n");
reiserfs_bitmap_find_zero_bit(bmp, &unused_block);
if (unused_block == 0 || unused_block >= bnd) {
fputs("resize_reiserfs: can\'t find free block\n", stderr);
quit_resizer(fs);
}
/* blocknr changing */
bh2 = getblk(fs->fs_dev, unused_block, fs->fs_blocksize);
memcpy(bh2->b_data, bh->b_data, bh2->b_size);
reiserfs_bitmap_clear_bit(bmp, block);
reiserfs_bitmap_set_bit(bmp, unused_block);
brelse(bh);
mark_buffer_uptodate(bh2, 1);
mark_buffer_dirty(bh2);
bwrite(bh2);
brelse(bh2);
total_moved_cnt++;
return unused_block;
}
static unsigned long move_unformatted_block(reiserfs_filsys_t *fs,
unsigned long block,
unsigned long bnd, int h)
{
unsigned long b;
unfm_node_cnt++;
b = move_generic_block(fs, block, bnd, h);
if (b)
unfm_moved_cnt++;
return b;
}
/* recursive function processing all tree nodes */
static unsigned long move_formatted_block(reiserfs_filsys_t *fs,
unsigned long block,
unsigned long bnd, int h)
{
struct buffer_head *bh;
struct item_head *ih;
unsigned long new_blocknr = 0;
int node_is_internal = 0;
unsigned int i, j;
bh = bread(fs->fs_dev, block, fs->fs_blocksize);
if (!bh)
reiserfs_exit(1, "move_formatted_block: bread failed");
if (is_leaf_node(bh)) {
leaf_node_cnt++;
for (i = 0; i < B_NR_ITEMS(bh); i++) {
ih = B_N_PITEM_HEAD(bh, i);
/* skip the bad blocks. */
if (get_key_objectid(&ih->ih_key) == BADBLOCK_OBJID &&
get_key_dirid(&ih->ih_key) == BADBLOCK_DIRID)
continue;
if (is_indirect_ih(ih)) {
__u32 *indirect;
indirect = (__u32 *) B_I_PITEM(bh, ih);
for (j = 0; j < I_UNFM_NUM(ih); j++) {
unsigned long unfm_block;
if (d32_get(indirect, j) == 0) /* hole */
continue;
unfm_block =
move_unformatted_block(fs,
d32_get
(indirect,
j), bnd,
h + 1);
if (unfm_block) {
d32_put(indirect, j,
unfm_block);
mark_buffer_dirty(bh);
}
}
}
}
} else if (is_internal_node(bh)) { /* internal node */
int_node_cnt++;
node_is_internal = 1;
for (i = 0; i <= B_NR_ITEMS(bh); i++) {
unsigned long moved_block;
moved_block =
move_formatted_block(fs,
get_dc_child_blocknr(B_N_CHILD
(bh, i)),
bnd, h + 1);
if (moved_block) {
set_dc_child_blocknr(B_N_CHILD(bh, i),
moved_block);
mark_buffer_dirty(bh);
}
}
} else {
DIE("block (%lu) has invalid format\n", block);
}
if (buffer_dirty(bh)) {
mark_buffer_uptodate(bh, 1);
bwrite(bh);
}
brelse(bh);
new_blocknr = move_generic_block(fs, block, bnd, h);
if (new_blocknr) {
if (node_is_internal)
int_moved_cnt++;
else
leaf_moved_cnt++;
}
return new_blocknr;
}
int shrink_fs(reiserfs_filsys_t *fs, long long int blocks)
{
unsigned long n_root_block;
unsigned int bmap_nr_new;
unsigned long bad_count;
ondisk_sb = fs->fs_ondisk_sb;
bmap_nr_new = (blocks - 1) / (8 * fs->fs_blocksize) + 1;
/* is shrinking possible ? */
if (get_sb_block_count(ondisk_sb) - blocks >
get_sb_free_blocks(ondisk_sb) + reiserfs_fs_bmap_nr(fs) -
bmap_nr_new) {
fprintf(stderr,
"resize_reiserfs: can\'t shrink fs; too many "
"blocks already allocated\n");
return -1;
}
/* warn about alpha version */
{
int c;
printf("You are running BETA version of reiserfs shrinker.\n"
"This version is only for testing or VERY CAREFUL use.\n"
"Backup of you data is recommended.\n\n"
"Do you want to continue? [y/N]:");
fflush(stdout);
c = getchar();
if (c != 'y' && c != 'Y')
exit(1);
}
reiserfs_reopen(fs, O_RDWR);
if (reiserfs_open_ondisk_bitmap(fs))
reiserfs_exit(1, "cannot open ondisk bitmap");
bmp = fs->fs_bitmap2;
ondisk_sb = fs->fs_ondisk_sb;
set_sb_fs_state(fs->fs_ondisk_sb, FS_ERROR);
mark_buffer_uptodate(fs->fs_super_bh, 1);
mark_buffer_dirty(fs->fs_super_bh);
bwrite(fs->fs_super_bh);
/* calculate number of data blocks */
blocks_used = get_sb_block_count(fs->fs_ondisk_sb)
- get_sb_free_blocks(fs->fs_ondisk_sb)
- reiserfs_fs_bmap_nr(fs)
- get_jp_journal_size(sb_jp(fs->fs_ondisk_sb))
- REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize - 2; /* superblock itself and 1 descriptor after the journal */
unused_block = 1;
if (opt_verbose) {
printf("Processing the tree: ");
fflush(stdout);
}
n_root_block = move_formatted_block(fs, get_sb_root_block(ondisk_sb),
blocks, 0);
if (n_root_block)
set_sb_root_block(ondisk_sb, n_root_block);
if (opt_verbose)
printf("\n\nnodes processed (moved):\n"
"int %lu (%lu),\n"
"leaves %lu (%lu),\n"
"unfm %lu (%lu),\n"
"total %lu (%lu).\n\n",
int_node_cnt, int_moved_cnt,
leaf_node_cnt, leaf_moved_cnt,
unfm_node_cnt, unfm_moved_cnt,
(unsigned long)total_node_cnt, total_moved_cnt);
if (block_count_mismatch) {
fprintf(stderr, "resize_reiserfs: data block count %lu"
" doesn\'t match data block count %lu from super block\n",
(unsigned long)total_node_cnt, blocks_used);
}
{
unsigned long l;
/* make sure that none of truncated block are in use */
printf("check for used blocks in truncated region\n");
for (l = blocks; l < fs->fs_bitmap2->bm_bit_size; l++) {
if ((l % (fs->fs_blocksize * 8)) == 0)
continue;
if (reiserfs_bitmap_test_bit(fs->fs_bitmap2, l))
printf("<%lu>", l);
}
printf("\n");
}
badblock_list(fs, mark_badblock, NULL);
if (fs->fs_badblocks_bm) {
bad_count = reiserfs_bitmap_ones(fs->fs_badblocks_bm);
reiserfs_shrink_bitmap(fs->fs_badblocks_bm, blocks);
add_badblock_list(fs, 1);
bad_count -= reiserfs_bitmap_ones(fs->fs_badblocks_bm);
} else
bad_count = 0;
reiserfs_shrink_bitmap(fs->fs_bitmap2, blocks);
set_sb_free_blocks(ondisk_sb, get_sb_free_blocks(ondisk_sb)
- (get_sb_block_count(ondisk_sb) - blocks)
+ (reiserfs_fs_bmap_nr(fs) - bmap_nr_new)
+ bad_count);
set_sb_block_count(ondisk_sb, blocks);
set_sb_bmap_nr(ondisk_sb, bmap_nr_new);
set_sb_bmap_nr(fs->fs_ondisk_sb,
reiserfs_bmap_over(bmap_nr_new) ? 0 : bmap_nr_new);
return 0;
}