pandora: defconfig: update
[pandora-kernel.git] / fs / block_dev.c
index b07f1da..a693d0c 100644 (file)
@@ -55,20 +55,27 @@ static void bdev_inode_switch_bdi(struct inode *inode,
                        struct backing_dev_info *dst)
 {
        struct backing_dev_info *old = inode->i_data.backing_dev_info;
+       bool wakeup_bdi = false;
 
        if (unlikely(dst == old))               /* deadlock avoidance */
                return;
        bdi_lock_two(&old->wb, &dst->wb);
        spin_lock(&inode->i_lock);
        inode->i_data.backing_dev_info = dst;
-       if (inode->i_state & I_DIRTY)
+       if (inode->i_state & I_DIRTY) {
+               if (bdi_cap_writeback_dirty(dst) && !wb_has_dirty_io(&dst->wb))
+                       wakeup_bdi = true;
                list_move(&inode->i_wb_list, &dst->wb.b_dirty);
+       }
        spin_unlock(&inode->i_lock);
        spin_unlock(&old->wb.list_lock);
        spin_unlock(&dst->wb.list_lock);
+
+       if (wakeup_bdi)
+               bdi_wakeup_thread_delayed(dst);
 }
 
-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 +89,14 @@ 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)
                return;
        invalidate_bh_lrus();
        truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
 }      
+EXPORT_SYMBOL(kill_bdev);
 
 int set_blocksize(struct block_device *bdev, int size)
 {
@@ -139,7 +147,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 +169,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) {
@@ -586,6 +594,7 @@ struct block_device *bdgrab(struct block_device *bdev)
        ihold(bdev->bd_inode);
        return bdev;
 }
+EXPORT_SYMBOL(bdgrab);
 
 long nr_blockdev_pages(void)
 {
@@ -678,7 +687,7 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole,
                return true;     /* already a holder */
        else if (bdev->bd_holder != NULL)
                return false;    /* held by someone else */
-       else if (bdev->bd_contains == bdev)
+       else if (whole == bdev)
                return true;     /* is a whole device which isn't held */
 
        else if (whole->bd_holder == bd_may_claim)
@@ -1024,6 +1033,7 @@ int revalidate_disk(struct gendisk *disk)
 
        mutex_lock(&bdev->bd_mutex);
        check_disk_size_change(disk, bdev);
+       bdev->bd_invalidated = 0;
        mutex_unlock(&bdev->bd_mutex);
        bdput(bdev);
        return ret;
@@ -1062,7 +1072,9 @@ void bd_set_size(struct block_device *bdev, loff_t size)
 {
        unsigned bsize = bdev_logical_block_size(bdev);
 
-       bdev->bd_inode->i_size = size;
+       mutex_lock(&bdev->bd_inode->i_mutex);
+       i_size_write(bdev->bd_inode, size);
+       mutex_unlock(&bdev->bd_inode->i_mutex);
        while (bsize < PAGE_CACHE_SIZE) {
                if (size & bsize)
                        break;
@@ -1159,8 +1171,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 +1206,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;
                }