/* block moving */ static unsigned long move_generic_block(unsigned long block, unsigned long bnd, int h) { struct buffer_head * bh, * bh2; /* primitive fsck */ if (block > rs_block_count(rs)) { fprintf(stderr, "resize_reiserfs: invalid block number (%lu) found.\n", block); quit_resizer(); } /* progress bar, 3D style :) */ if (opt_verbose) print_how_far(&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->s_dev, block, fs->s_blocksize); 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(); } /* blocknr changing */ bh2 = getblk(fs->s_dev, unused_block, fs->s_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 void go_through (reiserfs_filsys_t fs) { struct buffer_head * bh; int i; int what_node; unsigned long done = 0, total; if (fsck_mode (fs) == DO_TEST) { /* just to test pass0_correct_leaf */ bh = bread (fs->s_dev, stats(fs)->test, fs->s_blocksize); /* if (is_leaf_bad (bh)) { fsck_progress ("############### bad #################\n"); } */ pass0_correct_leaf (fs, bh); print_block (stdout, fs, bh, 3, -1, -1); if (is_leaf_bad (bh)) { fsck_progress ("############### still bad #################\n"); } brelse (bh); reiserfs_free (fs); exit(4); } total = reiserfs_bitmap_ones (fsck_disk_bitmap (fs)); fsck_progress ("\nPass 0 (%lu (of %lu) blocks will be read):\n", total, SB_BLOCK_COUNT (fs)); for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) { if (!is_to_be_read (fs, i)) continue; print_how_far (&done, total, 1, fsck_quiet (fs)); bh = bread (fs->s_dev, i, fs->s_blocksize); if (!bh) { /* we were reading one block at time, and failed, so mark block bad */ fsck_progress ("pass0: reading block %lu failed\n", i); continue; } if (not_data_block (fs, i)) reiserfs_panic ("not data block found"); stats (fs)->analyzed ++; what_node = who_is_this (bh->b_data, fs->s_blocksize); if ( what_node != THE_LEAF ) { brelse (bh); continue; } pass0_correct_leaf (fs, bh); brelse (bh); } #if 0 for (i = 0; i < SB_BLOCK_COUNT (fs); i += nr_to_read) { to_scan = how_many_to_scan (fs, i, nr_to_read); if (to_scan) { print_how_far (&done, total, to_scan, fsck_quiet (fs)); /* at least one of nr_to_read blocks is to be checked */ bbh = bread (fs->s_dev, i / nr_to_read, fs->s_blocksize * nr_to_read); if (bbh) { for (j = 0; j < nr_to_read; j ++) { if (!is_to_be_read (fs, i + j)) continue; if (not_data_block (fs, i + j)) reiserfs_panic ("not data block found"); stats (fs)->analyzed ++; data = bbh->b_data + j * fs->s_blocksize; what_node = who_is_this (data, fs->s_blocksize); if ( what_node != THE_LEAF ) { continue; } /* the node looks like a leaf, but it still can be not perfect */ bh = make_buffer (fs->s_dev, i + j, fs->s_blocksize, data); /*printf ("block %lu .. ", bh->b_blocknr);fflush(stdout);*/ pass0_correct_leaf (fs, bh); /*printf ("ok\n");fflush(stdout);*/ brelse (bh); } if (buffer_dirty (bbh)) bwrite (bbh); bforget (bbh); } else { done -= to_scan; /* bread failed */ if (nr_to_read != 1) { /* we tryied to read bunch of blocks. Try to read them by one */ nr_to_read = 1; i --; continue; } else { /* we were reading one block at time, and failed, so mark block bad */ fsck_progress ("pass0: block %lu is bad, marked used\n", i); } } } if (nr_to_read == 1 && ((i + 1) % NR_TO_READ) == 0) { /* we have read NR_TO_READ blocks one at time, switch back to reading NR_TO_READ blocks at time */ i -= (NR_TO_READ - 1); nr_to_read = NR_TO_READ; } } #endif /* just in case */ mark_objectid_really_used (proper_id_map (fs), REISERFS_ROOT_OBJECTID); fsck_progress ("\n"); if (fsck_save_leaf_bitmap (fs)) { reiserfs_bitmap_save (stats (fs)->new_bitmap_file_name, leaves_bitmap); } }
// // set up start journal block and journal size // make journal unreplayable by kernel replay routine // void reset_journal (struct super_block * s) { int i ; struct buffer_head *bh ; int done = 0; int len; int start; /* first block of journal */ s->u.reiserfs_sb.s_rs->s_journal_block = get_journal_start (s); start = s->u.reiserfs_sb.s_rs->s_journal_block; /* journal size */ s->u.reiserfs_sb.s_rs->s_orig_journal_size = get_journal_size (s); len = s->u.reiserfs_sb.s_rs->s_orig_journal_size + 1; printf ("Resetting journal - "); fflush (stdout); for (i = 0 ; i < len ; i++) { print_how_far (&done, len); bh = getblk (s->s_dev, start + i, s->s_blocksize) ; memset(bh->b_data, 0, s->s_blocksize) ; mark_buffer_dirty(bh,0) ; mark_buffer_uptodate(bh,0) ; bwrite (bh); brelse(bh) ; } printf ("\n"); fflush (stdout); #if 0 /* need better way to make journal unreplayable */ /* have journal_read to replay nothing: look for first non-desc block and set j_first_unflushed_offset to it */ { int offset; struct buffer_head * bh, *jh_bh; struct reiserfs_journal_header * j_head; struct reiserfs_journal_desc * desc; jh_bh = bread (s->s_dev, s->u.reiserfs_sb.s_rs->s_journal_block + s->u.reiserfs_sb.s_rs->s_orig_journal_size, s->s_blocksize); j_head = (struct reiserfs_journal_header *)(jh_bh->b_data); for (offset = 0; offset < s->u.reiserfs_sb.s_rs->s_orig_journal_size; offset ++) { bh = bread (s->s_dev, s->u.reiserfs_sb.s_rs->s_journal_block + offset, s->s_blocksize); desc = (struct reiserfs_journal_desc *)((bh)->b_data); if (memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8)) { /* not desc block found */ j_head->j_first_unflushed_offset = offset; brelse (bh); break; } brelse (bh); } mark_buffer_uptodate (jh_bh, 1); mark_buffer_dirty (jh_bh, 1); bwrite (jh_bh); brelse (jh_bh); } #endif }
void pack_partition (struct super_block * s) { int i, j, k; uint32_t blocknumber32; uint16_t reclen16, data16; __u32 done = 0; char * data; long long bytes_to_transfer = 0; struct buffer_head * bh; int total_block_number; total_block_number = get_total_block_number (); /* write filesystem's block size to stdout as 16 bit number */ reclen16 = htons (s->s_blocksize); if (opt_pack == 'p' || opt_pack_all == 'p') write (1, &reclen16, sizeof (uint16_t)); bytes_to_transfer = sizeof (uint16_t); /* go through blocks which are marked used in cautious bitmap */ for (i = 0; i < SB_BMAP_NR (s); i ++) { for (j = 0; j < s->s_blocksize; j ++) { /* make sure, that we are not out of the device */ if (i * s->s_blocksize * 8 + j * 8 == SB_BLOCK_COUNT (s)) goto out_of_bitmap; if (i * s->s_blocksize * 8 + j * 8 + 8 > SB_BLOCK_COUNT (s)) die ("build_the_tree: Out of bitmap"); if (opt_pack_all == 0) if (SB_AP_BITMAP (s)[i]->b_data[j] == 0) { /* skip busy block if 'a' not specified */ continue; } /* read 8 blocks at once */ bh = bread (s->s_dev, i * s->s_blocksize + j, s->s_blocksize * 8); for (k = 0; k < 8; k ++) { __u32 block; block = i * s->s_blocksize * 8 + j * 8 + k; if (opt_pack_all == 0 && (SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0) continue; #if 0 if ((SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0 || /* k-th block is free */ block < SB_BUFFER_WITH_SB (s)->b_blocknr) /* is in skipped for drive manager area */ continue; #endif print_how_far (&done, total_block_number); data = bh->b_data + k * s->s_blocksize; if (not_formatted_node (data, s->s_blocksize)) { /* ok, could not find formatted node here. But this can be commit block, or bitmap which has to be transferred */ if (!not_data_block (s, block)) { /* this is usual unformatted node. Transfer its number only to erase previously existed formatted nodes on the partition we will apply transferred metadata to */ /* size of following record in network byte order */ reclen16 = htons (2); /* the record record */ data16 = htons (MAX_HEIGHT + 1);/*?*/ data = (char *)&data16; } else { /* write super block and bitmap block must be transferred as are */ /* size of record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = data; } } else { /* any kind of formatted nodes gets here (super block, desc block of journal): FIXME: it would be useful to be able to find commit blocks */ zero_direct_items (data); /* FIXME: do other packing */ /* write size of following record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = data; #if 0 if (blkh->blk_level > DISK_LEAF_NODE_LEVEL) { /* block must look like internal node on the target partition. But (currently) fsck do not consider internal nodes, therefore we do not have to transfer contents of internal nodes */ /* size of following record in network byte order */ reclen16 = htons (2); /* the record itself */ data16 = htons (DISK_LEAF_NODE_LEVEL + 1); data = (char *)&data16; } else { /* leaf node found */ ih = (struct item_head *)(blkh + 1); /* fill direct items with 0s */ for (l = 0; l < blkh->blk_nr_item; l ++, ih ++) if (I_IS_DIRECT_ITEM (ih)) { direct_items ++; direct_item_total_length += ih->ih_item_len; memset ((char *)blkh + ih->ih_item_location, 0, ih->ih_item_len); } /* write size of following record */ reclen16 = htons (s->s_blocksize); /* the record itself */ data = (char *)blkh; } #endif } /*fprintf (stderr, "block %d, reclen %d\n", block, ntohs (reclen16));*/ /* write block number */ blocknumber32 = htonl (block); bytes_to_transfer += sizeof (uint32_t) + sizeof (uint16_t) + ntohs (reclen16); if (opt_pack == 'p' || opt_pack_all == 'p') { write (1, &blocknumber32, sizeof (uint32_t)); /* write record len */ write (1, &reclen16, sizeof (uint16_t)); /* write the record */ write (1, data, ntohs (reclen16)); } } bforget (bh); } } out_of_bitmap: fprintf (stderr, "done\n"); if (opt_pack == 'c' || opt_pack_all == 'c') fprintf (stderr, "Bytes to transfer %Ld, sequential 0s %d in %d sequeneces (%items (%d unreacable))\n", bytes_to_transfer, direct_item_total_length, direct_items, items, unreachable_items); else fprintf (stderr, "Bytes dumped %Ld, sequential 0s %d in %d sequeneces\n", bytes_to_transfer, direct_item_total_length, direct_items); }