diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 31 |
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 | ||
290 | static inline void __bd_forget(struct inode *inode) | 292 | static 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 | */ | ||
1243 | static 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 | |||
1223 | static const struct address_space_operations def_blk_aops = { | 1253 | static 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 | ||