/*
* Copyright (C) 2003 Sistina Software Limited.
*
* This file is released under the GPL.
*/
#include "dm.h"
#include "dm-daemon.h"
#include "dm-io.h"
#include "dm-log.h"
#include "kcopyd.h"
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
static struct dm_daemon _kmirrord;
/*-----------------------------------------------------------------
* buffer lists:
*
* We play with singly linked lists of buffers, but we want to be
* careful to add new buffers to the back of the list, to avoid
* buffers being starved of attention.
*---------------------------------------------------------------*/
struct buffer_list {
struct buffer_head *head;
struct buffer_head *tail;
};
static inline void buffer_list_init(struct buffer_list *bl)
{
bl->head = bl->tail = NULL;
}
static inline void buffer_list_add(struct buffer_list *bl,
struct buffer_head *bh)
{
bh->b_reqnext = NULL;
if (bl->tail) {
bl->tail->b_reqnext = bh;
bl->tail = bh;
} else
bl->head = bl->tail = bh;
}
static struct buffer_head *buffer_list_pop(struct buffer_list *bl)
{
struct buffer_head *bh = bl->head;
if (bh) {
bl->head = bl->head->b_reqnext;
if (!bl->head)
bl->tail = NULL;
bh->b_reqnext = NULL;
}
return bh;
}
/*-----------------------------------------------------------------
* Region hash
*
* The mirror splits itself up into discrete regions. Each
* region can be in one of three states: clean, dirty,
* nosync. There is no need to put clean regions in the hash.
*
* In addition to being present in the hash table a region _may_
* be present on one of three lists.
*
* clean_regions: Regions on this list have no io pending to
* them, they are in sync, we are no longer interested in them,
* they are dull. rh_update_states() will remove them from the
* hash table.
*
* quiesced_regions: These regions have been spun down, ready
* for recovery. rh_recovery_start() will remove regions from
* this list and hand them to kmirrord, which will schedule the
* recovery io with kcopyd.
*
* recovered_regions: Regions that kcopyd has successfully
* recovered. rh_update_states() will now schedule any delayed
* io, up the recovery_count, and remove the region from the
* hash.
*
* There are 2 locks:
* A rw spin lock 'hash_lock' protects just the hash table,
* this is never held in write mode from interrupt context,
* which I believe means that we only have to disable irqs when
* doing a write lock.
*
* An ordinary spin lock 'region_lock' that protects the three
* lists in the region_hash, with the 'state', 'list' and
* 'bhs_delayed' fields of the regions. This is used from irq
* context, so all other uses will have to suspend local irqs.
*---------------------------------------------------------------*/
struct mirror_set;
struct region_hash {
struct mirror_set *ms;
sector_t region_size;
/* holds persistent region state */
struct dirty_log *log;
/* hash table */
rwlock_t hash_lock;
mempool_t *region_pool;
unsigned int mask;
unsigned int nr_buckets;
struct list_head *buckets;
spinlock_t region_lock;
struct semaphore recovery_count;
struct list_head clean_regions;
struct list_head quiesced_regions;
struct list_head recovered_regions;
};
enum {
RH_CLEAN,
RH_DIRTY,
RH_NOSYNC,
RH_RECOVERING
};
struct region {
struct region_hash *rh; /* FIXME: can we get rid of this ? */
region_t key;
int state;
struct list_head hash_list;
struct list_head list;
atomic_t pending;
struct buffer_head *delayed_bhs;
};
/*
* Conversion fns
*/
static inline region_t bh_to_region(struct region_hash *rh,
struct buffer_head *bh)
{
return bh->b_rsector / rh->region_size;
}
static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
{
return region * rh->region_size;
}
/* FIXME move this */
static void queue_bh(struct mirror_set *ms, struct buffer_head *bh, int rw);
static void *region_alloc(int gfp_mask, void *pool_data)
{
return kmalloc(sizeof(struct region), gfp_mask);
}
static void region_free(void *element, void *pool_data)
{
kfree(element);
}
#define MIN_REGIONS 64
#define MAX_RECOVERY 1
static int rh_init(struct region_hash *rh, struct mirror_set *ms,
struct dirty_log *log, sector_t region_size,
region_t nr_regions)
{
unsigned int nr_buckets, max_buckets;
size_t i;
/*
* Calculate a suitable number of buckets for our hash
* table.
*/
max_buckets = nr_regions >> 6;
for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1)
;
nr_buckets >>= 1;
rh->ms = ms;
rh->log = log;
rh->region_size = region_size;
rwlock_init(&rh->hash_lock);
rh->mask = nr_buckets - 1;
rh->nr_buckets = nr_buckets;
rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
if (!rh->buckets) {
DMERR("unable to allocate region hash memory");
return -ENOMEM;
}
for (i = 0; i < nr_buckets; i++)
INIT_LIST_HEAD(rh->buckets + i);
spin_lock_init(&rh->region_lock);
sema_init(&rh->recovery_count, 0);
INIT_LIST_HEAD(&rh->clean_regions);
INIT_LIST_HEAD(&rh->quiesced_regions);
INIT_LIST_HEAD(&rh->recovered_regions);
rh->region_pool = mempool_create(MIN_REGIONS, region_alloc,
region_free, NULL);
if (!rh->region_pool) {
vfree(rh->buckets);
rh->buckets = NULL;
return -ENOMEM;
}
return 0;
}
static void rh_exit(struct region_hash *rh)
{
unsigned int h;
struct region *reg;
struct list_head *tmp, *tmp2;
BUG_ON(!list_empty(&rh->quiesced_regions));
for (h = 0; h < rh->nr_buckets; h++) {
list_for_each_safe (tmp, tmp2, rh->buckets + h) {
reg = list_entry(tmp, struct region, hash_list);
BUG_ON(atomic_read(®->pending));
mempool_free(reg, rh->region_pool);
}
}
if (rh->log)
dm_destroy_dirty_log(rh->log);
if (rh->region_pool)
mempool_destroy(rh->region_pool);
vfree(rh->buckets);
}
#define RH_HASH_MULT 2654435387U
static inline unsigned int rh_hash(struct region_hash *rh, region_t region)
{
return (unsigned int) ((region * RH_HASH_MULT) >> 12) & rh->mask;
}
static struct region *__rh_lookup(struct region_hash *rh, region_t region)
{
struct region *reg;
list_for_each_entry (reg, rh->buckets + rh_hash(rh, region), hash_list)
if (reg->key == region)
return reg;
return NULL;
}
static void __rh_insert(struct region_hash *rh, struct region *reg)
{
unsigned int h = rh_hash(rh, reg->key);
list_add(®->hash_list, rh->buckets + h);
}
static struct region *__rh_alloc(struct region_hash *rh, region_t region)
{
struct region *reg, *nreg;
read_unlock(&rh->hash_lock);
nreg = mempool_alloc(rh->region_pool, GFP_NOIO);
nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
RH_CLEAN : RH_NOSYNC;
nreg->rh = rh;
nreg->key = region;
INIT_LIST_HEAD(&nreg->list);
atomic_set(&nreg->pending, 0);
nreg->delayed_bhs = NULL;
write_lock_irq(&rh->hash_lock);
reg = __rh_lookup(rh, region);
if (reg)
/* we lost the race */
mempool_free(nreg, rh->region_pool);
else {
__rh_insert(rh, nreg);
if (nreg->state == RH_CLEAN) {
spin_lock_irq(&rh->region_lock);
list_add(&nreg->list, &rh->clean_regions);
spin_unlock_irq(&rh->region_lock);
}
reg = nreg;
}
write_unlock_irq(&rh->hash_lock);
read_lock(&rh->hash_lock);
return reg;
}
static inline struct region *__rh_find(struct region_hash *rh, region_t region)
{
struct region *reg;
reg = __rh_lookup(rh, region);
if (!reg)
reg = __rh_alloc(rh, region);
return reg;
}
static int rh_state(struct region_hash *rh, region_t region, int may_block)
{
int r;
struct region *reg;
read_lock(&rh->hash_lock);
reg = __rh_lookup(rh, region);
read_unlock(&rh->hash_lock);
if (reg)
return reg->state;
/*
* The region wasn't in the hash, so we fall back to the
* dirty log.
*/
r = rh->log->type->in_sync(rh->log, region, may_block);
/*
* Any error from the dirty log (eg. -
没有合适的资源?快使用搜索试试~ 我知道了~
device-mapper.1.01.04.tgz
4星 · 超过85%的资源 需积分: 10 31 下载量 102 浏览量
2008-09-23
16:32:17
上传
评论
收藏 858KB TGZ 举报
温馨提示
共138个文件
patch:60个
c:26个
h:20个
device-mapper.1.01.04.tgz
资源推荐
资源详情
资源评论
收起资源包目录
device-mapper.1.01.04.tgz (138个子文件)
dmsetup.8 6KB
kcopyd.c.async 16KB
dm-raid1.c 29KB
libdm-iface.c 29KB
dm-ioctl.c 27KB
dm-snapshot.c 25KB
dmsetup.c 24KB
dm.c 21KB
dm-exception-store.c 14KB
kcopyd.c 13KB
dm-table.c 13KB
libdm-common.c 9KB
dmfs-table.c 8KB
libdevmapper.c 8KB
dm-io.c 8KB
dm-log.c 7KB
dmfs-lv.c 6KB
dm-stripe.c 5KB
dm-reverse.c 4KB
dmfs-root.c 4KB
dmfs-super.c 4KB
dm-target.c 3KB
dmfs-error.c 3KB
dm-linear.c 2KB
dmfs-suspend.c 2KB
dm-daemon.c 2KB
libdm-file.c 2KB
dmfs-status.c 1KB
configure 178KB
COPYING 18KB
.exported_symbols 520B
config.guess 41KB
dm-ioctl.h 9KB
list.h 5KB
dm.h 5KB
libdevmapper.h 4KB
libdm-compat.h 4KB
dm-snapshot.h 3KB
dm-log.h 3KB
device-mapper.h 3KB
dm-io.h 2KB
libdm-targets.h 1KB
log.h 1KB
kcopyd.h 1KB
lib.h 975B
pogen.h 850B
libdm-file.h 826B
intl.h 789B
libdm-targets.h 784B
kdev_t.h 779B
dm-daemon.h 588B
dmfs.h 575B
configure.in 12KB
make.tmpl.in 5KB
Makefile.in 3KB
Makefile.in 2KB
Makefile.in 1KB
Makefile.in 1KB
Makefile.in 1KB
libdm-common.h.in 1KB
Makefile.in 1KB
Makefile.in 915B
INSTALL 5KB
install-sh 8KB
INTRO 2KB
COPYING.LIB 25KB
linux-2.4.28-pre4-devmapper-ioctl.patch 232KB
linux-2.4.27-devmapper-ioctl.patch 232KB
linux-2.4.26-rc1-devmapper-ioctl.patch 231KB
linux-2.4.20-devmapper-ioctl.patch 231KB
linux-2.4.21-devmapper-ioctl.patch 228KB
linux-2.4.22-devmapper-ioctl.patch 227KB
linux-2.4.28-pre4-devmapper.patch 207KB
linux-2.4.27-devmapper.patch 207KB
linux-2.4.26-rc1-devmapper.patch 207KB
linux-2.4.21-devmapper.patch 204KB
linux-2.4.20-devmapper.patch 204KB
linux-2.4.22-devmapper.patch 204KB
linux-2.4.21-mempool.patch 10KB
linux-2.4.20-mempool.patch 10KB
linux-2.4.28-pre4-mempool.patch 10KB
linux-2.4.27-mempool.patch 10KB
linux-2.4.22-mempool.patch 10KB
linux-2.4.26-rc1-mempool.patch 10KB
linux-2.4.22-memalloc.patch 10KB
linux-2.4.21-memalloc.patch 10KB
linux-2.4.22-VFS-lock.patch 9KB
linux-2.4.21-VFS-lock-experimental.patch 9KB
linux-2.4.21-VFS-lock.patch 7KB
linux-2.4.21-arch64.patch 7KB
linux-2.4.20-arch64.patch 7KB
linux-2.4.28-pre4-arch64.patch 7KB
linux-2.4.27-arch64.patch 7KB
linux-2.4.26-rc1-arch64.patch 6KB
linux-2.4.20-VFS-lock.patch 6KB
linux-2.4.22-arch64.patch 6KB
linux-2.4.20-b_private.patch 5KB
linux-2.4.28-pre4-b_private.patch 2KB
linux-2.4.27-b_private.patch 2KB
linux-2.4.21-b_private.patch 2KB
共 138 条
- 1
- 2
资源评论
- Ellco2012-04-27谢了,我的libvirt终于装成功了!
- cherryinlove2012-05-02要修改代码完成一些自定义功能,还在看,谢啦
mosquito88881
- 粉丝: 4
- 资源: 13
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功