It is better to iterate over all_bdevs list in iterate_bdevs() because inode list of blockdev_super contains also inodes which are not describing any block device (e.g. root of bdev filesystem). Signed-off-by: Jan Kara <jack@xxxxxxx> --- fs/block_dev.c | 45 +++++++++++++++++++++++++-------------------- 1 files changed, 25 insertions(+), 20 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 38e721b..220391c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1716,36 +1716,41 @@ EXPORT_SYMBOL(__invalidate_device); void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) { - struct inode *inode, *old_inode = NULL; - - spin_lock(&inode_sb_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, *old_bdev = NULL; + struct inode *inode; + spin_lock(&bdev_lock); + list_for_each_entry(bdev, &all_bdevs, bd_list) { + inode = bdev->bd_inode; spin_lock(&inode->i_lock); + /* + * With i_lock we can safely check bdev isn't freeing and + * grab our reference. + */ if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) || - mapping->nrpages == 0) { + inode->i_mapping->nrpages == 0) { spin_unlock(&inode->i_lock); continue; } - __iget(inode); + bdgrab(bdev); spin_unlock(&inode->i_lock); - spin_unlock(&inode_sb_list_lock); + spin_unlock(&bdev_lock); /* - * We hold a reference to 'inode' so it couldn't have been - * removed from s_inodes list while we dropped the - * inode_sb_list_lock. We cannot iput the inode now as we can - * be holding the last reference and we cannot iput it under - * inode_sb_list_lock. So we keep the reference and iput it - * later. + * We hold a reference to 'bdev' so it couldn't have been + * removed from the list while we dropped the bdev_lock. We + * cannot put the reference now as we can be holding the last + * reference and we cannot put it under bdev_lock. So we keep + * the reference and put it later. */ - iput(old_inode); - old_inode = inode; + if (old_bdev) + bdput(old_bdev); + old_bdev = bdev; - func(I_BDEV(inode), arg); + func(bdev, arg); - spin_lock(&inode_sb_list_lock); + spin_lock(&bdev_lock); } - spin_unlock(&inode_sb_list_lock); - iput(old_inode); + spin_unlock(&bdev_lock); + if (old_bdev) + bdput(old_bdev); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html