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, 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
303static struct super_block *bd_get_sb(struct file_system_type *fs_type, 301static 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
309static struct file_system_type bd_type = { 307static struct file_system_type bd_type = {
@@ -414,21 +412,31 @@ EXPORT_SYMBOL(bdput);
414static struct block_device *bd_acquire(struct inode *inode) 412static 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
439void bd_forget(struct inode *inode) 447void 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
447int bd_claim(struct block_device *bdev, void *holder) 463int 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
1080struct address_space_operations def_blk_aops = { 1096const 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,