📄 do_shrink.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) + get_sb_bmap_nr(ondisk_sb) - 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) - get_sb_bmap_nr(fs->fs_ondisk_sb) - 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) + (get_sb_bmap_nr(ondisk_sb) - bmap_nr_new) + bad_count); set_sb_block_count (ondisk_sb, blocks); set_sb_bmap_nr (ondisk_sb, bmap_nr_new); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -