From 04555ae65080ad89c956a5bd4bb8b442c978d830 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Fri, 31 Aug 2001 15:13:33 +0000 Subject: [PATCH] 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 --- driver/device-mapper/device-mapper.h | 13 +- driver/device-mapper/dm-fs.c | 44 ++++-- driver/device-mapper/dm-table.c | 196 +++++++++++++++----------- driver/device-mapper/dm-target.c | 15 +- driver/device-mapper/dm.c | 199 +++++++++++++++++---------- driver/device-mapper/dm.h | 53 ++++--- 6 files changed, 321 insertions(+), 199 deletions(-) diff --git a/driver/device-mapper/device-mapper.h b/driver/device-mapper/device-mapper.h index a186e0183..6ee085d52 100644 --- a/driver/device-mapper/device-mapper.h +++ b/driver/device-mapper/device-mapper.h @@ -35,11 +35,11 @@ /* FIXME: Use value from local range for now, for co-existence with LVM 1 */ #define DM_BLK_MAJOR 124 -struct mapped_device; +struct dm_table; typedef unsigned int offset_t; /* 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); typedef void (*dm_dtr_fn)(void *c); 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, dm_map_fn map); -/* contructors should call this to make sure any destination devices - are handled correctly (ie. opened/closed) */ -int dm_add_device(struct mapped_device *md, kdev_t dev); + +/* contructors should call this to make sure any + * destination devices are handled correctly + * (ie. opened/closed). + */ +int dm_table_add_device(struct dm_table *t, kdev_t dev); #endif #endif diff --git a/driver/device-mapper/dm-fs.c b/driver/device-mapper/dm-fs.c index 9c981a391..c61008ca2 100644 --- a/driver/device-mapper/dm-fs.c +++ b/driver/device-mapper/dm-fs.c @@ -49,21 +49,25 @@ static struct proc_dir_entry *_control; 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, 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, const char **wb, const char **we); static int tok_cmp(const char *str, const char *b, const char *e); static void tok_cpy(char *dest, size_t max, 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 { process_fn fn; int minor; + struct dm_table *map; }; int dm_fs_init(void) @@ -119,6 +123,7 @@ int dm_fs_add(struct mapped_device *md) pfd->fn = process_table; pfd->minor = MINOR(md->dev); + pfd->map = 0; if (!(md->pde = create_proc_entry(md->name, S_IRUGO | S_IWUSR, _proc_dir))) { @@ -148,6 +153,11 @@ int dm_fs_add(struct mapped_device *md) int dm_fs_remove(struct mapped_device *md) { 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); remove_proc_entry(md->name, _proc_dir); md->pde = 0; @@ -158,7 +168,8 @@ int dm_fs_remove(struct mapped_device *md) 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; char name[64]; @@ -201,10 +212,12 @@ static int process_control(const char *b, const char *e, int minor) 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; struct mapped_device *md = dm_find_by_minor(minor); + struct dm_table *table = *map; void *context; int r; @@ -219,12 +232,15 @@ static int process_table(const char *b, const char *e, int minor) dm_suspend(md); /* start loading a table */ - dm_table_start(md); + table = *map = dm_table_create(); } else if (!tok_cmp("end", b, e)) { /* activate the device ... ... */ - dm_table_complete(md); - dm_activate(md); + if (table) { + dm_table_complete(table); + dm_bind(md, table); + dm_activate(md); + } } else { /* add the new entry */ @@ -253,18 +269,18 @@ static int process_table(const char *b, const char *e, int minor) return -EINVAL; /* check there isn't a gap */ - if ((md->num_targets && - start != md->highs[md->num_targets - 1] + 1) || - (!md->num_targets && start)) { + if ((table->num_targets && + start != table->highs[table->num_targets - 1] + 1) || + (!table->num_targets && start)) { WARN("gap in target ranges"); return -EINVAL; } 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; - if ((r = dm_table_add_entry(md, high, t->map, context))) + if ((r = dm_table_add_entry(table, high, t->map, context))) return r; } @@ -302,7 +318,7 @@ static int line_splitter(struct file *file, const char *buffer, while((b != e) && *b != '\n') b++; - if ((r = pfd->fn(lb, b, pfd->minor))) + if ((r = pfd->fn(lb, b, pfd->minor, &pfd->map))) return r; } diff --git a/driver/device-mapper/dm-table.c b/driver/device-mapper/dm-table.c index adb9a67d0..fbe0713a4 100644 --- a/driver/device-mapper/dm-table.c +++ b/driver/device-mapper/dm-table.c @@ -41,7 +41,7 @@ static inline ulong div_up(ulong n, ulong size) } /* ceiling(log_size(n)) */ -static uint int_log(ulong base, ulong n) +static uint int_log(ulong n, ulong base) { int result = 0; @@ -57,14 +57,14 @@ static uint int_log(ulong base, ulong n) * return the highest key that you could lookup * 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) { - if (n >= md->counts[l]) + if (n >= t->counts[l]) return (offset_t) -1; - if (l == md->depth - 1) - return md->index[l][((n + 1) * KEYS_PER_NODE) - 1]; + if (l == t->depth - 1) + return t->index[l][((n + 1) * KEYS_PER_NODE) - 1]; l++; 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 * 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; - for (n = 0, cn = 0; n < md->counts[l]; n++) { - offset_t *k = md->index[l] + (n * KEYS_PER_NODE); + for (n = 0, cn = 0; n < t->counts[l]; n++) { + offset_t *k = t->index[l] + (n * KEYS_PER_NODE); 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 greater than all keys */ } @@ -93,31 +93,15 @@ static int setup_btree_index(int l, struct mapped_device *md) 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 - * dynamic arrays during a table load. + * highs, and targets are managed as dynamic + * 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; struct target *n_targets; + int n = t->num_targets; if (!(n_highs = vmalloc(sizeof(*n_highs) * num))) return -ENOMEM; @@ -127,93 +111,143 @@ static int alloc_targets(struct mapped_device *md, int num) return -ENOMEM; } - if (md->num_targets) { - memcpy(n_highs, md->highs, - sizeof(*n_highs) * md->num_targets); - - memcpy(n_targets, md->targets, - sizeof(*n_targets) * md->num_targets); + if (n) { + memcpy(n_highs, t->highs, sizeof(*n_highs) * n); + memcpy(n_targets, t->targets, sizeof(*n_targets) * n); } - vfree(md->highs); - vfree(md->targets); + vfree(t->highs); + vfree(t->targets); - md->num_allocated = num; - md->highs = n_highs; - md->targets = n_targets; + t->num_allocated = num; + t->highs = n_highs; + t->targets = n_targets; return 0; } -int dm_table_start(struct mapped_device *md) +struct dm_table *dm_table_create(void) { - int r; - set_bit(DM_LOADING, &md->state); + struct dm_table *t = kmalloc(sizeof(struct dm_table), GFP_NOIO); - dm_table_free(md); + if (!t) + return 0; - /* allocate a single nodes worth to start with */ - if ((r = alloc_targets(md, KEYS_PER_NODE))) + memset(t, 0, sizeof(*t)); + + /* 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; + n = t->num_targets++; + t->highs[n] = high; + t->targets[n].map = target; + t->targets[n].private = private; + 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) - return alloc_targets(md, md->num_allocated * 2); + struct dev_list *d = kmalloc(sizeof(*d), GFP_KERNEL); + + if (!d) + return -ENOMEM; + + d->dev = dev; + d->next = t->devices; + t->devices = d; return 0; } -int dm_table_add_entry(struct mapped_device *md, offset_t high, - dm_map_fn target, void *context) -{ - int r; - - 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) +/* + * builds the btree to index the map + */ +int dm_table_complete(struct dm_table *t) { int i, leaf_nodes; - clear_bit(DM_LOADING, &md->state); - /* 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); - md->depth = i; - md->counts[md->depth - 1] = div_up(md->num_targets, KEYS_PER_NODE); + /* work out how many nodes are in each layer */ + t->depth = i; + t->counts[t->depth - 1] = div_up(t->num_targets, KEYS_PER_NODE); 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++) { - size_t s = NODE_SIZE * md->counts[i]; - md->index[i] = vmalloc(s); - memset(md->index[i], -1, s); + /* allocate memory for the internal nodes */ + for (i = 0; i < (t->depth - 1); i++) { + size_t s = NODE_SIZE * t->counts[i]; + t->index[i] = vmalloc(s); + memset(t->index[i], -1, s); } - /* bottom layer is easy */ - md->index[md->depth - 1] = md->highs; + /* leaf layer has already been set up */ + t->index[t->depth - 1] = t->highs; /* fill in higher levels */ - for (i = md->depth - 1; i; i--) - setup_btree_index(i - 1, md); + for (i = t->depth - 1; i; i--) + setup_btree_index(i - 1, t); - set_bit(DM_LOADED, &md->state); return 0; } +EXPORT_SYMBOL(dm_table_add_device); diff --git a/driver/device-mapper/dm-target.c b/driver/device-mapper/dm-target.c index f286eadae..4e320f97c 100644 --- a/driver/device-mapper/dm-target.c +++ b/driver/device-mapper/dm-target.c @@ -47,6 +47,9 @@ struct target_type *dm_get_target(const char *name) return t; } +/* + * register a new target_type. + */ int register_map_target(const char *name, dm_ctr_fn ctr, 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 * 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) { /* this takes no arguments */ @@ -109,11 +112,13 @@ struct linear_c { 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. + * + */ +static int linear_ctr(offset_t low, offset_t high, struct dm_table *t, const char *cb, const char *ce, void **result) { - /* */ - struct linear_c *lc; unsigned int major, minor, start; 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->offset = (int) start - (int) low; - if ((r = dm_add_device(md, lc->dev))) { + if ((r = dm_table_add_device(t, lc->dev))) { kfree(lc); return r; } diff --git a/driver/device-mapper/dm.c b/driver/device-mapper/dm.c index da87593f8..2ca8529a8 100644 --- a/driver/device-mapper/dm.c +++ b/driver/device-mapper/dm.c @@ -63,23 +63,12 @@ static int _block_size[MAX_DEVICES]; static int _blksize_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); /* * setup and teardown the driver */ -static int init_dm(void) +static int dm_init(void) { int ret; @@ -112,7 +101,7 @@ static int init_dm(void) return 0; } -static void exit_dm(void) +static void dm_exit(void) { if(kmem_cache_shrink(_io_hook_cache)) 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); } +/* + * 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) { 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); } +/* + * add the bh to the list of deferred io. + */ static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw) { 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; } - +/* + * do the bh mapping for a given leaf + */ 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; void *context; struct io_hook *ih = 0; int r; - struct target *ti = md->targets + node; + struct target *ti = md->map->targets + leaf; fn = ti->map; context = ti->private; @@ -334,15 +333,17 @@ inline static int __map_buffer(struct mapped_device *md, 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; offset_t *node; - /* search the btree for the correct target */ - for (l = 0; l < md->depth; l++) { + for (l = 0; l < t->depth; l++) { 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++) if (node[i] >= bh->b_rsector) @@ -363,7 +364,7 @@ static int request(request_queue_t *q, int rw, struct buffer_head *bh) rl; md = _devs[minor]; - if (!md || !test_bit(DM_LOADED, &md->state)) + if (!md || !md->map) goto bad; /* 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 */ } - if (!__map_buffer(md, bh, __find_node(md, bh))) + if (!__map_buffer(md, bh, __find_node(md->map, bh))) goto bad; ru; @@ -394,6 +395,10 @@ static int request(request_queue_t *q, int rw, struct buffer_head *bh) return 0; } +/* + * see if the device with a specific minor # is + * free. + */ static inline int __specific_dev(int minor) { if (minor > MAX_DEVICES) { @@ -407,6 +412,9 @@ static inline int __specific_dev(int minor) return -1; } +/* + * find the first free device. + */ static inline int __any_old_dev(void) { int i; @@ -418,6 +426,9 @@ static inline int __any_old_dev(void) return -1; } +/* + * allocate and initialise a blank device. + */ static struct mapped_device *alloc_dev(int minor) { struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); @@ -445,16 +456,10 @@ static struct mapped_device *alloc_dev(int minor) return md; } -static inline struct mapped_device *__find_by_name(const char *name) -{ - int i; - for (i = 0; i < MAX_DEVICES; i++) - if (_devs[i] && !strcmp(_devs[i]->name, name)) - return _devs[i]; - - return 0; -} - +/* + * open a device so we can use it as a map + * destination. + */ static int open_dev(struct dev_list *d) { int err; @@ -470,6 +475,9 @@ static int open_dev(struct dev_list *d) return 0; } +/* + * close a device that we've been using. + */ static void close_dev(struct dev_list *d) { blkdev_put(d->bd, BDEV_FILE); @@ -477,18 +485,14 @@ static void close_dev(struct dev_list *d) 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; - struct dev_list *dl; + int i; + 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) { - s = get_hardsect_size(dl->dev); - if (s < r) - r = s; - } - - return r; + return 0; } 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; } +/* + * constructor for a new device + */ int dm_create(const char *name, int minor) { int r; @@ -544,10 +551,14 @@ int dm_create(const char *name, int minor) return 0; } +/* + * destructor for the device. md->map is + * deliberately not destroyed, dm-fs should manage + * table objects. + */ int dm_remove(const char *name) { struct mapped_device *md; - struct dev_list *d, *n; int minor, r; wl; @@ -566,12 +577,6 @@ int dm_remove(const char *name) return r; } - dm_table_free(md); - for (d = md->devices; d; d = n) { - n = d->next; - kfree(d); - } - minor = MINOR(md->dev); kfree(md); _devs[minor] = 0; @@ -580,20 +585,57 @@ int dm_remove(const char *name) 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) - return -EINVAL; + while(dl) { + size = get_hardsect_size(dl->dev); + if (size < result) + result = size; + dl = dl->next; + } - d->dev = dev; - d->next = md->devices; - md->devices = d; + return result; +} + +/* + * 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; } +/* + * requeue the deferred buffer_heads by calling + * generic_make_request. + */ static void __flush_deferred_io(struct mapped_device *md) { 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 ret, minor; + int ret; struct dev_list *d, *od; wl; @@ -617,27 +664,17 @@ int dm_activate(struct mapped_device *md) return 0; } - if (!md->num_targets) { + if (!md->map) { wu; return -ENXIO; } /* 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))) 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); - __flush_deferred_io(md); wu; @@ -645,17 +682,27 @@ int dm_activate(struct mapped_device *md) bad: od = d; - for (d = md->devices; d != od; d = d->next) + for (d = md->map->devices; d != od; d = d->next) close_dev(d); ru; 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) { DECLARE_WAITQUEUE(wait, current); struct dev_list *d; + if (!is_active(md)) return; @@ -676,7 +723,7 @@ void dm_suspend(struct mapped_device *md) remove_wait_queue(&md->wait, &wait); /* close all the devices */ - for (d = md->devices; d; d = d->next) + for (d = md->map->devices; d; d = d->next) close_dev(d); 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_init(init_dm); -module_exit(exit_dm); +module_init(dm_init); +module_exit(dm_exit); /* * Local variables: diff --git a/driver/device-mapper/dm.h b/driver/device-mapper/dm.h index e040c7348..9876e8987 100644 --- a/driver/device-mapper/dm.h +++ b/driver/device-mapper/dm.h @@ -137,9 +137,8 @@ #define DM_NAME_LEN 64 enum { - DM_LOADED = 0, - DM_LOADING, - DM_ACTIVE, + DM_BOUND = 0, /* device has been bound to a table */ + DM_ACTIVE, /* device is running */ }; /* @@ -182,6 +181,24 @@ struct target { 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 */ @@ -198,46 +215,40 @@ struct mapped_device { /* a list of io's that arrived while we were suspended */ struct deferred_io *deferred; - /* 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; + struct dm_table *map; /* used by dm-fs.c */ devfs_handle_t devfs_entry; 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; + /* dm-target.c */ int dm_target_init(void); struct target_type *dm_get_target(const char *name); + /* dm.c */ struct mapped_device *dm_find_by_name(const char *name); struct mapped_device *dm_find_by_minor(int minor); int dm_create(const char *name, int minor); int dm_remove(const char *name); - +int dm_bind(struct mapped_device *md, struct dm_table *t); int dm_activate(struct mapped_device *md); void dm_suspend(struct mapped_device *md); + /* dm-table.c */ -int dm_table_start(struct mapped_device *md); -int dm_table_add_entry(struct mapped_device *md, offset_t high, - dm_map_fn target, void *context); -int dm_table_complete(struct mapped_device *md); -void dm_table_free(struct mapped_device *md); +struct dm_table *dm_table_create(void); +void dm_table_destroy(struct dm_table *t); + +int dm_table_add_entry(struct dm_table *t, offset_t high, + dm_map_fn target, void *private); +int dm_table_complete(struct dm_table *t); + /* dm-fs.c */ int dm_fs_init(void);