|
@@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput);
|
|
static struct block_device *bd_acquire(struct inode *inode)
|
|
static struct block_device *bd_acquire(struct inode *inode)
|
|
{
|
|
{
|
|
struct block_device *bdev;
|
|
struct block_device *bdev;
|
|
|
|
+
|
|
spin_lock(&bdev_lock);
|
|
spin_lock(&bdev_lock);
|
|
bdev = inode->i_bdev;
|
|
bdev = inode->i_bdev;
|
|
- if (bdev && igrab(bdev->bd_inode)) {
|
|
|
|
|
|
+ if (bdev) {
|
|
|
|
+ atomic_inc(&bdev->bd_inode->i_count);
|
|
spin_unlock(&bdev_lock);
|
|
spin_unlock(&bdev_lock);
|
|
return bdev;
|
|
return bdev;
|
|
}
|
|
}
|
|
spin_unlock(&bdev_lock);
|
|
spin_unlock(&bdev_lock);
|
|
|
|
+
|
|
bdev = bdget(inode->i_rdev);
|
|
bdev = bdget(inode->i_rdev);
|
|
if (bdev) {
|
|
if (bdev) {
|
|
spin_lock(&bdev_lock);
|
|
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);
|
|
spin_unlock(&bdev_lock);
|
|
}
|
|
}
|
|
return bdev;
|
|
return bdev;
|
|
@@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode)
|
|
|
|
|
|
void bd_forget(struct inode *inode)
|
|
void bd_forget(struct inode *inode)
|
|
{
|
|
{
|
|
|
|
+ struct block_device *bdev = NULL;
|
|
|
|
+
|
|
spin_lock(&bdev_lock);
|
|
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);
|
|
__bd_forget(inode);
|
|
|
|
+ }
|
|
spin_unlock(&bdev_lock);
|
|
spin_unlock(&bdev_lock);
|
|
|
|
+
|
|
|
|
+ if (bdev)
|
|
|
|
+ iput(bdev->bd_inode);
|
|
}
|
|
}
|
|
|
|
|
|
int bd_claim(struct block_device *bdev, void *holder)
|
|
int bd_claim(struct block_device *bdev, void *holder)
|