diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index f5958f413bd1..9633a490dab0 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -5,14 +5,12 @@ | |||
5 | * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE | 5 | * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/config.h> | ||
9 | #include <linux/init.h> | 8 | #include <linux/init.h> |
10 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
11 | #include <linux/fcntl.h> | 10 | #include <linux/fcntl.h> |
12 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
13 | #include <linux/kmod.h> | 12 | #include <linux/kmod.h> |
14 | #include <linux/major.h> | 13 | #include <linux/major.h> |
15 | #include <linux/devfs_fs_kernel.h> | ||
16 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
17 | #include <linux/highmem.h> | 15 | #include <linux/highmem.h> |
18 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
@@ -300,10 +298,10 @@ static struct super_operations bdev_sops = { | |||
300 | .clear_inode = bdev_clear_inode, | 298 | .clear_inode = bdev_clear_inode, |
301 | }; | 299 | }; |
302 | 300 | ||
303 | static struct super_block *bd_get_sb(struct file_system_type *fs_type, | 301 | static int bd_get_sb(struct file_system_type *fs_type, |
304 | int flags, const char *dev_name, void *data) | 302 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
305 | { | 303 | { |
306 | return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576); | 304 | return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt); |
307 | } | 305 | } |
308 | 306 | ||
309 | static struct file_system_type bd_type = { | 307 | static struct file_system_type bd_type = { |
@@ -414,21 +412,31 @@ EXPORT_SYMBOL(bdput); | |||
414 | static struct block_device *bd_acquire(struct inode *inode) | 412 | static struct block_device *bd_acquire(struct inode *inode) |
415 | { | 413 | { |
416 | struct block_device *bdev; | 414 | struct block_device *bdev; |
415 | |||
417 | spin_lock(&bdev_lock); | 416 | spin_lock(&bdev_lock); |
418 | bdev = inode->i_bdev; | 417 | bdev = inode->i_bdev; |
419 | if (bdev && igrab(bdev->bd_inode)) { | 418 | if (bdev) { |
419 | atomic_inc(&bdev->bd_inode->i_count); | ||
420 | spin_unlock(&bdev_lock); | 420 | spin_unlock(&bdev_lock); |
421 | return bdev; | 421 | return bdev; |
422 | } | 422 | } |
423 | spin_unlock(&bdev_lock); | 423 | spin_unlock(&bdev_lock); |
424 | |||
424 | bdev = bdget(inode->i_rdev); | 425 | bdev = bdget(inode->i_rdev); |
425 | if (bdev) { | 426 | if (bdev) { |
426 | spin_lock(&bdev_lock); | 427 | spin_lock(&bdev_lock); |
427 | if (inode->i_bdev) | 428 | if (!inode->i_bdev) { |
428 | __bd_forget(inode); | 429 | /* |
429 | inode->i_bdev = bdev; | 430 | * We take an additional bd_inode->i_count for inode, |
430 | inode->i_mapping = bdev->bd_inode->i_mapping; | 431 | * and it's released in clear_inode() of inode. |
431 | list_add(&inode->i_devices, &bdev->bd_inodes); | 432 | * So, we can access it via ->i_mapping always |
433 | * without igrab(). | ||
434 | */ | ||
435 | atomic_inc(&bdev->bd_inode->i_count); | ||
436 | inode->i_bdev = bdev; | ||
437 | inode->i_mapping = bdev->bd_inode->i_mapping; | ||
438 | list_add(&inode->i_devices, &bdev->bd_inodes); | ||
439 | } | ||
432 | spin_unlock(&bdev_lock); | 440 | spin_unlock(&bdev_lock); |
433 | } | 441 | } |
434 | return bdev; | 442 | return bdev; |
@@ -438,10 +446,18 @@ static struct block_device *bd_acquire(struct inode *inode) | |||
438 | 446 | ||
439 | void bd_forget(struct inode *inode) | 447 | void bd_forget(struct inode *inode) |
440 | { | 448 | { |
449 | struct block_device *bdev = NULL; | ||
450 | |||
441 | spin_lock(&bdev_lock); | 451 | spin_lock(&bdev_lock); |
442 | if (inode->i_bdev) | 452 | if (inode->i_bdev) { |
453 | if (inode->i_sb != blockdev_superblock) | ||
454 | bdev = inode->i_bdev; | ||
443 | __bd_forget(inode); | 455 | __bd_forget(inode); |
456 | } | ||
444 | spin_unlock(&bdev_lock); | 457 | spin_unlock(&bdev_lock); |
458 | |||
459 | if (bdev) | ||
460 | iput(bdev->bd_inode); | ||
445 | } | 461 | } |
446 | 462 | ||
447 | int bd_claim(struct block_device *bdev, void *holder) | 463 | int bd_claim(struct block_device *bdev, void *holder) |
@@ -1077,7 +1093,7 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
1077 | return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); | 1093 | return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); |
1078 | } | 1094 | } |
1079 | 1095 | ||
1080 | struct address_space_operations def_blk_aops = { | 1096 | const struct address_space_operations def_blk_aops = { |
1081 | .readpage = blkdev_readpage, | 1097 | .readpage = blkdev_readpage, |
1082 | .writepage = blkdev_writepage, | 1098 | .writepage = blkdev_writepage, |
1083 | .sync_page = block_sync_page, | 1099 | .sync_page = block_sync_page, |