1
0
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:
Patrick Caulfield 2001-12-11 16:49:40 +00:00
parent 5b82db9a17
commit f4a7ce7c49
2 changed files with 201 additions and 36 deletions

View File

@ -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, &sectsize)) if (!dev_get_sectsize(dev, &sectsize))
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, &sectsize))
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);
}

View File

@ -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);