Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[linux-flexiantxendom0-3.2.10.git] / fs / block_dev.c
index b07f1da..ba11c30 100644 (file)
@@ -16,7 +16,9 @@
 #include <linux/blkdev.h>
 #include <linux/module.h>
 #include <linux/blkpg.h>
+#include <linux/magic.h>
 #include <linux/buffer_head.h>
+#include <linux/swap.h>
 #include <linux/pagevec.h>
 #include <linux/writeback.h>
 #include <linux/mpage.h>
@@ -24,7 +26,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"
 
@@ -68,7 +70,7 @@ static void bdev_inode_switch_bdi(struct inode *inode,
        spin_unlock(&dst->wb.list_lock);
 }
 
-static sector_t max_block(struct block_device *bdev)
+sector_t blkdev_max_block(struct block_device *bdev)
 {
        sector_t retval = ~((sector_t)0);
        loff_t sz = i_size_read(bdev->bd_inode);
@@ -82,13 +84,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_invalidate_inode(mapping);
+}
+EXPORT_SYMBOL(invalidate_bdev);
 
 int set_blocksize(struct block_device *bdev, int size)
 {
@@ -139,7 +163,7 @@ static int
 blkdev_get_block(struct inode *inode, sector_t iblock,
                struct buffer_head *bh, int create)
 {
-       if (iblock >= max_block(I_BDEV(inode))) {
+       if (iblock >= blkdev_max_block(I_BDEV(inode))) {
                if (create)
                        return -EIO;
 
@@ -161,7 +185,7 @@ static int
 blkdev_get_blocks(struct inode *inode, sector_t iblock,
                struct buffer_head *bh, int create)
 {
-       sector_t end_block = max_block(I_BDEV(inode));
+       sector_t end_block = blkdev_max_block(I_BDEV(inode));
        unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
 
        if ((iblock + max_blocks) > end_block) {
@@ -425,7 +449,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);
 }
 
@@ -484,7 +507,7 @@ static const struct super_operations bdev_sops = {
 static struct dentry *bd_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
-       return mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, 0x62646576);
+       return mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC);
 }
 
 static struct file_system_type bd_type = {
@@ -493,12 +516,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 +533,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 +657,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 +1140,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 +1161,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);
@@ -1159,8 +1184,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                         * The latter is necessary to prevent ghost
                         * partitions on a removed medium.
                         */
-                       if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
-                               rescan_partitions(disk, bdev);
+                       if (bdev->bd_invalidated) {
+                               if (!ret)
+                                       rescan_partitions(disk, bdev);
+                               else if (ret == -ENOMEDIUM)
+                                       invalidate_partitions(disk, bdev);
+                       }
                        if (ret)
                                goto out_clear;
                } else {
@@ -1190,8 +1219,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                        if (bdev->bd_disk->fops->open)
                                ret = bdev->bd_disk->fops->open(bdev, mode);
                        /* the same as first opener case, read comment there */
-                       if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
-                               rescan_partitions(bdev->bd_disk, bdev);
+                       if (bdev->bd_invalidated) {
+                               if (!ret)
+                                       rescan_partitions(bdev->bd_disk, bdev);
+                               else if (ret == -ENOMEDIUM)
+                                       invalidate_partitions(bdev->bd_disk, bdev);
+                       }
                        if (ret)
                                goto out_unlock_bdev;
                }
@@ -1210,6 +1243,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);