示例#1
0
文件: lvmls.c 项目: tavisrudd/lvmts
// 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;
}
int lvm2_run(void *handle, const char *cmdline)
{
    int argc, ret, oneoff = 0;
    char *args[MAX_ARGS], **argv, *cmdcopy = NULL;
    struct cmd_context *cmd;

    argv = args;

    if (!handle) {
        oneoff = 1;
        if (!(handle = lvm2_init())) {
            log_error("Handle initialisation failed.");
            return ECMD_FAILED;
        }
    }

    cmd = (struct cmd_context *) handle;

    cmd->argv = argv;

    if (!(cmdcopy = dm_strdup(cmdline))) {
        log_error("Cmdline copy failed.");
        ret = ECMD_FAILED;
        goto out;
    }

    if (lvm_split(cmdcopy, &argc, argv, MAX_ARGS) == MAX_ARGS) {
        log_error("Too many arguments.  Limit is %d.", MAX_ARGS);
        ret = EINVALID_CMD_LINE;
        goto out;
    }

    if (!argc) {
        log_error("No command supplied");
        ret = EINVALID_CMD_LINE;
        goto out;
    }

    /* FIXME Temporary - move to libdevmapper */
    ret = ECMD_PROCESSED;
    if (!strcmp(cmdline, "_memlock_inc"))
        memlock_inc_daemon(cmd);
    else if (!strcmp(cmdline, "_memlock_dec"))
        memlock_dec_daemon(cmd);
    else
        ret = lvm_run_command(cmd, argc, argv);

out:
    dm_free(cmdcopy);

    if (oneoff)
        lvm2_exit(handle);

    return ret;
}
示例#3
0
int main(int argc, char **argv)
{
	void *handle;
	int r;

	lvm2_log_fn(test_log_fn);

	handle = lvm2_init();

	lvm2_log_level(handle, 1);
	r = lvm2_run(handle, "vgs --noheadings vg1");

	/* More commands here */

	lvm2_exit(handle);

	return r;
}
示例#4
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;
}