Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
The 02/15/2021 19:08, Mike Snitzer wrote: > On Mon, Feb 15 2021 at 5:34am -0500, > Sergei Shtepa wrote: > > > The 02/12/2021 19:06, Mike Snitzer wrote: > > > On Fri, Feb 12 2021 at 6:34am -0500, > > > Sergei Shtepa wrote: > > > > > > > The 02/11/2021 20:51, Mike Snitzer wrote: > > > > > On Tue, Feb 09 2021 at 9:30am -0500, > > > > > Sergei Shtepa wrote: > > > > > > > > > > > The 'noexcl' option allow to open underlying block-device > > > > > > without FMODE_EXCL. > > > > > > > > > > > > Signed-off-by: Sergei Shtepa > > > > > > --- > > > > > > drivers/md/dm-linear.c| 14 +- > > > > > > drivers/md/dm-table.c | 14 -- > > > > > > drivers/md/dm.c | 26 +++--- > > > > > > drivers/md/dm.h | 2 +- > > > > > > include/linux/device-mapper.h | 7 +++ > > > > > > 5 files changed, 48 insertions(+), 15 deletions(-) > > > > > > > > > > > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > > > > > > index 00774b5d7668..b16d89802b9d 100644 > > > > > > --- a/drivers/md/dm-linear.c > > > > > > +++ b/drivers/md/dm-linear.c > > > > > > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, > > > > > > unsigned int argc, char **argv) > > > > > > char dummy; > > > > > > int ret; > > > > > > > > > > > > - if (argc != 2) { > > > > > > + if ((argc < 2) || (argc > 3)) { > > > > > > ti->error = "Invalid argument count"; > > > > > > return -EINVAL; > > > > > > } > > > > > > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, > > > > > > unsigned int argc, char **argv) > > > > > > } > > > > > > lc->start = tmp; > > > > > > > > > > > > + ti->non_exclusive = false; > > > > > > + if (argc > 2) { > > > > > > + if (strcmp("noexcl", argv[2]) == 0) > > > > > > + ti->non_exclusive = true; > > > > > > + else if (strcmp("excl", argv[2]) == 0) > > > > > > + ti->non_exclusive = false; > > > > > > + else { > > > > > > + ti->error = "Invalid exclusive option"; > > > > > > + return -EINVAL; > > > > > > + } > > > > > > + } > > > > > > + > > > > > > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > > > > > > >dev); > > > > > > if (ret) { > > > > > > ti->error = "Device lookup failed"; > > > > > > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > > > > > > index 4acf2342f7ad..f020459465bd 100644 > > > > > > --- a/drivers/md/dm-table.c > > > > > > +++ b/drivers/md/dm-table.c > > > > > > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct > > > > > > dm_target *ti, struct dm_dev *dev, > > > > > > * device and not to touch the existing bdev field in case > > > > > > * it is accessed concurrently. > > > > > > */ > > > > > > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t > > > > > > new_mode, > > > > > > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t > > > > > > new_mode, bool non_exclusive, > > > > > > struct mapped_device *md) > > > > > > { > > > > > > int r; > > > > > > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal > > > > > > *dd, fmode_t new_mode, > > > > > > > > > > > > old_dev = dd->dm_dev; > > > > > > > > > > > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > > > - dd->dm_dev->mode | new_mode, _dev); > > > > > > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > > > dd->dm_dev->mode | new_mode, > > > > > > + non_exclusive, _dev); > > > > > > if (r) > > > > > > return r; > > > > > > > > > > > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const > > > > > > char *path, fmode_t mode, > > > > > > if (!dd) > > > > > > return -ENOMEM; > > > > > > > > > > > > - if ((r = dm_get_table_device(t->md, dev, mode, > > > > > > >dm_dev))) { > > > > > > + r = dm_get_table_device(t->md, dev, mode, > > > > > > ti->non_exclusive, >dm_dev); > > > > > > + if (r) { > > > > > > kfree(dd); > > > > > > return r; > > > > > > } > > > > > > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const > > > > > > char *path, fmode_t mode, > > > > > > list_add(>list, >devices); > > > > > > goto out; > > > > > > > > > > > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > > > > > > - r = upgrade_mode(dd, mode, t->md); > > > > > > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > > > > > > + (dd->dm_dev->non_exclusive != ti->non_exclusive)) { > > > > > > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > > > > > > if (r) > > > > > > return r; > > > > > > }
Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
On Mon, Feb 15 2021 at 5:34am -0500, Sergei Shtepa wrote: > The 02/12/2021 19:06, Mike Snitzer wrote: > > On Fri, Feb 12 2021 at 6:34am -0500, > > Sergei Shtepa wrote: > > > > > The 02/11/2021 20:51, Mike Snitzer wrote: > > > > On Tue, Feb 09 2021 at 9:30am -0500, > > > > Sergei Shtepa wrote: > > > > > > > > > The 'noexcl' option allow to open underlying block-device > > > > > without FMODE_EXCL. > > > > > > > > > > Signed-off-by: Sergei Shtepa > > > > > --- > > > > > drivers/md/dm-linear.c| 14 +- > > > > > drivers/md/dm-table.c | 14 -- > > > > > drivers/md/dm.c | 26 +++--- > > > > > drivers/md/dm.h | 2 +- > > > > > include/linux/device-mapper.h | 7 +++ > > > > > 5 files changed, 48 insertions(+), 15 deletions(-) > > > > > > > > > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > > > > > index 00774b5d7668..b16d89802b9d 100644 > > > > > --- a/drivers/md/dm-linear.c > > > > > +++ b/drivers/md/dm-linear.c > > > > > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, > > > > > unsigned int argc, char **argv) > > > > > char dummy; > > > > > int ret; > > > > > > > > > > - if (argc != 2) { > > > > > + if ((argc < 2) || (argc > 3)) { > > > > > ti->error = "Invalid argument count"; > > > > > return -EINVAL; > > > > > } > > > > > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, > > > > > unsigned int argc, char **argv) > > > > > } > > > > > lc->start = tmp; > > > > > > > > > > + ti->non_exclusive = false; > > > > > + if (argc > 2) { > > > > > + if (strcmp("noexcl", argv[2]) == 0) > > > > > + ti->non_exclusive = true; > > > > > + else if (strcmp("excl", argv[2]) == 0) > > > > > + ti->non_exclusive = false; > > > > > + else { > > > > > + ti->error = "Invalid exclusive option"; > > > > > + return -EINVAL; > > > > > + } > > > > > + } > > > > > + > > > > > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > > > > > >dev); > > > > > if (ret) { > > > > > ti->error = "Device lookup failed"; > > > > > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > > > > > index 4acf2342f7ad..f020459465bd 100644 > > > > > --- a/drivers/md/dm-table.c > > > > > +++ b/drivers/md/dm-table.c > > > > > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct > > > > > dm_target *ti, struct dm_dev *dev, > > > > > * device and not to touch the existing bdev field in case > > > > > * it is accessed concurrently. > > > > > */ > > > > > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > > > > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t > > > > > new_mode, bool non_exclusive, > > > > > struct mapped_device *md) > > > > > { > > > > > int r; > > > > > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal > > > > > *dd, fmode_t new_mode, > > > > > > > > > > old_dev = dd->dm_dev; > > > > > > > > > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > > - dd->dm_dev->mode | new_mode, _dev); > > > > > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > > dd->dm_dev->mode | new_mode, > > > > > + non_exclusive, _dev); > > > > > if (r) > > > > > return r; > > > > > > > > > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const > > > > > char *path, fmode_t mode, > > > > > if (!dd) > > > > > return -ENOMEM; > > > > > > > > > > - if ((r = dm_get_table_device(t->md, dev, mode, > > > > > >dm_dev))) { > > > > > + r = dm_get_table_device(t->md, dev, mode, > > > > > ti->non_exclusive, >dm_dev); > > > > > + if (r) { > > > > > kfree(dd); > > > > > return r; > > > > > } > > > > > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const > > > > > char *path, fmode_t mode, > > > > > list_add(>list, >devices); > > > > > goto out; > > > > > > > > > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > > > > > - r = upgrade_mode(dd, mode, t->md); > > > > > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > > > > > +(dd->dm_dev->non_exclusive != ti->non_exclusive)) { > > > > > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > > > > > if (r) > > > > > return r; > > > > > } > > > > > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > > > > > index 00c41aa6d092..c25dcc2fdb89 100644 > > > > > --- a/drivers/md/dm.c > > > > > +++ b/drivers/md/dm.c > > > >
Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
The 02/12/2021 19:06, Mike Snitzer wrote: > On Fri, Feb 12 2021 at 6:34am -0500, > Sergei Shtepa wrote: > > > The 02/11/2021 20:51, Mike Snitzer wrote: > > > On Tue, Feb 09 2021 at 9:30am -0500, > > > Sergei Shtepa wrote: > > > > > > > The 'noexcl' option allow to open underlying block-device > > > > without FMODE_EXCL. > > > > > > > > Signed-off-by: Sergei Shtepa > > > > --- > > > > drivers/md/dm-linear.c| 14 +- > > > > drivers/md/dm-table.c | 14 -- > > > > drivers/md/dm.c | 26 +++--- > > > > drivers/md/dm.h | 2 +- > > > > include/linux/device-mapper.h | 7 +++ > > > > 5 files changed, 48 insertions(+), 15 deletions(-) > > > > > > > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > > > > index 00774b5d7668..b16d89802b9d 100644 > > > > --- a/drivers/md/dm-linear.c > > > > +++ b/drivers/md/dm-linear.c > > > > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, unsigned > > > > int argc, char **argv) > > > > char dummy; > > > > int ret; > > > > > > > > - if (argc != 2) { > > > > + if ((argc < 2) || (argc > 3)) { > > > > ti->error = "Invalid argument count"; > > > > return -EINVAL; > > > > } > > > > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, unsigned > > > > int argc, char **argv) > > > > } > > > > lc->start = tmp; > > > > > > > > + ti->non_exclusive = false; > > > > + if (argc > 2) { > > > > + if (strcmp("noexcl", argv[2]) == 0) > > > > + ti->non_exclusive = true; > > > > + else if (strcmp("excl", argv[2]) == 0) > > > > + ti->non_exclusive = false; > > > > + else { > > > > + ti->error = "Invalid exclusive option"; > > > > + return -EINVAL; > > > > + } > > > > + } > > > > + > > > > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > > > > >dev); > > > > if (ret) { > > > > ti->error = "Device lookup failed"; > > > > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > > > > index 4acf2342f7ad..f020459465bd 100644 > > > > --- a/drivers/md/dm-table.c > > > > +++ b/drivers/md/dm-table.c > > > > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct dm_target > > > > *ti, struct dm_dev *dev, > > > > * device and not to touch the existing bdev field in case > > > > * it is accessed concurrently. > > > > */ > > > > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > > > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > > > bool non_exclusive, > > > > struct mapped_device *md) > > > > { > > > > int r; > > > > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal *dd, > > > > fmode_t new_mode, > > > > > > > > old_dev = dd->dm_dev; > > > > > > > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > - dd->dm_dev->mode | new_mode, _dev); > > > > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > > dd->dm_dev->mode | new_mode, > > > > + non_exclusive, _dev); > > > > if (r) > > > > return r; > > > > > > > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const char > > > > *path, fmode_t mode, > > > > if (!dd) > > > > return -ENOMEM; > > > > > > > > - if ((r = dm_get_table_device(t->md, dev, mode, > > > > >dm_dev))) { > > > > + r = dm_get_table_device(t->md, dev, mode, > > > > ti->non_exclusive, >dm_dev); > > > > + if (r) { > > > > kfree(dd); > > > > return r; > > > > } > > > > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const char > > > > *path, fmode_t mode, > > > > list_add(>list, >devices); > > > > goto out; > > > > > > > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > > > > - r = upgrade_mode(dd, mode, t->md); > > > > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > > > > + (dd->dm_dev->non_exclusive != ti->non_exclusive)) { > > > > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > > > > if (r) > > > > return r; > > > > } > > > > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > > > > index 00c41aa6d092..c25dcc2fdb89 100644 > > > > --- a/drivers/md/dm.c > > > > +++ b/drivers/md/dm.c > > > > @@ -1117,33 +1117,44 @@ static void close_table_device(struct > > > > table_device *td, struct mapped_device *md > > > > if (!td->dm_dev.bdev) > > > > return; > >
Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
On Fri, Feb 12 2021 at 6:34am -0500, Sergei Shtepa wrote: > The 02/11/2021 20:51, Mike Snitzer wrote: > > On Tue, Feb 09 2021 at 9:30am -0500, > > Sergei Shtepa wrote: > > > > > The 'noexcl' option allow to open underlying block-device > > > without FMODE_EXCL. > > > > > > Signed-off-by: Sergei Shtepa > > > --- > > > drivers/md/dm-linear.c| 14 +- > > > drivers/md/dm-table.c | 14 -- > > > drivers/md/dm.c | 26 +++--- > > > drivers/md/dm.h | 2 +- > > > include/linux/device-mapper.h | 7 +++ > > > 5 files changed, 48 insertions(+), 15 deletions(-) > > > > > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > > > index 00774b5d7668..b16d89802b9d 100644 > > > --- a/drivers/md/dm-linear.c > > > +++ b/drivers/md/dm-linear.c > > > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, unsigned > > > int argc, char **argv) > > > char dummy; > > > int ret; > > > > > > - if (argc != 2) { > > > + if ((argc < 2) || (argc > 3)) { > > > ti->error = "Invalid argument count"; > > > return -EINVAL; > > > } > > > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, unsigned > > > int argc, char **argv) > > > } > > > lc->start = tmp; > > > > > > + ti->non_exclusive = false; > > > + if (argc > 2) { > > > + if (strcmp("noexcl", argv[2]) == 0) > > > + ti->non_exclusive = true; > > > + else if (strcmp("excl", argv[2]) == 0) > > > + ti->non_exclusive = false; > > > + else { > > > + ti->error = "Invalid exclusive option"; > > > + return -EINVAL; > > > + } > > > + } > > > + > > > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > > > >dev); > > > if (ret) { > > > ti->error = "Device lookup failed"; > > > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > > > index 4acf2342f7ad..f020459465bd 100644 > > > --- a/drivers/md/dm-table.c > > > +++ b/drivers/md/dm-table.c > > > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct dm_target > > > *ti, struct dm_dev *dev, > > > * device and not to touch the existing bdev field in case > > > * it is accessed concurrently. > > > */ > > > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > > bool non_exclusive, > > > struct mapped_device *md) > > > { > > > int r; > > > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal *dd, > > > fmode_t new_mode, > > > > > > old_dev = dd->dm_dev; > > > > > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > > - dd->dm_dev->mode | new_mode, _dev); > > > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, dd->dm_dev->mode > > > | new_mode, > > > + non_exclusive, _dev); > > > if (r) > > > return r; > > > > > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const char > > > *path, fmode_t mode, > > > if (!dd) > > > return -ENOMEM; > > > > > > - if ((r = dm_get_table_device(t->md, dev, mode, >dm_dev))) { > > > + r = dm_get_table_device(t->md, dev, mode, ti->non_exclusive, > > > >dm_dev); > > > + if (r) { > > > kfree(dd); > > > return r; > > > } > > > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const char > > > *path, fmode_t mode, > > > list_add(>list, >devices); > > > goto out; > > > > > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > > > - r = upgrade_mode(dd, mode, t->md); > > > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > > > +(dd->dm_dev->non_exclusive != ti->non_exclusive)) { > > > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > > > if (r) > > > return r; > > > } > > > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > > > index 00c41aa6d092..c25dcc2fdb89 100644 > > > --- a/drivers/md/dm.c > > > +++ b/drivers/md/dm.c > > > @@ -1117,33 +1117,44 @@ static void close_table_device(struct > > > table_device *td, struct mapped_device *md > > > if (!td->dm_dev.bdev) > > > return; > > > > > > - bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > > > - blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > > > + if (td->dm_dev.non_exclusive) > > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > > > + else { > > > + bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > > > + } > > > + > > > + > > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > > > + > > > put_dax(td->dm_dev.dax_dev); > > > td->dm_dev.bdev = NULL; > > > td->dm_dev.dax_dev = NULL; > > > +
Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
The 02/11/2021 20:51, Mike Snitzer wrote: > On Tue, Feb 09 2021 at 9:30am -0500, > Sergei Shtepa wrote: > > > The 'noexcl' option allow to open underlying block-device > > without FMODE_EXCL. > > > > Signed-off-by: Sergei Shtepa > > --- > > drivers/md/dm-linear.c| 14 +- > > drivers/md/dm-table.c | 14 -- > > drivers/md/dm.c | 26 +++--- > > drivers/md/dm.h | 2 +- > > include/linux/device-mapper.h | 7 +++ > > 5 files changed, 48 insertions(+), 15 deletions(-) > > > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > > index 00774b5d7668..b16d89802b9d 100644 > > --- a/drivers/md/dm-linear.c > > +++ b/drivers/md/dm-linear.c > > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int > > argc, char **argv) > > char dummy; > > int ret; > > > > - if (argc != 2) { > > + if ((argc < 2) || (argc > 3)) { > > ti->error = "Invalid argument count"; > > return -EINVAL; > > } > > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, unsigned int > > argc, char **argv) > > } > > lc->start = tmp; > > > > + ti->non_exclusive = false; > > + if (argc > 2) { > > + if (strcmp("noexcl", argv[2]) == 0) > > + ti->non_exclusive = true; > > + else if (strcmp("excl", argv[2]) == 0) > > + ti->non_exclusive = false; > > + else { > > + ti->error = "Invalid exclusive option"; > > + return -EINVAL; > > + } > > + } > > + > > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > > >dev); > > if (ret) { > > ti->error = "Device lookup failed"; > > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > > index 4acf2342f7ad..f020459465bd 100644 > > --- a/drivers/md/dm-table.c > > +++ b/drivers/md/dm-table.c > > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct dm_target *ti, > > struct dm_dev *dev, > > * device and not to touch the existing bdev field in case > > * it is accessed concurrently. > > */ > > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, bool > > non_exclusive, > > struct mapped_device *md) > > { > > int r; > > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal *dd, > > fmode_t new_mode, > > > > old_dev = dd->dm_dev; > > > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > > - dd->dm_dev->mode | new_mode, _dev); > > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, dd->dm_dev->mode > > | new_mode, > > + non_exclusive, _dev); > > if (r) > > return r; > > > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const char > > *path, fmode_t mode, > > if (!dd) > > return -ENOMEM; > > > > - if ((r = dm_get_table_device(t->md, dev, mode, >dm_dev))) { > > + r = dm_get_table_device(t->md, dev, mode, ti->non_exclusive, > > >dm_dev); > > + if (r) { > > kfree(dd); > > return r; > > } > > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const char > > *path, fmode_t mode, > > list_add(>list, >devices); > > goto out; > > > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > > - r = upgrade_mode(dd, mode, t->md); > > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > > + (dd->dm_dev->non_exclusive != ti->non_exclusive)) { > > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > > if (r) > > return r; > > } > > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > > index 00c41aa6d092..c25dcc2fdb89 100644 > > --- a/drivers/md/dm.c > > +++ b/drivers/md/dm.c > > @@ -1117,33 +1117,44 @@ static void close_table_device(struct table_device > > *td, struct mapped_device *md > > if (!td->dm_dev.bdev) > > return; > > > > - bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > > - blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > > + if (td->dm_dev.non_exclusive) > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > > + else { > > + bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > > + } > > + > > + > > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > > + > > put_dax(td->dm_dev.dax_dev); > > td->dm_dev.bdev = NULL; > > td->dm_dev.dax_dev = NULL; > > + td->dm_dev.non_exclusive = false; > > } > > > > static struct table_device *find_table_device(struct list_head *l, dev_t > > dev, > > - fmode_t
Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
On Tue, Feb 09 2021 at 9:30am -0500, Sergei Shtepa wrote: > The 'noexcl' option allow to open underlying block-device > without FMODE_EXCL. > > Signed-off-by: Sergei Shtepa > --- > drivers/md/dm-linear.c| 14 +- > drivers/md/dm-table.c | 14 -- > drivers/md/dm.c | 26 +++--- > drivers/md/dm.h | 2 +- > include/linux/device-mapper.h | 7 +++ > 5 files changed, 48 insertions(+), 15 deletions(-) > > diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c > index 00774b5d7668..b16d89802b9d 100644 > --- a/drivers/md/dm-linear.c > +++ b/drivers/md/dm-linear.c > @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int > argc, char **argv) > char dummy; > int ret; > > - if (argc != 2) { > + if ((argc < 2) || (argc > 3)) { > ti->error = "Invalid argument count"; > return -EINVAL; > } > @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, unsigned int > argc, char **argv) > } > lc->start = tmp; > > + ti->non_exclusive = false; > + if (argc > 2) { > + if (strcmp("noexcl", argv[2]) == 0) > + ti->non_exclusive = true; > + else if (strcmp("excl", argv[2]) == 0) > + ti->non_exclusive = false; > + else { > + ti->error = "Invalid exclusive option"; > + return -EINVAL; > + } > + } > + > ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), > >dev); > if (ret) { > ti->error = "Device lookup failed"; > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > index 4acf2342f7ad..f020459465bd 100644 > --- a/drivers/md/dm-table.c > +++ b/drivers/md/dm-table.c > @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct dm_target *ti, > struct dm_dev *dev, > * device and not to touch the existing bdev field in case > * it is accessed concurrently. > */ > -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, > +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, bool > non_exclusive, > struct mapped_device *md) > { > int r; > @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal *dd, > fmode_t new_mode, > > old_dev = dd->dm_dev; > > - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, > - dd->dm_dev->mode | new_mode, _dev); > + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, dd->dm_dev->mode > | new_mode, > + non_exclusive, _dev); > if (r) > return r; > > @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const char *path, > fmode_t mode, > if (!dd) > return -ENOMEM; > > - if ((r = dm_get_table_device(t->md, dev, mode, >dm_dev))) { > + r = dm_get_table_device(t->md, dev, mode, ti->non_exclusive, > >dm_dev); > + if (r) { > kfree(dd); > return r; > } > @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const char *path, > fmode_t mode, > list_add(>list, >devices); > goto out; > > - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { > - r = upgrade_mode(dd, mode, t->md); > + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && > +(dd->dm_dev->non_exclusive != ti->non_exclusive)) { > + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); > if (r) > return r; > } > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > index 00c41aa6d092..c25dcc2fdb89 100644 > --- a/drivers/md/dm.c > +++ b/drivers/md/dm.c > @@ -1117,33 +1117,44 @@ static void close_table_device(struct table_device > *td, struct mapped_device *md > if (!td->dm_dev.bdev) > return; > > - bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > - blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > + if (td->dm_dev.non_exclusive) > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > + else { > + bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); > + } > + > + > + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); > + > put_dax(td->dm_dev.dax_dev); > td->dm_dev.bdev = NULL; > td->dm_dev.dax_dev = NULL; > + td->dm_dev.non_exclusive = false; > } > > static struct table_device *find_table_device(struct list_head *l, dev_t dev, > - fmode_t mode) > + fmode_t mode, bool non_exclusive) > { > struct table_device *td; > > list_for_each_entry(td, l, list) > -
[PATCH v5 5/6] dm: add 'noexcl' option for dm-linear
The 'noexcl' option allow to open underlying block-device without FMODE_EXCL. Signed-off-by: Sergei Shtepa --- drivers/md/dm-linear.c| 14 +- drivers/md/dm-table.c | 14 -- drivers/md/dm.c | 26 +++--- drivers/md/dm.h | 2 +- include/linux/device-mapper.h | 7 +++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 00774b5d7668..b16d89802b9d 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -33,7 +33,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) char dummy; int ret; - if (argc != 2) { + if ((argc < 2) || (argc > 3)) { ti->error = "Invalid argument count"; return -EINVAL; } @@ -51,6 +51,18 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) } lc->start = tmp; + ti->non_exclusive = false; + if (argc > 2) { + if (strcmp("noexcl", argv[2]) == 0) + ti->non_exclusive = true; + else if (strcmp("excl", argv[2]) == 0) + ti->non_exclusive = false; + else { + ti->error = "Invalid exclusive option"; + return -EINVAL; + } + } + ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), >dev); if (ret) { ti->error = "Device lookup failed"; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4acf2342f7ad..f020459465bd 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -322,7 +322,7 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, * device and not to touch the existing bdev field in case * it is accessed concurrently. */ -static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, +static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, bool non_exclusive, struct mapped_device *md) { int r; @@ -330,8 +330,8 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, old_dev = dd->dm_dev; - r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, - dd->dm_dev->mode | new_mode, _dev); + r = dm_get_table_device(md, dd->dm_dev->bdev->bd_dev, dd->dm_dev->mode | new_mode, + non_exclusive, _dev); if (r) return r; @@ -387,7 +387,8 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, if (!dd) return -ENOMEM; - if ((r = dm_get_table_device(t->md, dev, mode, >dm_dev))) { + r = dm_get_table_device(t->md, dev, mode, ti->non_exclusive, >dm_dev); + if (r) { kfree(dd); return r; } @@ -396,8 +397,9 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, list_add(>list, >devices); goto out; - } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) { - r = upgrade_mode(dd, mode, t->md); + } else if ((dd->dm_dev->mode != (mode | dd->dm_dev->mode)) && + (dd->dm_dev->non_exclusive != ti->non_exclusive)) { + r = upgrade_mode(dd, mode, ti->non_exclusive, t->md); if (r) return r; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 00c41aa6d092..c25dcc2fdb89 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1117,33 +1117,44 @@ static void close_table_device(struct table_device *td, struct mapped_device *md if (!td->dm_dev.bdev) return; - bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); - blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); + if (td->dm_dev.non_exclusive) + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); + else { + bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md)); + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL); + } + + + blkdev_put(td->dm_dev.bdev, td->dm_dev.mode); + put_dax(td->dm_dev.dax_dev); td->dm_dev.bdev = NULL; td->dm_dev.dax_dev = NULL; + td->dm_dev.non_exclusive = false; } static struct table_device *find_table_device(struct list_head *l, dev_t dev, - fmode_t mode) + fmode_t mode, bool non_exclusive) { struct table_device *td; list_for_each_entry(td, l, list) - if (td->dm_dev.bdev->bd_dev == dev && td->dm_dev.mode == mode) + if (td->dm_dev.bdev->bd_dev == dev && + td->dm_dev.mode == mode && +