xfs: remove i_iocount
We now have an i_dio_count filed and surrounding infrastructure to wait for direct I/O completion instead of i_icount, and we have never needed to iocount waits for buffered I/O given that we only set the page uptodate after finishing all required work. Thus remove i_iocount, and replace the actually needed waits with calls to inode_dio_wait. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Alex Elder <aelder@sgi.com>
This commit is contained in:
committed by
Alex Elder
parent
2b3ffd7eb7
commit
4a06fd262d
@@ -38,40 +38,6 @@
|
|||||||
#include <linux/pagevec.h>
|
#include <linux/pagevec.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prime number of hash buckets since address is used as the key.
|
|
||||||
*/
|
|
||||||
#define NVSYNC 37
|
|
||||||
#define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC])
|
|
||||||
static wait_queue_head_t xfs_ioend_wq[NVSYNC];
|
|
||||||
|
|
||||||
void __init
|
|
||||||
xfs_ioend_init(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NVSYNC; i++)
|
|
||||||
init_waitqueue_head(&xfs_ioend_wq[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xfs_ioend_wait(
|
|
||||||
xfs_inode_t *ip)
|
|
||||||
{
|
|
||||||
wait_queue_head_t *wq = to_ioend_wq(ip);
|
|
||||||
|
|
||||||
wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_ioend_wake(
|
|
||||||
xfs_inode_t *ip)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&ip->i_iocount))
|
|
||||||
wake_up(to_ioend_wq(ip));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_count_page_state(
|
xfs_count_page_state(
|
||||||
struct page *page,
|
struct page *page,
|
||||||
@@ -115,7 +81,6 @@ xfs_destroy_ioend(
|
|||||||
xfs_ioend_t *ioend)
|
xfs_ioend_t *ioend)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh, *next;
|
struct buffer_head *bh, *next;
|
||||||
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
|
||||||
|
|
||||||
for (bh = ioend->io_buffer_head; bh; bh = next) {
|
for (bh = ioend->io_buffer_head; bh; bh = next) {
|
||||||
next = bh->b_private;
|
next = bh->b_private;
|
||||||
@@ -127,7 +92,7 @@ xfs_destroy_ioend(
|
|||||||
aio_complete(ioend->io_iocb, ioend->io_result, 0);
|
aio_complete(ioend->io_iocb, ioend->io_result, 0);
|
||||||
inode_dio_done(ioend->io_inode);
|
inode_dio_done(ioend->io_inode);
|
||||||
}
|
}
|
||||||
xfs_ioend_wake(ip);
|
|
||||||
mempool_free(ioend, xfs_ioend_pool);
|
mempool_free(ioend, xfs_ioend_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +263,6 @@ xfs_alloc_ioend(
|
|||||||
ioend->io_inode = inode;
|
ioend->io_inode = inode;
|
||||||
ioend->io_buffer_head = NULL;
|
ioend->io_buffer_head = NULL;
|
||||||
ioend->io_buffer_tail = NULL;
|
ioend->io_buffer_tail = NULL;
|
||||||
atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
|
|
||||||
ioend->io_offset = 0;
|
ioend->io_offset = 0;
|
||||||
ioend->io_size = 0;
|
ioend->io_size = 0;
|
||||||
ioend->io_iocb = NULL;
|
ioend->io_iocb = NULL;
|
||||||
@@ -558,7 +522,6 @@ xfs_cancel_ioend(
|
|||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
} while ((bh = next_bh) != NULL);
|
} while ((bh = next_bh) != NULL);
|
||||||
|
|
||||||
xfs_ioend_wake(XFS_I(ioend->io_inode));
|
|
||||||
mempool_free(ioend, xfs_ioend_pool);
|
mempool_free(ioend, xfs_ioend_pool);
|
||||||
} while ((ioend = next) != NULL);
|
} while ((ioend = next) != NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ typedef struct xfs_ioend {
|
|||||||
extern const struct address_space_operations xfs_address_space_operations;
|
extern const struct address_space_operations xfs_address_space_operations;
|
||||||
extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
|
extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
|
||||||
|
|
||||||
extern void xfs_ioend_init(void);
|
|
||||||
extern void xfs_ioend_wait(struct xfs_inode *);
|
|
||||||
|
|
||||||
extern void xfs_count_page_state(struct page *, int *, int *);
|
extern void xfs_count_page_state(struct page *, int *, int *);
|
||||||
|
|
||||||
#endif /* __XFS_AOPS_H__ */
|
#endif /* __XFS_AOPS_H__ */
|
||||||
|
|||||||
@@ -149,10 +149,6 @@ xfs_file_fsync(
|
|||||||
|
|
||||||
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
|
||||||
|
|
||||||
if (mp->m_flags & XFS_MOUNT_BARRIER) {
|
if (mp->m_flags & XFS_MOUNT_BARRIER) {
|
||||||
/*
|
/*
|
||||||
* If we have an RT and/or log subvolume we need to make sure
|
* If we have an RT and/or log subvolume we need to make sure
|
||||||
@@ -758,7 +754,7 @@ restart:
|
|||||||
* the dio layer. To avoid the problem with aio, we also need to wait for
|
* the dio layer. To avoid the problem with aio, we also need to wait for
|
||||||
* outstanding IOs to complete so that unwritten extent conversion is completed
|
* outstanding IOs to complete so that unwritten extent conversion is completed
|
||||||
* before we try to map the overlapping block. This is currently implemented by
|
* before we try to map the overlapping block. This is currently implemented by
|
||||||
* hitting it with a big hammer (i.e. xfs_ioend_wait()).
|
* hitting it with a big hammer (i.e. inode_dio_wait()).
|
||||||
*
|
*
|
||||||
* Returns with locks held indicated by @iolock and errors indicated by
|
* Returns with locks held indicated by @iolock and errors indicated by
|
||||||
* negative return values.
|
* negative return values.
|
||||||
@@ -821,7 +817,7 @@ xfs_file_dio_aio_write(
|
|||||||
* otherwise demote the lock if we had to flush cached pages
|
* otherwise demote the lock if we had to flush cached pages
|
||||||
*/
|
*/
|
||||||
if (unaligned_io)
|
if (unaligned_io)
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(inode);
|
||||||
else if (*iolock == XFS_IOLOCK_EXCL) {
|
else if (*iolock == XFS_IOLOCK_EXCL) {
|
||||||
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
||||||
*iolock = XFS_IOLOCK_SHARED;
|
*iolock = XFS_IOLOCK_SHARED;
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ xfs_inode_alloc(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
||||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||||
ASSERT(completion_done(&ip->i_flush));
|
ASSERT(completion_done(&ip->i_flush));
|
||||||
@@ -150,7 +149,6 @@ xfs_inode_free(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* asserts to verify all state is correct here */
|
/* asserts to verify all state is correct here */
|
||||||
ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
||||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||||
ASSERT(completion_done(&ip->i_flush));
|
ASSERT(completion_done(&ip->i_flush));
|
||||||
|
|||||||
@@ -257,7 +257,6 @@ typedef struct xfs_inode {
|
|||||||
|
|
||||||
xfs_fsize_t i_size; /* in-memory size */
|
xfs_fsize_t i_size; /* in-memory size */
|
||||||
xfs_fsize_t i_new_size; /* size when write completes */
|
xfs_fsize_t i_new_size; /* size when write completes */
|
||||||
atomic_t i_iocount; /* outstanding I/O count */
|
|
||||||
|
|
||||||
/* VFS inode */
|
/* VFS inode */
|
||||||
struct inode i_vnode; /* embedded VFS inode */
|
struct inode i_vnode; /* embedded VFS inode */
|
||||||
|
|||||||
@@ -840,9 +840,9 @@ xfs_setattr_size(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for all I/O to complete.
|
* Wait for all direct I/O to complete.
|
||||||
*/
|
*/
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(inode);
|
||||||
|
|
||||||
error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
|
error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
|
||||||
xfs_get_blocks);
|
xfs_get_blocks);
|
||||||
|
|||||||
@@ -796,8 +796,6 @@ xfs_fs_destroy_inode(
|
|||||||
if (is_bad_inode(inode))
|
if (is_bad_inode(inode))
|
||||||
goto out_reclaim;
|
goto out_reclaim;
|
||||||
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
|
|
||||||
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
|
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -837,7 +835,6 @@ xfs_fs_inode_init_once(
|
|||||||
inode_init_once(VFS_I(ip));
|
inode_init_once(VFS_I(ip));
|
||||||
|
|
||||||
/* xfs inode */
|
/* xfs inode */
|
||||||
atomic_set(&ip->i_iocount, 0);
|
|
||||||
atomic_set(&ip->i_pincount, 0);
|
atomic_set(&ip->i_pincount, 0);
|
||||||
spin_lock_init(&ip->i_flags_lock);
|
spin_lock_init(&ip->i_flags_lock);
|
||||||
init_waitqueue_head(&ip->i_ipin_wait);
|
init_waitqueue_head(&ip->i_ipin_wait);
|
||||||
@@ -914,9 +911,8 @@ xfs_fs_write_inode(
|
|||||||
* of forcing it all the way to stable storage using a
|
* of forcing it all the way to stable storage using a
|
||||||
* synchronous transaction we let the log force inside the
|
* synchronous transaction we let the log force inside the
|
||||||
* ->sync_fs call do that for thus, which reduces the number
|
* ->sync_fs call do that for thus, which reduces the number
|
||||||
* of synchronous log foces dramatically.
|
* of synchronous log forces dramatically.
|
||||||
*/
|
*/
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
error = xfs_log_inode(ip);
|
error = xfs_log_inode(ip);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1681,7 +1677,6 @@ init_xfs_fs(void)
|
|||||||
printk(KERN_INFO XFS_VERSION_STRING " with "
|
printk(KERN_INFO XFS_VERSION_STRING " with "
|
||||||
XFS_BUILD_OPTIONS " enabled\n");
|
XFS_BUILD_OPTIONS " enabled\n");
|
||||||
|
|
||||||
xfs_ioend_init();
|
|
||||||
xfs_dir_startup();
|
xfs_dir_startup();
|
||||||
|
|
||||||
error = xfs_init_zones();
|
error = xfs_init_zones();
|
||||||
|
|||||||
@@ -227,21 +227,17 @@ xfs_sync_inode_data(
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
||||||
goto out_wait;
|
return 0;
|
||||||
|
|
||||||
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
|
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
|
||||||
if (flags & SYNC_TRYLOCK)
|
if (flags & SYNC_TRYLOCK)
|
||||||
goto out_wait;
|
return 0;
|
||||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
|
error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
|
||||||
0 : XBF_ASYNC, FI_NONE);
|
0 : XBF_ASYNC, FI_NONE);
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||||
|
|
||||||
out_wait:
|
|
||||||
if (flags & SYNC_WAIT)
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -647,8 +647,6 @@ xfs_inactive(
|
|||||||
if (truncate) {
|
if (truncate) {
|
||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||||
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
|
|
||||||
error = xfs_trans_reserve(tp, 0,
|
error = xfs_trans_reserve(tp, 0,
|
||||||
XFS_ITRUNCATE_LOG_RES(mp),
|
XFS_ITRUNCATE_LOG_RES(mp),
|
||||||
0, XFS_TRANS_PERM_LOG_RES,
|
0, XFS_TRANS_PERM_LOG_RES,
|
||||||
@@ -2076,7 +2074,7 @@ xfs_free_file_space(
|
|||||||
if (need_iolock) {
|
if (need_iolock) {
|
||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||||
/* wait for the completion of any pending DIOs */
|
/* wait for the completion of any pending DIOs */
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(VFS_I(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
|
rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
|
||||||
|
|||||||
Reference in New Issue
Block a user