mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
- Change label format to include a string disk_type and a version number.
- The iterator can find labels by string and also appropriate version number (==, <= or any) if you want. - Add labels_match() call that compares the two labels and returns an error if they do not match. - Write labels in sector 1 & last rather than 2 & last as per Joe.
This commit is contained in:
parent
5b82db9a17
commit
f4a7ce7c49
@ -7,6 +7,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -27,16 +28,19 @@ static void *label_pool = NULL;
|
|||||||
struct label_ondisk
|
struct label_ondisk
|
||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t format_type;
|
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
uint16_t datalen;
|
uint16_t datalen;
|
||||||
uint16_t pad;
|
|
||||||
|
char disk_type[32];
|
||||||
|
uint32_t version[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filter_private
|
struct filter_private
|
||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
uint32_t format_type;
|
char disk_type[32];
|
||||||
|
uint32_t version[3];
|
||||||
|
int version_match;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +51,9 @@ static uint32_t calc_checksum(struct label *label)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
csum += label->magic;
|
csum += label->magic;
|
||||||
csum += label->format_type;
|
csum += label->version[0];
|
||||||
|
csum += label->version[1];
|
||||||
|
csum += label->version[2];
|
||||||
csum += label->datalen;
|
csum += label->datalen;
|
||||||
|
|
||||||
for (i=0; i<label->datalen; i++)
|
for (i=0; i<label->datalen; i++)
|
||||||
@ -55,6 +61,11 @@ static uint32_t calc_checksum(struct label *label)
|
|||||||
csum += label->data[i];
|
csum += label->data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<strlen(label->disk_type); i++)
|
||||||
|
{
|
||||||
|
csum += label->disk_type[i];
|
||||||
|
}
|
||||||
|
|
||||||
return csum;
|
return csum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +87,7 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
if (!dev_get_sectsize(dev, §size))
|
if (!dev_get_sectsize(dev, §size))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!dev_open(dev, O_RDWR))
|
if (!dev_open(dev, O_RDONLY))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (label_pool == NULL)
|
if (label_pool == NULL)
|
||||||
@ -86,38 +97,59 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
stack;
|
stack;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
ondisk = (struct label_ondisk *)block;
|
ondisk = (struct label_ondisk *)block;
|
||||||
|
|
||||||
status = dev_read(dev, sectsize*2, sectsize, block);
|
|
||||||
|
|
||||||
/* If the first label is bad then use the second */
|
/* If the first label is bad then use the second */
|
||||||
for (iter = 0; iter <= 1; iter++)
|
for (iter = 0; iter <= 1; iter++)
|
||||||
{
|
{
|
||||||
if (iter == 0)
|
if (iter == 0)
|
||||||
status = dev_read(dev, sectsize*2, sectsize, block);
|
status = dev_read(dev, sectsize, sectsize, block);
|
||||||
else
|
else
|
||||||
status = dev_read(dev, size*512 - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
status = dev_read(dev, size*512 - sectsize, sectsize, block);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
struct label incore;
|
struct label incore;
|
||||||
|
int i;
|
||||||
|
int found_nul;
|
||||||
|
|
||||||
|
/* If the MAGIC doesn't match there's no point in
|
||||||
|
carrying on */
|
||||||
|
if (xlate32(ondisk->magic) != LABEL_MAGIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Look for a NUL in the disk_type string so we don't
|
||||||
|
SEGV is something has gone horribly wrong */
|
||||||
|
found_nul = 0;
|
||||||
|
for (i=0; i<sizeof(ondisk->disk_type); i++)
|
||||||
|
if (ondisk->disk_type[i] == '\0')
|
||||||
|
found_nul = 1;
|
||||||
|
|
||||||
|
if (!found_nul)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Copy and convert endianness */
|
/* Copy and convert endianness */
|
||||||
incore.magic = xlate32(ondisk->magic);
|
incore.magic = xlate32(ondisk->magic);
|
||||||
incore.format_type = xlate32(ondisk->format_type);
|
incore.version[0] = xlate32(ondisk->version[0]);
|
||||||
|
incore.version[1] = xlate32(ondisk->version[1]);
|
||||||
|
incore.version[2] = xlate32(ondisk->version[2]);
|
||||||
|
for (i=0; i<strlen(ondisk->disk_type)+1; i++)
|
||||||
|
incore.disk_type[i] = ondisk->disk_type[i];
|
||||||
incore.checksum = xlate32(ondisk->checksum);
|
incore.checksum = xlate32(ondisk->checksum);
|
||||||
incore.datalen = xlate16(ondisk->datalen);
|
incore.datalen = xlate16(ondisk->datalen);
|
||||||
incore.data = block + sizeof(struct label_ondisk);
|
incore.data = block + sizeof(struct label_ondisk);
|
||||||
|
|
||||||
if (incore.magic != LABEL_MAGIC)
|
/* Make sure datalen is a sensible size too */
|
||||||
|
if (incore.datalen > sectsize)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check Checksum */
|
/* Check Checksum */
|
||||||
if (incore.checksum != calc_checksum(&incore))
|
if (incore.checksum != calc_checksum(&incore))
|
||||||
{
|
{
|
||||||
log_error("Checksum %d on device %s does not match. got %x, need %x", iter, dev_name(dev), incore.checksum, calc_checksum(&incore));
|
log_error("Checksum %d on device %s does not match. got %x, expected %x",
|
||||||
|
iter, dev_name(dev), incore.checksum, calc_checksum(&incore));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +159,9 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
if (!label->data)
|
if (!label->data)
|
||||||
{
|
{
|
||||||
stack;
|
stack;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(label->data, incore.data, incore.datalen);
|
memcpy(label->data, incore.data, incore.datalen);
|
||||||
label->pool = label_pool;
|
|
||||||
|
|
||||||
pool_free(label_pool, block);
|
pool_free(label_pool, block);
|
||||||
dev_close(dev);
|
dev_close(dev);
|
||||||
@ -152,6 +183,7 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
char *block;
|
char *block;
|
||||||
struct label_ondisk *ondisk;
|
struct label_ondisk *ondisk;
|
||||||
int status1, status2;
|
int status1, status2;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size))
|
if (!dev_get_size(dev, &size))
|
||||||
return 0;
|
return 0;
|
||||||
@ -170,7 +202,7 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
stack;
|
stack;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ondisk = (struct label_ondisk *)block;
|
ondisk = (struct label_ondisk *)block;
|
||||||
@ -178,7 +210,12 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
/* Make into ondisk format */
|
/* Make into ondisk format */
|
||||||
label->magic = LABEL_MAGIC;
|
label->magic = LABEL_MAGIC;
|
||||||
ondisk->magic = xlate32(LABEL_MAGIC);
|
ondisk->magic = xlate32(LABEL_MAGIC);
|
||||||
ondisk->format_type = xlate32(label->format_type);
|
|
||||||
|
ondisk->version[0] = xlate32(label->version[0]);
|
||||||
|
ondisk->version[1] = xlate32(label->version[1]);
|
||||||
|
ondisk->version[2] = xlate32(label->version[2]);
|
||||||
|
for (i=0; i<strlen(label->disk_type)+1; i++)
|
||||||
|
ondisk->disk_type[i] = label->disk_type[i];
|
||||||
ondisk->datalen = xlate16(label->datalen);
|
ondisk->datalen = xlate16(label->datalen);
|
||||||
ondisk->checksum = xlate32(calc_checksum(label));
|
ondisk->checksum = xlate32(calc_checksum(label));
|
||||||
memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
|
memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
|
||||||
@ -190,7 +227,7 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status1 = dev_write(dev, sectsize*2, sizeof(struct label_ondisk) + label->datalen, block);
|
status1 = dev_write(dev, sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
|
|
||||||
/* Write another at the end of the device */
|
/* Write another at the end of the device */
|
||||||
status2 = dev_write(dev, size*512 - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
status2 = dev_write(dev, size*512 - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
@ -210,7 +247,7 @@ int is_labelled(struct device *dev)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = label_read(dev, &l);
|
status = label_read(dev, &l);
|
||||||
if (status) pool_free(l.pool, l.data);
|
if (status) label_free(&l);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -220,14 +257,41 @@ static int _accept_format(struct dev_filter *f, struct device *dev)
|
|||||||
{
|
{
|
||||||
struct label l;
|
struct label l;
|
||||||
int status;
|
int status;
|
||||||
|
struct filter_private *fp = (struct filter_private *) f->private;
|
||||||
|
|
||||||
status = label_read(dev, &l);
|
status = label_read(dev, &l);
|
||||||
if (status) pool_free(l.pool, l.data);
|
if (status) label_free(&l);
|
||||||
|
|
||||||
if (status && l.format_type == (uint32_t)f->private)
|
if (status)
|
||||||
|
{
|
||||||
|
if (strcmp(l.disk_type, fp->disk_type) == 0)
|
||||||
|
{
|
||||||
|
switch (fp->version_match)
|
||||||
|
{
|
||||||
|
case VERSION_MATCH_EQUAL:
|
||||||
|
if (l.version[0] == fp->version[0] &&
|
||||||
|
l.version[1] == fp->version[1] &&
|
||||||
|
l.version[2] == fp->version[2])
|
||||||
return 1;
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
else
|
case VERSION_MATCH_LESSTHAN:
|
||||||
|
if (l.version[0] == fp->version[0] &&
|
||||||
|
l.version[1] < fp->version[1])
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VERSION_MATCH_LESSEQUAL:
|
||||||
|
if (l.version[0] == fp->version[0] &&
|
||||||
|
l.version[1] <= fp->version[1])
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VERSION_MATCH_ANY:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,12 +308,20 @@ static void _destroy(struct dev_filter *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* A filter to find devices with a particular label type on them */
|
/* A filter to find devices with a particular label type on them */
|
||||||
struct dev_filter *label_format_filter_create(uint32_t format_type)
|
struct dev_filter *label_format_filter_create(char *disk_type, uint32_t version[3], int match_type)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(10 * 1024);
|
struct pool *mem;
|
||||||
struct filter_private *fp;
|
struct filter_private *fp;
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
|
/* Validate the match type */
|
||||||
|
if (match_type != VERSION_MATCH_EQUAL &&
|
||||||
|
match_type != VERSION_MATCH_LESSTHAN &&
|
||||||
|
match_type != VERSION_MATCH_LESSEQUAL &&
|
||||||
|
match_type != VERSION_MATCH_ANY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mem = pool_create(10 * 1024);
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -266,7 +338,11 @@ struct dev_filter *label_format_filter_create(uint32_t format_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fp->mem = mem;
|
fp->mem = mem;
|
||||||
fp->format_type = format_type;
|
strcpy(fp->disk_type, disk_type);
|
||||||
|
fp->version[0] = version[0];
|
||||||
|
fp->version[1] = version[1];
|
||||||
|
fp->version[2] = version[2];
|
||||||
|
fp->version_match = match_type;
|
||||||
f->passes_filter = _accept_format;
|
f->passes_filter = _accept_format;
|
||||||
f->destroy = _destroy;
|
f->destroy = _destroy;
|
||||||
f->private = fp;
|
f->private = fp;
|
||||||
@ -311,3 +387,85 @@ struct dev_filter *label_filter_create()
|
|||||||
pool_destroy(mem);
|
pool_destroy(mem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if both labels are identical, 0 if not or there was an error */
|
||||||
|
int labels_match(struct device *dev)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t sectsize;
|
||||||
|
char *block1;
|
||||||
|
char *block2;
|
||||||
|
struct label_ondisk *ondisk1;
|
||||||
|
struct label_ondisk *ondisk2;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if (!dev_get_size(dev, &size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_get_sectsize(dev, §size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (label_pool == NULL)
|
||||||
|
label_pool = pool_create(512);
|
||||||
|
|
||||||
|
/* ALlocate some space for the blocks we are going to read in */
|
||||||
|
block1 = pool_alloc(label_pool, sectsize);
|
||||||
|
if (!block1)
|
||||||
|
{
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
block2 = pool_alloc(label_pool, sectsize);
|
||||||
|
if (!block2)
|
||||||
|
{
|
||||||
|
stack;
|
||||||
|
pool_free(label_pool, block1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ondisk1 = (struct label_ondisk *)block1;
|
||||||
|
ondisk2 = (struct label_ondisk *)block2;
|
||||||
|
|
||||||
|
/* Fetch em */
|
||||||
|
if (!dev_open(dev, O_RDONLY))
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
if (!dev_read(dev, sectsize, sectsize, block1))
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
if (!dev_read(dev, size*512 - sectsize, sectsize, block2))
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
dev_close(dev);
|
||||||
|
|
||||||
|
/* Is it labelled? */
|
||||||
|
if (xlate32(ondisk1->magic) != LABEL_MAGIC)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
/* Compare the whole structs */
|
||||||
|
if (memcmp(ondisk1, ondisk2, sizeof(struct label_ondisk)) != 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
/* OK, check the data area */
|
||||||
|
if (memcmp(block1 + sizeof(struct label_ondisk),
|
||||||
|
block2 + sizeof(struct label_ondisk),
|
||||||
|
xlate16(ondisk1->datalen)) != 0)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
/* They match !! */
|
||||||
|
status = 1;
|
||||||
|
|
||||||
|
finish:
|
||||||
|
pool_free(label_pool, block2);
|
||||||
|
pool_free(label_pool, block1);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free data area allocated by label_read() */
|
||||||
|
void label_free(struct label *label)
|
||||||
|
{
|
||||||
|
if (label->data)
|
||||||
|
pool_free(label_pool, label->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -7,18 +7,25 @@
|
|||||||
struct label
|
struct label
|
||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t format_type;
|
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
uint16_t datalen;
|
uint16_t datalen;
|
||||||
char *data;
|
|
||||||
void *pool; /* Pool that data is allocated from */
|
char disk_type[32];
|
||||||
|
uint32_t version[3];
|
||||||
|
|
||||||
|
char *data; /* Should be freed with label_free() */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define VERSION_MATCH_EQUAL 1
|
||||||
|
#define VERSION_MATCH_LESSTHAN 2
|
||||||
|
#define VERSION_MATCH_LESSEQUAL 3
|
||||||
|
#define VERSION_MATCH_ANY 4
|
||||||
|
|
||||||
extern int label_write(struct device *dev, struct label *label);
|
extern int label_write(struct device *dev, struct label *label);
|
||||||
extern int label_read(struct device *dev, struct label *label);
|
extern int label_read(struct device *dev, struct label *label);
|
||||||
|
extern void label_free(struct label *label);
|
||||||
extern int is_labelled(struct device *dev);
|
extern int is_labelled(struct device *dev);
|
||||||
|
extern int labels_match(struct device *dev);
|
||||||
|
|
||||||
extern struct dev_filter *label_filter_create();
|
extern struct dev_filter *label_filter_create();
|
||||||
extern struct dev_filter *label_format_filter_create(uint32_t format_type);
|
extern struct dev_filter *label_format_filter_create(char *disk_type, uint32_t version[3], int match_type);
|
||||||
|
Loading…
Reference in New Issue
Block a user