dm-log.c

来自「linux 内核源代码」· C语言 代码 · 共 740 行 · 第 1/2 页

C
740
字号
	lc->recovering_bits = vmalloc(bitset_size);	if (!lc->recovering_bits) {		DMWARN("couldn't allocate sync bitset");		vfree(lc->sync_bits);		if (!dev)			vfree(lc->clean_bits);		vfree(lc->disk_header);		kfree(lc);		return -ENOMEM;	}	memset(lc->recovering_bits, 0, bitset_size);	lc->sync_search = 0;	log->context = lc;	return 0;}static int core_ctr(struct dirty_log *log, struct dm_target *ti,		    unsigned int argc, char **argv){	return create_log_context(log, ti, argc, argv, NULL);}static void destroy_log_context(struct log_c *lc){	vfree(lc->sync_bits);	vfree(lc->recovering_bits);	kfree(lc);}static void core_dtr(struct dirty_log *log){	struct log_c *lc = (struct log_c *) log->context;	vfree(lc->clean_bits);	destroy_log_context(lc);}/*---------------------------------------------------------------- * disk log constructor/destructor * * argv contains log_device region_size followed optionally by [no]sync *--------------------------------------------------------------*/static int disk_ctr(struct dirty_log *log, struct dm_target *ti,		    unsigned int argc, char **argv){	int r;	struct dm_dev *dev;	if (argc < 2 || argc > 3) {		DMWARN("wrong number of arguments to disk mirror log");		return -EINVAL;	}	r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */,			  FMODE_READ | FMODE_WRITE, &dev);	if (r)		return r;	r = create_log_context(log, ti, argc - 1, argv + 1, dev);	if (r) {		dm_put_device(ti, dev);		return r;	}	return 0;}static void disk_dtr(struct dirty_log *log){	struct log_c *lc = (struct log_c *) log->context;	dm_put_device(lc->ti, lc->log_dev);	vfree(lc->disk_header);	dm_io_client_destroy(lc->io_req.client);	destroy_log_context(lc);}static int count_bits32(uint32_t *addr, unsigned size){	int count = 0, i;	for (i = 0; i < size; i++) {		count += hweight32(*(addr+i));	}	return count;}static void fail_log_device(struct log_c *lc){	if (lc->log_dev_failed)		return;	lc->log_dev_failed = 1;	dm_table_event(lc->ti->table);}static int disk_resume(struct dirty_log *log){	int r;	unsigned i;	struct log_c *lc = (struct log_c *) log->context;	size_t size = lc->bitset_uint32_count * sizeof(uint32_t);	/* read the disk header */	r = read_header(lc);	if (r) {		DMWARN("%s: Failed to read header on mirror log device",		       lc->log_dev->name);		fail_log_device(lc);		/*		 * If the log device cannot be read, we must assume		 * all regions are out-of-sync.  If we simply return		 * here, the state will be uninitialized and could		 * lead us to return 'in-sync' status for regions		 * that are actually 'out-of-sync'.		 */		lc->header.nr_regions = 0;	}	/* set or clear any new bits -- device has grown */	if (lc->sync == NOSYNC)		for (i = lc->header.nr_regions; i < lc->region_count; i++)			/* FIXME: amazingly inefficient */			log_set_bit(lc, lc->clean_bits, i);	else		for (i = lc->header.nr_regions; i < lc->region_count; i++)			/* FIXME: amazingly inefficient */			log_clear_bit(lc, lc->clean_bits, i);	/* clear any old bits -- device has shrunk */	for (i = lc->region_count; i % (sizeof(*lc->clean_bits) << BYTE_SHIFT); i++)		log_clear_bit(lc, lc->clean_bits, i);	/* copy clean across to sync */	memcpy(lc->sync_bits, lc->clean_bits, size);	lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count);	lc->sync_search = 0;	/* set the correct number of regions in the header */	lc->header.nr_regions = lc->region_count;	/* write the new header */	r = write_header(lc);	if (r) {		DMWARN("%s: Failed to write header on mirror log device",		       lc->log_dev->name);		fail_log_device(lc);	}	return r;}static uint32_t core_get_region_size(struct dirty_log *log){	struct log_c *lc = (struct log_c *) log->context;	return lc->region_size;}static int core_resume(struct dirty_log *log){	struct log_c *lc = (struct log_c *) log->context;	lc->sync_search = 0;	return 0;}static int core_is_clean(struct dirty_log *log, region_t region){	struct log_c *lc = (struct log_c *) log->context;	return log_test_bit(lc->clean_bits, region);}static int core_in_sync(struct dirty_log *log, region_t region, int block){	struct log_c *lc = (struct log_c *) log->context;	return log_test_bit(lc->sync_bits, region);}static int core_flush(struct dirty_log *log){	/* no op */	return 0;}static int disk_flush(struct dirty_log *log){	int r;	struct log_c *lc = (struct log_c *) log->context;	/* only write if the log has changed */	if (!lc->touched)		return 0;	r = write_header(lc);	if (r)		fail_log_device(lc);	else		lc->touched = 0;	return r;}static void core_mark_region(struct dirty_log *log, region_t region){	struct log_c *lc = (struct log_c *) log->context;	log_clear_bit(lc, lc->clean_bits, region);}static void core_clear_region(struct dirty_log *log, region_t region){	struct log_c *lc = (struct log_c *) log->context;	log_set_bit(lc, lc->clean_bits, region);}static int core_get_resync_work(struct dirty_log *log, region_t *region){	struct log_c *lc = (struct log_c *) log->context;	if (lc->sync_search >= lc->region_count)		return 0;	do {		*region = ext2_find_next_zero_bit(					     (unsigned long *) lc->sync_bits,					     lc->region_count,					     lc->sync_search);		lc->sync_search = *region + 1;		if (*region >= lc->region_count)			return 0;	} while (log_test_bit(lc->recovering_bits, *region));	log_set_bit(lc, lc->recovering_bits, *region);	return 1;}static void core_set_region_sync(struct dirty_log *log, region_t region,				 int in_sync){	struct log_c *lc = (struct log_c *) log->context;	log_clear_bit(lc, lc->recovering_bits, region);	if (in_sync) {		log_set_bit(lc, lc->sync_bits, region);                lc->sync_count++;        } else if (log_test_bit(lc->sync_bits, region)) {		lc->sync_count--;		log_clear_bit(lc, lc->sync_bits, region);	}}static region_t core_get_sync_count(struct dirty_log *log){        struct log_c *lc = (struct log_c *) log->context;        return lc->sync_count;}#define	DMEMIT_SYNC \	if (lc->sync != DEFAULTSYNC) \		DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")static int core_status(struct dirty_log *log, status_type_t status,		       char *result, unsigned int maxlen){	int sz = 0;	struct log_c *lc = log->context;	switch(status) {	case STATUSTYPE_INFO:		DMEMIT("1 %s", log->type->name);		break;	case STATUSTYPE_TABLE:		DMEMIT("%s %u %u ", log->type->name,		       lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size);		DMEMIT_SYNC;	}	return sz;}static int disk_status(struct dirty_log *log, status_type_t status,		       char *result, unsigned int maxlen){	int sz = 0;	struct log_c *lc = log->context;	switch(status) {	case STATUSTYPE_INFO:		DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name,		       lc->log_dev_failed ? 'D' : 'A');		break;	case STATUSTYPE_TABLE:		DMEMIT("%s %u %s %u ", log->type->name,		       lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name,		       lc->region_size);		DMEMIT_SYNC;	}	return sz;}static struct dirty_log_type _core_type = {	.name = "core",	.module = THIS_MODULE,	.ctr = core_ctr,	.dtr = core_dtr,	.resume = core_resume,	.get_region_size = core_get_region_size,	.is_clean = core_is_clean,	.in_sync = core_in_sync,	.flush = core_flush,	.mark_region = core_mark_region,	.clear_region = core_clear_region,	.get_resync_work = core_get_resync_work,	.set_region_sync = core_set_region_sync,	.get_sync_count = core_get_sync_count,	.status = core_status,};static struct dirty_log_type _disk_type = {	.name = "disk",	.module = THIS_MODULE,	.ctr = disk_ctr,	.dtr = disk_dtr,	.postsuspend = disk_flush,	.resume = disk_resume,	.get_region_size = core_get_region_size,	.is_clean = core_is_clean,	.in_sync = core_in_sync,	.flush = disk_flush,	.mark_region = core_mark_region,	.clear_region = core_clear_region,	.get_resync_work = core_get_resync_work,	.set_region_sync = core_set_region_sync,	.get_sync_count = core_get_sync_count,	.status = disk_status,};int __init dm_dirty_log_init(void){	int r;	r = dm_register_dirty_log_type(&_core_type);	if (r)		DMWARN("couldn't register core log");	r = dm_register_dirty_log_type(&_disk_type);	if (r) {		DMWARN("couldn't register disk type");		dm_unregister_dirty_log_type(&_core_type);	}	return r;}void dm_dirty_log_exit(void){	dm_unregister_dirty_log_type(&_disk_type);	dm_unregister_dirty_log_type(&_core_type);}EXPORT_SYMBOL(dm_register_dirty_log_type);EXPORT_SYMBOL(dm_unregister_dirty_log_type);EXPORT_SYMBOL(dm_create_dirty_log);EXPORT_SYMBOL(dm_destroy_dirty_log);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?