Message ID | 14b09a61-8e8f-166d-45b9-7dd07922286e@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hello, On Mon, Aug 29, 2016 at 11:33:41PM +0200, Vegard Nossum wrote: > On 08/29/2016 09:55 PM, Tejun Heo wrote: > > I think the right thing to do there is doing blkdev_get() / > > blkdev_put() around func() invocation in iterate_bdevs() rather than > > holding bd_mutex across the callback. Can you please verify whether > > that works? > > Didn't work for me, I kept getting use-after-free in __blkdev_get() on > bdev->bd_invalidated after it calls bdev->bd_disk->fops->open(). I tried > a few related things without much luck. I see. It could be that it's doing blkdev_get() on a dying device. > The only thing that worked for me without holding the mutex across the > call was this: ... > + mutex_lock(&bdev->bd_mutex); > + bdev->bd_openers++; > + bdev->bd_holders++; > + mutex_unlock(&bdev->bd_mutex); > + > + func(bdev, arg); > + > + mutex_lock(&bdev->bd_mutex); > + bdev->bd_openers--; > + bdev->bd_holders--; > + mutex_unlock(&bdev->bd_mutex); And this might not be too far fetched. I think what we want is * Bump bd_openers if there are other users already; otherwise, skip. * blkdev_put() after the callback is finished. Thanks.
diff --git a/fs/block_dev.c b/fs/block_dev.c index 08ae993..586d745 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1885,6 +1885,7 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) spin_lock(&blockdev_superblock->s_inode_list_lock); list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) { struct address_space *mapping = inode->i_mapping; + struct block_device *bdev; spin_lock(&inode->i_lock);