When an app does a pr_reserve it will go to whatever path we happen to
be using at the time. This can result in errors where the app does a
second pr_reserve call and expects success but gets a failure becuase
the reserve is not done on the holder's path. This patch has us always
start trying to do reserves from the first path in the first group.

Signed-off-by: Mike Christie <[email protected]>
---
 drivers/md/dm.c | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 67b46ae896b1..cdd1656b99d6 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -3048,6 +3048,7 @@ struct dm_pr {
        u32     flags;
        bool    fail_early;
        int     ret;
+       enum pr_type type;
 };
 
 static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn,
@@ -3139,25 +3140,42 @@ static int dm_pr_register(struct block_device *bdev, 
u64 old_key, u64 new_key,
        return ret;
 }
 
+
+static int __dm_pr_reserve(struct dm_target *ti, struct dm_dev *dev,
+                          sector_t start, sector_t len, void *data)
+{
+       struct dm_pr *pr = data;
+       const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops;
+
+       if (!ops || !ops->pr_reserve) {
+               pr->ret = -EOPNOTSUPP;
+               return -1;
+       }
+
+       pr->ret = ops->pr_reserve(dev->bdev, pr->old_key, pr->type, pr->flags);
+       if (!pr->ret)
+               return -1;
+
+       return 0;
+}
+
 static int dm_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
                         u32 flags)
 {
-       struct mapped_device *md = bdev->bd_disk->private_data;
-       const struct pr_ops *ops;
-       int r, srcu_idx;
+       struct dm_pr pr = {
+               .old_key        = key,
+               .flags          = flags,
+               .type           = type,
+               .fail_early     = false,
+               .ret            = 0,
+       };
+       int ret;
 
-       r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
-       if (r < 0)
-               goto out;
+       ret = dm_call_pr(bdev, __dm_pr_reserve, &pr);
+       if (ret)
+               return ret;
 
-       ops = bdev->bd_disk->fops->pr_ops;
-       if (ops && ops->pr_reserve)
-               r = ops->pr_reserve(bdev, key, type, flags);
-       else
-               r = -EOPNOTSUPP;
-out:
-       dm_unprepare_ioctl(md, srcu_idx);
-       return r;
+       return pr.ret;
 }
 
 static int dm_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
-- 
2.25.1

--
dm-devel mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/dm-devel

Reply via email to