mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Write the location of both labels in the labels so we can check them. I don't do
much with this ATM (apart from check that they all match up). Use a different CRC routine.
This commit is contained in:
parent
6b4657e81f
commit
515df8784a
@ -32,6 +32,8 @@ struct label_ondisk
|
|||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
|
uint64_t label1_loc;
|
||||||
|
uint64_t label2_loc;
|
||||||
uint16_t datalen;
|
uint16_t datalen;
|
||||||
uint16_t pad;
|
uint16_t pad;
|
||||||
|
|
||||||
@ -48,33 +50,25 @@ struct filter_private
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* CRC32 code taken from Linux kernel */
|
/* Calculate CRC32 of a buffer */
|
||||||
static int crc32( int initial, char * s, int length )
|
static uint32_t crc32(uint32_t initial, const unsigned char *databuf, size_t datalen)
|
||||||
{
|
{
|
||||||
/* indices */
|
uint32_t idx, crc = initial;
|
||||||
int perByte;
|
static const u_int crctab[] = {
|
||||||
int perBit;
|
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||||
|
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||||
|
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||||
|
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
|
||||||
|
};
|
||||||
|
|
||||||
/* crc polynomial for Ethernet */
|
for (idx = 0; idx < datalen; idx++) {
|
||||||
const unsigned long poly = 0xedb88320;
|
crc ^= *databuf++;
|
||||||
|
crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||||
/* crc value - carry over */
|
crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||||
unsigned long crc_value = initial;
|
}
|
||||||
|
return crc;
|
||||||
for ( perByte = 0; perByte < length; perByte ++ ) {
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
c = *(s++);
|
|
||||||
for ( perBit = 0; perBit < 8; perBit++ ) {
|
|
||||||
crc_value = (crc_value>>1)^
|
|
||||||
(((crc_value^c)&0x01)?poly:0);
|
|
||||||
c >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return crc_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Calculate crc */
|
/* Calculate crc */
|
||||||
static uint32_t calc_crc(struct label *label)
|
static uint32_t calc_crc(struct label *label)
|
||||||
{
|
{
|
||||||
@ -89,6 +83,13 @@ static uint32_t calc_crc(struct label *label)
|
|||||||
return crcval;
|
return crcval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate the locations we should find the labels in */
|
||||||
|
static inline void get_label_locations(uint64_t size, uint32_t sectsize, long *first, long *second)
|
||||||
|
{
|
||||||
|
*first = sectsize;
|
||||||
|
*second = size*BLOCK_SIZE - sectsize;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read a label off disk - the data area is allocated
|
/* Read a label off disk - the data area is allocated
|
||||||
from the pool in label->pool and should be freed by
|
from the pool in label->pool and should be freed by
|
||||||
the caller */
|
the caller */
|
||||||
@ -100,6 +101,7 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
struct label_ondisk *ondisk;
|
struct label_ondisk *ondisk;
|
||||||
int status;
|
int status;
|
||||||
int iter;
|
int iter;
|
||||||
|
long offset[2];
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size))
|
if (!dev_get_size(dev, &size))
|
||||||
return 0;
|
return 0;
|
||||||
@ -120,15 +122,12 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ondisk = (struct label_ondisk *)block;
|
ondisk = (struct label_ondisk *)block;
|
||||||
|
get_label_locations(size, sectsize, &offset[0], &offset[1]);
|
||||||
|
|
||||||
/* 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)
|
status = dev_read(dev, offset[iter], sectsize, block);
|
||||||
status = dev_read(dev, sectsize, sectsize, block);
|
|
||||||
else
|
|
||||||
status = dev_read(dev, size*BLOCK_SIZE - sectsize, sectsize, block);
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
struct label incore;
|
struct label incore;
|
||||||
@ -156,6 +155,8 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
incore.version[0] = xlate32(ondisk->version[0]);
|
incore.version[0] = xlate32(ondisk->version[0]);
|
||||||
incore.version[1] = xlate32(ondisk->version[1]);
|
incore.version[1] = xlate32(ondisk->version[1]);
|
||||||
incore.version[2] = xlate32(ondisk->version[2]);
|
incore.version[2] = xlate32(ondisk->version[2]);
|
||||||
|
incore.label1_loc = xlate64(ondisk->label1_loc);
|
||||||
|
incore.label2_loc = xlate64(ondisk->label2_loc);
|
||||||
incore.datalen = xlate16(ondisk->datalen);
|
incore.datalen = xlate16(ondisk->datalen);
|
||||||
incore.data = block + sizeof(struct label_ondisk);
|
incore.data = block + sizeof(struct label_ondisk);
|
||||||
incore.crc = xlate32(ondisk->crc);
|
incore.crc = xlate32(ondisk->crc);
|
||||||
@ -172,6 +173,14 @@ int label_read(struct device *dev, struct label *label)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check label locations match our view of the device */
|
||||||
|
if (incore.label1_loc != offset[0])
|
||||||
|
log_error("Label 1 location is wrong in label %d - check block size of the device\n",
|
||||||
|
iter);
|
||||||
|
if (incore.label2_loc != offset[1])
|
||||||
|
log_error("Label 2 location is wrong in label %d - the size of the device must have changed\n",
|
||||||
|
iter);
|
||||||
|
|
||||||
/* Copy to user's data area */
|
/* Copy to user's data area */
|
||||||
*label = incore;
|
*label = incore;
|
||||||
label->data = pool_alloc(label_pool, incore.datalen);
|
label->data = pool_alloc(label_pool, incore.datalen);
|
||||||
@ -202,6 +211,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;
|
||||||
|
long offset[2];
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size))
|
if (!dev_get_size(dev, &size))
|
||||||
return 0;
|
return 0;
|
||||||
@ -226,12 +236,18 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
|
|
||||||
/* Make sure the label has the right magic number in it */
|
/* Make sure the label has the right magic number in it */
|
||||||
label->magic = LABEL_MAGIC;
|
label->magic = LABEL_MAGIC;
|
||||||
|
label->label1_loc = offset[0];
|
||||||
|
label->label2_loc = offset[1];
|
||||||
|
|
||||||
|
get_label_locations(size, sectsize, &offset[0], &offset[1]);
|
||||||
|
|
||||||
/* Make into ondisk format */
|
/* Make into ondisk format */
|
||||||
ondisk->magic = xlate32(LABEL_MAGIC);
|
ondisk->magic = xlate32(LABEL_MAGIC);
|
||||||
ondisk->version[0] = xlate32(label->version[0]);
|
ondisk->version[0] = xlate32(label->version[0]);
|
||||||
ondisk->version[1] = xlate32(label->version[1]);
|
ondisk->version[1] = xlate32(label->version[1]);
|
||||||
ondisk->version[2] = xlate32(label->version[2]);
|
ondisk->version[2] = xlate32(label->version[2]);
|
||||||
|
ondisk->label1_loc = xlate64(offset[0]);
|
||||||
|
ondisk->label2_loc = xlate64(offset[1]);
|
||||||
ondisk->datalen = xlate16(label->datalen);
|
ondisk->datalen = xlate16(label->datalen);
|
||||||
strncpy(ondisk->disk_type, label->disk_type, sizeof(ondisk->disk_type));
|
strncpy(ondisk->disk_type, label->disk_type, sizeof(ondisk->disk_type));
|
||||||
memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
|
memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
|
||||||
@ -244,13 +260,13 @@ int label_write(struct device *dev, struct label *label)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status1 = dev_write(dev, sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
status1 = dev_write(dev, offset[0], sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
if (!status1)
|
if (!status1)
|
||||||
log_error("Error writing label 1\n");
|
log_error("Error writing label 1\n");
|
||||||
|
|
||||||
/* Write another at the end of the device */
|
/* Write another at the end of the device */
|
||||||
status2 = dev_write(dev, size*BLOCK_SIZE - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
status2 = dev_write(dev, offset[1], sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
if (!status1)
|
if (!status2)
|
||||||
log_error("Error writing label 2\n");
|
log_error("Error writing label 2\n");
|
||||||
|
|
||||||
pool_free(label_pool, block);
|
pool_free(label_pool, block);
|
||||||
@ -419,6 +435,7 @@ int labels_match(struct device *dev)
|
|||||||
struct label_ondisk *ondisk1;
|
struct label_ondisk *ondisk1;
|
||||||
struct label_ondisk *ondisk2;
|
struct label_ondisk *ondisk2;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
long offset[2];
|
||||||
|
|
||||||
if (!dev_get_size(dev, &size))
|
if (!dev_get_size(dev, &size))
|
||||||
return 0;
|
return 0;
|
||||||
@ -447,14 +464,16 @@ int labels_match(struct device *dev)
|
|||||||
ondisk1 = (struct label_ondisk *)block1;
|
ondisk1 = (struct label_ondisk *)block1;
|
||||||
ondisk2 = (struct label_ondisk *)block2;
|
ondisk2 = (struct label_ondisk *)block2;
|
||||||
|
|
||||||
|
get_label_locations(size, sectsize, &offset[0], &offset[1]);
|
||||||
|
|
||||||
/* Fetch em */
|
/* Fetch em */
|
||||||
if (!dev_open(dev, O_RDONLY))
|
if (!dev_open(dev, O_RDONLY))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (!dev_read(dev, sectsize, sectsize, block1))
|
if (!dev_read(dev, offset[0], sectsize, block1))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (!dev_read(dev, size*BLOCK_SIZE - sectsize, sectsize, block2))
|
if (!dev_read(dev, offset[1], sectsize, block2))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
dev_close(dev);
|
dev_close(dev);
|
||||||
|
@ -8,6 +8,8 @@ struct label
|
|||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
|
uint64_t label1_loc;
|
||||||
|
uint64_t label2_loc;
|
||||||
uint16_t datalen;
|
uint16_t datalen;
|
||||||
|
|
||||||
char disk_type[32];
|
char disk_type[32];
|
||||||
|
Loading…
Reference in New Issue
Block a user