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 c2bbe1fb132..1e519195d45 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); +}  |