Ejemplo n.º 1
0
// initialize or reload cache variables
void init_le_to_pe()
{
    void *handle;
    int r;

    if(pv_segments)
        le_to_pe_exit();
    
    vg_pe_sizes = NULL;
    vg_pe_sizes_len = 0;

    lvm2_log_fn(parse_pvs_segments);

    handle = lvm2_init();

    lvm2_log_level(handle, 1);
    r = lvm2_run(handle, "pvs --noheadings --segments -o+lv_name,"
        "seg_start_pe,segtype");

//    if (r)
//      fprintf(stderr, "command failed\n");

    sort_segments(pv_segments, pv_segments_num);
    
    lvm2_log_fn(parse_vgs_pe_size);

    r = lvm2_run(handle, "vgs -o vg_name,vg_extent_size --noheadings");

    lvm2_exit(handle);

    return;
}
Ejemplo n.º 2
0
/** destroy program_params */
void
free_program_params(struct program_params *pp)
{
    if(!pp)
        return;

    if(pp->conf_file_path)
        free(pp->conf_file_path);

    cfg_free(pp->cfg);

    if (pp->lvm2_handle)
        lvm2_exit(pp->lvm2_handle);

    le_to_pe_exit(pp);

    free(pp);
}
Ejemplo n.º 3
0
Archivo: lvmtscat.c Proyecto: nlm/lvmts
int
main(int argc, char **argv)
{
    int ret = 0;
    int n;
    double mean_lifetime = 3 * 24 * 60 * 60;

    if (parse_arguments(argc, argv))
        return 1;

    struct activity_stats *as = NULL;

    if (file == NULL) {
        fprintf(stderr, "No file name provided\n");
        usage();
        return 1;
    }

    if (!print_le && (!lv_name || !vg_name)) {
        fprintf(stderr, "You must ask for logical extents or provide volume"
                " group and logical volume name.\n");
        usage();
        return 1;
    }

    struct program_params pp = { .lvm2_handle = NULL };

    if (!print_le) {
        init_le_to_pe(&pp);
    }

    n = read_activity_stats(&as, file);
    assert(!n);

    struct block_scores *bs = NULL;

    if(get_max)
        get_best_blocks_with_max_score(as, &bs, blocks, read_mult,
                                       write_mult, mean_lifetime, max_score);
    else
        get_best_blocks(as, &bs, blocks, read_mult, write_mult, mean_lifetime);

    if (pvmove_output) {
        if (print_le) {
            printf("%llu", bs[0].offset);
            for (int i=1; i< blocks; i++) {
                printf(":%llu", bs[i].offset);
            }
            printf("\n");
        } else {
            struct pv_info *pvi;
            struct pv_info *pvn;
            pvi = LE_to_PE(vg_name, lv_name, bs[0].offset);
            printf("%s:%llu", pvi->pv_name, pvi->start_seg);
            for (int i=1; i<blocks; i++) {
                pvn = LE_to_PE(vg_name, lv_name, bs[i].offset);
                if (!pvn)
                    continue;
                if (!strcmp(pvi->pv_name, pvn->pv_name)) {
                    printf(":%llu", pvn->start_seg);
                    pv_info_free(pvn);
                    continue;
                } else {
                    printf("\n%s:%llu", pvn->pv_name, pvn->start_seg);
                    pv_info_free(pvi);
                    pvi = pvn;
                    continue;
                }
            }
            printf("\n");
            pv_info_free(pvi);
        }
    } else {
        if (!print_le) {
            fprintf(stderr, "Unsupported combination of parameters"
                    " (add --pvmove or --LE)\n");
        } else
            print_block_scores(bs, blocks);
    }

    free(bs);
    bs = NULL;

    //dump_activity_stats(as);

    destroy_activity_stats(as);
    as = NULL;

    if (!print_le) {
        le_to_pe_exit(&pp);
    }

    return ret;
}
Ejemplo n.º 4
0
Archivo: lvmtsd.c Proyecto: Auboo/lvmts
void print_extents(struct extent_info_t *extent_info)
{
    struct extent_score_t *extent_score;

    extent_score = convert_extent_info_to_extent_score(extent_info);

    qsort(extent_score, EXTENTS, sizeof(struct extent_score_t), extent_cmp);

    init_le_to_pe();

    time_t res;

    res = time(NULL);

    printf("\n\n");
    printf("%s", asctime(localtime(&res)));
    printf("%i most active physical extents: (from most to least)\n", ext_to_print);
    for(int i=EXTENTS-1, num=0; num<ext_to_print; i--) {

        struct pv_info *ret;

        if(!extent_score[i].read_score && !extent_score[i].write_score)
            break;

        ret = LE_to_PE(vg_name, lv_name, extent_score[i].offset);

        if(num%10==9)
            printf("%lu\n", ret->start_seg);
        else
            printf("%lu:", ret->start_seg);

        num++;
        free(ret->pv_name);
        free(ret);
    }
    printf("\n\n");

    qsort(extent_score, EXTENTS, sizeof(struct extent_score_t), extent_read_cmp);

    printf("%i most read extents (from most to least):\n", ext_to_print);
    for(int i=EXTENTS-1, num=0; num<ext_to_print; i--) {

        struct pv_info *ret;

        if(!extent_score[i].read_score)
            break;

        ret = LE_to_PE(vg_name, lv_name, extent_score[i].offset);

        if(num%10==9)
            printf("%lu\n", ret->start_seg);
        else
            printf("%lu:", ret->start_seg);

        num++;
        free(ret->pv_name);
        free(ret);
    }
    printf("\n\n");

    qsort(extent_score, EXTENTS, sizeof(struct extent_score_t), extent_write_cmp);
    printf("%i most write extents (from most to least):\n", ext_to_print);
    for(int i=EXTENTS-1, num=0; num<ext_to_print; i--) {

        struct pv_info *ret;

        if(!extent_score[i].write_score)
            break;

        ret = LE_to_PE(vg_name, lv_name, extent_score[i].offset);

        if(num%10==9)
            printf("%lu\n", ret->start_seg);
        else
            printf("%lu:", ret->start_seg);

        num++;
        free(ret->pv_name);
        free(ret);
    }

    free(extent_score);
    le_to_pe_exit();
}
Ejemplo n.º 5
0
int
main(int argc, char **argv)
{
    if (argc != 4) {
        fprintf(stderr, "Tool to defragment LogicalVolume on selected PhysicalVolume\n");
        fprintf(stderr, "Usage: lvmdefrag VolumeGroup LogicalVolume PhysicalVolume\n");
        return EXIT_FAILURE;
    }

    char *vg_name = argv[1];
    char *lv_name = argv[2];
    char *pv_name = argv[3];

    struct program_params pp = { .lvm2_handle = NULL };
    init_le_to_pe(&pp);

    struct le_info first_le;

    first_le = get_first_LE_info(vg_name, lv_name, pv_name);

    for(size_t i=0; i < pv_segments_num; i ++)
        if( !strcmp(pv_segments[i].lv_name, lv_name) &&
            !strcmp(pv_segments[i].vg_name, vg_name) &&
            !strcmp(pv_segments[i].pv_name, pv_name)) {

            long int optimal_pos;
            optimal_pos = first_le.pe + pv_segments[i].lv_start - first_le.le;

            if (pv_segments[i].pv_start == optimal_pos)
                  continue;

            struct le_info optimal;
            long int move_extent = 0;

            for (long int j=optimal_pos;
                 j < optimal_pos + pv_segments[i].pv_length;
                 j++) {

                optimal = get_PE_allocation(vg_name, pv_name, j);

                if (optimal.dev == NULL) {
                    printf("# Optimal position for LE %li-%li on %s is after end of "
                        "the device\n",
                        pv_segments[i].lv_start,
                        pv_segments[i].lv_start + pv_segments[i].pv_length,
                        pv_name);
                    break;
                } else if (strcmp(optimal.lv_name, "free")) {
                    printf("# Optimal position for LE %li-%li is used by %s LE %li\n",
                        pv_segments[i].lv_start,
                        pv_segments[i].lv_start + pv_segments[i].pv_length,
                        optimal.lv_name, optimal.le);
                    break;
                }

                move_extent++;
            }

            if (move_extent) {
                  printf("pvmove -i1 --alloc anywhere %s:%li-%li %s:%li-%li # LE %li (size: %li)\n",
                      pv_name,
                      pv_segments[i].pv_start,
                      pv_segments[i].pv_start + move_extent - 1,
                      pv_name,
                      optimal_pos,
                      optimal_pos + move_extent - 1,
                      pv_segments[i].lv_start,
                      move_extent);
            }
        }

    le_to_pe_exit(&pp);
    lvm2_exit(pp.lvm2_handle);

    return EXIT_SUCCESS;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
// convert logical extent from logical volume specified by lv_name,
// vg_name and logical extent number (le_num) to physical extent
// on specific device
struct pv_info *LE_to_PE(const char *vg_name, const char *lv_name, uint64_t le_num)
{
    struct pv_allocations pv_alloc = { .lv_name = (char *)lv_name,
                                       .vg_name = (char *)vg_name,
                                       .lv_start = le_num };

    struct pv_allocations *needle;

    needle = bsearch(&pv_alloc, pv_segments, pv_segments_num,
                sizeof(struct pv_allocations), _find_segment);

    if (!needle)
        return NULL;

    struct pv_info *pv_info;

    pv_info = malloc(sizeof(struct pv_info));
    if (!pv_info) {
        fprintf(stderr, "Out of memory\n");
        exit(1);
    }

    pv_info->pv_name = strdup(needle->pv_name);
    if (!pv_info->pv_name) {
        fprintf(stderr, "Out of memory\n");
        exit(1);
    }

    pv_info->start_seg = needle->pv_start +
      (le_num - needle->lv_start);

    return pv_info;
}

struct vg_pe_sizes {
    char *vg_name;
    uint64_t pe_size;
};

struct vg_pe_sizes *vg_pe_sizes;
size_t vg_pe_sizes_len;

// parse output from lvm2cmd about extent sizes
void parse_vgs_pe_size(int level, const char *file, int line,
                 int dm_errno, const char *format)
{
    // disregard debug output
    if (level != 4)
      return;

    char vg_name[4096], pe_size[4096];
    uint64_t pe_size_bytes=0;
    int r;

    r = sscanf(format, " %4095s %4095s ", vg_name, pe_size);
    if (r == EOF || r != 2) {
        fprintf(stderr, "%s:%i Error parsing line %i: %s\n",
            __FILE__, __LINE__, line, format);
        return;
    }

    double temp;
    char *tail;

    temp = strtod(pe_size, &tail);
    if (temp == 0.0) {
        fprintf(stderr, "%s:%i Error parsing line %i: %s\n",
            __FILE__, __LINE__, line, format);
        return;
    }

    switch(tail[0]){
	    case 'b':
	    case 'B':
	        pe_size_bytes = temp;
	        break;
	    case 'S':
	        pe_size_bytes = temp * 512;
            break;
        case 'k':
	        pe_size_bytes = temp * 1024;
	        break;
        case 'K':
            pe_size_bytes = temp * 1000;
            break;
        case 'm':
            pe_size_bytes = temp * 1024 * 1024;
	        break;
        case 'M':
	        pe_size_bytes = temp * 1000 * 1000;
            break;
        case 'g':
            pe_size_bytes = temp * 1024 * 1024 * 1024;
            break;
        case 'G':
            pe_size_bytes = temp * 1000 * 1000 * 1000;
            break;
        case 't':
            pe_size_bytes = temp * 1024 * 1024 * 1024 * 1024;
            break;
        case 'T':
            pe_size_bytes = temp * 1000 * 1000 * 1000 * 1000;
            break;
        case 'p':
            pe_size_bytes = temp * 1024 * 1024 * 1024 * 1024 * 1024;
            break;
        case 'P':
            pe_size_bytes = temp * 1000 * 1000 * 1000 * 1000 * 1000;
            break;
        case 'e':
            pe_size_bytes = temp * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
            break;
        case 'E':
            pe_size_bytes = temp * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
            break;
        default:
            pe_size_bytes = temp;
            /* break; */
    }

    // save info about first volume group
    if (vg_pe_sizes_len == 0) {
        vg_pe_sizes = malloc(sizeof(struct vg_pe_sizes));
        if (!vg_pe_sizes)
            goto vgs_failure;

        vg_pe_sizes[0].vg_name = strdup(vg_name);
        if (!vg_pe_sizes[0].vg_name)
            goto vgs_failure;

        vg_pe_sizes[0].pe_size = pe_size_bytes;

        vg_pe_sizes_len=1;

        return;
    }

    // save info about subsequent groups
    vg_pe_sizes = realloc(vg_pe_sizes, sizeof(struct vg_pe_sizes)*
        (vg_pe_sizes_len+1));
    if (!vg_pe_sizes)
        goto vgs_failure;

    vg_pe_sizes[vg_pe_sizes_len].vg_name = malloc(strlen(vg_name)+1);
    if(!vg_pe_sizes[vg_pe_sizes_len].vg_name)
        goto vgs_failure;
    strcpy(vg_pe_sizes[vg_pe_sizes_len].vg_name, vg_name);
    vg_pe_sizes[vg_pe_sizes_len].pe_size = pe_size_bytes;

    vg_pe_sizes_len+=1;

    return;

vgs_failure:
    fprintf(stderr, "Out of memory\n");
    exit(1);
}

// return size of extents in provided volume group
uint64_t get_pe_size(const char *vg_name)
{
    for(size_t i=0; i<vg_pe_sizes_len; i++)
        if (!strcmp(vg_pe_sizes[i].vg_name, vg_name))
            return vg_pe_sizes[i].pe_size;

    return 0;
}

// free allocated memory and objects
void le_to_pe_exit(struct program_params *pp)
{
    for(size_t i=0; i<pv_segments_num; i++){
        free(pv_segments[i].pv_name);
        free(pv_segments[i].vg_name);
        free(pv_segments[i].vg_format);
        free(pv_segments[i].vg_attr);
        free(pv_segments[i].lv_name);
        free(pv_segments[i].pv_type);
    }
    free(pv_segments);
    pv_segments = NULL;
    pv_segments_num = 0;

    for(size_t i=0; i<vg_pe_sizes_len; i++)
        free(vg_pe_sizes[i].vg_name);

    free(vg_pe_sizes);
    vg_pe_sizes = NULL;
    vg_pe_sizes_len = 0;
}

// initialize or reload cache variables
void init_le_to_pe(struct program_params *pp)
{
//    int r;

    if(pv_segments)
        le_to_pe_exit(pp);

    vg_pe_sizes = NULL;
    vg_pe_sizes_len = 0;


    lvm2_log_fn(parse_pvs_segments);
    if (!pp->lvm2_handle)
        pp->lvm2_handle = lvm2_init();

    lvm2_log_level(pp->lvm2_handle, 1);
//    r =
      lvm2_run(pp->lvm2_handle, "pvs --noheadings --segments -o+lv_name,"
        "seg_start_pe,segtype --units=b");

//    if (r)
//      fprintf(stderr, "command failed\n");

    sort_segments(pv_segments, pv_segments_num);

    lvm2_log_fn(parse_vgs_pe_size);

//    r =
      lvm2_run(pp->lvm2_handle, "vgs -o vg_name,vg_extent_size --noheadings --units=b");

    return;
}

// return number of free extents in PV in specified volume group
// or in whole volume group if pv_name is NULL
uint64_t get_free_extent_number(const char *vg_name, const char *pv_name)
{
    if (!vg_name)
        return 0;

    uint64_t sum=0;

    if(pv_name)
        for(size_t i=0; i < pv_segments_num; i++) {
            if (!strcmp(pv_segments[i].vg_name, vg_name) &&
                !strcmp(pv_segments[i].pv_name, pv_name) &&
                !strcmp(pv_segments[i].pv_type, "free"))
              sum+=pv_segments[i].pv_length;
        }
    else
        for(size_t i=0; i < pv_segments_num; i++)
            if (!strcmp(pv_segments[i].vg_name, vg_name) &&
                !strcmp(pv_segments[i].pv_type, "free"))
              sum+=pv_segments[i].pv_length;

    return sum;
}

struct le_info
get_first_LE_info(const char *vg_name, const char *lv_name,
    const char *pv_name)
{
    struct le_info ret = { .dev = NULL };

    for (size_t i=0; i < pv_segments_num; i++) {
        if (!strcmp(pv_segments[i].vg_name, vg_name) &&
            !strcmp(pv_segments[i].pv_name, pv_name) &&
            !strcmp(pv_segments[i].lv_name, lv_name)) {

            if (ret.dev == NULL) { // save first segment info
                ret.le = pv_segments[i].lv_start;
                ret.pe = pv_segments[i].pv_start;
                ret.dev = pv_segments[i].pv_name;
            } else {
                if (ret.le > pv_segments[i].lv_start) {
                    ret.le = pv_segments[i].lv_start;
                    ret.pe = pv_segments[i].pv_start;
                    ret.dev = pv_segments[i].pv_name;
                }
            }
        }
    }

    return ret;
}

struct le_info
get_PE_allocation(const char *vg_name, const char *pv_name,
    uint64_t pe_num)
{
    const char *free_str = "free";

    struct le_info ret = { .dev = NULL, .lv_name = NULL };

    for (size_t i=0; i < pv_segments_num; i++) {
        if (!strcmp(pv_segments[i].vg_name, vg_name) &&
            !strcmp(pv_segments[i].pv_name, pv_name) &&
            pv_segments[i].pv_start <= pe_num &&
            pv_segments[i].pv_start + pv_segments[i].pv_length > pe_num) {

            ret.dev = pv_segments[i].pv_name;
            if (!strcmp(pv_segments[i].pv_type, free_str))
                ret.lv_name = free_str;
            else
                ret.lv_name = pv_segments[i].lv_name;

            uint64_t diff = pe_num - pv_segments[i].pv_start;

            ret.le = pv_segments[i].lv_start + diff;
            ret.pe = pv_segments[i].pv_start + diff;

            return ret;
        }
    }

    return ret;
}

// return used number of extents by LV on provided PV
uint64_t get_used_space_on_pv(const char *vg_name, const char *lv_name,
    const char *pv_name)
{
    assert(vg_name);
    assert(lv_name);
    assert(pv_name);

    uint64_t sum = 0;

    for(size_t i=0; i < pv_segments_num; i++) {
        if(!strcmp(pv_segments[i].lv_name, lv_name) &&
           !strcmp(pv_segments[i].vg_name, vg_name) &&
           !strcmp(pv_segments[i].pv_name, pv_name)) {

            sum += pv_segments[i].pv_length;
        }
    }

    return sum;
}