From 3ac73d0a6d6d0c39f7bfb7b5f4d26de257f4a83b Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 22 Jun 2006 14:47:21 -0700 Subject: [PATCH] --- yaml --- r: 28566 b: refs/heads/master c: 09d967c6f32b35eab15b45862ae16e4f06259d8e h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/block_dev.c | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 676bc6a252c6..c7689e35797f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0e5b3781591cc954037c08ef78edf7f1192d38c5 +refs/heads/master: 09d967c6f32b35eab15b45862ae16e4f06259d8e diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index f5958f413bd1..44aaba202f78 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput); static struct block_device *bd_acquire(struct inode *inode) { struct block_device *bdev; + spin_lock(&bdev_lock); bdev = inode->i_bdev; - if (bdev && igrab(bdev->bd_inode)) { + if (bdev) { + atomic_inc(&bdev->bd_inode->i_count); spin_unlock(&bdev_lock); return bdev; } spin_unlock(&bdev_lock); + bdev = bdget(inode->i_rdev); if (bdev) { spin_lock(&bdev_lock); - if (inode->i_bdev) - __bd_forget(inode); - inode->i_bdev = bdev; - inode->i_mapping = bdev->bd_inode->i_mapping; - list_add(&inode->i_devices, &bdev->bd_inodes); + if (!inode->i_bdev) { + /* + * We take an additional bd_inode->i_count for inode, + * and it's released in clear_inode() of inode. + * So, we can access it via ->i_mapping always + * without igrab(). + */ + atomic_inc(&bdev->bd_inode->i_count); + inode->i_bdev = bdev; + inode->i_mapping = bdev->bd_inode->i_mapping; + list_add(&inode->i_devices, &bdev->bd_inodes); + } spin_unlock(&bdev_lock); } return bdev; @@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode) void bd_forget(struct inode *inode) { + struct block_device *bdev = NULL; + spin_lock(&bdev_lock); - if (inode->i_bdev) + if (inode->i_bdev) { + if (inode->i_sb != blockdev_superblock) + bdev = inode->i_bdev; __bd_forget(inode); + } spin_unlock(&bdev_lock); + + if (bdev) + iput(bdev->bd_inode); } int bd_claim(struct block_device *bdev, void *holder)