示例#1
0
int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t root,
		     uint32_t old_nr_entries, uint32_t new_nr_entries,
		     bool default_value, dm_block_t *new_root)
{
	uint32_t old_blocks = dm_div_up(old_nr_entries, BITS_PER_ARRAY_ENTRY);
	uint32_t new_blocks = dm_div_up(new_nr_entries, BITS_PER_ARRAY_ENTRY);
	__le64 value = default_value ? cpu_to_le64(~0) : cpu_to_le64(0);

	__dm_bless_for_disk(&value);
	return dm_array_resize(&info->array_info, root, old_blocks, new_blocks,
			       &value, new_root);
}
示例#2
0
static int setup_indexes(struct dm_table *t)
{
	int i;
	unsigned int total = 0;
	sector_t *indexes;

	/* allocate the space for *all* the indexes */
	for (i = t->depth - 2; i >= 0; i--) {
		t->counts[i] = dm_div_up(t->counts[i + 1], CHILDREN_PER_NODE);
		total += t->counts[i];
	}

	indexes = (sector_t *) dm_vcalloc(total, (unsigned long) NODE_SIZE);
	if (!indexes)
		return -ENOMEM;

	/* set up internal nodes, bottom-up */
	for (i = t->depth - 2, total = 0; i >= 0; i--) {
		t->index[i] = indexes;
		indexes += (KEYS_PER_NODE * t->counts[i]);
		setup_btree_index(i, t);
	}

	return 0;
}
示例#3
0
/*
 * Similar to ceiling(log_size(n))
 */
static unsigned int int_log(unsigned int n, unsigned int base)
{
	int result = 0;

	while (n > 1) {
		n = dm_div_up(n, base);
		result++;
	}

	return result;
}
示例#4
0
/*
 * Builds the btree to index the map.
 */
int dm_table_complete(struct dm_table *t)
{
	int r = 0;
	unsigned int leaf_nodes;

	check_for_valid_limits(&t->limits);

	/* how many indexes will the btree have ? */
	leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
	t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);

	/* leaf layer has already been set up */
	t->counts[t->depth - 1] = leaf_nodes;
	t->index[t->depth - 1] = t->highs;

	if (t->depth >= 2)
		r = setup_indexes(t);

	return r;
}
示例#5
0
static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
                              unsigned int argc, char **argv,
                              struct dm_dev *dev)
{
    enum sync sync = DEFAULTSYNC;

    struct log_c *lc;
    uint32_t region_size;
    unsigned int region_count;
    size_t bitset_size, buf_size;
    int r;

    if (argc < 1 || argc > 2) {
        DMWARN("wrong number of arguments to dirty region log");
        return -EINVAL;
    }

    if (argc > 1) {
        if (!strcmp(argv[1], "sync"))
            sync = FORCESYNC;
        else if (!strcmp(argv[1], "nosync"))
            sync = NOSYNC;
        else {
            DMWARN("unrecognised sync argument to "
                   "dirty region log: %s", argv[1]);
            return -EINVAL;
        }
    }

    if (sscanf(argv[0], "%u", &region_size) != 1 ||
            !_check_region_size(ti, region_size)) {
        DMWARN("invalid region size %s", argv[0]);
        return -EINVAL;
    }

    region_count = dm_sector_div_up(ti->len, region_size);

    lc = kmalloc(sizeof(*lc), GFP_KERNEL);
    if (!lc) {
        DMWARN("couldn't allocate core log");
        return -ENOMEM;
    }

    lc->ti = ti;
    lc->touched_dirtied = 0;
    lc->touched_cleaned = 0;
    lc->flush_failed = 0;
    lc->region_size = region_size;
    lc->region_count = region_count;
    lc->sync = sync;

    /*
     * Work out how many "unsigned long"s we need to hold the bitset.
     */
    bitset_size = dm_round_up(region_count,
                              sizeof(*lc->clean_bits) << BYTE_SHIFT);
    bitset_size >>= BYTE_SHIFT;

    lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits);

    /*
     * Disk log?
     */
    if (!dev) {
        lc->clean_bits = vmalloc(bitset_size);
        if (!lc->clean_bits) {
            DMWARN("couldn't allocate clean bitset");
            kfree(lc);
            return -ENOMEM;
        }
        lc->disk_header = NULL;
    } else {
        lc->log_dev = dev;
        lc->log_dev_failed = 0;
        lc->log_dev_flush_failed = 0;
        lc->header_location.bdev = lc->log_dev->bdev;
        lc->header_location.sector = 0;

        /*
         * Buffer holds both header and bitset.
         */
        buf_size =
            dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size,
                        bdev_logical_block_size(lc->header_location.
                                                bdev));

        if (buf_size > i_size_read(dev->bdev->bd_inode)) {
            DMWARN("log device %s too small: need %llu bytes",
                   dev->name, (unsigned long long)buf_size);
            kfree(lc);
            return -EINVAL;
        }

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

        lc->io_req.mem.type = DM_IO_VMA;
        lc->io_req.notify.fn = NULL;
        lc->io_req.client = dm_io_client_create(dm_div_up(buf_size,
                                                PAGE_SIZE));
        if (IS_ERR(lc->io_req.client)) {
            r = PTR_ERR(lc->io_req.client);
            DMWARN("couldn't allocate disk io client");
            kfree(lc);
            return -ENOMEM;
        }

        lc->disk_header = vmalloc(buf_size);
        if (!lc->disk_header) {
            DMWARN("couldn't allocate disk log buffer");
            dm_io_client_destroy(lc->io_req.client);
            kfree(lc);
            return -ENOMEM;
        }

        lc->io_req.mem.ptr.vma = lc->disk_header;
        lc->clean_bits = (void *)lc->disk_header +
                         (LOG_OFFSET << SECTOR_SHIFT);
    }

    memset(lc->clean_bits, -1, bitset_size);

    lc->sync_bits = vmalloc(bitset_size);
    if (!lc->sync_bits) {
        DMWARN("couldn't allocate sync bitset");
        if (!dev)
            vfree(lc->clean_bits);
        else
            dm_io_client_destroy(lc->io_req.client);
        vfree(lc->disk_header);
        kfree(lc);
        return -ENOMEM;
    }
    memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size);
    lc->sync_count = (sync == NOSYNC) ? region_count : 0;

    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);
        else
            dm_io_client_destroy(lc->io_req.client);
        vfree(lc->disk_header);
        kfree(lc);
        return -ENOMEM;
    }
    memset(lc->recovering_bits, 0, bitset_size);
    lc->sync_search = 0;
    log->context = lc;

    return 0;
}
示例#6
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;
}
示例#7
0
static unsigned long *alloc_bitset(unsigned nr_entries)
{
	size_t s = sizeof(unsigned long) * dm_div_up(nr_entries, BITS_PER_LONG);
	return vzalloc(s);
}