1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00
lvm2/lib/metadata/lvm_v1.c
2001-10-01 15:14:39 +00:00

502 lines
10 KiB
C

/*
* Copyright (C) 2001 Sistina Software
*
* This LVM library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This LVM library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this LVM library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include "dbg_malloc.h"
#include "dev-manager.h"
#include "log.h"
#include "metadata.h"
/*
* FIXME: these should not allocate memory
*/
pv_t *pv_copy_from_disk(pv_disk_t * pv_disk)
{
pv_t *pv;
if (!pv_disk || !(pv = (pv_t *) dbg_malloc(sizeof (*pv))))
return 0;
#define xx16(v) pv->v = LVM_TO_CORE16(pv_disk->v)
#define xx32(v) pv->v = LVM_TO_CORE32(pv_disk->v)
memset(pv, 0, sizeof (*pv));
strncpy(pv->id, pv_disk->id, sizeof (pv->id));
xx16(version);
xx32(pv_on_disk.base);
xx32(pv_on_disk.size);
xx32(vg_on_disk.base);
xx32(vg_on_disk.size);
xx32(pv_uuidlist_on_disk.base);
xx32(pv_uuidlist_on_disk.size);
xx32(lv_on_disk.base);
xx32(lv_on_disk.size);
xx32(pe_on_disk.base);
xx32(pe_on_disk.size);
memset(pv->pv_name, 0, sizeof (pv->pv_name));
memset(pv->pv_uuid, 0, sizeof (pv->pv_uuid));
memcpy(pv->pv_uuid, pv_disk->pv_uuid, UUID_LEN);
strncpy(pv->vg_name, pv_disk->vg_name, sizeof (pv->vg_name));
strncpy(pv->system_id, pv_disk->system_id, sizeof (pv->system_id));
pv->pv_dev = LVM_TO_CORE32(pv_disk->pv_major);
xx32(pv_number);
xx32(pv_status);
xx32(pv_allocatable);
xx32(pv_size);
xx32(lv_cur);
xx32(pe_size);
xx32(pe_total);
xx32(pe_allocated);
pv->pe_stale = 0;
xx32(pe_start);
#undef xx16
#undef xx32
return pv;
}
pv_disk_t *pv_copy_to_disk(pv_t * pv_core)
{
pv_disk_t *pv;
if (!pv_core || !(pv = dbg_malloc(sizeof (*pv))))
return 0;
#define xx16(v) pv->v = LVM_TO_DISK16(pv_core->v)
#define xx32(v) pv->v = LVM_TO_DISK32(pv_core->v)
memset(pv, 0, sizeof (*pv));
strncpy(pv->id, pv_core->id, sizeof (pv->id));
xx16(version);
xx32(pv_on_disk.base);
xx32(pv_on_disk.size);
xx32(vg_on_disk.base);
xx32(vg_on_disk.size);
xx32(pv_uuidlist_on_disk.base);
xx32(pv_uuidlist_on_disk.size);
xx32(lv_on_disk.base);
xx32(lv_on_disk.size);
xx32(pe_on_disk.base);
xx32(pe_on_disk.size);
memcpy(pv->pv_uuid, pv_core->pv_uuid, UUID_LEN);
strncpy(pv->vg_name, pv_core->vg_name, sizeof (pv->vg_name));
strncpy(pv->system_id, pv_core->system_id, sizeof (pv->system_id));
/* core type is kdev_t; but no matter what it is,
only store major for check in pv_read() */
pv->pv_major = LVM_TO_DISK32(MAJOR(pv_core->pv_dev));
xx32(pv_number);
xx32(pv_status);
xx32(pv_allocatable);
xx32(pv_size);
xx32(lv_cur);
xx32(pe_size);
xx32(pe_total);
xx32(pe_allocated);
xx32(pe_start);
#undef xx16
#undef xx32
return pv;
}
lv_t *lv_copy_from_disk(lv_disk_t * lv_disk)
{
lv_t *lv;
if (!lv_disk || !(lv = dbg_malloc(sizeof (*lv))))
return 0;
memset(lv, 0, sizeof (*lv));
#define xx16(v) lv->v = LVM_TO_CORE16(lv_disk->v)
#define xx32(v) lv->v = LVM_TO_CORE32(lv_disk->v)
strncpy(lv->lv_name, lv_disk->lv_name, sizeof (lv->lv_name));
strncpy(lv->vg_name, lv_disk->vg_name, sizeof (lv->vg_name));
xx32(lv_access);
xx32(lv_status);
lv->lv_open = 0;
xx32(lv_dev);
xx32(lv_number);
xx32(lv_mirror_copies);
xx32(lv_recovery);
xx32(lv_schedule);
xx32(lv_size);
lv->lv_current_pe = NULL;
xx32(lv_allocated_le);
lv->lv_current_le = lv->lv_allocated_le;
xx32(lv_stripes);
xx32(lv_stripesize);
xx32(lv_badblock);
xx32(lv_allocation);
xx32(lv_io_timeout);
xx32(lv_read_ahead);
lv->lv_snapshot_org = NULL;
lv->lv_snapshot_prev = NULL;
lv->lv_snapshot_next = NULL;
lv->lv_block_exception = NULL;
lv->lv_remap_ptr = 0;
lv->lv_remap_end = 0;
xx32(lv_snapshot_minor);
xx16(lv_chunk_size);
#undef xx32
#undef xx16
return lv;
}
lv_disk_t *lv_copy_to_disk(lv_t * lv_core)
{
lv_disk_t *lv;
if (!lv_core || !(lv = dbg_malloc(sizeof (*lv))))
return 0;
memset(lv, 0, sizeof (*lv));
#define xx16(v) lv->v = LVM_TO_DISK16(lv_core->v)
#define xx32(v) lv->v = LVM_TO_DISK32(lv_core->v)
strncpy(lv->lv_name, lv_core->lv_name, sizeof (lv->lv_name));
strncpy(lv->vg_name, lv_core->vg_name, sizeof (lv->vg_name));
xx32(lv_access);
xx32(lv_status);
lv->lv_open = 0;
xx32(lv_dev);
xx32(lv_number);
xx32(lv_mirror_copies);
xx32(lv_recovery);
xx32(lv_schedule);
xx32(lv_size);
xx32(lv_snapshot_minor);
xx16(lv_chunk_size);
lv->dummy = 0;
xx32(lv_allocated_le);
xx32(lv_stripes);
xx32(lv_stripesize);
xx32(lv_badblock);
xx32(lv_allocation);
xx32(lv_io_timeout);
xx32(lv_read_ahead);
#undef xx32
#undef xx16
return lv;
}
vg_t *vg_copy_from_disk(vg_disk_t * vg_disk)
{
vg_t *vg;
if (!vg_disk || !(vg = dbg_malloc(sizeof (*vg))))
return 0;
#define xx32(v) vg->v = LVM_TO_CORE32(vg_disk->v)
memset(vg, 0, sizeof (vg_t));
xx32(vg_number);
xx32(vg_access);
xx32(vg_status);
xx32(lv_max);
xx32(lv_cur);
vg->lv_open = 0;
xx32(pv_max);
xx32(pv_cur);
xx32(pv_act);
vg->dummy = 0;
xx32(vgda);
xx32(pe_size);
xx32(pe_total);
xx32(pe_allocated);
xx32(pvg_total);
#undef xx32
memset(&vg->pv, 0, sizeof (vg->pv));
memset(&vg->lv, 0, sizeof (vg->lv));
memset(vg->vg_uuid, 0, sizeof (vg->vg_uuid));
memcpy(vg->vg_uuid, vg_disk->vg_uuid, UUID_LEN);
return vg;
}
vg_disk_t *vg_copy_to_disk(vg_t * vg_core)
{
vg_disk_t *vg;
if (!vg_core ||
/* FIXME: vg_check_consistency(vg_core) || */
!(vg = dbg_malloc(sizeof (*vg))))
return 0;
memset(vg, 0, sizeof (*vg));
#define xx32(v) vg->v = LVM_TO_DISK32(vg_core->v)
xx32(vg_number);
xx32(vg_access);
xx32(vg_status);
xx32(lv_max);
xx32(lv_cur);
vg->lv_open = 0;
xx32(pv_max);
xx32(pv_cur);
xx32(pv_act);
vg->dummy = 0;
xx32(vgda);
xx32(pe_size);
xx32(pe_total);
xx32(pe_allocated);
xx32(pvg_total);
#undef xx32
memcpy(vg->vg_uuid, vg_core->vg_uuid, UUID_LEN);
return vg;
}
pe_disk_t *pe_copy_from_disk(pe_disk_t * pe_file, int count)
{
int i;
pe_disk_t *pe;
size_t s = sizeof (*pe) * count;
if (!pe_file || count <= 0 || !(pe = dbg_malloc(s)))
return 0;
memset(pe, 0, s);
for (i = 0; i < count; i++) {
pe[i].lv_num = LVM_TO_CORE16(pe_file[i].lv_num);
pe[i].le_num = LVM_TO_CORE16(pe_file[i].le_num);
}
return pe;
}
pe_disk_t *pe_copy_to_disk(pe_disk_t * pe_core, int count)
{
int i;
pe_disk_t *pe;
size_t s = sizeof (*pe) * count;
if (!pe_core || count <= 0 || !(pe = dbg_malloc(s)))
return 0;
memset(pe, 0, s);
for (i = 0; i < count; i++) {
pe[i].lv_num = LVM_TO_DISK16(pe_core[i].lv_num);
pe[i].le_num = LVM_TO_DISK16(pe_core[i].le_num);
}
return pe;
}
pv_t *pv_read_lvm_v1(struct dev_mgr * dm, const char *pv_name)
{
int pv_handle = -1;
ssize_t read_ret;
ssize_t bytes_read = 0;
static pv_disk_t pv_this;
struct stat stat_b;
pv_t *pv = NULL;
struct device *pv_dev;
if ((pv_handle = open(pv_name, O_RDONLY)) == -1) {
log_error("%s: open failed: %s", pv_name, strerror(errno));
return NULL;
}
if ((fstat(pv_handle, &stat_b))) {
log_error("%s: fstat failed: %s", pv_name, strerror(errno));
goto pv_read_lvm_v1_out;
}
while ((bytes_read < sizeof (pv_this) &&
(read_ret = read(pv_handle, &pv_this + bytes_read,
sizeof (pv_this) - bytes_read)) != -1))
bytes_read += read_ret;
if (read_ret == -1) {
log_error("%s: read failed: %s", pv_name, strerror(errno));
goto pv_read_lvm_v1_out;
}
pv = pv_copy_from_disk(&pv_this);
/* correct for imported/moved volumes */
if (!(pv_dev = dev_by_dev(dm, stat_b.st_rdev))) {
log_error("Device missing from cache");
goto pv_read_lvm_v1_out;
}
memset(pv->pv_name, 0, sizeof (pv->pv_name));
strncpy(pv->pv_name, pv_dev->name, sizeof (pv->pv_name) - 1);
/* FIXME: Deleted version / consistency / export checks! */
pv->pv_dev = stat_b.st_rdev;
pv_read_lvm_v1_out:
if (pv_handle != -1)
close(pv_handle);
return pv;
}
pe_disk_t *pv_read_pe_lvm_v1(const char *pv_name, const pv_t * pv)
{
int pv_handle = -1;
uint size = 0;
ssize_t read_ret;
ssize_t bytes_read = 0;
pe_disk_t *pe = NULL;
pe_disk_t *pe_this;
size = pv->pe_total * sizeof (pe_disk_t);
if (size > pv->pe_on_disk.size) {
log_error("PEs extend beyond end of volume group!");
return pe; /*NULL*/
}
if ((pv_handle = open(pv_name, O_RDONLY)) == -1) {
log_error("%s: open failed: %s", pv_name, strerror(errno));
goto pv_read_pe_out;
}
if (lseek(pv_handle, pv->pe_on_disk.base, SEEK_SET) !=
pv->pe_on_disk.base) {
log_error("%s: lseek to PE failed: %s", pv_name, strerror(errno));
goto pv_read_pe_out;
}
if (!(pe_this = dbg_malloc(size))) {
log_error("PE malloc failed");
goto pv_read_pe_out;
}
while ((bytes_read < size &&
(read_ret = read(pv_handle, (void *)pe_this + bytes_read,
size - bytes_read)) != -1))
bytes_read += read_ret;
if (read_ret == -1) {
log_error("%s: read failed: %s", pv_name, strerror(errno));
goto pv_read_pe_out;
}
pe = pe_copy_from_disk(pe_this, pv->pe_total);
pv_read_pe_out:
if (pv_handle != -1)
close(pv_handle);
dbg_free(pe_this);
return pe;
}
lv_disk_t *pv_read_lvs_lvm_v1(const pv_t *pv)
{
int pv_handle = -1;
uint size = 0;
ssize_t read_ret;
ssize_t bytes_read = 0;
lv_disk_t *lvs;
/* FIXME: replace lv_cur? */
size = pv->lv_cur * sizeof (lv_disk_t);
if ((pv_handle = open(pv->pv_name, O_RDONLY)) == -1) {
log_error("%s: open failed: %s", pv->pv_name, strerror(errno));
goto pv_read_lvs_out;
}
if (lseek(pv_handle, pv->lv_on_disk.base, SEEK_SET) !=
pv->lv_on_disk.base) {
log_error("%s: lseek to LV failed: %s", pv->pv_name, strerror(errno));
goto pv_read_lvs_out;
}
if (!(lvs = dbg_malloc(size))) {
log_error("PE malloc failed");
goto pv_read_lvs_out;
}
while ((bytes_read < size &&
(read_ret = read(pv_handle, (void *) lvs + bytes_read,
size - bytes_read)) != -1))
bytes_read += read_ret;
if (read_ret == -1) {
log_error("%s: read failed: %s", pv->pv_name, strerror(errno));
goto pv_read_lvs_out;
}
pv_read_lvs_out:
if (pv_handle != -1)
close(pv_handle);
/* Caller frees */
return lvs;
}