aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
authorLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2009-01-14 00:29:08 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2009-01-14 00:29:08 -0500
commitc088f4e9da74b901f7ed1749ad697d77622ed0f9 (patch)
tree84cddf20369f82f10c1c3712e6cce20dd1b9d863 /fs/block_dev.c
parentce79735c12d62c3cda38eb31762cf98e87c7b087 (diff)
parenta6525042bfdfcab128bd91fad264de10fd24a55e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b957717e25ab..b3c1efff5e1d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -285,6 +285,8 @@ static void init_once(void *foo)
285 INIT_LIST_HEAD(&bdev->bd_holder_list); 285 INIT_LIST_HEAD(&bdev->bd_holder_list);
286#endif 286#endif
287 inode_init_once(&ei->vfs_inode); 287 inode_init_once(&ei->vfs_inode);
288 /* Initialize mutex for freeze. */
289 mutex_init(&bdev->bd_fsfreeze_mutex);
288} 290}
289 291
290static inline void __bd_forget(struct inode *inode) 292static inline void __bd_forget(struct inode *inode)
@@ -1005,6 +1007,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1005 } 1007 }
1006 1008
1007 lock_kernel(); 1009 lock_kernel();
1010 restart:
1008 1011
1009 ret = -ENXIO; 1012 ret = -ENXIO;
1010 disk = get_gendisk(bdev->bd_dev, &partno); 1013 disk = get_gendisk(bdev->bd_dev, &partno);
@@ -1025,6 +1028,19 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1025 1028
1026 if (disk->fops->open) { 1029 if (disk->fops->open) {
1027 ret = disk->fops->open(bdev, mode); 1030 ret = disk->fops->open(bdev, mode);
1031 if (ret == -ERESTARTSYS) {
1032 /* Lost a race with 'disk' being
1033 * deleted, try again.
1034 * See md.c
1035 */
1036 disk_put_part(bdev->bd_part);
1037 bdev->bd_part = NULL;
1038 module_put(disk->fops->owner);
1039 put_disk(disk);
1040 bdev->bd_disk = NULL;
1041 mutex_unlock(&bdev->bd_mutex);
1042 goto restart;
1043 }
1028 if (ret) 1044 if (ret)
1029 goto out_clear; 1045 goto out_clear;
1030 } 1046 }
@@ -1220,6 +1236,20 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1220 return blkdev_ioctl(bdev, mode, cmd, arg); 1236 return blkdev_ioctl(bdev, mode, cmd, arg);
1221} 1237}
1222 1238
1239/*
1240 * Try to release a page associated with block device when the system
1241 * is under memory pressure.
1242 */
1243static int blkdev_releasepage(struct page *page, gfp_t wait)
1244{
1245 struct super_block *super = BDEV_I(page->mapping->host)->bdev.bd_super;
1246
1247 if (super && super->s_op->bdev_try_to_free_page)
1248 return super->s_op->bdev_try_to_free_page(super, page, wait);
1249
1250 return try_to_free_buffers(page);
1251}
1252
1223static const struct address_space_operations def_blk_aops = { 1253static const struct address_space_operations def_blk_aops = {
1224 .readpage = blkdev_readpage, 1254 .readpage = blkdev_readpage,
1225 .writepage = blkdev_writepage, 1255 .writepage = blkdev_writepage,
@@ -1227,6 +1257,7 @@ static const struct address_space_operations def_blk_aops = {
1227 .write_begin = blkdev_write_begin, 1257 .write_begin = blkdev_write_begin,
1228 .write_end = blkdev_write_end, 1258 .write_end = blkdev_write_end,
1229 .writepages = generic_writepages, 1259 .writepages = generic_writepages,
1260 .releasepage = blkdev_releasepage,
1230 .direct_IO = blkdev_direct_IO, 1261 .direct_IO = blkdev_direct_IO,
1231}; 1262};
1232 1263