--- drivers/md/dm-thin.c | 283 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 169 insertions(+), 114 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 @@ -454,7 +454,7 @@ struct pool { unsigned block_shift; dm_block_t offset_mask; dm_block_t low_water_mark; - unsigned zero_new_blocks; + unsigned zero_new_blocks:1; struct bio_prison *prison; struct dm_kcopyd_client *copier; @@ -490,7 +490,7 @@ struct pool_c { struct dm_target_callbacks callbacks; sector_t low_water_mark; - unsigned zero_new_blocks; + unsigned zero_new_blocks:1; }; /* @@ -971,7 +971,7 @@ static void process_shared_bio(struct th /* * If cell is already occupied, then sharing is already * in the process of being broken so we have nothing - * futher to do here. + * further to do here. */ build_data_key(tc->td, lookup_result->block, &key); if (bio_detain_if_occupied(pool->prison, &key, bio, &cell)) @@ -1445,7 +1445,7 @@ static void pool_dtr(struct dm_target *t } struct pool_features { - unsigned zero_new_blocks; + unsigned zero_new_blocks:1; }; static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf, @@ -1689,145 +1689,200 @@ static void pool_postsuspend(struct dm_t pool->pool_md = NULL; } -/* - * Messages supported: - * new-thin - * new-snap - * del - * trim - * trans-id - */ -static int pool_message(struct dm_target *ti, unsigned argc, char **argv) +static int check_arg_count(unsigned argc, unsigned args_required) { - /* ti->error doesn't have a const qualifier :( */ - char *invalid_args = "Incorrect number of arguments"; + if (argc != args_required) { + DMWARN("Message received with %u arguments instead of %u.", + argc, args_required); + return -EINVAL; + } - int r; - struct pool_c *pt = ti->private; - struct pool *pool = pt->pool; - dm_thin_dev_t dev_id; + return 0; +} + +static int read_dev_id(char *arg, dm_thin_dev_t *dev_id) +{ char *end; - if (!strcmp(argv[0], "new-thin")) { - if (argc != 2) { - ti->error = invalid_args; - return -EINVAL; - } + *dev_id = simple_strtoull(arg, &end, 10); + if (*end) { + DMWARN("Message received with invalid device id: %s", arg); + return -EINVAL; + } - dev_id = simple_strtoull(argv[1], &end, 10); - if (*end) { - ti->error = "Invalid device id"; - return -EINVAL; - } + return 0; +} - r = dm_thin_metadata_create_thin(pool->tmd, dev_id); - if (r) { - ti->error = "Creation of thin provisioned device failed"; - return r; - } +static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool) +{ + dm_thin_dev_t dev_id; + int r; - } else if (!strcmp(argv[0], "new-snap")) { - dm_thin_dev_t origin_id; + r = check_arg_count(argc, 2); + if (r) + return r; - if (argc != 3) { - ti->error = invalid_args; - return -EINVAL; - } + r = read_dev_id(argv[1], &dev_id); + if (r) + return r; - dev_id = simple_strtoull(argv[1], &end, 10); - if (*end) { - ti->error = "Invalid device id"; - return -EINVAL; - } + r = dm_thin_metadata_create_thin(pool->tmd, dev_id); + if (r) { + DMWARN("Creation of new thinly-provisioned device with id %s failed.", + argv[1]); + return r; + } - origin_id = simple_strtoull(argv[2], &end, 10); - if (*end) { - ti->error = "Invalid origin id"; - return -EINVAL; - } + return 0; +} - r = dm_thin_metadata_create_snap(pool->tmd, dev_id, origin_id); - if (r) { - ti->error = "Creation of snapshot failed"; - return r; - } +static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool) +{ + dm_thin_dev_t dev_id; + dm_thin_dev_t origin_dev_id; + int r; - } else if (!strcmp(argv[0], "del")) { - if (argc != 2) { - ti->error = invalid_args; - return -EINVAL; - } + r = check_arg_count(argc, 3); + if (r) + return r; - dev_id = simple_strtoull(argv[1], &end, 10); - if (*end) { - ti->error = "Invalid device id"; - return -EINVAL; - } + r = read_dev_id(argv[1], &dev_id); + if (r) + return r; - r = dm_thin_metadata_delete_device(pool->tmd, dev_id); + r = read_dev_id(argv[2], &origin_dev_id); + if (r) + return r; - } else if (!strcmp(argv[0], "trim")) { - sector_t new_size; + r = dm_thin_metadata_create_snap(pool->tmd, dev_id, origin_dev_id); + if (r) { + DMWARN("Creation of new snapshot %s of device %s failed.", + argv[1], argv[2]); + return r; + } - if (argc != 3) { - ti->error = invalid_args; - return -EINVAL; - } + return 0; +} - dev_id = simple_strtoull(argv[1], &end, 10); - if (*end) { - ti->error = "Invalid device id"; - return -EINVAL; - } +static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool) +{ + dm_thin_dev_t dev_id; + int r; - new_size = simple_strtoull(argv[2], &end, 10); - if (*end) { - ti->error = "Invalid size"; - return -EINVAL; - } + r = check_arg_count(argc, 2); + if (r) + return r; + + r = read_dev_id(argv[1], &dev_id); + if (r) + return r; + + r = dm_thin_metadata_delete_device(pool->tmd, dev_id); + if (r) + DMWARN("Deletion of thin device %s failed.", argv[1]); + + return r; +} + +static int process_trim_mesg(unsigned argc, char **argv, struct pool *pool) +{ + dm_thin_dev_t dev_id; + sector_t new_size; + char *end; + int r; + + r = check_arg_count(argc, 3); + if (r) + return r; + + r = read_dev_id(argv[1], &dev_id); + if (r) + return r; - r = dm_thin_metadata_trim_thin_dev( - pool->tmd, dev_id, + new_size = simple_strtoull(argv[2], &end, 10); + if (*end) { + DMWARN("trim device %s: Invalid new size: %s sectors.", + argv[1], argv[2]); + return -EINVAL; + } + + r = dm_thin_metadata_trim_thin_dev(pool->tmd, dev_id, dm_div_up(new_size, pool->sectors_per_block)); - if (r) { - ti->error = "Couldn't trim thin device"; - return r; - } + if (r) + DMWARN("Attempt to trim thin device %s failed.", argv[1]); - } else if (!strcmp(argv[0], "trans-id")) { - uint64_t old_id, new_id; + return r; +} - if (argc != 3) { - ti->error = invalid_args; - return -EINVAL; - } +static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool) +{ + char *end; + uint64_t old_id, new_id; + int r; - old_id = simple_strtoull(argv[1], &end, 10); - if (*end) { - ti->error = "Invalid current transaction id"; - return -EINVAL; - } + r = check_arg_count(argc, 3); + if (r) + return r; - new_id = simple_strtoull(argv[2], &end, 10); - if (*end) { - ti->error = "Invalid new transaction id"; - return -EINVAL; - } + old_id = simple_strtoull(argv[1], &end, 10); + if (*end) { + DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]); + return -EINVAL; + } - r = dm_thin_metadata_set_transaction_id(pool->tmd, - old_id, new_id); - if (r) { - ti->error = "Setting userspace transaction id failed"; - return r; - } - } else + new_id = simple_strtoull(argv[2], &end, 10); + if (*end) { + DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]); return -EINVAL; + } + + r = dm_thin_metadata_set_transaction_id(pool->tmd, old_id, new_id); + if (r) { + DMWARN("Failed to change transaction id from %s to %s.", + argv[1], argv[2]); + return r; + } + + return 0; +} + +/* + * Messages supported: + * create_thin + * create_snap + * delete + * trim + * set_transaction_id + */ +static int pool_message(struct dm_target *ti, unsigned argc, char **argv) +{ + int r = -EINVAL; + struct pool_c *pt = ti->private; + struct pool *pool = pt->pool; + + if (!strcasecmp(argv[0], "create_thin")) + r = process_create_thin_mesg(argc, argv, pool); + + else if (!strcasecmp(argv[0], "create_snap")) + r = process_create_snap_mesg(argc, argv, pool); + + else if (!strcasecmp(argv[0], "delete")) + r = process_delete_mesg(argc, argv, pool); + + else if (!strcasecmp(argv[0], "trim")) + r = process_trim_mesg(argc, argv, pool); + + else if (!strcasecmp(argv[0], "set_transaction_id")) + r = process_set_transaction_id_mesg(argc, argv, pool); + + else + DMWARN("Unrecognised thin target message received."); if (!r) { r = dm_thin_metadata_commit(pool->tmd); if (r) - DMERR("%s: dm_thin_metadata_commit() failed, error = %d", - __func__, r); + DMERR("%s message: dm_thin_metadata_commit() failed, error = %d", + argv[0], r); } return r; @@ -1984,7 +2039,7 @@ static int thin_ctr(struct dm_target *ti return -ENOMEM; } - r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &pool_dev); + r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev); if (r) { ti->error = "Error opening pool device"; goto bad_pool_dev;