aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 99e0ae1a4c78..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)
@@ -326,12 +328,13 @@ static struct file_system_type bd_type = {
326 .kill_sb = kill_anon_super, 328 .kill_sb = kill_anon_super,
327}; 329};
328 330
329static struct vfsmount *bd_mnt __read_mostly; 331struct super_block *blockdev_superblock __read_mostly;
330struct super_block *blockdev_superblock;
331 332
332void __init bdev_cache_init(void) 333void __init bdev_cache_init(void)
333{ 334{
334 int err; 335 int err;
336 struct vfsmount *bd_mnt;
337
335 bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), 338 bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
336 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 339 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
337 SLAB_MEM_SPREAD|SLAB_PANIC), 340 SLAB_MEM_SPREAD|SLAB_PANIC),
@@ -373,7 +376,7 @@ struct block_device *bdget(dev_t dev)
373 struct block_device *bdev; 376 struct block_device *bdev;
374 struct inode *inode; 377 struct inode *inode;
375 378
376 inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), 379 inode = iget5_locked(blockdev_superblock, hash(dev),
377 bdev_test, bdev_set, &dev); 380 bdev_test, bdev_set, &dev);
378 381
379 if (!inode) 382 if (!inode)
@@ -463,7 +466,7 @@ void bd_forget(struct inode *inode)
463 466
464 spin_lock(&bdev_lock); 467 spin_lock(&bdev_lock);
465 if (inode->i_bdev) { 468 if (inode->i_bdev) {
466 if (inode->i_sb != blockdev_superblock) 469 if (!sb_is_blkdev_sb(inode->i_sb))
467 bdev = inode->i_bdev; 470 bdev = inode->i_bdev;
468 __bd_forget(inode); 471 __bd_forget(inode);
469 } 472 }
@@ -1004,6 +1007,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1004 } 1007 }
1005 1008
1006 lock_kernel(); 1009 lock_kernel();
1010 restart:
1007 1011
1008 ret = -ENXIO; 1012 ret = -ENXIO;
1009 disk = get_gendisk(bdev->bd_dev, &partno); 1013 disk = get_gendisk(bdev->bd_dev, &partno);
@@ -1024,6 +1028,19 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
1024 1028
1025 if (disk->fops->open) { 1029 if (disk->fops->open) {
1026 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 }
1027 if (ret) 1044 if (ret)
1028 goto out_clear; 1045 goto out_clear;
1029 } 1046 }
@@ -1219,6 +1236,20 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1219 return blkdev_ioctl(bdev, mode, cmd, arg); 1236 return blkdev_ioctl(bdev, mode, cmd, arg);
1220} 1237}
1221 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
1222static const struct address_space_operations def_blk_aops = { 1253static const struct address_space_operations def_blk_aops = {
1223 .readpage = blkdev_readpage, 1254 .readpage = blkdev_readpage,
1224 .writepage = blkdev_writepage, 1255 .writepage = blkdev_writepage,
@@ -1226,6 +1257,7 @@ static const struct address_space_operations def_blk_aops = {
1226 .write_begin = blkdev_write_begin, 1257 .write_begin = blkdev_write_begin,
1227 .write_end = blkdev_write_end, 1258 .write_end = blkdev_write_end,
1228 .writepages = generic_writepages, 1259 .writepages = generic_writepages,
1260 .releasepage = blkdev_releasepage,
1229 .direct_IO = blkdev_direct_IO, 1261 .direct_IO = blkdev_direct_IO,
1230}; 1262};
1231 1263
@@ -1261,7 +1293,7 @@ EXPORT_SYMBOL(ioctl_by_bdev);
1261 1293
1262/** 1294/**
1263 * lookup_bdev - lookup a struct block_device by name 1295 * lookup_bdev - lookup a struct block_device by name
1264 * @path: special file representing the block device 1296 * @pathname: special file representing the block device
1265 * 1297 *
1266 * Get a reference to the blockdevice at @pathname in the current 1298 * Get a reference to the blockdevice at @pathname in the current
1267 * namespace if possible and return it. Return ERR_PTR(error) 1299 * namespace if possible and return it. Return ERR_PTR(error)