diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 51 | 
1 files changed, 38 insertions, 13 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index b07f1da1de4..0e575d1304b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -17,6 +17,7 @@  #include <linux/module.h>  #include <linux/blkpg.h>  #include <linux/buffer_head.h> +#include <linux/swap.h>  #include <linux/pagevec.h>  #include <linux/writeback.h>  #include <linux/mpage.h> @@ -24,7 +25,7 @@  #include <linux/uio.h>  #include <linux/namei.h>  #include <linux/log2.h> -#include <linux/kmemleak.h> +#include <linux/cleancache.h>  #include <asm/uaccess.h>  #include "internal.h" @@ -82,13 +83,35 @@ static sector_t max_block(struct block_device *bdev)  }  /* Kill _all_ buffers and pagecache , dirty or not.. */ -static void kill_bdev(struct block_device *bdev) +void kill_bdev(struct block_device *bdev)  { -	if (bdev->bd_inode->i_mapping->nrpages == 0) +	struct address_space *mapping = bdev->bd_inode->i_mapping; + +	if (mapping->nrpages == 0)  		return; +  	invalidate_bh_lrus(); -	truncate_inode_pages(bdev->bd_inode->i_mapping, 0); +	truncate_inode_pages(mapping, 0);  }	 +EXPORT_SYMBOL(kill_bdev); + +/* Invalidate clean unused buffers and pagecache. */ +void invalidate_bdev(struct block_device *bdev) +{ +	struct address_space *mapping = bdev->bd_inode->i_mapping; + +	if (mapping->nrpages == 0) +		return; + +	invalidate_bh_lrus(); +	lru_add_drain_all();	/* make sure all lru add caches are flushed */ +	invalidate_mapping_pages(mapping, 0, -1); +	/* 99% of the time, we don't need to flush the cleancache on the bdev. +	 * But, for the strange corners, lets be cautious +	 */ +	cleancache_flush_inode(mapping); +} +EXPORT_SYMBOL(invalidate_bdev);  int set_blocksize(struct block_device *bdev, int size)  { @@ -425,7 +448,6 @@ static void bdev_i_callback(struct rcu_head *head)  	struct inode *inode = container_of(head, struct inode, i_rcu);  	struct bdev_inode *bdi = BDEV_I(inode); -	INIT_LIST_HEAD(&inode->i_dentry);  	kmem_cache_free(bdev_cachep, bdi);  } @@ -493,12 +515,12 @@ static struct file_system_type bd_type = {  	.kill_sb	= kill_anon_super,  }; -struct super_block *blockdev_superblock __read_mostly; +static struct super_block *blockdev_superblock __read_mostly;  void __init bdev_cache_init(void)  {  	int err; -	struct vfsmount *bd_mnt; +	static struct vfsmount *bd_mnt;  	bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),  			0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| @@ -510,12 +532,7 @@ void __init bdev_cache_init(void)  	bd_mnt = kern_mount(&bd_type);  	if (IS_ERR(bd_mnt))  		panic("Cannot create bdev pseudo-fs"); -	/* -	 * This vfsmount structure is only used to obtain the -	 * blockdev_superblock, so tell kmemleak not to report it. -	 */ -	kmemleak_not_leak(bd_mnt); -	blockdev_superblock = bd_mnt->mnt_sb;	/* For writeback */ +	blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */  }  /* @@ -639,6 +656,11 @@ static struct block_device *bd_acquire(struct inode *inode)  	return bdev;  } +static inline int sb_is_blkdev_sb(struct super_block *sb) +{ +	return sb == blockdev_superblock; +} +  /* Call when you free inode */  void bd_forget(struct inode *inode) @@ -1117,6 +1139,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)  	mutex_lock_nested(&bdev->bd_mutex, for_part);  	if (!bdev->bd_openers) {  		bdev->bd_disk = disk; +		bdev->bd_queue = disk->queue;  		bdev->bd_contains = bdev;  		if (!partno) {  			struct backing_dev_info *bdi; @@ -1137,6 +1160,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)  					disk_put_part(bdev->bd_part);  					bdev->bd_part = NULL;  					bdev->bd_disk = NULL; +					bdev->bd_queue = NULL;  					mutex_unlock(&bdev->bd_mutex);  					disk_unblock_events(disk);  					put_disk(disk); @@ -1210,6 +1234,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)  	disk_put_part(bdev->bd_part);  	bdev->bd_disk = NULL;  	bdev->bd_part = NULL; +	bdev->bd_queue = NULL;  	bdev_inode_switch_bdi(bdev->bd_inode, &default_backing_dev_info);  	if (bdev != bdev->bd_contains)  		__blkdev_put(bdev->bd_contains, mode, 1);  | 
