--- drivers/md/dm-thin.c | 68 ++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 30 deletions(-) Index: linux-3.0-rc7/drivers/md/dm-thin.c =================================================================== --- linux-3.0-rc7.orig/drivers/md/dm-thin.c +++ linux-3.0-rc7/drivers/md/dm-thin.c @@ -904,7 +904,8 @@ static void process_discard(struct thin_ break; case -ENODATA: - /* Either this isn't provisioned, or preparation for + /* + * Either this isn't provisioned, or preparation for * provisioning may be pending (we could find out by * calling bio_detain_if_occupied). But even in this case * it's easier to just forget the discard. @@ -997,9 +998,13 @@ static void provision_block(struct thin_ struct cell *cell; struct cell_key key; + /* + * If cell is already occupied, then the block is already + * being provisioned so we have nothing further to do here. + */ build_virtual_key(tc->td, block, &key); if (bio_detain(tc->pool->prison, &key, bio, &cell)) - return; /* already underway */ + return; r = alloc_data_block(tc, &data_block); switch (r) { @@ -1034,7 +1039,11 @@ static void process_bio(struct thin_c *t break; case -ENODATA: - if (bio_rw(bio) == READ || bio_rw(bio) == READA) { + /* + * When reading, we return zeroes regardless of the + * zero_new_blocks setting. + */ + if (bio_data_dir(bio) == READ) { zero_fill_bio(bio); bio_endio(bio, 0); } else @@ -1182,6 +1191,9 @@ static int bio_map(struct dm_target *ti, r = dm_thin_metadata_lookup(td, block, 0, &result); + /* + * Note that we defer readahead too. + */ switch (r) { case 0: if (unlikely(result.shared)) { @@ -1208,7 +1220,14 @@ static int bio_map(struct dm_target *ti, break; case -ENODATA: - if (bio_rw(bio) == READA || bio_rw(bio) == READ) { + /* + * In future, the failed dm_thin_metadata_lookup above could + * provide the hint to load the metadata into cache. + * + * When reading, we return zeroes regardless of the + * zero_new_blocks setting. + */ + if (bio_data_dir(bio) == READ) { zero_fill_bio(bio); bio_endio(bio, 0); } else @@ -1337,7 +1356,8 @@ static struct pool *pool_create(struct b goto bad_kcopyd_client; } - /* Create singlethreaded workqueue that will service all devices + /* + * Create singlethreaded workqueues that will service all devices * that use this metadata. */ pool->producer_wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX "-producer", @@ -1503,7 +1523,6 @@ static int pool_ctr(struct dm_target *ti unsigned long block_size; dm_block_t low_water; struct dm_dev *metadata_dev; - char *end; if (argc < 4) { ti->error = "Invalid argument count"; @@ -1524,15 +1543,14 @@ static int pool_ctr(struct dm_target *ti goto out_data_dev; } - block_size = simple_strtoul(argv[2], &end, 10); - if (!block_size || *end) { + if (kstrtoul(argv[2], 10, &block_size) || !block_size) { ti->error = "Invalid block size"; r = -EINVAL; goto out; } - low_water = simple_strtoull(argv[3], &end, 10); - if (!low_water || *end) { + if (kstrtoull(argv[3], 10, (unsigned long long *)&low_water) || + !low_water) { ti->error = "Invalid low water mark"; r = -EINVAL; goto out; @@ -1702,10 +1720,7 @@ static int check_arg_count(unsigned argc static int read_dev_id(char *arg, dm_thin_dev_t *dev_id) { - char *end; - - *dev_id = simple_strtoull(arg, &end, 10); - if (*end) { + if (kstrtoull(arg, 10, (unsigned long long *)dev_id)) { DMWARN("Message received with invalid device id: %s", arg); return -EINVAL; } @@ -1788,7 +1803,6 @@ static int process_trim_mesg(unsigned ar { dm_thin_dev_t dev_id; sector_t new_size; - char *end; int r; r = check_arg_count(argc, 3); @@ -1799,8 +1813,7 @@ static int process_trim_mesg(unsigned ar if (r) return r; - new_size = simple_strtoull(argv[2], &end, 10); - if (*end) { + if (kstrtoull(argv[2], 10, (unsigned long long *)&new_size)) { DMWARN("trim device %s: Invalid new size: %s sectors.", argv[1], argv[2]); return -EINVAL; @@ -1816,22 +1829,19 @@ static int process_trim_mesg(unsigned ar static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool) { - char *end; - uint64_t old_id, new_id; + dm_thin_dev_t old_id, new_id; int r; r = check_arg_count(argc, 3); if (r) return r; - old_id = simple_strtoull(argv[1], &end, 10); - if (*end) { + if (kstrtoull(argv[1], 10, (unsigned long long *)&old_id)) { DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]); return -EINVAL; } - new_id = simple_strtoull(argv[2], &end, 10); - if (*end) { + if (kstrtoull(argv[2], 10, (unsigned long long *)&new_id)) { DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]); return -EINVAL; } @@ -1876,7 +1886,7 @@ static int pool_message(struct dm_target r = process_set_transaction_id_mesg(argc, argv, pool); else - DMWARN("Unrecognised thin target message received."); + DMWARN("Unrecognised thin pool target message received."); if (!r) { r = dm_thin_metadata_commit(pool->tmd); @@ -2015,10 +2025,10 @@ static void thin_dtr(struct dm_target *t /* * Thin target parameters: * - * + * * - * pool dev: the path to the pool (eg, /dev/mapper/my_pool) - * dev id: the internal device identifier + * pool_dev: the path to the pool (eg, /dev/mapper/my_pool) + * dev_id: the internal device identifier */ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) { @@ -2026,7 +2036,6 @@ static int thin_ctr(struct dm_target *ti struct thin_c *tc; struct dm_dev *pool_dev; struct mapped_device *pool_md; - char *end; if (argc != 2) { ti->error = "Invalid argument count"; @@ -2046,8 +2055,7 @@ static int thin_ctr(struct dm_target *ti } tc->pool_dev = pool_dev; - tc->dev_id = simple_strtoull(argv[1], &end, 10); - if (*end) { + if (kstrtoull(argv[1], 10, (unsigned long long *)&tc->dev_id)) { ti->error = "Invalid device id"; r = -EINVAL; goto bad_common;