void read_bitmap(char* device, file_system_info fs_info, unsigned long* bitmap, int pui) { uint32_t offset, total, current; uint32_t used_block = 0, free_block = 0, err_block = 0; int status = 0; int start = 0; int bit_size = 1; fs_open(device); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, fs_info.totalblock, fs_info.totalblock, BITMAP, bit_size); offset = logical_volume_offset(fs); total = fs->fbb->bmh.total_items + offset; // containing the volume information and the LVM information for(current = 0; current < offset; current++){ pc_set_bit(current, bitmap); used_block++; update_pui(&prog, current, current, 0); } // the logical volume for(current = offset; current < total; current++){ status = vmfs_block_get_status(fs, VMFS_BLK_FB_BUILD(current-offset,0)); if (status == -1) { err_block++; pc_clear_bit(current, bitmap); } else if (status == 1){ used_block++; pc_set_bit(current, bitmap); } else if (status == 0){ free_block++; pc_clear_bit(current, bitmap); } log_mesg(2, 0, 0, fs_opt.debug, "%s: Block 0x%8.8x status: %i\n", __FILE__, current, status); update_pui(&prog, current, current, 0); } fs_close(); update_pui(&prog, 1, 1, 1); log_mesg(0, 0, 0, fs_opt.debug, "%s: Used:%"PRIu32", Free:%"PRIu32", Status err:%"PRIu32"\n", __FILE__, used_block, free_block, err_block); }
/// readbitmap - read bitmap extern void readbitmap(char* device, image_head image_hdr, unsigned long* bitmap, int pui) { uint32_t current = 0, used_block = 0, free_block = 0, err_block = 0, total = 0, alloc = 0; int status = 0; int start = 0; int bit_size = 1; fs_open(device); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, image_hdr.totalblock, image_hdr.totalblock, BITMAP, bit_size); total = fs->fbb->bmh.total_items; alloc = vmfs_bitmap_allocated_items(fs->fbb); for(current = 0; current < total; current++){ status = vmfs_block_get_status(fs, VMFS_BLK_FB_BUILD(current)); if (status == -1) { err_block++; pc_clear_bit(current, bitmap); } else if (status == 1){ used_block++; pc_set_bit(current, bitmap); } else if (status == 0){ free_block++; pc_clear_bit(current, bitmap); } log_mesg(2, 0, 0, fs_opt.debug, "%s: Block 0x%8.8x status: %i\n", __FILE__, current, status); update_pui(&prog, current, current, 0); } fs_close(); update_pui(&prog, 1, 1, 1); log_mesg(0, 0, 0, fs_opt.debug, "%s: Used:%lld, Free:%lld, Status err:%lld\n", __FILE__, used_block, free_block, err_block); }
static int cmd_remove(vmfs_fs_t *fs,int argc,char *argv[]) { /* Dangerous */ vmfs_lvm_t *lvm = (vmfs_lvm_t *)fs->dev; vmfs_volume_t *extent; DECL_ALIGNED_BUFFER(buf,512); vmfs_bitmap_entry_t entry; uint32_t i, blocks_per_segment, items_per_area, items_in_last_entry, old_area_count; fprintf(stderr, "Extents removal is experimental ! Use at your own risk !\n"); while (1) { char *answer = local_readline("Are you sure you want to go further? [y/N] "); char a = answer[0]; char null = answer[1]; free(answer); if ((a == 0) || ((tolower(a) == 'n') && (null == 0))) return(2); if ((tolower(a) == 'y') && (null == 0)) break; } if (lvm->lvm_info.num_extents == 1) { fprintf(stderr, "Can't remove an extent when there is only one\n"); return(1); } /* Get last extent */ extent = lvm->extents[lvm->loaded_extents - 1]; /* Check whether data blocks are used on the last extents */ blocks_per_segment = VMFS_LVM_SEGMENT_SIZE / vmfs_fs_get_blocksize(fs); for (i = extent->vol_info.first_segment * blocks_per_segment; i < extent->vol_info.last_segment * blocks_per_segment; i++) if (vmfs_block_get_status(fs, VMFS_BLK_FB_BUILD(i, 0))) { fprintf(stderr, "There is data on the last extent ; can't remove it\n"); return(1); } /* At filesystem level, only the FBB needs to be downsized */ fs->fbb->bmh.total_items -= extent->vol_info.num_segments * blocks_per_segment; items_per_area = fs->fbb->bmh.items_per_bitmap_entry * fs->fbb->bmh.bmp_entries_per_area; old_area_count = fs->fbb->bmh.area_count; fs->fbb->bmh.area_count = (fs->fbb->bmh.total_items + items_per_area - 1) / items_per_area; memset(buf, 0, buf_len); vmfs_bmh_write(&fs->fbb->bmh, buf); /* TODO: Error handling */ vmfs_file_pwrite(fs->fbb->f, buf, buf_len, 0); /* Adjust new last entry */ if ((items_in_last_entry = fs->fbb->bmh.total_items % fs->fbb->bmh.items_per_bitmap_entry)) { vmfs_bitmap_get_entry(fs->fbb, 0, fs->fbb->bmh.total_items, &entry); entry.free -= entry.total - items_in_last_entry; entry.total = items_in_last_entry; if (entry.ffree > entry.total) entry.ffree = 0; /* Adjust bitmap in last entry */ if (items_in_last_entry % 8) entry.bitmap[items_in_last_entry / 8] &= 0xff << (8 - (items_in_last_entry % 8)); memset(&entry.bitmap[(items_in_last_entry + 7) / 8], 0, (fs->fbb->bmh.items_per_bitmap_entry - items_in_last_entry - 7) / 8); vmfs_bme_update(fs, &entry); } /* Truncate the fbb file depending on the new area count */ if (old_area_count != fs->fbb->bmh.area_count) vmfs_file_truncate(fs->fbb->f, fs->fbb->bmh.hdr_size + fs->fbb->bmh.area_count * fs->fbb->bmh.area_size); /* Adjust entries after the new last one */ for (i = fs->fbb->bmh.total_items + (items_in_last_entry ? (fs->fbb->bmh.items_per_bitmap_entry - items_in_last_entry) : 0); i < fs->fbb->bmh.area_count * items_per_area; i += fs->fbb->bmh.items_per_bitmap_entry) { uint64_t pos; vmfs_bitmap_get_entry(fs->fbb, 0, i, &entry); pos = entry.mdh.pos; memset(&entry, 0, sizeof(entry)); vmfs_device_write(fs->dev, pos, (u_char *)&entry, sizeof(entry)); } /* At LVM level, all extents need to have the LVM information updated */ for (i = 0; i < lvm->loaded_extents - 1; i++) { lvm->extents[i]->vol_info.blocks -= extent->vol_info.num_segments + 1; lvm->extents[i]->vol_info.num_extents--; lvm->extents[i]->vol_info.lvm_size = (lvm->extents[i]->vol_info.blocks - lvm->extents[i]->vol_info.num_extents) * VMFS_LVM_SEGMENT_SIZE; /* Until there is an API for that, do it by hand */ m_pread(lvm->extents[i]->fd,buf,buf_len, lvm->extents[i]->vmfs_base + VMFS_LVMINFO_OFFSET); write_le64(buf, VMFS_LVMINFO_OFS_SIZE - VMFS_LVMINFO_OFFSET, lvm->extents[i]->vol_info.lvm_size); write_le64(buf, VMFS_LVMINFO_OFS_BLKS - VMFS_LVMINFO_OFFSET, lvm->extents[i]->vol_info.blocks); write_le32(buf, VMFS_LVMINFO_OFS_NUM_EXTENTS - VMFS_LVMINFO_OFFSET, lvm->extents[i]->vol_info.num_extents); m_pwrite(lvm->extents[i]->fd,buf,buf_len, lvm->extents[i]->vmfs_base + VMFS_LVMINFO_OFFSET); } return(0); }