#include <linux/hdreg.h>
#include <linux/blktrace_api.h>
+#define DM_MSG_PREFIX "core"
+
static const char *_name = DM_NAME;
static unsigned int major = 0;
union map_info *dm_get_mapinfo(struct bio *bio)
{
- if (bio && bio->bi_private)
- return &((struct target_io *)bio->bi_private)->info;
- return NULL;
+ if (bio && bio->bi_private)
+ return &((struct target_io *)bio->bi_private)->info;
+ return NULL;
}
#define MINOR_ALLOCED ((void *)-1)
#define DMF_SUSPENDED 1
#define DMF_FROZEN 2
#define DMF_FREEING 3
+#define DMF_DELETING 4
struct mapped_device {
struct rw_semaphore io_lock;
struct semaphore suspend_lock;
rwlock_t map_lock;
atomic_t holders;
+ atomic_t open_count;
unsigned long flags;
bioset_free(dm_set);
if (unregister_blkdev(_major, _name) < 0)
- DMERR("devfs_unregister_blkdev failed");
+ DMERR("unregister_blkdev failed");
_major = 0;
if (!md)
goto out;
- if (test_bit(DMF_FREEING, &md->flags)) {
+ if (test_bit(DMF_FREEING, &md->flags) ||
+ test_bit(DMF_DELETING, &md->flags)) {
md = NULL;
goto out;
}
dm_get(md);
+ atomic_inc(&md->open_count);
out:
spin_unlock(&_minor_lock);
struct mapped_device *md;
md = inode->i_bdev->bd_disk->private_data;
+ atomic_dec(&md->open_count);
dm_put(md);
return 0;
}
+int dm_open_count(struct mapped_device *md)
+{
+ return atomic_read(&md->open_count);
+}
+
+/*
+ * Guarantees nothing is using the device before it's deleted.
+ */
+int dm_lock_for_deletion(struct mapped_device *md)
+{
+ int r = 0;
+
+ spin_lock(&_minor_lock);
+
+ if (dm_open_count(md))
+ r = -EBUSY;
+ else
+ set_bit(DMF_DELETING, &md->flags);
+
+ spin_unlock(&_minor_lock);
+
+ return r;
+}
+
static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct mapped_device *md = bdev->bd_disk->private_data;
if (r > 0) {
/* the bio has been remapped so dispatch it */
- blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone,
- tio->io->bio->bi_bdev->bd_dev, sector,
+ blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone,
+ tio->io->bio->bi_bdev->bd_dev, sector,
clone->bi_sector);
generic_make_request(clone);
init_MUTEX(&md->suspend_lock);
rwlock_init(&md->map_lock);
atomic_set(&md->holders, 1);
+ atomic_set(&md->open_count, 0);
atomic_set(&md->event_nr, 0);
md->queue = blk_alloc_queue(GFP_KERNEL);
md = idr_find(&_minor_idr, minor);
if (md && (md == MINOR_ALLOCED ||
(dm_disk(md)->first_minor != minor) ||
- test_bit(DMF_FREEING, &md->flags))) {
+ test_bit(DMF_FREEING, &md->flags))) {
md = NULL;
goto out;
}
atomic_inc(&md->holders);
}
+const char *dm_device_name(struct mapped_device *md)
+{
+ return md->name;
+}
+EXPORT_SYMBOL_GPL(dm_device_name);
+
void dm_put(struct mapped_device *md)
{
struct dm_table *map;