struct extent_info_t* read_stdin(uint64_t start_time, struct extent_info_t *extent_info) { char in_buf[8192]= {0}; char blk_dev_num[4096]= {0}; int cpu_id=0; uint64_t seq_num=0; double time_stamp=0; int proc_id=0; char action_id[8]= {0}; char rwbs[8]= {0}; uint64_t offset=0; char plus_sgn[8]= {0}; uint64_t len=0; char err_val[16]; // number of sectors in extent init_le_to_pe(); uint64_t sec_in_ext = get_pe_size(vg_name); if (sec_in_ext == 0) { fprintf(stderr, "No volume group named %s\n", vg_name); exit(1); } FILE *btrace; // offset in extents uint64_t extent_num=0; int r; uint64_t last_print = 0; char cmd[8192]= {0}; sprintf(cmd, "btrace -t -a complete /dev/%s/%s", vg_name, lv_name); // XXX UGLY!! btrace = popen(cmd, "r"); if(!btrace) { fprintf(stderr, "can't invoke btrace"); exit(1); } while (fgets(in_buf, 8191, btrace)) { r = sscanf(in_buf, "%4095s %100i %" SCNu64 " %64lf %64i %7s %7s %" SCNu64 " %4s " "%" SCNu64 " %15s", blk_dev_num, &cpu_id, &seq_num, &time_stamp, &proc_id, action_id, rwbs, &offset, plus_sgn, &len, err_val); // ignore all non Complete events if (strcmp(action_id,"C")) continue; // print current stats every 5 minutes if (last_print+60*5<time_stamp) { print_extents(extent_info); last_print = time_stamp; } // round up extent_num=(offset+(sec_in_ext-1))/sec_in_ext; if (extents<=extent_num) { extent_info = realloc(extent_info, sizeof(struct extent_info_t)*(extent_num+100)); if (!extent_info) { fprintf(stderr, "out of memory\n"); exit(1); } memset(&extent_info[extents], 0, (extent_num+100-extents)*sizeof(struct extent_info_t)); extents=extent_num+100; } if (rwbs[0] == 'R') add_io(&extent_info[(size_t)extent_num], start_time + time_stamp, READ); if (rwbs[0] == 'W') add_io(&extent_info[(size_t)extent_num], start_time + time_stamp, WRITE); } pclose(btrace); return extent_info; }
int main(int argc, char **argv) { struct program_params pp = { .lvm2_handle = NULL }; init_le_to_pe(&pp); if (argc != 4) { printf("Usage: %s VolumeGroupName LogicalVolumeName" " LogicalVolumeExtent\n", argv[0]); le_to_pe_exit(&pp); return 1; } for(int i=0; i < pv_segments_num; i++) if(!strcmp(pv_segments[i].lv_name, argv[1])) printf("%s %li-%li (%li-%li)\n", pv_segments[i].pv_name, pv_segments[i].pv_start, pv_segments[i].pv_start+pv_segments[i].pv_length, pv_segments[i].lv_start, pv_segments[i].lv_start+pv_segments[i].pv_length); if (argc <= 2) return 0; struct pv_info *pv_info; pv_info = LE_to_PE(argv[1], argv[2], atoi(argv[3])); if (pv_info) printf("LE no %i of %s-%s is at: %s:%li\n", atoi(argv[3]), argv[1], argv[2], pv_info->pv_name, pv_info->start_seg); else printf("no LE found\n"); printf("vg: %s, extent size: %lu bytes\n", argv[1], get_pe_size(argv[1])); long int free_extents = get_free_extent_number(argv[1], pv_info->pv_name); printf("vg: %s, pv: %s, free space: %lue (%luB)\n", argv[1], pv_info->pv_name, free_extents, free_extents * get_pe_size(argv[1])); long int used_extents = get_used_space_on_pv(argv[1], argv[2], pv_info->pv_name); printf("Space used by lv %s on pv %s: %lue (%luB)\n", argv[2], pv_info->pv_name, used_extents, used_extents * get_pe_size(argv[1])); struct le_info le_inf; le_inf = get_first_LE_info(argv[1], argv[2], pv_info->pv_name); printf("First LE on %s is %li at PE %li\n", le_inf.dev, le_inf.le, le_inf.pe); long int optimal_pe = le_inf.pe + atoi(argv[3]) - le_inf.le; printf("Optimal position for LE %i is at %s:%li\n", atoi(argv[3]), le_inf.dev, optimal_pe); printf("%s:%li is ", le_inf.dev, optimal_pe); if (optimal_pe == pv_info->start_seg) { printf("allocated correctly\n"); } else { struct le_info optimal; optimal = get_PE_allocation(argv[1], pv_info->pv_name, optimal_pe); if (optimal.dev == NULL) printf("after the end of the device\n"); else if (!strcmp(optimal.lv_name, "free")) printf("free\n"); else printf("allocated to %s, LE: %li\n", optimal.lv_name, optimal.le); } pv_info_free(pv_info); le_to_pe_exit(&pp); lvm2_exit(pp.lvm2_handle); return 0; }