mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
Label reading/writing code.
Not tested the filter yet.
This commit is contained in:
parent
db73838ca4
commit
3dd5cbe54f
304
lib/label/label.c
Normal file
304
lib/label/label.c
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001 Sistina Software
|
||||||
|
*
|
||||||
|
* This file is released under the LGPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "dev-cache.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "label.h"
|
||||||
|
#include "pool.h"
|
||||||
|
#include "xlate.h"
|
||||||
|
|
||||||
|
/* Label Magic is "LnXl" - error: imagination failure */
|
||||||
|
#define LABEL_MAGIC 0x6c586e4c
|
||||||
|
|
||||||
|
/* Our memory pool */
|
||||||
|
static void *label_pool = NULL;
|
||||||
|
|
||||||
|
/* This is just the "struct label" with the data pointer removed */
|
||||||
|
struct label_ondisk
|
||||||
|
{
|
||||||
|
uint32_t magic;
|
||||||
|
uint32_t format_type;
|
||||||
|
uint32_t checksum;
|
||||||
|
uint16_t datalen;
|
||||||
|
uint16_t pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct filter_private
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
uint32_t format_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Calculate checksum */
|
||||||
|
static uint32_t calc_checksum(struct label *label)
|
||||||
|
{
|
||||||
|
uint32_t csum = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
csum += label->magic;
|
||||||
|
csum += label->format_type;
|
||||||
|
csum += label->datalen;
|
||||||
|
|
||||||
|
for (i=0; i<label->datalen; i++)
|
||||||
|
{
|
||||||
|
csum += label->data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return csum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int label_read(struct device *dev, struct label *label)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t sectsize;
|
||||||
|
char *block;
|
||||||
|
struct label_ondisk *ondisk;
|
||||||
|
int status;
|
||||||
|
int iter;
|
||||||
|
|
||||||
|
if (!dev_get_size(dev, &size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_get_sectsize(dev, §size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (dev_open(dev, O_RDWR))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (label_pool == NULL)
|
||||||
|
label_pool = pool_create(512);
|
||||||
|
|
||||||
|
block = pool_alloc(label_pool, sectsize);
|
||||||
|
if (!block)
|
||||||
|
{
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ondisk = (struct label_ondisk *)block;
|
||||||
|
|
||||||
|
status = dev_read(dev, sectsize*2, sectsize, block);
|
||||||
|
|
||||||
|
/* If the first label is bad then use the second */
|
||||||
|
for (iter = 0; iter <= 1; iter++)
|
||||||
|
{
|
||||||
|
if (iter == 0)
|
||||||
|
status = dev_read(dev, sectsize*2, sectsize, block);
|
||||||
|
else
|
||||||
|
status = dev_read(dev, size*512 - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
struct label incore;
|
||||||
|
|
||||||
|
/* Copy and convert endianness */
|
||||||
|
incore.magic = xlate32(ondisk->magic);
|
||||||
|
incore.checksum = xlate32(ondisk->checksum);
|
||||||
|
incore.datalen = xlate16(ondisk->datalen);
|
||||||
|
incore.data = block + sizeof(struct label_ondisk);
|
||||||
|
|
||||||
|
if (incore.magic != LABEL_MAGIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check Checksum */
|
||||||
|
if (incore.checksum != calc_checksum(&incore))
|
||||||
|
{
|
||||||
|
log_error("Checksum %d does not match\n", iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*label = incore;
|
||||||
|
label->data = pool_alloc(label_pool, incore.datalen);
|
||||||
|
if (!label->data)
|
||||||
|
{
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
label->pool = label_pool;
|
||||||
|
if (label->data) memcpy(label->data, incore.data, incore.datalen);
|
||||||
|
pool_free(label_pool, block);
|
||||||
|
dev_close(dev);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_free(label_pool, block);
|
||||||
|
dev_close(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int label_write(struct device *dev, struct label *label)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t sectsize;
|
||||||
|
char *block;
|
||||||
|
struct label_ondisk *ondisk;
|
||||||
|
int status1, status2;
|
||||||
|
|
||||||
|
if (!dev_get_size(dev, &size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_get_sectsize(dev, §size))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Can the metata fit in the remaining space ? */
|
||||||
|
if (label->datalen > sectsize - sizeof(struct label_ondisk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (label_pool == NULL)
|
||||||
|
label_pool = pool_create(512);
|
||||||
|
|
||||||
|
block = pool_alloc(label_pool, sizeof(struct label_ondisk) + label->datalen);
|
||||||
|
if (!block)
|
||||||
|
{
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ondisk = (struct label_ondisk *)block;
|
||||||
|
|
||||||
|
/* Make into ondisk format */
|
||||||
|
ondisk->magic = xlate32(LABEL_MAGIC);
|
||||||
|
ondisk->format_type = xlate32(label->format_type);
|
||||||
|
ondisk->datalen = xlate16(label->datalen);
|
||||||
|
ondisk->checksum = xlate32(calc_checksum(label));
|
||||||
|
memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
|
||||||
|
|
||||||
|
/* Write metadata to disk */
|
||||||
|
if (!dev_open(dev, O_RDWR))
|
||||||
|
{
|
||||||
|
pool_free(label_pool, block);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status1 = dev_write(dev, sectsize*2, sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
|
|
||||||
|
/* Write another at the end of the device */
|
||||||
|
status2 = dev_write(dev, size*512 - sectsize, sizeof(struct label_ondisk) + label->datalen, block);
|
||||||
|
|
||||||
|
pool_free(label_pool, block);
|
||||||
|
dev_close(dev);
|
||||||
|
|
||||||
|
return ((status1 != 0) && (status2 != 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return 1 for Yes, 0 for No */
|
||||||
|
int is_labelled(struct device *dev)
|
||||||
|
{
|
||||||
|
struct label l;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = label_read(dev, &l);
|
||||||
|
pool_free(l.pool, l.data);
|
||||||
|
|
||||||
|
return 1-status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the device is labelled and has the right format_type */
|
||||||
|
static int _accept_format(struct dev_filter *f, struct device *dev)
|
||||||
|
{
|
||||||
|
struct label l;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = label_read(dev, &l);
|
||||||
|
pool_free(l.pool, l.data);
|
||||||
|
|
||||||
|
if (status && l.format_type == (uint32_t)f->private)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We just want to know if it's labelled or not */
|
||||||
|
static int _accept_label(struct dev_filter *f, struct device *dev)
|
||||||
|
{
|
||||||
|
return is_labelled(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _destroy(struct dev_filter *f)
|
||||||
|
{
|
||||||
|
struct filter_private *fp = (struct filter_private *) f->private;
|
||||||
|
pool_destroy(fp->mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A filter to find devices with a particular label type on them */
|
||||||
|
struct dev_filter *label_format_filter_create(uint32_t format_type)
|
||||||
|
{
|
||||||
|
struct pool *mem = pool_create(10 * 1024);
|
||||||
|
struct filter_private *fp;
|
||||||
|
struct dev_filter *f;
|
||||||
|
|
||||||
|
if (!mem) {
|
||||||
|
stack;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
|
||||||
|
stack;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fp = pool_zalloc(mem, sizeof(*fp)))) {
|
||||||
|
stack;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->mem = mem;
|
||||||
|
fp->format_type = format_type;
|
||||||
|
f->passes_filter = _accept_format;
|
||||||
|
f->destroy = _destroy;
|
||||||
|
f->private = fp;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
pool_destroy(mem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A filter to find devices with any label on them */
|
||||||
|
struct dev_filter *label_filter_create()
|
||||||
|
{
|
||||||
|
struct pool *mem = pool_create(10 * 1024);
|
||||||
|
struct filter_private *fp;
|
||||||
|
struct dev_filter *f;
|
||||||
|
|
||||||
|
if (!mem) {
|
||||||
|
stack;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
|
||||||
|
stack;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fp = pool_zalloc(mem, sizeof(*fp)))) {
|
||||||
|
stack;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->mem = mem;
|
||||||
|
f->passes_filter = _accept_label;
|
||||||
|
f->destroy = _destroy;
|
||||||
|
f->private = fp;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
pool_destroy(mem);
|
||||||
|
return NULL;
|
||||||
|
}
|
24
lib/label/label.h
Normal file
24
lib/label/label.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||||
|
*
|
||||||
|
* This file is released under the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct label
|
||||||
|
{
|
||||||
|
uint32_t magic;
|
||||||
|
uint32_t format_type;
|
||||||
|
uint32_t checksum;
|
||||||
|
uint16_t datalen;
|
||||||
|
char *data;
|
||||||
|
void *pool; /* Pool that data is allocated from */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern int label_write(struct device *dev, struct label *label);
|
||||||
|
extern int label_read(struct device *dev, struct label *label);
|
||||||
|
extern int is_labelled(struct device *dev);
|
||||||
|
|
||||||
|
extern struct dev_filter *label_filter_create();
|
||||||
|
extern struct dev_filter *label_format_filter_create(uint32_t format_type);
|
Loading…
Reference in New Issue
Block a user