Skip to content

Commit 9c72bad

Browse files
Christoph Hellwigsnitm
authored andcommitted
dm: call PR reserve/unreserve on each underlying device
So far we tried to rely on the SCSI 'all target ports' bit to register all path, but for many setups this didn't work properly as the different paths are seen as separate initiators to the target instead of multiple ports of the same initiator. Because of that we'll stop setting the 'all target ports' bit in SCSI, and let device mapper handle iterating over the device for each path and register them manually. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Mike Christie <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 01f90dd commit 9c72bad

File tree

1 file changed

+65
-15
lines changed

1 file changed

+65
-15
lines changed

drivers/md/dm.c

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,26 +2521,76 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
25212521
kfree(pools);
25222522
}
25232523

2524-
static int dm_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
2525-
u32 flags)
2524+
struct dm_pr {
2525+
u64 old_key;
2526+
u64 new_key;
2527+
u32 flags;
2528+
bool fail_early;
2529+
};
2530+
2531+
static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn,
2532+
void *data)
25262533
{
25272534
struct mapped_device *md = bdev->bd_disk->private_data;
2528-
const struct pr_ops *ops;
2529-
fmode_t mode;
2530-
int r;
2535+
struct dm_table *table;
2536+
struct dm_target *ti;
2537+
int ret = -ENOTTY, srcu_idx;
25312538

2532-
r = dm_grab_bdev_for_ioctl(md, &bdev, &mode);
2533-
if (r < 0)
2534-
return r;
2539+
table = dm_get_live_table(md, &srcu_idx);
2540+
if (!table || !dm_table_get_size(table))
2541+
goto out;
25352542

2536-
ops = bdev->bd_disk->fops->pr_ops;
2537-
if (ops && ops->pr_register)
2538-
r = ops->pr_register(bdev, old_key, new_key, flags);
2539-
else
2540-
r = -EOPNOTSUPP;
2543+
/* We only support devices that have a single target */
2544+
if (dm_table_get_num_targets(table) != 1)
2545+
goto out;
2546+
ti = dm_table_get_target(table, 0);
25412547

2542-
bdput(bdev);
2543-
return r;
2548+
ret = -EINVAL;
2549+
if (!ti->type->iterate_devices)
2550+
goto out;
2551+
2552+
ret = ti->type->iterate_devices(ti, fn, data);
2553+
out:
2554+
dm_put_live_table(md, srcu_idx);
2555+
return ret;
2556+
}
2557+
2558+
/*
2559+
* For register / unregister we need to manually call out to every path.
2560+
*/
2561+
static int __dm_pr_register(struct dm_target *ti, struct dm_dev *dev,
2562+
sector_t start, sector_t len, void *data)
2563+
{
2564+
struct dm_pr *pr = data;
2565+
const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops;
2566+
2567+
if (!ops || !ops->pr_register)
2568+
return -EOPNOTSUPP;
2569+
return ops->pr_register(dev->bdev, pr->old_key, pr->new_key, pr->flags);
2570+
}
2571+
2572+
static int dm_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
2573+
u32 flags)
2574+
{
2575+
struct dm_pr pr = {
2576+
.old_key = old_key,
2577+
.new_key = new_key,
2578+
.flags = flags,
2579+
.fail_early = true,
2580+
};
2581+
int ret;
2582+
2583+
ret = dm_call_pr(bdev, __dm_pr_register, &pr);
2584+
if (ret && new_key) {
2585+
/* unregister all paths if we failed to register any path */
2586+
pr.old_key = new_key;
2587+
pr.new_key = 0;
2588+
pr.flags = 0;
2589+
pr.fail_early = false;
2590+
dm_call_pr(bdev, __dm_pr_register, &pr);
2591+
}
2592+
2593+
return ret;
25442594
}
25452595

25462596
static int dm_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,

0 commit comments

Comments
 (0)