diff -Naur linux-2.6.0-test7/drivers/md/dm.c linux-2.6.0-test7-work/drivers/md/dm.c --- linux-2.6.0-test7/drivers/md/dm.c 2003-10-08 12:24:27.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm.c 2003-10-14 17:50:09.000000000 -0700 @@ -32,45 +32,6 @@ struct deferred_io *next; }; -/* - * Bits for the md->flags field. - */ -#define DMF_BLOCK_IO 0 -#define DMF_SUSPENDED 1 - -struct mapped_device { - struct rw_semaphore lock; - atomic_t holders; - - unsigned long flags; - - request_queue_t *queue; - struct gendisk *disk; - - /* - * A list of ios that arrived while we were suspended. - */ - atomic_t pending; - wait_queue_head_t wait; - struct deferred_io *deferred; - - /* - * The current mapping. - */ - struct dm_table *map; - - /* - * io objects are allocated from here. - */ - mempool_t *io_pool; - - /* - * Event handling. - */ - uint32_t event_nr; - wait_queue_head_t eventq; -}; - #define MIN_IOS 256 static kmem_cache_t *_io_cache; @@ -636,6 +597,8 @@ sprintf(md->disk->disk_name, "dm-%d", minor); add_disk(md->disk); + dm_sysfs_register_md(md); + atomic_set(&md->pending, 0); init_waitqueue_head(&md->wait); init_waitqueue_head(&md->eventq); @@ -645,12 +608,7 @@ static void free_dev(struct mapped_device *md) { - free_minor(md->disk->first_minor); - mempool_destroy(md->io_pool); - del_gendisk(md->disk); - put_disk(md->disk); - blk_put_queue(md->queue); - kfree(md); + dm_sysfs_unregister_md(md); } /* @@ -672,6 +630,8 @@ sector_t size; md->map = t; + dm_sysfs_register_table(md); + size = dm_table_get_size(t); set_capacity(md->disk, size); if (size == 0) @@ -690,9 +650,9 @@ return; dm_table_event_callback(md->map, NULL, NULL); - dm_table_put(md->map); - md->map = NULL; set_capacity(md->disk, 0); + dm_sysfs_unregister_table(md->map); + md->map = NULL; } /* diff -Naur linux-2.6.0-test7/drivers/md/dm.h linux-2.6.0-test7-work/drivers/md/dm.h --- linux-2.6.0-test7/drivers/md/dm.h 2003-10-08 12:24:04.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm.h 2003-10-14 15:55:16.000000000 -0700 @@ -42,12 +42,109 @@ atomic_t count; int mode; struct block_device *bdev; + + /* target specific data */ + void *private; + + struct kobject kobj; + struct attribute_group *attr_group; +}; + +/* + * Bits for the md->flags field. + */ +#define DMF_BLOCK_IO 0 +#define DMF_SUSPENDED 1 + +struct mapped_device { + struct rw_semaphore lock; + atomic_t holders; + + unsigned long flags; + + request_queue_t *queue; + struct gendisk *disk; + + /* + * A list of ios that arrived while we were suspended. + */ + atomic_t pending; + wait_queue_head_t wait; + struct deferred_io *deferred; + + /* + * The current mapping. + */ + struct dm_table *map; + + /* + * io objects are allocated from here. + */ + mempool_t *io_pool; + + /* + * Event handling. + */ + uint32_t event_nr; + wait_queue_head_t eventq; + + /* + * driver model + */ + struct kobject kobj; +}; + +#define MAX_DEPTH 16 + +struct dm_table { + atomic_t holders; + + /* btree table */ + unsigned int depth; + unsigned int counts[MAX_DEPTH]; /* in nodes */ + sector_t *index[MAX_DEPTH]; + + unsigned int num_targets; + unsigned int num_allocated; + sector_t *highs; + struct dm_target *targets; + + /* + * Indicates the rw permissions for the new logical + * device. This should be a combination of FMODE_READ + * and FMODE_WRITE. + */ + int mode; + + /* + * These are optimistic limits taken from all the + * targets, some targets will need smaller limits. + */ + struct io_restrictions limits; + + /* events get handed up using this callback */ + void (*event_fn)(void *); + void *event_context; + + /* + * driver model + */ + struct kobject kobj; }; struct dm_table; struct mapped_device; /*----------------------------------------------------------------- + * Functions for registering a mapped_device and table with sysfs. + *---------------------------------------------------------------*/ +int dm_sysfs_register_md(struct mapped_device *md); +void dm_sysfs_unregister_md(struct mapped_device *md); + +int dm_sysfs_register_table(struct mapped_device *md); +void dm_sysfs_unregister_table(struct dm_table *tbl); + +/*----------------------------------------------------------------- * Functions for manipulating a struct mapped_device. * Drop the reference with dm_put when you finish with the object. *---------------------------------------------------------------*/ @@ -111,7 +208,7 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); unsigned int dm_table_get_num_targets(struct dm_table *t); -struct list_head *dm_table_get_devices(struct dm_table *t); +struct list_head *dm_target_get_devices(struct dm_target *t); int dm_table_get_mode(struct dm_table *t); void dm_table_suspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); diff -Naur linux-2.6.0-test7/drivers/md/dm-ioctl-v4.c linux-2.6.0-test7-work/drivers/md/dm-ioctl-v4.c --- linux-2.6.0-test7/drivers/md/dm-ioctl-v4.c 2003-10-08 12:24:00.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm-ioctl-v4.c 2003-10-14 15:55:16.000000000 -0700 @@ -933,17 +933,22 @@ struct dm_ioctl *param, size_t param_size) { unsigned int count = 0; - struct list_head *tmp; size_t len, needed; struct dm_target_deps *deps; + int i, num_tgts = dm_table_get_num_targets(table); deps = get_result_buffer(param, param_size, &len); /* * Count the devices. */ - list_for_each(tmp, dm_table_get_devices(table)) - count++; + for (i = 0; i < num_tgts; i++) { + struct dm_target *tgt = dm_table_get_target(table, i); + struct list_head *tmp; + + list_for_each(tmp, dm_target_get_devices(tgt)) + count++; + } /* * Check we have enough space. @@ -959,9 +964,15 @@ */ deps->count = count; count = 0; - list_for_each(tmp, dm_table_get_devices(table)) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); - deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); + for (i = 0; i < num_tgts; i++) { + struct dm_target *tgt = dm_table_get_target(table, i); + struct list_head *tmp; + + list_for_each(tmp, dm_target_get_devices(tgt)) { + struct dm_dev *dd = list_entry(tmp, struct dm_dev, + list); + deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); + } } param->data_size = param->data_start + needed; diff -Naur linux-2.6.0-test7/drivers/md/dm-linear.c linux-2.6.0-test7-work/drivers/md/dm-linear.c --- linux-2.6.0-test7/drivers/md/dm-linear.c 2003-10-08 12:24:07.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm-linear.c 2003-10-14 15:55:16.000000000 -0700 @@ -20,6 +20,28 @@ sector_t start; }; +static ssize_t show_start(struct dm_dev *dmdev, char *buf) +{ + struct linear_c *lc = (struct linear_c*) dmdev->private; + return snprintf(buf, 32, ""SECTOR_FORMAT"\n", lc->start); +} + +static struct dm_dev_sysfs_entry start_entry = { + .attr = {.name = "start", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = show_start, +}; + +static struct attribute *linear_attrs[] = { + &start_entry.attr, + NULL +}; + +static struct attribute_group linear_attr_group = { + .attrs = linear_attrs, +}; + /* * Construct a linear mapping: */ @@ -49,6 +71,7 @@ goto bad; } + dm_sysfs_init_dev(lc->dev, lc, &linear_attr_group); ti->private = lc; return 0; diff -Naur linux-2.6.0-test7/drivers/md/dm-stripe.c linux-2.6.0-test7-work/drivers/md/dm-stripe.c --- linux-2.6.0-test7/drivers/md/dm-stripe.c 2003-10-08 12:24:05.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm-stripe.c 2003-10-14 15:55:16.000000000 -0700 @@ -17,6 +17,28 @@ sector_t physical_start; }; +static ssize_t show_start(struct dm_dev *dmdev, char *buf) +{ + struct stripe *s = (struct stripe *) dmdev->private; + return snprintf(buf, 32, ""SECTOR_FORMAT"\n", s->physical_start); +} + +static struct dm_dev_sysfs_entry start_entry = { + .attr = {.name = "start", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = show_start, +}; + +static struct attribute *stripe_attrs[] = { + &start_entry.attr, + NULL +}; + +static struct attribute_group stripe_attr_group = { + .attrs = stripe_attrs, +}; + struct stripe_c { uint32_t stripes; @@ -30,6 +52,42 @@ struct stripe stripe[0]; }; +static ssize_t show_num_stripes(struct dm_target *tgt, char *buf) +{ + struct stripe_c *sc = (struct stripe_c *) tgt->private; + return snprintf(buf, 32, "%u\n", sc->stripes); +} + +static ssize_t show_chunk_size(struct dm_target *tgt, char *buf) +{ + struct stripe_c *sc = (struct stripe_c *) tgt->private; + return snprintf(buf, 32, "%u\n", sc->stripe_width); +} + +static struct dm_target_sysfs_entry num_stripes_entry = { + .attr = {.name = "num_stripes", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = show_num_stripes, +}; + +static struct dm_target_sysfs_entry chunk_size_entry = { + .attr = {.name = "chunk_size", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = show_chunk_size, +}; + +static struct attribute *stripe_c_attrs[] = { + &num_stripes_entry.attr, + &chunk_size_entry.attr, + NULL +}; + +static struct attribute_group stripe_c_attr_group = { + .attrs = stripe_c_attrs, +}; + static inline struct stripe_c *alloc_context(unsigned int stripes) { size_t len; @@ -60,6 +118,10 @@ return -ENXIO; sc->stripe[stripe].physical_start = start; + dm_sysfs_init_dev(sc->stripe[stripe].dev, + &sc->stripe[stripe], + &stripe_attr_group); + return 0; } @@ -151,6 +213,7 @@ } } + dm_sysfs_init_target(ti, &stripe_c_attr_group); ti->private = sc; return 0; } diff -Naur linux-2.6.0-test7/drivers/md/dm-sysfs.c linux-2.6.0-test7-work/drivers/md/dm-sysfs.c --- linux-2.6.0-test7/drivers/md/dm-sysfs.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.0-test7-work/drivers/md/dm-sysfs.c 2003-10-14 15:55:16.000000000 -0700 @@ -0,0 +1,488 @@ +/* + * dm-sysfs.c - sysfs code for Device Mapper + * Written by Mike Christie (mikenc@us.ibm.com) + * Copyright (C) 2003 IBM Corp. + */ + +#include "dm.h" + +#include +#include + +/********************************************************* + * + * device mapper mapped_device sysfs functions + * + *********************************************************/ + +inline struct mapped_device *dm_kobj_to_md(struct kobject *kobj) +{ + return container_of(kobj, struct mapped_device, kobj); +} + +struct md_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct mapped_device *, char *); + ssize_t (*store)(struct mapped_device *, + const char *, size_t); +}; + +static ssize_t md_show_event(struct mapped_device *md, char *buf) +{ + return snprintf(buf, 20, "%u\n", md->event_nr); +} + +static ssize_t md_show_flags(struct mapped_device *md, char *buf) +{ + unsigned int flags = 0; + + if (dm_suspended(md)) + flags |= DM_SUSPEND_FLAG; + + if (md->disk->policy) + flags |= DM_READONLY_FLAG; + + if (md->map) + flags |= DM_ACTIVE_PRESENT_FLAG; + + return snprintf(buf, 20, "0x%x\n", flags); +} + +static struct md_sysfs_entry md_event_entry = { + .attr = {.name = "event_nr", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = md_show_event, +}; + +static struct md_sysfs_entry md_flags_entry = { + .attr = {.name = "flags", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = md_show_flags, +}; + +static struct attribute *md_attrs[] = { + &md_event_entry.attr, + &md_flags_entry.attr, + NULL +}; + +static inline struct md_sysfs_entry *attr_to_md_entry(struct attribute *attr) +{ + return container_of((attr), struct md_sysfs_entry, attr); +} + +static ssize_t md_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct md_sysfs_entry *entry = attr_to_md_entry(attr); + struct mapped_device *md; + + if (!entry->show) + return 0; + + md = dm_kobj_to_md(kobj); + return entry->show(md, buf); +} + +static ssize_t md_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct md_sysfs_entry *entry = attr_to_md_entry(attr); + struct mapped_device *md; + + if (!entry->store) + return-EINVAL; + + md = dm_kobj_to_md(kobj); + return entry->store(md, page, length); +} + +static struct sysfs_ops md_sysfs_ops = { + .show = md_attr_show, + .store = md_attr_store, +}; + +static void md_kobj_release(struct kobject *kobj) +{ + struct mapped_device *md; + struct kobject *parent; + + md = dm_kobj_to_md(kobj); + parent = &md->disk->kobj; + + del_gendisk(md->disk); + put_disk(md->disk); + blk_put_queue(md->queue); + mempool_destroy(md->io_pool); + kfree(md); + + kobject_put(parent); +} + +struct kobj_type md_ktype = { + .release = md_kobj_release, + .sysfs_ops = &md_sysfs_ops, + .default_attrs = md_attrs, +}; + +int dm_sysfs_register_md(struct mapped_device *md) +{ + if (!md) return -EINVAL; + + md->kobj.parent = kobject_get(&md->disk->kobj); + if (!md->kobj.parent) return -EINVAL; + + snprintf(md->kobj.name, KOBJ_NAME_LEN, "%s", "mapped_device"); + md->kobj.ktype = &md_ktype; + + return kobject_register(&md->kobj); +} + +void dm_sysfs_unregister_md(struct mapped_device *md) +{ + if (md) kobject_unregister(&md->kobj); +} + + +/********************************************************* + * + * device mapper dm_dev sysfs functions + * + *********************************************************/ + +static inline struct dm_dev *kobj_to_device(struct kobject *kobj) +{ + return container_of(kobj, struct dm_dev, kobj); +} + +static inline struct dm_dev_sysfs_entry *attr_to_device_entry(struct attribute *attr) +{ + return container_of((attr), struct dm_dev_sysfs_entry, attr); +} + +static ssize_t device_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct dm_dev_sysfs_entry *entry = attr_to_device_entry(attr); + struct dm_dev *dmdev; + + if (!entry->show) + return 0; + + dmdev = kobj_to_device(kobj); + return entry->show(dmdev, buf); +} + +static ssize_t device_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct dm_dev_sysfs_entry *entry = attr_to_device_entry(attr); + struct dm_dev *dmdev; + + if (!entry->store) + return -EINVAL; + + dmdev = kobj_to_device(kobj); + return entry->store(dmdev, page, length); +} + +static struct sysfs_ops device_sysfs_ops = { + .show = device_attr_show, + .store = device_attr_store, +}; + +static void device_kobj_release(struct kobject *kobj) +{ + struct kobject *parent = kobj->parent; + struct dm_dev *dmdev; + + dmdev = kobj_to_device(kobj); + kobject_put(parent); +} + +static struct kobj_type dmdev_ktype = { + .release = device_kobj_release, + .sysfs_ops = &device_sysfs_ops, +}; + +static int device_sysfs_register(struct dm_target *tgt, + struct dm_dev *dmdev) +{ + int err; + struct gendisk *disk = dmdev->bdev->bd_disk; + + dmdev->kobj.parent = kobject_get(&tgt->kobj); + snprintf(dmdev->kobj.name, KOBJ_NAME_LEN, "%s", + disk->disk_name); + dmdev->kobj.ktype = &dmdev_ktype; + + err = kobject_register(&dmdev->kobj); + if (err) + return err; + + if (dmdev->attr_group) { + err = sysfs_create_group(&dmdev->kobj, + dmdev->attr_group); + if (err) { + kobject_unregister(&dmdev->kobj); + return err; + } + } + + sysfs_create_link(&dmdev->kobj, &disk->kobj, + disk->disk_name); + + return 0; +} + +static void device_sysfs_unregister(struct dm_dev *dmdev) +{ + struct gendisk *disk = dmdev->bdev->bd_disk; + + if (dmdev->attr_group) + sysfs_remove_group(&dmdev->kobj, dmdev->attr_group); + + sysfs_remove_link(&dmdev->kobj, disk->disk_name); + kobject_unregister(&dmdev->kobj); +} + +void dm_sysfs_init_dev(struct dm_dev *dmdev, void *priv, + struct attribute_group *attr_group) +{ + if (dmdev) { + dmdev->private = priv; + dmdev->attr_group = attr_group; + } +} + +/********************************************************* + * + * device mapper dm_target sysfs functions + * + *********************************************************/ + +static inline struct dm_target *kobj_to_target(struct kobject *kobj) +{ + return container_of(kobj, struct dm_target, kobj); +} + +static ssize_t target_show_begin(struct dm_target *tgt, char *buf) +{ + return snprintf(buf, 20, ""SECTOR_FORMAT"\n", tgt->begin); +} + +static ssize_t target_show_len(struct dm_target *tgt, char *buf) +{ + return snprintf(buf, 20, ""SECTOR_FORMAT"\n", tgt->len); +} + +static ssize_t target_show_type(struct dm_target *tgt, char *buf) +{ + return snprintf(buf, 32, "%s\n", tgt->type->name); +} + +static struct dm_target_sysfs_entry target_begin_entry = { + .attr = {.name = "start_sector", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = target_show_begin, +}; + +static struct dm_target_sysfs_entry target_len_entry = { + .attr = {.name = "num_sectors", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = target_show_len, +}; + +static struct dm_target_sysfs_entry target_type_entry = { + .attr = {.name = "type", + .mode = S_IRUGO, + .owner = THIS_MODULE }, + .show = target_show_type, +}; + +static struct attribute *default_target_attrs[] = { + &target_type_entry.attr, + &target_len_entry.attr, + &target_begin_entry.attr, + NULL +}; + +static inline struct dm_target_sysfs_entry *attr_to_tgt_entry(struct attribute *attr) +{ + return container_of((attr), struct dm_target_sysfs_entry, attr); +} + +static ssize_t target_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct dm_target_sysfs_entry *entry = attr_to_tgt_entry(attr); + struct dm_target *tgt; + + if (!entry->show) + return 0; + + tgt = kobj_to_target(kobj); + return entry->show(tgt, buf); +} + + +static ssize_t target_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct dm_target_sysfs_entry *entry = attr_to_tgt_entry(attr); + struct dm_target *tgt; + + if (!entry->store) + return -EINVAL; + + tgt = kobj_to_target(kobj); + return entry->store(tgt, page, length); +} + +static struct sysfs_ops target_sysfs_ops = { + .show = target_attr_show, + .store = target_attr_store, +}; + +static void target_kobj_release(struct kobject *kobj) +{ + struct kobject *parent = kobj->parent; + struct dm_target *tgt; + + tgt = kobj_to_target(kobj); + kobject_put(parent); +} + +static struct kobj_type target_ktype = { + .release = target_kobj_release, + .sysfs_ops = &target_sysfs_ops, + .default_attrs = default_target_attrs, +}; + +static int target_sysfs_register(struct dm_target *tgt, int i) +{ + struct list_head *curr; + int err; + + tgt->kobj.parent = kobject_get(&tgt->table->kobj); + snprintf(tgt->kobj.name, KOBJ_NAME_LEN, "%s%d", "target", i); + tgt->kobj.ktype = &target_ktype; + + err = kobject_register(&tgt->kobj); + if (err) + return err; + + if (tgt->attr_group) { + err = sysfs_create_group(&tgt->kobj, tgt->attr_group); + if (err) { + kobject_unregister(&tgt->kobj); + return err; + } + } + + list_for_each(curr, &tgt->devices) { + struct dm_dev *dmdev; + + dmdev = list_entry(curr, struct dm_dev, list); + device_sysfs_register(tgt, dmdev); + } + + return 0; +} + +static void target_sysfs_unregister(struct dm_target *tgt) +{ + struct list_head *curr; + + if (tgt->attr_group) + sysfs_remove_group(&tgt->kobj, tgt->attr_group); + + list_for_each(curr, &tgt->devices) { + struct dm_dev *dmdev; + + dmdev = list_entry(curr, struct dm_dev, list); + device_sysfs_unregister(dmdev); + } + + kobject_unregister(&tgt->kobj); +} + +void dm_sysfs_init_target(struct dm_target *tgt, + struct attribute_group *attr_group) +{ + if (tgt) tgt->attr_group = attr_group; +} + +/********************************************************* + * + * device mapper dm_table sysfs functions + * + *********************************************************/ + + +static inline struct dm_table *kobj_to_table(struct kobject *kobj) +{ + return container_of(kobj, struct dm_table, kobj); +} + +static void table_kobj_release(struct kobject *kobj) +{ + struct dm_table *tbl; + struct kobject *parent = kobj->parent; + + tbl = kobj_to_table(kobj); + dm_table_put(tbl); + + if (parent) + kobject_put(parent); +} + +static struct kobj_type table_ktype = { + .release = table_kobj_release, +}; + +int dm_sysfs_register_table(struct mapped_device *md) +{ + int err, i, num_tgts; + struct dm_table *tbl = md->map; + + if (!tbl) return -EINVAL; + + snprintf(tbl->kobj.name, KOBJ_NAME_LEN, "%s", "table"); + tbl->kobj.ktype = &table_ktype; + tbl->kobj.parent = kobject_get(&md->kobj); + + err = kobject_register(&tbl->kobj); + if (err) return err; + + num_tgts = dm_table_get_num_targets(tbl); + for (i = 0; i < num_tgts; i++) { + err = target_sysfs_register(dm_table_get_target(tbl, i), i); + if (err) { + kobject_unregister(&tbl->kobj); + break; + } + } + + return err; +} + +void dm_sysfs_unregister_table(struct dm_table *tbl) +{ + int i, num_tgts; + + if (!tbl) return; + + num_tgts = dm_table_get_num_targets(tbl); + for (i = 0; i < num_tgts; i++) + target_sysfs_unregister(dm_table_get_target(tbl, i)); + + kobject_unregister(&tbl->kobj); +} + +EXPORT_SYMBOL(dm_sysfs_init_dev); +EXPORT_SYMBOL(dm_sysfs_init_target); diff -Naur linux-2.6.0-test7/drivers/md/dm-table.c linux-2.6.0-test7-work/drivers/md/dm-table.c --- linux-2.6.0-test7/drivers/md/dm-table.c 2003-10-08 12:24:51.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/dm-table.c 2003-10-14 17:43:18.000000000 -0700 @@ -14,45 +14,10 @@ #include #include -#define MAX_DEPTH 16 #define NODE_SIZE L1_CACHE_BYTES #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) -struct dm_table { - atomic_t holders; - - /* btree table */ - unsigned int depth; - unsigned int counts[MAX_DEPTH]; /* in nodes */ - sector_t *index[MAX_DEPTH]; - - unsigned int num_targets; - unsigned int num_allocated; - sector_t *highs; - struct dm_target *targets; - - /* - * Indicates the rw permissions for the new logical - * device. This should be a combination of FMODE_READ - * and FMODE_WRITE. - */ - int mode; - - /* a list of devices used by this table */ - struct list_head devices; - - /* - * These are optimistic limits taken from all the - * targets, some targets will need smaller limits. - */ - struct io_restrictions limits; - - /* events get handed up using this callback */ - void (*event_fn)(void *); - void *event_context; -}; - /* * Similar to ceiling(log_size(n)) */ @@ -210,7 +175,6 @@ return -ENOMEM; memset(t, 0, sizeof(*t)); - INIT_LIST_HEAD(&t->devices); atomic_set(&t->holders, 1); /* allocate a single nodes worth of targets to begin with */ @@ -252,18 +216,16 @@ tgt->type->dtr(tgt); dm_put_target_type(tgt->type); - } - vfree(t->highs); + if (tgt->devices.next != &tgt->devices) { + DMWARN("devices still present during destroy: " + "dm_put_device calls missing"); - /* free the device list */ - if (t->devices.next != &t->devices) { - DMWARN("devices still present during destroy: " - "dm_table_remove_device calls missing"); - - free_devices(&t->devices); + free_devices(&tgt->devices); + } } + vfree(t->highs); kfree(t); } @@ -434,11 +396,12 @@ return r; } - dd = find_device(&t->devices, dev); + dd = find_device(&ti->devices, dev); if (!dd) { dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) return -ENOMEM; + memset(dd, 0, sizeof(*dd)); dd->mode = mode; dd->bdev = NULL; @@ -449,7 +412,7 @@ } atomic_set(&dd->count, 0); - list_add(&dd->list, &t->devices); + list_add(&dd->list, &ti->devices); } else if (dd->mode != (mode | dd->mode)) { r = upgrade_mode(dd, mode); @@ -626,6 +589,7 @@ tgt = t->targets + t->num_targets; memset(tgt, 0, sizeof(*tgt)); + INIT_LIST_HEAD(&tgt->devices); tgt->type = dm_get_target_type(type); if (!tgt->type) { @@ -789,9 +753,9 @@ return t->num_targets; } -struct list_head *dm_table_get_devices(struct dm_table *t) +struct list_head *dm_target_get_devices(struct dm_target *tgt) { - return &t->devices; + return &tgt->devices; } int dm_table_get_mode(struct dm_table *t) @@ -799,6 +763,11 @@ return t->mode; } +struct kobject *dm_table_get_kobj(struct dm_table *t) +{ + return &t->kobj; +} + void dm_table_suspend_targets(struct dm_table *t) { int i; diff -Naur linux-2.6.0-test7/drivers/md/Makefile linux-2.6.0-test7-work/drivers/md/Makefile --- linux-2.6.0-test7/drivers/md/Makefile 2003-10-08 12:24:07.000000000 -0700 +++ linux-2.6.0-test7-work/drivers/md/Makefile 2003-10-14 15:55:16.000000000 -0700 @@ -2,8 +2,8 @@ # Makefile for the kernel software RAID and LVM drivers. # -dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ - dm-ioctl.o +dm-mod-objs := dm-sysfs.o dm.o dm-table.o dm-target.o dm-linear.o \ + dm-stripe.o dm-ioctl.o # Note: link order is important. All raid personalities # and xor.o must come before md.o, as they each initialise diff -Naur linux-2.6.0-test7/include/linux/device-mapper.h linux-2.6.0-test7-work/include/linux/device-mapper.h --- linux-2.6.0-test7/include/linux/device-mapper.h 2003-10-08 12:24:17.000000000 -0700 +++ linux-2.6.0-test7-work/include/linux/device-mapper.h 2003-10-14 17:24:55.000000000 -0700 @@ -82,6 +82,9 @@ sector_t begin; sector_t len; + /* a list of devices used by this target */ + struct list_head devices; + /* FIXME: turn this into a mask, and merge with io_restrictions */ sector_t split_io; @@ -96,9 +99,35 @@ /* Used to provide an error string from the ctr */ char *error; + + /* driver model */ + struct kobject kobj; + struct attribute_group *attr_group; }; int dm_register_target(struct target_type *t); int dm_unregister_target(struct target_type *t); +/* + * Functions and structures for displaying target + * attributes in sysfs. + */ +struct dm_target_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct dm_target *, char *); + ssize_t (*store)(struct dm_target *, const char *, size_t); +}; + +void dm_sysfs_init_target(struct dm_target *tgt, + struct attribute_group *attr_group); + +struct dm_dev_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct dm_dev *, char *); + ssize_t (*store)(struct dm_dev *, const char *, size_t); +}; + +void dm_sysfs_init_dev(struct dm_dev *dmdev, void *priv, + struct attribute_group *attr_group); + #endif /* _LINUX_DEVICE_MAPPER_H */