mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
o split struct mapped_device into mapped_device and dm_table
o seperated loading of a table from binding a table to the device These should allow multiple tables to be managed by dm-fs
This commit is contained in:
parent
4183d3fe6c
commit
0f29dc2f2d
@ -35,11 +35,11 @@
|
|||||||
/* FIXME: Use value from local range for now, for co-existence with LVM 1 */
|
/* FIXME: Use value from local range for now, for co-existence with LVM 1 */
|
||||||
#define DM_BLK_MAJOR 124
|
#define DM_BLK_MAJOR 124
|
||||||
|
|
||||||
struct mapped_device;
|
struct dm_table;
|
||||||
typedef unsigned int offset_t;
|
typedef unsigned int offset_t;
|
||||||
|
|
||||||
/* constructor, destructor and map fn types */
|
/* constructor, destructor and map fn types */
|
||||||
typedef int (*dm_ctr_fn)(offset_t b, offset_t e, struct mapped_device *md,
|
typedef int (*dm_ctr_fn)(offset_t b, offset_t e, struct dm_table *t,
|
||||||
const char *cb, const char *ce, void **result);
|
const char *cb, const char *ce, void **result);
|
||||||
typedef void (*dm_dtr_fn)(void *c);
|
typedef void (*dm_dtr_fn)(void *c);
|
||||||
typedef int (*dm_map_fn)(struct buffer_head *bh, void *context);
|
typedef int (*dm_map_fn)(struct buffer_head *bh, void *context);
|
||||||
@ -47,9 +47,12 @@ typedef int (*dm_map_fn)(struct buffer_head *bh, void *context);
|
|||||||
int register_map_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
int register_map_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
||||||
dm_map_fn map);
|
dm_map_fn map);
|
||||||
|
|
||||||
/* contructors should call this to make sure any destination devices
|
|
||||||
are handled correctly (ie. opened/closed) */
|
/* contructors should call this to make sure any
|
||||||
int dm_add_device(struct mapped_device *md, kdev_t dev);
|
* destination devices are handled correctly
|
||||||
|
* (ie. opened/closed).
|
||||||
|
*/
|
||||||
|
int dm_table_add_device(struct dm_table *t, kdev_t dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,21 +49,25 @@ static struct proc_dir_entry *_control;
|
|||||||
|
|
||||||
static devfs_handle_t _dev_dir;
|
static devfs_handle_t _dev_dir;
|
||||||
|
|
||||||
|
static int process_control(const char *b, const char *e, int minor,
|
||||||
|
struct dm_table **map);
|
||||||
|
static int process_table(const char *b, const char *e, int minor,
|
||||||
|
struct dm_table **map);
|
||||||
static int line_splitter(struct file *file, const char *buffer,
|
static int line_splitter(struct file *file, const char *buffer,
|
||||||
unsigned long count, void *data);
|
unsigned long count, void *data);
|
||||||
static int process_control(const char *b, const char *e, int minor);
|
|
||||||
static int process_table(const char *b, const char *e, int minor);
|
|
||||||
static int get_word(const char *b, const char *e,
|
static int get_word(const char *b, const char *e,
|
||||||
const char **wb, const char **we);
|
const char **wb, const char **we);
|
||||||
static int tok_cmp(const char *str, const char *b, const char *e);
|
static int tok_cmp(const char *str, const char *b, const char *e);
|
||||||
static void tok_cpy(char *dest, size_t max,
|
static void tok_cpy(char *dest, size_t max,
|
||||||
const char *b, const char *e);
|
const char *b, const char *e);
|
||||||
|
|
||||||
typedef int (*process_fn)(const char *b, const char *e, int minor);
|
typedef int (*process_fn)(const char *b, const char *e, int minor,
|
||||||
|
struct dm_table **map);
|
||||||
|
|
||||||
struct pf_data {
|
struct pf_data {
|
||||||
process_fn fn;
|
process_fn fn;
|
||||||
int minor;
|
int minor;
|
||||||
|
struct dm_table *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
int dm_fs_init(void)
|
int dm_fs_init(void)
|
||||||
@ -119,6 +123,7 @@ int dm_fs_add(struct mapped_device *md)
|
|||||||
|
|
||||||
pfd->fn = process_table;
|
pfd->fn = process_table;
|
||||||
pfd->minor = MINOR(md->dev);
|
pfd->minor = MINOR(md->dev);
|
||||||
|
pfd->map = 0;
|
||||||
|
|
||||||
if (!(md->pde = create_proc_entry(md->name, S_IRUGO | S_IWUSR,
|
if (!(md->pde = create_proc_entry(md->name, S_IRUGO | S_IWUSR,
|
||||||
_proc_dir))) {
|
_proc_dir))) {
|
||||||
@ -148,6 +153,11 @@ int dm_fs_add(struct mapped_device *md)
|
|||||||
int dm_fs_remove(struct mapped_device *md)
|
int dm_fs_remove(struct mapped_device *md)
|
||||||
{
|
{
|
||||||
if (md->pde) {
|
if (md->pde) {
|
||||||
|
struct pf_data *pfd = (struct pf_data *) md->pde->data;
|
||||||
|
|
||||||
|
if (pfd->map)
|
||||||
|
dm_table_destroy(pfd->map);
|
||||||
|
|
||||||
kfree(md->pde->data);
|
kfree(md->pde->data);
|
||||||
remove_proc_entry(md->name, _proc_dir);
|
remove_proc_entry(md->name, _proc_dir);
|
||||||
md->pde = 0;
|
md->pde = 0;
|
||||||
@ -158,7 +168,8 @@ int dm_fs_remove(struct mapped_device *md)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_control(const char *b, const char *e, int minor)
|
static int process_control(const char *b, const char *e, int minor,
|
||||||
|
struct dm_table **map)
|
||||||
{
|
{
|
||||||
const char *wb, *we;
|
const char *wb, *we;
|
||||||
char name[64];
|
char name[64];
|
||||||
@ -201,10 +212,12 @@ static int process_control(const char *b, const char *e, int minor)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_table(const char *b, const char *e, int minor)
|
static int process_table(const char *b, const char *e, int minor,
|
||||||
|
struct dm_table **map)
|
||||||
{
|
{
|
||||||
const char *wb, *we;
|
const char *wb, *we;
|
||||||
struct mapped_device *md = dm_find_by_minor(minor);
|
struct mapped_device *md = dm_find_by_minor(minor);
|
||||||
|
struct dm_table *table = *map;
|
||||||
void *context;
|
void *context;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -219,12 +232,15 @@ static int process_table(const char *b, const char *e, int minor)
|
|||||||
dm_suspend(md);
|
dm_suspend(md);
|
||||||
|
|
||||||
/* start loading a table */
|
/* start loading a table */
|
||||||
dm_table_start(md);
|
table = *map = dm_table_create();
|
||||||
|
|
||||||
} else if (!tok_cmp("end", b, e)) {
|
} else if (!tok_cmp("end", b, e)) {
|
||||||
/* activate the device ... <evil chuckle> ... */
|
/* activate the device ... <evil chuckle> ... */
|
||||||
dm_table_complete(md);
|
if (table) {
|
||||||
|
dm_table_complete(table);
|
||||||
|
dm_bind(md, table);
|
||||||
dm_activate(md);
|
dm_activate(md);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* add the new entry */
|
/* add the new entry */
|
||||||
@ -253,18 +269,18 @@ static int process_table(const char *b, const char *e, int minor)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* check there isn't a gap */
|
/* check there isn't a gap */
|
||||||
if ((md->num_targets &&
|
if ((table->num_targets &&
|
||||||
start != md->highs[md->num_targets - 1] + 1) ||
|
start != table->highs[table->num_targets - 1] + 1) ||
|
||||||
(!md->num_targets && start)) {
|
(!table->num_targets && start)) {
|
||||||
WARN("gap in target ranges");
|
WARN("gap in target ranges");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
high = start + (size - 1);
|
high = start + (size - 1);
|
||||||
if ((r = t->ctr(start, high, md, we, e, &context)))
|
if ((r = t->ctr(start, high, table, we, e, &context)))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if ((r = dm_table_add_entry(md, high, t->map, context)))
|
if ((r = dm_table_add_entry(table, high, t->map, context)))
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +318,7 @@ static int line_splitter(struct file *file, const char *buffer,
|
|||||||
while((b != e) && *b != '\n')
|
while((b != e) && *b != '\n')
|
||||||
b++;
|
b++;
|
||||||
|
|
||||||
if ((r = pfd->fn(lb, b, pfd->minor)))
|
if ((r = pfd->fn(lb, b, pfd->minor, &pfd->map)))
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ static inline ulong div_up(ulong n, ulong size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ceiling(log_size(n)) */
|
/* ceiling(log_size(n)) */
|
||||||
static uint int_log(ulong base, ulong n)
|
static uint int_log(ulong n, ulong base)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
@ -57,14 +57,14 @@ static uint int_log(ulong base, ulong n)
|
|||||||
* return the highest key that you could lookup
|
* return the highest key that you could lookup
|
||||||
* from the n'th node on level l of the btree.
|
* from the n'th node on level l of the btree.
|
||||||
*/
|
*/
|
||||||
static offset_t high(struct mapped_device *md, int l, int n)
|
static offset_t high(struct dm_table *t, int l, int n)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
if (n >= md->counts[l])
|
if (n >= t->counts[l])
|
||||||
return (offset_t) -1;
|
return (offset_t) -1;
|
||||||
|
|
||||||
if (l == md->depth - 1)
|
if (l == t->depth - 1)
|
||||||
return md->index[l][((n + 1) * KEYS_PER_NODE) - 1];
|
return t->index[l][((n + 1) * KEYS_PER_NODE) - 1];
|
||||||
|
|
||||||
l++;
|
l++;
|
||||||
n = (n + 1) * (KEYS_PER_NODE + 1) - 1;
|
n = (n + 1) * (KEYS_PER_NODE + 1) - 1;
|
||||||
@ -77,15 +77,15 @@ static offset_t high(struct mapped_device *md, int l, int n)
|
|||||||
* fills in a level of the btree based on the
|
* fills in a level of the btree based on the
|
||||||
* highs of the level below it.
|
* highs of the level below it.
|
||||||
*/
|
*/
|
||||||
static int setup_btree_index(int l, struct mapped_device *md)
|
static int setup_btree_index(int l, struct dm_table *t)
|
||||||
{
|
{
|
||||||
int n, c, cn;
|
int n, c, cn;
|
||||||
|
|
||||||
for (n = 0, cn = 0; n < md->counts[l]; n++) {
|
for (n = 0, cn = 0; n < t->counts[l]; n++) {
|
||||||
offset_t *k = md->index[l] + (n * KEYS_PER_NODE);
|
offset_t *k = t->index[l] + (n * KEYS_PER_NODE);
|
||||||
|
|
||||||
for (c = 0; c < KEYS_PER_NODE; c++)
|
for (c = 0; c < KEYS_PER_NODE; c++)
|
||||||
k[c] = high(md, l + 1, cn++);
|
k[c] = high(t, l + 1, cn++);
|
||||||
cn++; /* one extra for the child that's
|
cn++; /* one extra for the child that's
|
||||||
greater than all keys */
|
greater than all keys */
|
||||||
}
|
}
|
||||||
@ -93,31 +93,15 @@ static int setup_btree_index(int l, struct mapped_device *md)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_table_free(struct mapped_device *md)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < md->depth; i++) {
|
|
||||||
vfree(md->index[i]);
|
|
||||||
md->index[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfree(md->targets);
|
|
||||||
|
|
||||||
md->highs = 0;
|
|
||||||
md->targets = 0;
|
|
||||||
|
|
||||||
md->num_targets = 0;
|
|
||||||
md->num_allocated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* md->highs, and md->targets are managed as
|
* highs, and targets are managed as dynamic
|
||||||
* dynamic arrays during a table load.
|
* arrays during a table load.
|
||||||
*/
|
*/
|
||||||
static int alloc_targets(struct mapped_device *md, int num)
|
static int alloc_targets(struct dm_table *t, int num)
|
||||||
{
|
{
|
||||||
offset_t *n_highs;
|
offset_t *n_highs;
|
||||||
struct target *n_targets;
|
struct target *n_targets;
|
||||||
|
int n = t->num_targets;
|
||||||
|
|
||||||
if (!(n_highs = vmalloc(sizeof(*n_highs) * num)))
|
if (!(n_highs = vmalloc(sizeof(*n_highs) * num)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -127,93 +111,143 @@ static int alloc_targets(struct mapped_device *md, int num)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md->num_targets) {
|
if (n) {
|
||||||
memcpy(n_highs, md->highs,
|
memcpy(n_highs, t->highs, sizeof(*n_highs) * n);
|
||||||
sizeof(*n_highs) * md->num_targets);
|
memcpy(n_targets, t->targets, sizeof(*n_targets) * n);
|
||||||
|
|
||||||
memcpy(n_targets, md->targets,
|
|
||||||
sizeof(*n_targets) * md->num_targets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vfree(md->highs);
|
vfree(t->highs);
|
||||||
vfree(md->targets);
|
vfree(t->targets);
|
||||||
|
|
||||||
md->num_allocated = num;
|
t->num_allocated = num;
|
||||||
md->highs = n_highs;
|
t->highs = n_highs;
|
||||||
md->targets = n_targets;
|
t->targets = n_targets;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_table_start(struct mapped_device *md)
|
struct dm_table *dm_table_create(void)
|
||||||
{
|
{
|
||||||
int r;
|
struct dm_table *t = kmalloc(sizeof(struct dm_table), GFP_NOIO);
|
||||||
set_bit(DM_LOADING, &md->state);
|
|
||||||
|
|
||||||
dm_table_free(md);
|
if (!t)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* allocate a single nodes worth to start with */
|
memset(t, 0, sizeof(*t));
|
||||||
if ((r = alloc_targets(md, KEYS_PER_NODE)))
|
|
||||||
|
/* allocate a single nodes worth of targets to
|
||||||
|
begin with */
|
||||||
|
if (t && alloc_targets(t, KEYS_PER_NODE)) {
|
||||||
|
kfree(t);
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_table_destroy(struct dm_table *t)
|
||||||
|
{
|
||||||
|
struct dev_list *d, *n;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* free the indexes */
|
||||||
|
for (i = 0; i < t->depth; i++) {
|
||||||
|
vfree(t->index[i]);
|
||||||
|
t->index[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* t->highs was already freed as t->index[t->depth - 1] */
|
||||||
|
vfree(t->targets);
|
||||||
|
kfree(t);
|
||||||
|
|
||||||
|
/* free the device list */
|
||||||
|
for (d = t->devices; d; d = n) {
|
||||||
|
n = d->next;
|
||||||
|
kfree(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checks to see if we need to extend highs or targets
|
||||||
|
*/
|
||||||
|
static inline int check_space(struct dm_table *t)
|
||||||
|
{
|
||||||
|
if (t->num_targets >= t->num_allocated)
|
||||||
|
return alloc_targets(t, t->num_allocated * 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adds a target to the map
|
||||||
|
*/
|
||||||
|
int dm_table_add_entry(struct dm_table *t, offset_t high,
|
||||||
|
dm_map_fn target, void *private)
|
||||||
|
{
|
||||||
|
int r, n;
|
||||||
|
|
||||||
|
if ((r = check_space(t)))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
n = t->num_targets++;
|
||||||
|
t->highs[n] = high;
|
||||||
|
t->targets[n].map = target;
|
||||||
|
t->targets[n].private = private;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int check_space(struct mapped_device *md)
|
int dm_table_add_device(struct dm_table *t, kdev_t dev)
|
||||||
{
|
{
|
||||||
if (md->num_targets >= md->num_allocated)
|
struct dev_list *d = kmalloc(sizeof(*d), GFP_KERNEL);
|
||||||
return alloc_targets(md, md->num_allocated * 2);
|
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
d->dev = dev;
|
||||||
|
d->next = t->devices;
|
||||||
|
t->devices = d;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_table_add_entry(struct mapped_device *md, offset_t high,
|
/*
|
||||||
dm_map_fn target, void *context)
|
* builds the btree to index the map
|
||||||
{
|
*/
|
||||||
int r;
|
int dm_table_complete(struct dm_table *t)
|
||||||
|
|
||||||
if ((r = check_space(md)))
|
|
||||||
return r;
|
|
||||||
|
|
||||||
md->highs[md->num_targets] = high;
|
|
||||||
md->targets[md->num_targets].map = target;
|
|
||||||
md->targets[md->num_targets].private = context;
|
|
||||||
md->num_targets++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dm_table_complete(struct mapped_device *md)
|
|
||||||
{
|
{
|
||||||
int i, leaf_nodes;
|
int i, leaf_nodes;
|
||||||
|
|
||||||
clear_bit(DM_LOADING, &md->state);
|
|
||||||
|
|
||||||
/* how many indexes will the btree have ? */
|
/* how many indexes will the btree have ? */
|
||||||
leaf_nodes = div_up(md->num_targets, KEYS_PER_NODE);
|
leaf_nodes = div_up(t->num_targets, KEYS_PER_NODE);
|
||||||
i = 1 + int_log(leaf_nodes, KEYS_PER_NODE + 1);
|
i = 1 + int_log(leaf_nodes, KEYS_PER_NODE + 1);
|
||||||
|
|
||||||
md->depth = i;
|
/* work out how many nodes are in each layer */
|
||||||
md->counts[md->depth - 1] = div_up(md->num_targets, KEYS_PER_NODE);
|
t->depth = i;
|
||||||
|
t->counts[t->depth - 1] = div_up(t->num_targets, KEYS_PER_NODE);
|
||||||
|
|
||||||
while (--i)
|
while (--i)
|
||||||
md->counts[i - 1] = div_up(md->counts[i], KEYS_PER_NODE + 1);
|
t->counts[i - 1] = div_up(t->counts[i], KEYS_PER_NODE + 1);
|
||||||
|
|
||||||
for (i = 0; i < (md->depth - 1); i++) {
|
/* allocate memory for the internal nodes */
|
||||||
size_t s = NODE_SIZE * md->counts[i];
|
for (i = 0; i < (t->depth - 1); i++) {
|
||||||
md->index[i] = vmalloc(s);
|
size_t s = NODE_SIZE * t->counts[i];
|
||||||
memset(md->index[i], -1, s);
|
t->index[i] = vmalloc(s);
|
||||||
|
memset(t->index[i], -1, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bottom layer is easy */
|
/* leaf layer has already been set up */
|
||||||
md->index[md->depth - 1] = md->highs;
|
t->index[t->depth - 1] = t->highs;
|
||||||
|
|
||||||
/* fill in higher levels */
|
/* fill in higher levels */
|
||||||
for (i = md->depth - 1; i; i--)
|
for (i = t->depth - 1; i; i--)
|
||||||
setup_btree_index(i - 1, md);
|
setup_btree_index(i - 1, t);
|
||||||
|
|
||||||
set_bit(DM_LOADED, &md->state);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(dm_table_add_device);
|
||||||
|
@ -47,6 +47,9 @@ struct target_type *dm_get_target(const char *name)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* register a new target_type.
|
||||||
|
*/
|
||||||
int register_map_target(const char *name, dm_ctr_fn ctr,
|
int register_map_target(const char *name, dm_ctr_fn ctr,
|
||||||
dm_dtr_fn dtr, dm_map_fn map)
|
dm_dtr_fn dtr, dm_map_fn map)
|
||||||
{
|
{
|
||||||
@ -82,7 +85,7 @@ int register_map_target(const char *name, dm_ctr_fn ctr,
|
|||||||
* io-err: always fails an io, useful for bringing
|
* io-err: always fails an io, useful for bringing
|
||||||
* up LV's that have holes in them.
|
* up LV's that have holes in them.
|
||||||
*/
|
*/
|
||||||
static int io_err_ctr(offset_t b, offset_t e, struct mapped_device *md,
|
static int io_err_ctr(offset_t b, offset_t e, struct dm_table *t,
|
||||||
const char *cb, const char *ce, void **result)
|
const char *cb, const char *ce, void **result)
|
||||||
{
|
{
|
||||||
/* this takes no arguments */
|
/* this takes no arguments */
|
||||||
@ -109,11 +112,13 @@ struct linear_c {
|
|||||||
int offset; /* FIXME: we need a signed offset type */
|
int offset; /* FIXME: we need a signed offset type */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int linear_ctr(offset_t low, offset_t high, struct mapped_device *md,
|
/*
|
||||||
|
* construct a linear mapping.
|
||||||
|
* <major> <minor> <offset>
|
||||||
|
*/
|
||||||
|
static int linear_ctr(offset_t low, offset_t high, struct dm_table *t,
|
||||||
const char *cb, const char *ce, void **result)
|
const char *cb, const char *ce, void **result)
|
||||||
{
|
{
|
||||||
/* <major> <minor> <offset> */
|
|
||||||
|
|
||||||
struct linear_c *lc;
|
struct linear_c *lc;
|
||||||
unsigned int major, minor, start;
|
unsigned int major, minor, start;
|
||||||
int r;
|
int r;
|
||||||
@ -135,7 +140,7 @@ static int linear_ctr(offset_t low, offset_t high, struct mapped_device *md,
|
|||||||
lc->dev = MKDEV((int) major, (int) minor);
|
lc->dev = MKDEV((int) major, (int) minor);
|
||||||
lc->offset = (int) start - (int) low;
|
lc->offset = (int) start - (int) low;
|
||||||
|
|
||||||
if ((r = dm_add_device(md, lc->dev))) {
|
if ((r = dm_table_add_device(t, lc->dev))) {
|
||||||
kfree(lc);
|
kfree(lc);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -63,23 +63,12 @@ static int _block_size[MAX_DEVICES];
|
|||||||
static int _blksize_size[MAX_DEVICES];
|
static int _blksize_size[MAX_DEVICES];
|
||||||
static int _hardsect_size[MAX_DEVICES];
|
static int _hardsect_size[MAX_DEVICES];
|
||||||
|
|
||||||
static int blk_open(struct inode *inode, struct file *file);
|
|
||||||
static int blk_close(struct inode *inode, struct file *file);
|
|
||||||
static int blk_ioctl(struct inode *inode, struct file *file,
|
|
||||||
uint command, ulong a);
|
|
||||||
|
|
||||||
struct block_device_operations dm_blk_dops = {
|
|
||||||
open: blk_open,
|
|
||||||
release: blk_close,
|
|
||||||
ioctl: blk_ioctl
|
|
||||||
};
|
|
||||||
|
|
||||||
static int request(request_queue_t *q, int rw, struct buffer_head *bh);
|
static int request(request_queue_t *q, int rw, struct buffer_head *bh);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setup and teardown the driver
|
* setup and teardown the driver
|
||||||
*/
|
*/
|
||||||
static int init_dm(void)
|
static int dm_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -112,7 +101,7 @@ static int init_dm(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit_dm(void)
|
static void dm_exit(void)
|
||||||
{
|
{
|
||||||
if(kmem_cache_shrink(_io_hook_cache))
|
if(kmem_cache_shrink(_io_hook_cache))
|
||||||
WARN("it looks like there are still some io_hooks allocated");
|
WARN("it looks like there are still some io_hooks allocated");
|
||||||
@ -252,6 +241,11 @@ inline static void free_deferred(struct deferred_io *di)
|
|||||||
kfree(di);
|
kfree(di);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bh->b_end_io routine that decrements the
|
||||||
|
* pending count and then calls the original
|
||||||
|
* bh->b_end_io fn.
|
||||||
|
*/
|
||||||
static void dec_pending(struct buffer_head *bh, int uptodate)
|
static void dec_pending(struct buffer_head *bh, int uptodate)
|
||||||
{
|
{
|
||||||
struct io_hook *ih = bh->b_private;
|
struct io_hook *ih = bh->b_private;
|
||||||
@ -267,6 +261,9 @@ static void dec_pending(struct buffer_head *bh, int uptodate)
|
|||||||
bh->b_end_io(bh, uptodate);
|
bh->b_end_io(bh, uptodate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add the bh to the list of deferred io.
|
||||||
|
*/
|
||||||
static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw)
|
static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw)
|
||||||
{
|
{
|
||||||
struct deferred_io *di = alloc_deferred();
|
struct deferred_io *di = alloc_deferred();
|
||||||
@ -289,15 +286,17 @@ static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do the bh mapping for a given leaf
|
||||||
|
*/
|
||||||
inline static int __map_buffer(struct mapped_device *md,
|
inline static int __map_buffer(struct mapped_device *md,
|
||||||
struct buffer_head *bh, int node)
|
struct buffer_head *bh, int leaf)
|
||||||
{
|
{
|
||||||
dm_map_fn fn;
|
dm_map_fn fn;
|
||||||
void *context;
|
void *context;
|
||||||
struct io_hook *ih = 0;
|
struct io_hook *ih = 0;
|
||||||
int r;
|
int r;
|
||||||
struct target *ti = md->targets + node;
|
struct target *ti = md->map->targets + leaf;
|
||||||
|
|
||||||
fn = ti->map;
|
fn = ti->map;
|
||||||
context = ti->private;
|
context = ti->private;
|
||||||
@ -334,15 +333,17 @@ inline static int __map_buffer(struct mapped_device *md,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int __find_node(struct mapped_device *md, struct buffer_head *bh)
|
/*
|
||||||
|
* search the btree for the correct target.
|
||||||
|
*/
|
||||||
|
inline static int __find_node(struct dm_table *t, struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
int i = 0, l, r = 0;
|
int i = 0, l, r = 0;
|
||||||
offset_t *node;
|
offset_t *node;
|
||||||
|
|
||||||
/* search the btree for the correct target */
|
for (l = 0; l < t->depth; l++) {
|
||||||
for (l = 0; l < md->depth; l++) {
|
|
||||||
r = ((KEYS_PER_NODE + 1) * r) + i;
|
r = ((KEYS_PER_NODE + 1) * r) + i;
|
||||||
node = md->index[l] + (r * KEYS_PER_NODE);
|
node = t->index[l] + (r * KEYS_PER_NODE);
|
||||||
|
|
||||||
for (i = 0; i < KEYS_PER_NODE; i++)
|
for (i = 0; i < KEYS_PER_NODE; i++)
|
||||||
if (node[i] >= bh->b_rsector)
|
if (node[i] >= bh->b_rsector)
|
||||||
@ -363,7 +364,7 @@ static int request(request_queue_t *q, int rw, struct buffer_head *bh)
|
|||||||
rl;
|
rl;
|
||||||
md = _devs[minor];
|
md = _devs[minor];
|
||||||
|
|
||||||
if (!md || !test_bit(DM_LOADED, &md->state))
|
if (!md || !md->map)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
/* if we're suspended we have to queue this io for later */
|
/* if we're suspended we have to queue this io for later */
|
||||||
@ -380,7 +381,7 @@ static int request(request_queue_t *q, int rw, struct buffer_head *bh)
|
|||||||
rl; /* FIXME: there's still a race here */
|
rl; /* FIXME: there's still a race here */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!__map_buffer(md, bh, __find_node(md, bh)))
|
if (!__map_buffer(md, bh, __find_node(md->map, bh)))
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
ru;
|
ru;
|
||||||
@ -394,6 +395,10 @@ static int request(request_queue_t *q, int rw, struct buffer_head *bh)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see if the device with a specific minor # is
|
||||||
|
* free.
|
||||||
|
*/
|
||||||
static inline int __specific_dev(int minor)
|
static inline int __specific_dev(int minor)
|
||||||
{
|
{
|
||||||
if (minor > MAX_DEVICES) {
|
if (minor > MAX_DEVICES) {
|
||||||
@ -407,6 +412,9 @@ static inline int __specific_dev(int minor)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find the first free device.
|
||||||
|
*/
|
||||||
static inline int __any_old_dev(void)
|
static inline int __any_old_dev(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -418,6 +426,9 @@ static inline int __any_old_dev(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocate and initialise a blank device.
|
||||||
|
*/
|
||||||
static struct mapped_device *alloc_dev(int minor)
|
static struct mapped_device *alloc_dev(int minor)
|
||||||
{
|
{
|
||||||
struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
|
struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
|
||||||
@ -445,16 +456,10 @@ static struct mapped_device *alloc_dev(int minor)
|
|||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct mapped_device *__find_by_name(const char *name)
|
/*
|
||||||
{
|
* open a device so we can use it as a map
|
||||||
int i;
|
* destination.
|
||||||
for (i = 0; i < MAX_DEVICES; i++)
|
*/
|
||||||
if (_devs[i] && !strcmp(_devs[i]->name, name))
|
|
||||||
return _devs[i];
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int open_dev(struct dev_list *d)
|
static int open_dev(struct dev_list *d)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@ -470,6 +475,9 @@ static int open_dev(struct dev_list *d)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close a device that we've been using.
|
||||||
|
*/
|
||||||
static void close_dev(struct dev_list *d)
|
static void close_dev(struct dev_list *d)
|
||||||
{
|
{
|
||||||
blkdev_put(d->bd, BDEV_FILE);
|
blkdev_put(d->bd, BDEV_FILE);
|
||||||
@ -477,18 +485,14 @@ static void close_dev(struct dev_list *d)
|
|||||||
d->bd = 0;
|
d->bd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __find_hardsect_size(struct mapped_device *md)
|
static inline struct mapped_device *__find_by_name(const char *name)
|
||||||
{
|
{
|
||||||
int r = INT_MAX, s;
|
int i;
|
||||||
struct dev_list *dl;
|
for (i = 0; i < MAX_DEVICES; i++)
|
||||||
|
if (_devs[i] && !strcmp(_devs[i]->name, name))
|
||||||
|
return _devs[i];
|
||||||
|
|
||||||
for (dl = md->devices; dl; dl = dl->next) {
|
return 0;
|
||||||
s = get_hardsect_size(dl->dev);
|
|
||||||
if (s < r)
|
|
||||||
r = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mapped_device *dm_find_by_name(const char *name)
|
struct mapped_device *dm_find_by_name(const char *name)
|
||||||
@ -513,6 +517,9 @@ struct mapped_device *dm_find_by_minor(int minor)
|
|||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor for a new device
|
||||||
|
*/
|
||||||
int dm_create(const char *name, int minor)
|
int dm_create(const char *name, int minor)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@ -544,10 +551,14 @@ int dm_create(const char *name, int minor)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destructor for the device. md->map is
|
||||||
|
* deliberately not destroyed, dm-fs should manage
|
||||||
|
* table objects.
|
||||||
|
*/
|
||||||
int dm_remove(const char *name)
|
int dm_remove(const char *name)
|
||||||
{
|
{
|
||||||
struct mapped_device *md;
|
struct mapped_device *md;
|
||||||
struct dev_list *d, *n;
|
|
||||||
int minor, r;
|
int minor, r;
|
||||||
|
|
||||||
wl;
|
wl;
|
||||||
@ -566,12 +577,6 @@ int dm_remove(const char *name)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_table_free(md);
|
|
||||||
for (d = md->devices; d; d = n) {
|
|
||||||
n = d->next;
|
|
||||||
kfree(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
minor = MINOR(md->dev);
|
minor = MINOR(md->dev);
|
||||||
kfree(md);
|
kfree(md);
|
||||||
_devs[minor] = 0;
|
_devs[minor] = 0;
|
||||||
@ -580,20 +585,57 @@ int dm_remove(const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_add_device(struct mapped_device *md, kdev_t dev)
|
/*
|
||||||
|
* the hardsect size for a mapped device is the
|
||||||
|
* smallest hard sect size from the devices it
|
||||||
|
* maps onto.
|
||||||
|
*/
|
||||||
|
static int __find_hardsect_size(struct dev_list *dl)
|
||||||
{
|
{
|
||||||
struct dev_list *d = kmalloc(sizeof(*d), GFP_KERNEL);
|
int result = INT_MAX, size;
|
||||||
|
|
||||||
if (!d)
|
while(dl) {
|
||||||
return -EINVAL;
|
size = get_hardsect_size(dl->dev);
|
||||||
|
if (size < result)
|
||||||
|
result = size;
|
||||||
|
dl = dl->next;
|
||||||
|
}
|
||||||
|
|
||||||
d->dev = dev;
|
return result;
|
||||||
d->next = md->devices;
|
}
|
||||||
md->devices = d;
|
|
||||||
|
/*
|
||||||
|
* bind a table to the device, the device must not
|
||||||
|
* be active, though it could have another table
|
||||||
|
* aready bound.
|
||||||
|
*/
|
||||||
|
int dm_bind(struct mapped_device *md, struct dm_table *t)
|
||||||
|
{
|
||||||
|
int minor = MINOR(md->dev);
|
||||||
|
|
||||||
|
wl;
|
||||||
|
if (is_active(md)) {
|
||||||
|
wu;
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
md->map = t;
|
||||||
|
|
||||||
|
_block_size[minor] = (t->highs[t->num_targets - 1] + 1) >> 1;
|
||||||
|
|
||||||
|
/* FIXME: block size depends on the mapping table */
|
||||||
|
_blksize_size[minor] = BLOCK_SIZE;
|
||||||
|
_hardsect_size[minor] = __find_hardsect_size(t->devices);
|
||||||
|
register_disk(NULL, md->dev, 1, &dm_blk_dops, _block_size[minor]);
|
||||||
|
wu;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* requeue the deferred buffer_heads by calling
|
||||||
|
* generic_make_request.
|
||||||
|
*/
|
||||||
static void __flush_deferred_io(struct mapped_device *md)
|
static void __flush_deferred_io(struct mapped_device *md)
|
||||||
{
|
{
|
||||||
struct deferred_io *c, *n;
|
struct deferred_io *c, *n;
|
||||||
@ -605,9 +647,14 @@ static void __flush_deferred_io(struct mapped_device *md)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make the device available for use, if was
|
||||||
|
* previously suspended rather than newly created
|
||||||
|
* then all queued io is flushed
|
||||||
|
*/
|
||||||
int dm_activate(struct mapped_device *md)
|
int dm_activate(struct mapped_device *md)
|
||||||
{
|
{
|
||||||
int ret, minor;
|
int ret;
|
||||||
struct dev_list *d, *od;
|
struct dev_list *d, *od;
|
||||||
|
|
||||||
wl;
|
wl;
|
||||||
@ -617,27 +664,17 @@ int dm_activate(struct mapped_device *md)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!md->num_targets) {
|
if (!md->map) {
|
||||||
wu;
|
wu;
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open all the devices */
|
/* open all the devices */
|
||||||
for (d = md->devices; d; d = d->next)
|
for (d = md->map->devices; d; d = d->next)
|
||||||
if ((ret = open_dev(d)))
|
if ((ret = open_dev(d)))
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
minor = MINOR(md->dev);
|
|
||||||
|
|
||||||
_block_size[minor] = (md->highs[md->num_targets - 1] + 1) >> 1;
|
|
||||||
_blksize_size[minor] = BLOCK_SIZE; /* FIXME: this depends on
|
|
||||||
the mapping table */
|
|
||||||
_hardsect_size[minor] = __find_hardsect_size(md);
|
|
||||||
|
|
||||||
register_disk(NULL, md->dev, 1, &dm_blk_dops, _block_size[minor]);
|
|
||||||
|
|
||||||
set_bit(DM_ACTIVE, &md->state);
|
set_bit(DM_ACTIVE, &md->state);
|
||||||
|
|
||||||
__flush_deferred_io(md);
|
__flush_deferred_io(md);
|
||||||
wu;
|
wu;
|
||||||
|
|
||||||
@ -645,17 +682,27 @@ int dm_activate(struct mapped_device *md)
|
|||||||
|
|
||||||
bad:
|
bad:
|
||||||
od = d;
|
od = d;
|
||||||
for (d = md->devices; d != od; d = d->next)
|
for (d = md->map->devices; d != od; d = d->next)
|
||||||
close_dev(d);
|
close_dev(d);
|
||||||
ru;
|
ru;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we need to be able to change a mapping table
|
||||||
|
* under a mounted filesystem. for example we
|
||||||
|
* might want to move some data in the background.
|
||||||
|
* Before the table can be swapped with
|
||||||
|
* dm_bind_table, dm_suspend must be called to
|
||||||
|
* flush any in flight buffer_heads and ensure
|
||||||
|
* that any further io gets deferred.
|
||||||
|
*/
|
||||||
void dm_suspend(struct mapped_device *md)
|
void dm_suspend(struct mapped_device *md)
|
||||||
{
|
{
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
struct dev_list *d;
|
struct dev_list *d;
|
||||||
|
|
||||||
if (!is_active(md))
|
if (!is_active(md))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -676,7 +723,7 @@ void dm_suspend(struct mapped_device *md)
|
|||||||
remove_wait_queue(&md->wait, &wait);
|
remove_wait_queue(&md->wait, &wait);
|
||||||
|
|
||||||
/* close all the devices */
|
/* close all the devices */
|
||||||
for (d = md->devices; d; d = d->next)
|
for (d = md->map->devices; d; d = d->next)
|
||||||
close_dev(d);
|
close_dev(d);
|
||||||
|
|
||||||
clear_bit(DM_ACTIVE, &md->state);
|
clear_bit(DM_ACTIVE, &md->state);
|
||||||
@ -684,11 +731,17 @@ void dm_suspend(struct mapped_device *md)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct block_device_operations dm_blk_dops = {
|
||||||
|
open: blk_open,
|
||||||
|
release: blk_close,
|
||||||
|
ioctl: blk_ioctl
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* module hooks
|
* module hooks
|
||||||
*/
|
*/
|
||||||
module_init(init_dm);
|
module_init(dm_init);
|
||||||
module_exit(exit_dm);
|
module_exit(dm_exit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
|
@ -137,9 +137,8 @@
|
|||||||
#define DM_NAME_LEN 64
|
#define DM_NAME_LEN 64
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DM_LOADED = 0,
|
DM_BOUND = 0, /* device has been bound to a table */
|
||||||
DM_LOADING,
|
DM_ACTIVE, /* device is running */
|
||||||
DM_ACTIVE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -182,6 +181,24 @@ struct target {
|
|||||||
void *private;
|
void *private;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the btree
|
||||||
|
*/
|
||||||
|
struct dm_table {
|
||||||
|
/* btree table */
|
||||||
|
int depth;
|
||||||
|
int counts[MAX_DEPTH]; /* in nodes */
|
||||||
|
offset_t *index[MAX_DEPTH];
|
||||||
|
|
||||||
|
int num_targets;
|
||||||
|
int num_allocated;
|
||||||
|
offset_t *highs;
|
||||||
|
struct target *targets;
|
||||||
|
|
||||||
|
/* a list of devices used by this table */
|
||||||
|
struct dev_list *devices;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the actual device struct
|
* the actual device struct
|
||||||
*/
|
*/
|
||||||
@ -198,46 +215,40 @@ struct mapped_device {
|
|||||||
/* a list of io's that arrived while we were suspended */
|
/* a list of io's that arrived while we were suspended */
|
||||||
struct deferred_io *deferred;
|
struct deferred_io *deferred;
|
||||||
|
|
||||||
/* btree table */
|
struct dm_table *map;
|
||||||
int depth;
|
|
||||||
int counts[MAX_DEPTH]; /* in nodes */
|
|
||||||
offset_t *index[MAX_DEPTH];
|
|
||||||
|
|
||||||
int num_targets;
|
|
||||||
int num_allocated;
|
|
||||||
offset_t *highs;
|
|
||||||
struct target *targets;
|
|
||||||
|
|
||||||
/* used by dm-fs.c */
|
/* used by dm-fs.c */
|
||||||
devfs_handle_t devfs_entry;
|
devfs_handle_t devfs_entry;
|
||||||
struct proc_dir_entry *pde;
|
struct proc_dir_entry *pde;
|
||||||
|
|
||||||
/* a list of devices used by this md */
|
|
||||||
struct dev_list *devices;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct block_device_operations dm_blk_dops;
|
extern struct block_device_operations dm_blk_dops;
|
||||||
|
|
||||||
|
|
||||||
/* dm-target.c */
|
/* dm-target.c */
|
||||||
int dm_target_init(void);
|
int dm_target_init(void);
|
||||||
struct target_type *dm_get_target(const char *name);
|
struct target_type *dm_get_target(const char *name);
|
||||||
|
|
||||||
|
|
||||||
/* dm.c */
|
/* dm.c */
|
||||||
struct mapped_device *dm_find_by_name(const char *name);
|
struct mapped_device *dm_find_by_name(const char *name);
|
||||||
struct mapped_device *dm_find_by_minor(int minor);
|
struct mapped_device *dm_find_by_minor(int minor);
|
||||||
|
|
||||||
int dm_create(const char *name, int minor);
|
int dm_create(const char *name, int minor);
|
||||||
int dm_remove(const char *name);
|
int dm_remove(const char *name);
|
||||||
|
int dm_bind(struct mapped_device *md, struct dm_table *t);
|
||||||
int dm_activate(struct mapped_device *md);
|
int dm_activate(struct mapped_device *md);
|
||||||
void dm_suspend(struct mapped_device *md);
|
void dm_suspend(struct mapped_device *md);
|
||||||
|
|
||||||
|
|
||||||
/* dm-table.c */
|
/* dm-table.c */
|
||||||
int dm_table_start(struct mapped_device *md);
|
struct dm_table *dm_table_create(void);
|
||||||
int dm_table_add_entry(struct mapped_device *md, offset_t high,
|
void dm_table_destroy(struct dm_table *t);
|
||||||
dm_map_fn target, void *context);
|
|
||||||
int dm_table_complete(struct mapped_device *md);
|
int dm_table_add_entry(struct dm_table *t, offset_t high,
|
||||||
void dm_table_free(struct mapped_device *md);
|
dm_map_fn target, void *private);
|
||||||
|
int dm_table_complete(struct dm_table *t);
|
||||||
|
|
||||||
|
|
||||||
/* dm-fs.c */
|
/* dm-fs.c */
|
||||||
int dm_fs_init(void);
|
int dm_fs_init(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user