Beispiel #1
0
/*----------------------------------------------------------------
 * 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;
	size_t size;
	struct log_c *lc;
	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 = core_ctr(log, ti, argc - 1, argv + 1);
	if (r) {
		dm_put_device(ti, dev);
		return r;
	}

	lc = (struct log_c *) log->context;
	lc->log_dev = dev;

	/* setup the disk header fields */
	lc->header_location.bdev = lc->log_dev->bdev;
	lc->header_location.sector = 0;
	lc->header_location.count = 1;

	/*
	 * We can't read less than this amount, even though we'll
	 * not be using most of this space.
	 */
	lc->disk_header = vmalloc(1 << SECTOR_SHIFT);
	if (!lc->disk_header)
		goto bad;

	/* setup the disk bitset fields */
	lc->bits_location.bdev = lc->log_dev->bdev;
	lc->bits_location.sector = LOG_OFFSET;

	size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t),
			   1 << SECTOR_SHIFT);
	lc->bits_location.count = size >> SECTOR_SHIFT;
	lc->disk_bits = vmalloc(size);
	if (!lc->disk_bits) {
		vfree(lc->disk_header);
		goto bad;
	}
	return 0;

 bad:
	dm_put_device(ti, lc->log_dev);
	core_dtr(log);
	return -ENOMEM;
}
Beispiel #2
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);
	vfree(lc->disk_bits);
	core_dtr(log);
}
Beispiel #3
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);
	dm_io_client_destroy(lc->io_req.client);
	vfree(lc->disk_header);
	lc->clean_bits = NULL;
	core_dtr(log);
}
Beispiel #4
0
/*----------------------------------------------------------------
 * disk log constructor/destructor
 *
 * argv contains 2 - 4 arguments:
 *	 <log_device> <region_size> [[no]sync] [block_on_error]
 *--------------------------------------------------------------*/
static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
		    unsigned int argc, char **argv)
{
	int r;
	size_t size, bitset_size;
	struct log_c *lc;
	struct dm_dev *dev;
	uint32_t *clean_bits;

	if (argc < 2 || argc > 4) {
		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 = core_ctr(log, ti, argc - 1, argv + 1);
	if (r) {
		dm_put_device(ti, dev);
		return r;
	}

	lc = (struct log_c *) log->context;
	lc->log_dev = dev;
	lc->log_dev_failed = 0;

	/* setup the disk header fields */
	lc->header_location.bdev = lc->log_dev->bdev;
	lc->header_location.sector = 0;

	/* Include both the header and the bitset in one buffer. */
	bitset_size = lc->bitset_uint32_count * sizeof(uint32_t);
	size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size,
			   ti->limits.hardsect_size);

	if (size > dev->bdev->bd_inode->i_size) {
		DMWARN("log device %s too small: need %llu bytes",
		       dev->name, (unsigned long long)size);
		r = -EINVAL;
		goto bad;
	}

	lc->header_location.count = size >> SECTOR_SHIFT;

	lc->disk_header = vmalloc(size);
	if (!lc->disk_header) {
		r = -ENOMEM;
		goto bad;
	}

	/*
	 * Deallocate the clean_bits buffer that was allocated in core_ctr()
	 * and point it at the appropriate place in the disk_header buffer.
	 */
	clean_bits = lc->clean_bits;
	lc->clean_bits = (void *)lc->disk_header + (LOG_OFFSET << SECTOR_SHIFT);
	memcpy(lc->clean_bits, clean_bits, bitset_size);
	vfree(clean_bits);

	lc->io_req.mem.type = DM_IO_VMA;
	lc->io_req.client = dm_io_client_create(dm_div_up(size, PAGE_SIZE));
	if (IS_ERR(lc->io_req.client)) {
		r = PTR_ERR(lc->io_req.client);
		DMWARN("couldn't allocate disk io client");
		vfree(lc->disk_header);
		goto bad;
	}
	return 0;

 bad:
	dm_put_device(ti, lc->log_dev);
	core_dtr(log);
	return r;
}