diff options
author | Jan Kara <jack@suse.cz> | 2012-07-03 16:45:31 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-22 23:58:45 +0400 |
commit | 5c0d6b60a0ba46d45020547eacf7199171920935 (patch) | |
tree | 7d9f99cc40981dc0872e1ac33317f48b9e1f2bfb /fs/block_dev.c | |
parent | b3de653105180b57af90ef2f5b8441f085f4ff56 (diff) | |
download | lwn-5c0d6b60a0ba46d45020547eacf7199171920935.tar.gz lwn-5c0d6b60a0ba46d45020547eacf7199171920935.zip |
vfs: Create function for iterating over block devices
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
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) return res; } 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; + + spin_lock(&inode->i_lock); + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) || + mapping->nrpages == 0) { + spin_unlock(&inode->i_lock); + continue; + } + __iget(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&inode_sb_list_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. + */ + iput(old_inode); + old_inode = inode; + + func(I_BDEV(inode), arg); + + spin_lock(&inode_sb_list_lock); + } + spin_unlock(&inode_sb_list_lock); + iput(old_inode); +} |