Unfinished - won't compile pool objects indexed by metadata devices: best way to detect multiple references and deal with them accordingly (i.e. error or handover/resize) - I'm still favouring this - all duplicate detection should be by reference to the underlying metadata device, not the pool device thin target references pool device (not pool metadata device) - it should, because (as currently implemented) it sends I/O directly to it - if we export the existing dm_table_find_target() then the thin target ctr can find the pool object (and store it for later use so this chain only needs following once, in the ctr) [dm_get_device -> dm_get_md -> dm_get_live_table -> dm_table_find_target] This chain of lookups emphasises implicit assumptions that need validating each time anyway: - the pool device already has a live table (no problem with that) - that live table contains only one target, which is type 'pool' (either enforce this explicitly, or add an offset to the pool ref on the thin table line. offset method is most general; if instead we enforce the restriction we should do this in core dm by the target type being defined as having to be the only target in tables containing it) --- drivers/md/dm-thin.c | 49 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 39 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 @@ -436,7 +436,7 @@ struct pool { struct dm_target *ti; /* only set if a pool target is bound */ struct block_device *pool_dev; - struct block_device *metadata_dev; + struct dm_dev *metadata_dev; struct dm_thin_metadata *mmd; uint32_t sectors_per_block; @@ -1271,7 +1271,7 @@ static void pool_destroy(struct pool *po { if (dm_thin_metadata_close(pool->mmd) < 0) DMWARN("%s: dm_thin_metadata_close() failed.", __func__); - blkdev_put(pool->metadata_dev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + dm_put_device(pool->metadata_dev); prison_destroy(pool->prison); dm_kcopyd_client_destroy(pool->copier); @@ -1287,46 +1287,17 @@ static void pool_destroy(struct pool *po kfree(pool); } -/* - * The lifetime of the pool object is potentially longer than that of the - * pool target. thin_get_device() is very similar to - * dm_get_device() except it doesn't associate the device with the target, - * which would prevent the target to be destroyed. - */ -static struct block_device *thin_get_device(const char *metadata_path, fmode_t mode) -{ - dev_t uninitialized_var(dev); - unsigned int major, minor; - struct block_device *bdev; - - if (sscanf(metadata_path, "%u:%u", &major, &minor) == 2) { - /* Extract the major/minor numbers */ - dev = MKDEV(major, minor); - if (MAJOR(dev) != major || MINOR(dev) != minor) - return ERR_PTR(-EOVERFLOW); - bdev = blkdev_get_by_dev(dev, mode, &thin_get_device); - } else - bdev = blkdev_get_by_path(metadata_path, mode, &thin_get_device); - - if (!bdev) - return ERR_PTR(-EINVAL); - - return bdev; -} - -static struct pool *pool_create(const char *metadata_path, +static struct pool *pool_create(struct dm_target *ti, const char *metadata_path, unsigned long block_size, char **error) { int r; void *err_p; struct pool *pool; struct dm_thin_metadata *mmd; - struct block_device *metadata_dev; - fmode_t metadata_dev_mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; + struct dm_dev *metadata_dev; - metadata_dev = thin_get_device(metadata_path, metadata_dev_mode); - if (IS_ERR(metadata_dev)) { - r = PTR_ERR(metadata_dev); + r = dm_get_device(ti, metadata_path, FMODE_READ | FMODE_WRITE, &metadata_dev); + if (r) { *error = "Error opening metadata block device"; return ERR_PTR(r); } @@ -1430,7 +1401,7 @@ bad_pool: if (dm_thin_metadata_close(mmd)) DMWARN("%s: dm_thin_metadata_close() failed.", __func__); bad_mmd_open: - blkdev_put(metadata_dev, metadata_dev_mode); + dm_put_device(ti, metadata_dev); return err_p; } @@ -1446,7 +1417,7 @@ static void pool_dec(struct pool *pool) pool_destroy(pool); } -static struct pool *pool_find(struct block_device *pool_bdev, +static struct pool *pool_find(struct dm_target *ti, struct block_device *pool_bdev, const char *metadata_path, unsigned long block_size, char **error) @@ -1458,7 +1429,7 @@ static struct pool *pool_find(struct blo // AGK FIXME metadata_path not validated here pool_inc(pool); else - pool = pool_create(metadata_path, block_size, error); + pool = pool_create(ti, metadata_path, block_size, error); return pool; } @@ -1577,7 +1548,7 @@ static int pool_ctr(struct dm_target *ti if (r) goto out; - pool = pool_find(get_target_bdev(ti), metadata_path, + pool = pool_find(ti, get_target_bdev(ti), metadata_path, block_size, &ti->error); if (IS_ERR(pool)) { r = PTR_ERR(pool);