Re: race between __sync_single_inode() andiput()/bdev_clear_inode()

From: OGAWA Hirofumi
Date: Sun Mar 20 2005 - 06:34:53 EST


Andrew Morton <akpm@xxxxxxxx> writes:

> The __sync_single_inode() caller takes a ref on the inode to prevent things
> like this from happening.

Yes. But, in this case, that inode->i_mapping is pointing the bdev's
->i_mapping by open("/dev/hda2").

open("/dev/hda2") -> blkdev_open() -> bd_acquire()

inode->i_bdev = bdev;
inode->i_mapping = bdev->bd_inode->i_mapping;
list_add(&inode->i_devices, &bdev->bd_inodes);

In this race case, the inode is not freeing, but ->i_mapping is freed.

> What was the call path on the other process? The one running
> destroy_inode()? unmount?

close("/dev/hda2").

The _bdev's_ inode is freed by close() path after restoreing
the inode->i_mapping of filesytem in bdev_clear_inode().

close("/dev/hda2")
-> blkdev_close()
-> [...]
-> iput()
-> generic_delete_inode()
-> bdev_clear_inode()
-> __bd_forget()

/* inode is filesystem's inode, not bdev. */
list_del_init(&inode->i_devices);
inode->i_bdev = NULL;
inode->i_mapping = &inode->i_data;

-> destroy_inode() <- is freeing the bdev's inode.

And __sync_single_inode() side is updating the inode->i_atime on filesystem.

>> +/* Called under inode_lock. */
>> +void wait_inode_ilock(struct inode *inode)
>> +{
>> + wait_queue_head_t *wqh;
>> + DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LOCK);
>> +
>> + if (!(inode->i_state & I_LOCK))
>> + return;
>> +
>> + wqh = bit_waitqueue(&inode->i_state, __I_LOCK);
>> + do {
>> + __iget(inode);
>> + spin_unlock(&inode_lock);
>> + __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE);
>> + iput(inode);
>> + spin_lock(&inode_lock);
>> + } while (inode->i_state & I_LOCK);
>> +}
>
> Does this differ from wait_on_inode()?

This checks I_LOCK after taking the inode_lock. So, caller can set the
I_LOCK after this.
--
OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/