xfs: replace i_flock with a sleeping bitlock
We almost never block on i_flock, the exception is synchronous inode flushing. Instead of bloating the inode with a 16/24-byte completion that we abuse as a semaphore just implement it as a bitlock that uses a bit waitqueue for the rare sleeping path. This primarily is a tradeoff between a much smaller inode and a faster non-blocking path vs faster wakeups, and we are much better off with the former. A small downside is that we will lose lockdep checking for i_flock, but given that it's always taken inside the ilock that should be acceptable. Note that for example the inode writeback locking is implemented in a very similar way. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
committed by
Ben Myers
parent
49e4c70e52
commit
474fce0675
@@ -77,7 +77,7 @@ xfs_inode_alloc(
|
||||
|
||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||
ASSERT(completion_done(&ip->i_flush));
|
||||
ASSERT(!xfs_isiflocked(ip));
|
||||
ASSERT(ip->i_ino == 0);
|
||||
|
||||
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
|
||||
@@ -150,7 +150,7 @@ xfs_inode_free(
|
||||
/* asserts to verify all state is correct here */
|
||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||
ASSERT(completion_done(&ip->i_flush));
|
||||
ASSERT(!xfs_isiflocked(ip));
|
||||
|
||||
/*
|
||||
* Because we use RCU freeing we need to ensure the inode always
|
||||
@@ -713,3 +713,19 @@ xfs_isilocked(
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
__xfs_iflock(
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
|
||||
DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
|
||||
|
||||
do {
|
||||
prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
|
||||
if (xfs_isiflocked(ip))
|
||||
io_schedule();
|
||||
} while (!xfs_iflock_nowait(ip));
|
||||
|
||||
finish_wait(wq, &wait.wait);
|
||||
}
|
||||
|
Reference in New Issue
Block a user