From 6e726498f7be60d1b1a3271069fd37a9fdac1cbb Mon Sep 17 00:00:00 2001 From: Ryan Ding Date: Fri, 16 Oct 2015 16:26:40 +0800 Subject: [PATCH] Revert "ocfs2: change ip_unaligned_aio to of type mutex from atomit_t" This reverts commit c18ceab01240fd4c354b78d877571b729908e4a3. Test shows ip_unaligned_aio will cost much cpu clock when doing aio+dio(in a function named mutex_spin_on_owner), and will significant affect performance in a system with poor cpu. The cause is we should not call mutex_unlock(see the comments above mutex_unlock) in ocfs2_dio_end_io, which will be in irq context when doing aio+dio. Revert the patch to use wait_event/wake_up_all to do the work. Signed-off-by: Ryan Ding Reviewed-by: Junxiao Bi --- fs/ocfs2/aops.c | 6 +++++- fs/ocfs2/aops.h | 5 +++++ fs/ocfs2/file.c | 15 ++++++++++++--- fs/ocfs2/inode.h | 2 +- fs/ocfs2/super.c | 9 +++++++-- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index e48299f7a0d4..95e2dcfd8e9b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -615,6 +615,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, { struct inode *inode = file_inode(iocb->ki_filp); int level; + wait_queue_head_t *wq = ocfs2_ioend_wq(inode); /* this io's submitter should not have unlocked this before we could */ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); @@ -625,7 +626,10 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, if (ocfs2_iocb_is_unaligned_aio(iocb)) { ocfs2_iocb_clear_unaligned_aio(iocb); - mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio); + if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) && + waitqueue_active(wq)) { + wake_up_all(wq); + } } ocfs2_iocb_clear_rw_locked(iocb); diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index dd59599b022d..65f10fb82ee4 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -102,4 +102,9 @@ enum ocfs2_iocb_lock_bits { #define ocfs2_iocb_is_unaligned_aio(iocb) \ test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) +#define OCFS2_IOEND_WQ_HASH_SZ 37 +#define ocfs2_ioend_wq(v) (&ocfs2__ioend_wq[((unsigned long)(v)) %\ + OCFS2_IOEND_WQ_HASH_SZ]) +extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; + #endif /* OCFS2_FILE_H */ diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index cdd30c04537e..cbb2ccdb326a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2074,6 +2074,13 @@ out: return ret; } +static void ocfs2_aiodio_wait(struct inode *inode) +{ + wait_queue_head_t *wq = ocfs2_ioend_wq(inode); + + wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0)); +} + static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos) { int blockmask = inode->i_sb->s_blocksize - 1; @@ -2378,8 +2385,10 @@ relock: * Wait on previous unaligned aio to complete before * proceeding. */ - mutex_lock(&OCFS2_I(inode)->ip_unaligned_aio); - /* Mark the iocb as needing an unlock in ocfs2_dio_end_io */ + ocfs2_aiodio_wait(inode); + + /* Mark the iocb as needing a decrement in ocfs2_dio_end_io */ + atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio); ocfs2_iocb_set_unaligned_aio(iocb); } @@ -2452,7 +2461,7 @@ relock: no_sync: if (unaligned_dio) { ocfs2_iocb_clear_unaligned_aio(iocb); - mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio); + atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio); } out: diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 5e86b247c821..c8723c65792d 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -44,7 +44,7 @@ struct ocfs2_inode_info struct rw_semaphore ip_xattr_sem; /* Number of outstanding AIO's which are not page aligned */ - struct mutex ip_unaligned_aio; + atomic_t ip_unaligned_aio; /* These fields are protected by ip_lock */ spinlock_t ip_lock; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index a8004a6ca266..a52344583c8d 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1594,9 +1594,14 @@ static int ocfs2_show_options(struct seq_file *s, struct dentry *root) return 0; } +wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; + static int __init ocfs2_init(void) { - int status; + int status, i; + + for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++) + init_waitqueue_head(&ocfs2__ioend_wq[i]); ocfs2_print_version(); status = init_ocfs2_uptodate_cache(); @@ -1740,7 +1745,7 @@ static void ocfs2_inode_init_once(void *data) ocfs2_extent_map_init(&oi->vfs_inode); INIT_LIST_HEAD(&oi->ip_io_markers); oi->ip_dir_start_lookup = 0; - mutex_init(&oi->ip_unaligned_aio); + atomic_set(&oi->ip_unaligned_aio, 0); init_rwsem(&oi->ip_alloc_sem); init_rwsem(&oi->ip_xattr_sem); mutex_init(&oi->ip_io_mutex); -- 2.50.1