/*
* Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
#include "dm.h"
#include "dm-bio-list.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/blkpg.h>
#include <linux/bio.h>
#include <linux/buffer_head.h>
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/idr.h>
static const char *_name = DM_NAME;
static unsigned int major = 0;
static unsigned int _major = 0;
/*
* One of these is allocated per bio.
*/
struct dm_io {
struct mapped_device *md;
int error;
struct bio *bio;
atomic_t io_count;
};
/*
* One of these is allocated per target within a bio. Hopefully
* this will be simplified out one day.
*/
struct target_io {
struct dm_io *io;
struct dm_target *ti;
union map_info info;
};
union map_info *dm_get_mapinfo(struct bio *bio)
{
if (bio && bio->bi_private)
return &((struct target_io *)bio->bi_private)->info;
return NULL;
}
/*
* Bits for the md->flags field.
*/
#define DMF_BLOCK_IO 0
#define DMF_SUSPENDED 1
struct mapped_device {
struct rw_semaphore io_lock;
struct semaphore suspend_lock;
rwlock_t map_lock;
atomic_t holders;
unsigned long flags;
request_queue_t *queue;
struct gendisk *disk;
void *interface_ptr;
/*
* A list of ios that arrived while we were suspended.
*/
atomic_t pending;
wait_queue_head_t wait;
struct bio_list deferred;
/*
* The current mapping.
*/
struct dm_table *map;
/*
* io objects are allocated from here.
*/
mempool_t *io_pool;
mempool_t *tio_pool;
/*
* Event handling.
*/
atomic_t event_nr;
wait_queue_head_t eventq;
/*
* freeze/thaw support require holding onto a super block
*/
struct super_block *frozen_sb;
struct block_device *frozen_bdev;
};
#define MIN_IOS 256
static kmem_cache_t *_io_cache;
static kmem_cache_t *_tio_cache;
static struct bio_set *dm_set;
static int __init local_init(void)
{
int r;
dm_set = bioset_create(16, 16, 4);
if (!dm_set)
return -ENOMEM;
/* allocate a slab for the dm_ios */
_io_cache = kmem_cache_create("dm_io",
sizeof(struct dm_io), 0, 0, NULL, NULL);
if (!_io_cache)
return -ENOMEM;
/* allocate a slab for the target ios */
_tio_cache = kmem_cache_create("dm_tio", sizeof(struct target_io),
0, 0, NULL, NULL);
if (!_tio_cache) {
kmem_cache_destroy(_io_cache);
return -ENOMEM;
}
_major = major;
r = register_blkdev(_major, _name);
if (r < 0) {
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
return r;
}
if (!_major)
_major = r<