diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index c2bbe1fb1326..1e519195d45b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1710,3 +1710,39 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty) | |||
1710 | return res; | 1710 | return res; |
1711 | } | 1711 | } |
1712 | EXPORT_SYMBOL(__invalidate_device); | 1712 | EXPORT_SYMBOL(__invalidate_device); |
1713 | |||
1714 | void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) | ||
1715 | { | ||
1716 | struct inode *inode, *old_inode = NULL; | ||
1717 | |||
1718 | spin_lock(&inode_sb_list_lock); | ||
1719 | list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) { | ||
1720 | struct address_space *mapping = inode->i_mapping; | ||
1721 | |||
1722 | spin_lock(&inode->i_lock); | ||
1723 | if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) || | ||
1724 | mapping->nrpages == 0) { | ||
1725 | spin_unlock(&inode->i_lock); | ||
1726 | continue; | ||
1727 | } | ||
1728 | __iget(inode); | ||
1729 | spin_unlock(&inode->i_lock); | ||
1730 | spin_unlock(&inode_sb_list_lock); | ||
1731 | /* | ||
1732 | * We hold a reference to 'inode' so it couldn't have been | ||
1733 | * removed from s_inodes list while we dropped the | ||
1734 | * inode_sb_list_lock. We cannot iput the inode now as we can | ||
1735 | * be holding the last reference and we cannot iput it under | ||
1736 | * inode_sb_list_lock. So we keep the reference and iput it | ||
1737 | * later. | ||
1738 | */ | ||
1739 | iput(old_inode); | ||
1740 | old_inode = inode; | ||
1741 | |||
1742 | func(I_BDEV(inode), arg); | ||
1743 | |||
1744 | spin_lock(&inode_sb_list_lock); | ||
1745 | } | ||
1746 | spin_unlock(&inode_sb_list_lock); | ||
1747 | iput(old_inode); | ||
1748 | } | ||