Re: [PATCH v5 5/6] dm: add 'noexcl' option for dm-linear

2021-02-24 Thread Sergei Shtepa
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

2021-02-15 Thread Mike Snitzer
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

2021-02-15 Thread Sergei Shtepa
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

2021-02-12 Thread Mike Snitzer
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

2021-02-12 Thread Sergei Shtepa
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

2021-02-11 Thread Mike Snitzer
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

2021-02-09 Thread Sergei Shtepa
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 &&
+