[dm-devel] [RFC PATCH 1/1] dm: add dust target

Benjamin Marzinski bmarzins at redhat.com
Tue Jan 8 17:36:00 UTC 2019


On Tue, Jan 08, 2019 at 10:30:32AM -0500, Bryan Gurney wrote:
> On Mon, Jan 7, 2019 at 7:10 PM Benjamin Marzinski <bmarzins at redhat.com> wrote:
> >
> > On Mon, Jan 07, 2019 at 02:31:23PM -0500, Bryan Gurney wrote:
> > > +
> > > +static int dust_add_block(struct dust_device *dd, unsigned long long block)
> > > +{
> > > +     struct badblock *bblock;
> > > +     unsigned long flags;
> > > +
> > > +     spin_lock_irqsave(&dd->dust_lock, flags);
> > > +     bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
> > > +
> > > +     if (bblock != NULL) {
> > > +             if (!dd->quiet_mode)
> > > +                     DMERR("addbadblock: block %llu already in badblocklist",
> > > +                           block);
> > > +             spin_unlock_irqrestore(&dd->dust_lock, flags);
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     bblock = kmalloc(sizeof(*bblock), GFP_KERNEL);
> >
> > You can't do a GFP_KERNEL allocation while holding a spinlock.  I think
> > it would be better to assume that the user was correctly adding a new
> > block, do the allocation, and then just call dust_rb_insert() under the
> > spinlock. dust_rb_insert() will return false if the block is already
> > inserted
> 
> Ah, okay.  I'll be spinning a v2 of this patch.  (I need to make some
> updates to the dm-dust.txt documentation file as well, so those
> updates will be in there.)
> 
> After reading through your description of the timeline, I created this
> revision of dust_add_block() (which compiles, and seems to work
> properly in my test module):
> 
> static int dust_add_block(struct dust_device *dd, unsigned long long block)
> {
>     struct badblock *bblock;
>     unsigned long flags;
> 
>     bblock = kmalloc(sizeof(*bblock), GFP_KERNEL);
>     if (bblock == NULL) {
>         if (!dd->quiet_mode)
>             DMERR("addbadblock: badblock allocation failed");
>         return -ENOMEM;
>     }
> 
>     spin_lock_irqsave(&dd->dust_lock, flags);
>     bblock->bb = block * dd->sect_per_block;
>     if (!dust_rb_insert(&dd->badblocklist, bblock)) {
>         if (!dd->quiet_mode)
>             DMERR("addbadblock: block %llu already in badblocklist",
>                   block);
>         spin_unlock_irqrestore(&dd->dust_lock, flags);
>         kfree(bblock);
>         return -EINVAL;
>     }
> 
>     dd->badblock_count++;
>     if (!dd->quiet_mode)
>         DMINFO("addbadblock: badblock added at block %llu", block);
>     spin_unlock_irqrestore(&dd->dust_lock, flags);
>     return 0;
> }
> 
> Test results:
> 
> # dmsetup message dust1 0 addbadblock 60
> kernel: device-mapper: dust: addbadblock: badblock added at block 60
> # dmsetup message dust1 0 addbadblock 60
> kernel: device-mapper: dust: addbadblock: block 60 already in badblocklist
> # dmsetup message dust1 0 addbadblock 60
> kernel: device-mapper: dust: addbadblock: block 60 already in badblocklist
> 
> The kmalloc() is before the spinlock, and if the block is already in
> the rbtree, it unlocks, and frees the unused "bblock".  Does this look
> good?
> 

Yep. That looks fine (other than your ">" and "&" characters getting
lost in translation)

-Ben




More information about the dm-devel mailing list