mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
o Changes to activation interface
o Add pointer lv->vg o Some naming tweaks to improve clarity
This commit is contained in:
parent
1b9fcf48b1
commit
0a5e4a1442
@ -7,12 +7,12 @@
|
|||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "activate.h"
|
#include "activate.h"
|
||||||
|
|
||||||
int lv_activate(struct volume_group *vg, struct logical_volume *lv)
|
int lv_activate(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lv_deactivate(struct volume_group *vg, struct logical_volume *lv)
|
int lv_deactivate(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -22,14 +22,33 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int activate_lvs_in_vg(struct volume_group *vg)
|
int lv_update_write_access(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int activate_lvs_in_vg(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
struct list *lvh;
|
||||||
|
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
list_iterate(lvh, &vg->lvs)
|
||||||
|
done += lv_activate(&list_item(lvh, struct lv_list)->lv);
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
int deactivate_lvs_in_vg(struct volume_group *vg)
|
int deactivate_lvs_in_vg(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
return 0;
|
struct list *lvh;
|
||||||
|
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
list_iterate(lvh, &vg->lvs)
|
||||||
|
done += lv_deactivate(&list_item(lvh, struct lv_list)->lv);
|
||||||
|
|
||||||
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,15 +9,16 @@
|
|||||||
|
|
||||||
/* FIXME Snapshot handling? */
|
/* FIXME Snapshot handling? */
|
||||||
|
|
||||||
int lv_activate(struct volume_group *vg,
|
int lv_activate(struct logical_volume *lv);
|
||||||
struct logical_volume *lv);
|
|
||||||
|
|
||||||
int lv_deactivate(struct volume_group *vg,
|
int lv_deactivate(struct logical_volume *lv);
|
||||||
struct logical_volume *lv);
|
|
||||||
|
|
||||||
/* Return number of LVs in the VG that are active */
|
/* Return number of LVs in the VG that are active */
|
||||||
int lvs_in_vg_activated(struct volume_group *vg);
|
int lvs_in_vg_activated(struct volume_group *vg);
|
||||||
|
|
||||||
|
/* Test for (lv->status & LVM_WRITE) */
|
||||||
|
int lv_update_write_access(struct logical_volume *lv);
|
||||||
|
|
||||||
/* Activate all LVs in the VG. Ignore any that are already active. */
|
/* Activate all LVs in the VG. Ignore any that are already active. */
|
||||||
/* Return number activated */
|
/* Return number activated */
|
||||||
int activate_lvs_in_vg(struct volume_group *vg);
|
int activate_lvs_in_vg(struct volume_group *vg);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* between disk and core. The same code works
|
* between disk and core. The same code works
|
||||||
* both ways of course.
|
* both ways of course.
|
||||||
*/
|
*/
|
||||||
static void _xlate_pv(struct pv_disk *disk)
|
static void _xlate_pvd(struct pv_disk *disk)
|
||||||
{
|
{
|
||||||
xx16(version);
|
xx16(version);
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ static void _xlate_pv(struct pv_disk *disk)
|
|||||||
xx32(pe_start);
|
xx32(pe_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _xlate_lv(struct lv_disk *disk)
|
static void _xlate_lvd(struct lv_disk *disk)
|
||||||
{
|
{
|
||||||
xx32(lv_access);
|
xx32(lv_access);
|
||||||
xx32(lv_status);
|
xx32(lv_status);
|
||||||
@ -64,7 +64,7 @@ static void _xlate_lv(struct lv_disk *disk)
|
|||||||
xx32(lv_read_ahead);
|
xx32(lv_read_ahead);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _xlate_vg(struct vg_disk *disk)
|
static void _xlate_vgd(struct vg_disk *disk)
|
||||||
{
|
{
|
||||||
xx32(vg_number);
|
xx32(vg_number);
|
||||||
xx32(vg_access);
|
xx32(vg_access);
|
||||||
@ -119,34 +119,34 @@ static int _munge_formats(struct pv_disk *pvd)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_pv(struct disk_list *data)
|
static int _read_pvd(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct pv_disk *pvd = &data->pv;
|
struct pv_disk *pvd = &data->pvd;
|
||||||
if (dev_read(data->dev, 0, sizeof(*pvd), pvd) != sizeof(*pvd))
|
if (dev_read(data->dev, 0, sizeof(*pvd), pvd) != sizeof(*pvd))
|
||||||
fail;
|
fail;
|
||||||
_xlate_pv(pvd);
|
_xlate_pvd(pvd);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_lv(struct device *dev, ulong pos, struct lv_disk *disk)
|
static int _read_lvd(struct device *dev, ulong pos, struct lv_disk *disk)
|
||||||
{
|
{
|
||||||
if (dev_read(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
|
if (dev_read(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_lv(disk);
|
_xlate_lvd(disk);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_vg(struct disk_list *data)
|
static int _read_vgd(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct vg_disk *vgd = &data->vg;
|
struct vg_disk *vgd = &data->vgd;
|
||||||
unsigned long pos = data->pv.vg_on_disk.base;
|
unsigned long pos = data->pvd.vg_on_disk.base;
|
||||||
if (dev_read(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
|
if (dev_read(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_vg(vgd);
|
_xlate_vgd(vgd);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -156,10 +156,10 @@ static int _read_uuids(struct disk_list *data)
|
|||||||
int num_read = 0;
|
int num_read = 0;
|
||||||
struct uuid_list *ul;
|
struct uuid_list *ul;
|
||||||
char buffer[NAME_LEN];
|
char buffer[NAME_LEN];
|
||||||
ulong pos = data->pv.pv_uuidlist_on_disk.base;
|
ulong pos = data->pvd.pv_uuidlist_on_disk.base;
|
||||||
ulong end = pos + data->pv.pv_uuidlist_on_disk.size;
|
ulong end = pos + data->pvd.pv_uuidlist_on_disk.size;
|
||||||
|
|
||||||
while(pos < end && num_read < data->vg.pv_cur) {
|
while(pos < end && num_read < data->vgd.pv_cur) {
|
||||||
if (dev_read(data->dev, pos, sizeof(buffer), buffer) !=
|
if (dev_read(data->dev, pos, sizeof(buffer), buffer) !=
|
||||||
sizeof(buffer))
|
sizeof(buffer))
|
||||||
fail;
|
fail;
|
||||||
@ -179,7 +179,7 @@ static int _read_uuids(struct disk_list *data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _check_lv(struct lv_disk *lvd)
|
static int _check_lvd(struct lv_disk *lvd)
|
||||||
{
|
{
|
||||||
/* FIXME: add more checks */
|
/* FIXME: add more checks */
|
||||||
if (lvd->lv_name[0] == '\0') {
|
if (lvd->lv_name[0] == '\0') {
|
||||||
@ -196,20 +196,20 @@ static int _read_lvs(struct disk_list *data)
|
|||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
struct lvd_list *ll;
|
struct lvd_list *ll;
|
||||||
|
|
||||||
for(i = 0; i < data->vg.lv_cur; i++) {
|
for(i = 0; i < data->vgd.lv_cur; i++) {
|
||||||
pos = data->pv.lv_on_disk.base + (i * sizeof(struct lv_disk));
|
pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
|
||||||
ll = pool_alloc(data->mem, sizeof(*ll));
|
ll = pool_alloc(data->mem, sizeof(*ll));
|
||||||
|
|
||||||
if (!ll)
|
if (!ll)
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
if (!_read_lv(data->dev, pos, &ll->lv))
|
if (!_read_lvd(data->dev, pos, &ll->lvd))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
if (!_check_lv(&ll->lv))
|
if (!_check_lvd(&ll->lvd))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
list_add(&data->lvs, &ll->list);
|
list_add(&data->lvds, &ll->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -217,9 +217,9 @@ static int _read_lvs(struct disk_list *data)
|
|||||||
|
|
||||||
static int _read_extents(struct disk_list *data)
|
static int _read_extents(struct disk_list *data)
|
||||||
{
|
{
|
||||||
size_t len = sizeof(struct pe_disk) * data->pv.pe_total;
|
size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
|
||||||
struct pe_disk *extents = pool_alloc(data->mem, len);
|
struct pe_disk *extents = pool_alloc(data->mem, len);
|
||||||
unsigned long pos = data->pv.pe_on_disk.base;
|
unsigned long pos = data->pvd.pe_on_disk.base;
|
||||||
|
|
||||||
if (!extents)
|
if (!extents)
|
||||||
fail;
|
fail;
|
||||||
@ -227,13 +227,13 @@ static int _read_extents(struct disk_list *data)
|
|||||||
if (dev_read(data->dev, pos, len, extents) != len)
|
if (dev_read(data->dev, pos, len, extents) != len)
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_extents(extents, data->pv.pe_total);
|
_xlate_extents(extents, data->pvd.pe_total);
|
||||||
data->extents = extents;
|
data->extents = extents;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct disk_list *read_pv(struct device *dev, struct pool *mem,
|
struct disk_list *read_disk(struct device *dev, struct pool *mem,
|
||||||
const char *vg_name)
|
const char *vg_name)
|
||||||
{
|
{
|
||||||
struct disk_list *data = pool_alloc(mem, sizeof(*data));
|
struct disk_list *data = pool_alloc(mem, sizeof(*data));
|
||||||
@ -242,40 +242,40 @@ struct disk_list *read_pv(struct device *dev, struct pool *mem,
|
|||||||
data->dev = dev;
|
data->dev = dev;
|
||||||
data->mem = mem;
|
data->mem = mem;
|
||||||
list_init(&data->uuids);
|
list_init(&data->uuids);
|
||||||
list_init(&data->lvs);
|
list_init(&data->lvds);
|
||||||
|
|
||||||
if (!_read_pv(data)) {
|
if (!_read_pvd(data)) {
|
||||||
log_debug("Failed to read PV data from %s", name);
|
log_debug("Failed to read PV data from %s", name);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->pv.id[0] != 'H' || data->pv.id[1] != 'M') {
|
if (data->pvd.id[0] != 'H' || data->pvd.id[1] != 'M') {
|
||||||
log_very_verbose("%s does not have a valid PV identifier",
|
log_very_verbose("%s does not have a valid PV identifier",
|
||||||
name);
|
name);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_munge_formats(&data->pv)) {
|
if (!_munge_formats(&data->pvd)) {
|
||||||
log_very_verbose("Unknown metadata version %d found on %s",
|
log_very_verbose("Unknown metadata version %d found on %s",
|
||||||
data->pv.version, name);
|
data->pvd.version, name);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is it an orphan ?
|
* is it an orphan ?
|
||||||
*/
|
*/
|
||||||
if (data->pv.vg_name == '\0') {
|
if (data->pvd.vg_name == '\0') {
|
||||||
log_very_verbose("%s is not a member of any VG", name);
|
log_very_verbose("%s is not a member of any VG", name);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vg_name && strcmp(vg_name, data->pv.vg_name)) {
|
if (vg_name && strcmp(vg_name, data->pvd.vg_name)) {
|
||||||
log_very_verbose("%s is not a member of the VG %s",
|
log_very_verbose("%s is not a member of the VG %s",
|
||||||
name, vg_name);
|
name, vg_name);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_read_vg(data)) {
|
if (!_read_vgd(data)) {
|
||||||
log_error("Failed to read VG data from PV (%s)", name);
|
log_error("Failed to read VG data from PV (%s)", name);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ struct disk_list *read_pv(struct device *dev, struct pool *mem,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_very_verbose("Found %s in VG %s", name, data->pv.vg_name);
|
log_very_verbose("Found %s in VG %s", name, data->pvd.vg_name);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
|
|||||||
struct disk_list *data = NULL;
|
struct disk_list *data = NULL;
|
||||||
|
|
||||||
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
|
||||||
if ((data = read_pv(dev, mem, vg_name)))
|
if ((data = read_pvd(dev, mem, vg_name)))
|
||||||
list_add(head, &data->list);
|
list_add(head, &data->list);
|
||||||
}
|
}
|
||||||
dev_iter_destroy(iter);
|
dev_iter_destroy(iter);
|
||||||
@ -330,16 +330,16 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _write_vg(struct disk_list *data)
|
static int _write_vgd(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct vg_disk *vgd = &data->vg;
|
struct vg_disk *vgd = &data->vgd;
|
||||||
unsigned long pos = data->pv.vg_on_disk.base;
|
unsigned long pos = data->pvd.vg_on_disk.base;
|
||||||
|
|
||||||
_xlate_vg(vgd);
|
_xlate_vgd(vgd);
|
||||||
if (dev_write(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
|
if (dev_write(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_vg(vgd);
|
_xlate_vgd(vgd);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -348,8 +348,8 @@ static int _write_uuids(struct disk_list *data)
|
|||||||
{
|
{
|
||||||
struct uuid_list *ul;
|
struct uuid_list *ul;
|
||||||
struct list *uh;
|
struct list *uh;
|
||||||
ulong pos = data->pv.pv_uuidlist_on_disk.base;
|
ulong pos = data->pvd.pv_uuidlist_on_disk.base;
|
||||||
ulong end = pos + data->pv.pv_uuidlist_on_disk.size;
|
ulong end = pos + data->pvd.pv_uuidlist_on_disk.size;
|
||||||
|
|
||||||
list_iterate(uh, &data->uuids) {
|
list_iterate(uh, &data->uuids) {
|
||||||
if (pos >= end) {
|
if (pos >= end) {
|
||||||
@ -368,13 +368,13 @@ static int _write_uuids(struct disk_list *data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _write_lv(struct device *dev, ulong pos, struct lv_disk *disk)
|
static int _write_lvd(struct device *dev, ulong pos, struct lv_disk *disk)
|
||||||
{
|
{
|
||||||
_xlate_lv(disk);
|
_xlate_lvd(disk);
|
||||||
if (dev_write(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
|
if (dev_write(dev, pos, sizeof(*disk), disk) != sizeof(*disk))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_lv(disk);
|
_xlate_lvd(disk);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -384,11 +384,11 @@ static int _write_lvs(struct disk_list *data)
|
|||||||
struct list *lvh;
|
struct list *lvh;
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
|
|
||||||
list_iterate(lvh, &data->lvs) {
|
list_iterate(lvh, &data->lvds) {
|
||||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
||||||
pos = data->pv.lv_on_disk.base;
|
pos = data->pvd.lv_on_disk.base;
|
||||||
|
|
||||||
if (!_write_lv(data->dev, pos, &ll->lv))
|
if (!_write_lvd(data->dev, pos, &ll->lvd))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
pos += sizeof(struct lv_disk);
|
pos += sizeof(struct lv_disk);
|
||||||
@ -399,37 +399,37 @@ static int _write_lvs(struct disk_list *data)
|
|||||||
|
|
||||||
static int _write_extents(struct disk_list *data)
|
static int _write_extents(struct disk_list *data)
|
||||||
{
|
{
|
||||||
size_t len = sizeof(struct pe_disk) * data->pv.pe_total;
|
size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
|
||||||
struct pe_disk *extents = data->extents;
|
struct pe_disk *extents = data->extents;
|
||||||
unsigned long pos = data->pv.pe_on_disk.base;
|
unsigned long pos = data->pvd.pe_on_disk.base;
|
||||||
|
|
||||||
_xlate_extents(extents, data->pv.pe_total);
|
_xlate_extents(extents, data->pvd.pe_total);
|
||||||
if (dev_write(data->dev, pos, len, extents) != len)
|
if (dev_write(data->dev, pos, len, extents) != len)
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_extents(extents, data->pv.pe_total);
|
_xlate_extents(extents, data->pvd.pe_total);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _write_pv(struct disk_list *data)
|
static int _write_pvd(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct pv_disk *disk = &data->pv;
|
struct pv_disk *disk = &data->pvd;
|
||||||
|
|
||||||
_xlate_pv(disk);
|
_xlate_pvd(disk);
|
||||||
if (dev_write(data->dev, 0, sizeof(*disk), disk) != sizeof(*disk))
|
if (dev_write(data->dev, 0, sizeof(*disk), disk) != sizeof(*disk))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
_xlate_pv(disk);
|
_xlate_pvd(disk);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _write_all_pv(struct disk_list *data)
|
static int _write_all_pvd(struct disk_list *data)
|
||||||
{
|
{
|
||||||
const char *pv_name = dev_name(data->dev);
|
const char *pv_name = dev_name(data->dev);
|
||||||
|
|
||||||
if (!_write_pv(data)) {
|
if (!_write_pvd(data)) {
|
||||||
log_error("Failed to write PV structure onto %s", pv_name);
|
log_error("Failed to write PV structure onto %s", pv_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -437,10 +437,10 @@ static int _write_all_pv(struct disk_list *data)
|
|||||||
/*
|
/*
|
||||||
* Stop here for orphan pv's.
|
* Stop here for orphan pv's.
|
||||||
*/
|
*/
|
||||||
if (data->pv.vg_name[0] == '\0')
|
if (data->pvd.vg_name[0] == '\0')
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!_write_vg(data)) {
|
if (!_write_vgd(data)) {
|
||||||
log_error("Failed to write VG data to %s", pv_name);
|
log_error("Failed to write VG data to %s", pv_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -468,14 +468,14 @@ static int _write_all_pv(struct disk_list *data)
|
|||||||
* little sanity checking, so make sure correct
|
* little sanity checking, so make sure correct
|
||||||
* data is passed to here.
|
* data is passed to here.
|
||||||
*/
|
*/
|
||||||
int write_pvs(struct list *pvs)
|
int write_pvds(struct list *pvs)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
struct list *pvh;
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
if (!(_write_all_pv(dl)))
|
if (!(_write_all_pvd(dl)))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
log_debug("Successfully wrote data to %s", dev_name(dl->dev));
|
log_debug("Successfully wrote data to %s", dev_name(dl->dev));
|
||||||
|
@ -140,7 +140,7 @@ struct uuid_list {
|
|||||||
|
|
||||||
struct lvd_list {
|
struct lvd_list {
|
||||||
struct list list;
|
struct list list;
|
||||||
struct lv_disk lv;
|
struct lv_disk lvd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct disk_list {
|
struct disk_list {
|
||||||
@ -148,10 +148,10 @@ struct disk_list {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct list list;
|
struct list list;
|
||||||
|
|
||||||
struct pv_disk pv;
|
struct pv_disk pvd;
|
||||||
struct vg_disk vg;
|
struct vg_disk vgd;
|
||||||
struct list uuids;
|
struct list uuids;
|
||||||
struct list lvs;
|
struct list lvds;
|
||||||
struct pe_disk *extents;
|
struct pe_disk *extents;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -178,13 +178,13 @@ int calculate_extent_count(struct physical_volume *pv);
|
|||||||
* Low level io routines which read/write
|
* Low level io routines which read/write
|
||||||
* disk_lists.
|
* disk_lists.
|
||||||
*/
|
*/
|
||||||
struct disk_list *read_pv(struct device *dev, struct pool *mem,
|
struct disk_list *read_pvd(struct device *dev, struct pool *mem,
|
||||||
const char *vg_name);
|
const char *vg_name);
|
||||||
|
|
||||||
int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
|
int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
|
||||||
struct pool *mem, struct list *results);
|
struct pool *mem, struct list *results);
|
||||||
|
|
||||||
int write_pvs(struct list *pvs);
|
int write_pvds(struct list *pvs);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -27,7 +27,7 @@ static int _check_vgs(struct list *pvs)
|
|||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
first = dl;
|
first = dl;
|
||||||
else if (memcmp(&first->vg, &dl->vg, sizeof(first->vg))) {
|
else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
|
||||||
log_err("VG data differs between PVs %s and %s",
|
log_err("VG data differs between PVs %s and %s",
|
||||||
dev_name(first->dev), dev_name(dl->dev));
|
dev_name(first->dev), dev_name(dl->dev));
|
||||||
return 0;
|
return 0;
|
||||||
@ -36,9 +36,9 @@ static int _check_vgs(struct list *pvs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* On entry to fn, list known to be non-empty */
|
/* On entry to fn, list known to be non-empty */
|
||||||
if (!(pv_count == dl->vg.pv_cur)) {
|
if (!(pv_count == dl->vgd.pv_cur)) {
|
||||||
log_error("Only %d out of %d PV(s) found for VG %s",
|
log_error("Only %d out of %d PV(s) found for VG %s",
|
||||||
pv_count, dl->vg.pv_cur, dl->pv.vg_name);
|
pv_count, dl->vgd.pv_cur, dl->pvd.vg_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,10 +129,10 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
|
|||||||
dl->dev = pv->dev;
|
dl->dev = pv->dev;
|
||||||
|
|
||||||
list_init(&dl->uuids);
|
list_init(&dl->uuids);
|
||||||
list_init(&dl->lvs);
|
list_init(&dl->lvds);
|
||||||
|
|
||||||
if (!export_pv(&dl->pv, pv) ||
|
if (!export_pv(&dl->pvd, pv) ||
|
||||||
!export_vg(&dl->vg, vg) ||
|
!export_vg(&dl->vgd, vg) ||
|
||||||
!export_uuids(dl, vg) ||
|
!export_uuids(dl, vg) ||
|
||||||
!export_lvs(dl, vg, pv, prefix) ||
|
!export_lvs(dl, vg, pv, prefix) ||
|
||||||
!calculate_layout(dl)) {
|
!calculate_layout(dl)) {
|
||||||
@ -188,7 +188,7 @@ static int _vg_write(struct io_space *is, struct volume_group *vg)
|
|||||||
list_init(&pvs);
|
list_init(&pvs);
|
||||||
|
|
||||||
r = (_flatten_vg(mem, vg, &pvs, is->prefix, is->filter) &&
|
r = (_flatten_vg(mem, vg, &pvs, is->prefix, is->filter) &&
|
||||||
write_pvs(&pvs));
|
write_pvds(&pvs));
|
||||||
pool_destroy(mem);
|
pool_destroy(mem);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ static struct physical_volume *_pv_read(struct io_space *is,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dl = read_pv(dev, mem, NULL))) {
|
if (!(dl = read_pvd(dev, mem, NULL))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ static struct physical_volume *_pv_read(struct io_space *is,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!import_pv(is->mem, dl->dev, pv, &dl->pv)) {
|
if (!import_pv(is->mem, dl->dev, pv, &dl->pvd)) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -382,13 +382,13 @@ static int _pv_write(struct io_space *is, struct physical_volume *pv)
|
|||||||
dl->mem = mem;
|
dl->mem = mem;
|
||||||
dl->dev = pv->dev;
|
dl->dev = pv->dev;
|
||||||
|
|
||||||
if (!export_pv(&dl->pv, pv)) {
|
if (!export_pv(&dl->pvd, pv)) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add(&pvs, &dl->list);
|
list_add(&pvs, &dl->list);
|
||||||
if (!write_pvs(&pvs)) {
|
if (!write_pvds(&pvs)) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||||
*
|
*
|
||||||
|
* Translates between disk and in-core formats.
|
||||||
|
*
|
||||||
* This file is released under the LGPL.
|
* This file is released under the LGPL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -41,10 +43,10 @@ static int _fill_lv_array(struct logical_volume **lvs,
|
|||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
list_iterate(lvh, &dl->lvs) {
|
list_iterate(lvh, &dl->lvds) {
|
||||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
||||||
|
|
||||||
if (!(lv = find_lv(vg, ll->lv.lv_name))) {
|
if (!(lv = find_lv(vg, ll->lvd.lv_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -141,15 +143,15 @@ int export_pv(struct pv_disk *pvd, struct physical_volume *pv)
|
|||||||
int import_vg(struct pool *mem,
|
int import_vg(struct pool *mem,
|
||||||
struct volume_group *vg, struct disk_list *dl)
|
struct volume_group *vg, struct disk_list *dl)
|
||||||
{
|
{
|
||||||
struct vg_disk *vgd = &dl->vg;
|
struct vg_disk *vgd = &dl->vgd;
|
||||||
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
|
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
|
||||||
|
|
||||||
if (!_check_vg_name(dl->pv.vg_name)) {
|
if (!_check_vg_name(dl->pvd.vg_name)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg->name = pool_strdup(mem, dl->pv.vg_name))) {
|
if (!(vg->name = pool_strdup(mem, dl->pvd.vg_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -338,13 +340,13 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < dl->pv.pe_total; i++) {
|
for (i = 0; i < dl->pvd.pe_total; i++) {
|
||||||
lv_num = e[i].lv_num;
|
lv_num = e[i].lv_num;
|
||||||
|
|
||||||
if (lv_num == UNMAPPED_EXTENT)
|
if (lv_num == UNMAPPED_EXTENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
else if(lv_num > dl->pv.lv_cur) {
|
else if(lv_num > dl->pvd.lv_cur) {
|
||||||
log_err("invalid lv in extent map\n");
|
log_err("invalid lv in extent map\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -396,7 +398,7 @@ int import_pvs(struct pool *mem, struct list *pvs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!import_pv(mem, dl->dev, &pvl->pv, &dl->pv)) {
|
if (!import_pv(mem, dl->dev, &pvl->pv, &dl->pvd)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -427,6 +429,7 @@ static struct logical_volume *_add_lv(struct pool *mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_add(&vg->lvs, &ll->list);
|
list_add(&vg->lvs, &ll->list);
|
||||||
|
lv->vg = vg;
|
||||||
vg->lv_count++;
|
vg->lv_count++;
|
||||||
|
|
||||||
return lv;
|
return lv;
|
||||||
@ -442,9 +445,9 @@ int import_lvs(struct pool *mem, struct volume_group *vg,
|
|||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
list_iterate(lvh, &dl->lvs) {
|
list_iterate(lvh, &dl->lvds) {
|
||||||
ll = list_item(lvh, struct lvd_list);
|
ll = list_item(lvh, struct lvd_list);
|
||||||
lvd = &ll->lv;
|
lvd = &ll->lvd;
|
||||||
|
|
||||||
if (!find_lv(vg, lvd->lv_name) &&
|
if (!find_lv(vg, lvd->lv_name) &&
|
||||||
!_add_lv(mem, vg, lvd)) {
|
!_add_lv(mem, vg, lvd)) {
|
||||||
@ -468,7 +471,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
/*
|
/*
|
||||||
* setup the pv's extents array
|
* setup the pv's extents array
|
||||||
*/
|
*/
|
||||||
len = sizeof(struct pe_disk) * dl->pv.pe_total;
|
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
|
||||||
if (!(dl->extents = pool_alloc(dl->mem, len))) {
|
if (!(dl->extents = pool_alloc(dl->mem, len))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
@ -483,14 +486,14 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export_lv(&lvdl->lv, vg, &ll->lv, prefix);
|
export_lv(&lvdl->lvd, vg, &ll->lv, prefix);
|
||||||
if (!export_extents(dl, lv_num++, &ll->lv, pv)) {
|
if (!export_extents(dl, lv_num++, &ll->lv, pv)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add(&dl->lvs, &lvdl->list);
|
list_add(&dl->lvds, &lvdl->list);
|
||||||
dl->pv.lv_cur++;
|
dl->pvd.lv_cur++;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -546,11 +549,11 @@ void export_numbers(struct list *pvs, struct volume_group *vg)
|
|||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
dl->pv.pv_number = pv_num++;
|
dl->pvd.pv_number = pv_num++;
|
||||||
|
|
||||||
list_iterate(lvh, &dl->lvs) {
|
list_iterate(lvh, &dl->lvds) {
|
||||||
ll = list_item(lvh, struct lvd_list);
|
ll = list_item(lvh, struct lvd_list);
|
||||||
ll->lv.lv_number = _get_lv_number(vg, ll->lv.lv_name);
|
ll->lvd.lv_number = _get_lv_number(vg, ll->lvd.lv_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,13 +569,13 @@ void export_pv_act(struct list *pvs)
|
|||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
if (dl->pv.pv_status & PV_ACTIVE)
|
if (dl->pvd.pv_status & PV_ACTIVE)
|
||||||
act++;
|
act++;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
dl->vg.pv_act = act;
|
dl->vgd.pv_act = act;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,7 +593,7 @@ int export_vg_number(struct list *pvs, const char *vg_name,
|
|||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate(pvh, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
dl->vg.vg_number = vg_num;
|
dl->vgd.vg_number = vg_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -66,17 +66,17 @@ static void _calc_simple_layout(struct pv_disk *pvd)
|
|||||||
|
|
||||||
int _check_vg_limits(struct disk_list *dl)
|
int _check_vg_limits(struct disk_list *dl)
|
||||||
{
|
{
|
||||||
if (dl->vg.lv_max >= MAX_LV) {
|
if (dl->vgd.lv_max >= MAX_LV) {
|
||||||
log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
|
log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
|
||||||
"for VG '%s'", dl->vg.lv_max, MAX_LV - 1,
|
"for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
|
||||||
dl->pv.vg_name);
|
dl->pvd.vg_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dl->vg.pv_max >= MAX_PV) {
|
if (dl->vgd.pv_max >= MAX_PV) {
|
||||||
log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
|
log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
|
||||||
"for VG '%s'", dl->vg.pv_max, MAX_PV - 1,
|
"for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
|
||||||
dl->pv.vg_name);
|
dl->pvd.vg_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ int _check_vg_limits(struct disk_list *dl)
|
|||||||
*/
|
*/
|
||||||
int calculate_layout(struct disk_list *dl)
|
int calculate_layout(struct disk_list *dl)
|
||||||
{
|
{
|
||||||
struct pv_disk *pvd = &dl->pv;
|
struct pv_disk *pvd = &dl->pvd;
|
||||||
|
|
||||||
_calc_simple_layout(pvd);
|
_calc_simple_layout(pvd);
|
||||||
if (!_adjust_pe_on_disk(pvd)) {
|
if (!_adjust_pe_on_disk(pvd)) {
|
||||||
|
@ -40,10 +40,10 @@ int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
|
|||||||
|
|
||||||
list_iterate(pvh, &all_pvs) {
|
list_iterate(pvh, &all_pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
dl = list_item(pvh, struct disk_list);
|
||||||
if (!strcmp(dl->pv.vg_name, candidate_vg))
|
if (!strcmp(dl->pvd.vg_name, candidate_vg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
numbers[dl->vg.vg_number] = 1;
|
numbers[dl->vgd.vg_number] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_VG; i++) {
|
for (i = 0; i < MAX_VG; i++) {
|
||||||
|
@ -64,22 +64,6 @@ struct pe_specifier {
|
|||||||
uint32_t pe;
|
uint32_t pe;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_volume {
|
|
||||||
/* disk */
|
|
||||||
struct id id;
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
uint32_t status;
|
|
||||||
uint32_t read_ahead;
|
|
||||||
uint32_t stripes;
|
|
||||||
|
|
||||||
uint64_t size;
|
|
||||||
uint32_t le_count;
|
|
||||||
|
|
||||||
/* le -> pe mapping array */
|
|
||||||
struct pe_specifier *map;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct volume_group {
|
struct volume_group {
|
||||||
struct id id;
|
struct id id;
|
||||||
char *name;
|
char *name;
|
||||||
@ -102,6 +86,24 @@ struct volume_group {
|
|||||||
struct list lvs;
|
struct list lvs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct logical_volume {
|
||||||
|
/* disk */
|
||||||
|
struct id id;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
struct volume_group *vg;
|
||||||
|
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t read_ahead;
|
||||||
|
uint32_t stripes;
|
||||||
|
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t le_count;
|
||||||
|
|
||||||
|
/* le -> pe mapping array */
|
||||||
|
struct pe_specifier *map;
|
||||||
|
};
|
||||||
|
|
||||||
struct name_list {
|
struct name_list {
|
||||||
struct list list;
|
struct list list;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -119,11 +119,6 @@ static int lvchange_single(char *lv_name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("Updating logical volume %s on disk(s)", lv->name);
|
|
||||||
|
|
||||||
if (!ios->vg_write(ios, vg))
|
|
||||||
return ECMD_FAILED;
|
|
||||||
|
|
||||||
/* FIXME activate change */
|
/* FIXME activate change */
|
||||||
|
|
||||||
log_print("Logical volume %s changed", lv->name);
|
log_print("Logical volume %s changed", lv->name);
|
||||||
@ -157,6 +152,14 @@ static int lvchange_permission(struct logical_volume *lv)
|
|||||||
log_verbose("Setting logical volume %s read-only", lv->name);
|
log_verbose("Setting logical volume %s read-only", lv->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Updating logical volume %s on disk(s)", lv->name);
|
||||||
|
if (!ios->vg_write(ios, lv->vg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_very_verbose("Updating permissions for %s in kernel", lv->name);
|
||||||
|
if (!lv_update_write_access(lv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +188,18 @@ static int lvchange_availability(struct logical_volume *lv)
|
|||||||
log_verbose("Deactivating logical volume %s", lv->name);
|
log_verbose("Deactivating logical volume %s", lv->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Updating logical volume %s on disk(s)", lv->name);
|
||||||
|
if (!ios->vg_write(ios, lv->vg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_very_verbose("Updating %s in kernel", lv->name);
|
||||||
|
if (lv_stat & ACTIVE) {
|
||||||
|
if (!lv_activate(lv))
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
if (!lv_deactivate(lv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +241,11 @@ static int lvchange_contiguous(struct logical_volume *lv)
|
|||||||
lv->name);
|
lv->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_verbose("Updating logical volume %s on disk(s)", lv->name);
|
||||||
|
|
||||||
|
if (!ios->vg_write(ios, lv->vg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,5 +271,10 @@ static int lvchange_readahead(struct logical_volume *lv)
|
|||||||
lv->read_ahead = read_ahead;
|
lv->read_ahead = read_ahead;
|
||||||
log_verbose("Setting read ahead to %u for %s", read_ahead, lv->name);
|
log_verbose("Setting read ahead to %u for %s", read_ahead, lv->name);
|
||||||
|
|
||||||
|
log_verbose("Updating logical volume %s on disk(s)", lv->name);
|
||||||
|
|
||||||
|
if (!ios->vg_write(ios, lv->vg))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user