static char * item_type (struct item_head * ih) { static char * types[] = { "SD", "DIR", "DRCT", "IND", "???" }; if (I_IS_STAT_DATA_ITEM(ih)) return types[0]; if (I_IS_DIRECTORY_ITEM(ih)) return types[1]; if (I_IS_DIRECT_ITEM(ih)) return types[2]; if (I_IS_INDIRECT_ITEM(ih)) return types[3]; return types[4]; }
/* fill direct items with 0s */ static void zero_direct_items (char * buf) { int i; struct item_head * ih; if (((struct block_head *)buf)->blk_level != DISK_LEAF_NODE_LEVEL) return; /* leaf node found */ ih = (struct item_head *)(buf + BLKH_SIZE); for (i = 0; i < ((struct block_head *)buf)->blk_nr_item; i ++, ih ++) { if (I_IS_DIRECT_ITEM (ih)) { /* FIXME: do not zero symlinks */ direct_items ++; direct_item_total_length += ih->ih_item_len; memset (buf + ih->ih_item_location, 0, ih->ih_item_len); } items ++; if (ih->u.ih_free_space == 0xffff) unreachable_items ++; } }
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); }