diff options
author | Wengang Wang <wen.gang.wang@oracle.com> | 2014-04-03 17:46:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-03 19:20:53 -0400 |
commit | c18ceab01240fd4c354b78d877571b729908e4a3 (patch) | |
tree | d9c0107c30019e3299fe1b712d2eebaf832e55ed | |
parent | 181a9a043b5424f2e6451297bbc27b196fe88475 (diff) |
ocfs2: change ip_unaligned_aio to of type mutex from atomit_t
There is a problem that waitqueue_active() may check stale data thus miss
a wakeup of threads waiting on ip_unaligned_aio.
The valid value of ip_unaligned_aio is only 0 and 1 so we can change it to
be of type mutex thus the above prolem is avoid. Another benifit is that
mutex which works as FIFO is fairer than wake_up_all().
Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ocfs2/aops.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/aops.h | 5 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 15 | ||||
-rw-r--r-- | fs/ocfs2/inode.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 9 |
5 files changed, 7 insertions, 30 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index aeb44e879c51..ebe44f7dce0b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -571,7 +571,6 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
571 | { | 571 | { |
572 | struct inode *inode = file_inode(iocb->ki_filp); | 572 | struct inode *inode = file_inode(iocb->ki_filp); |
573 | int level; | 573 | int level; |
574 | wait_queue_head_t *wq = ocfs2_ioend_wq(inode); | ||
575 | 574 | ||
576 | /* this io's submitter should not have unlocked this before we could */ | 575 | /* this io's submitter should not have unlocked this before we could */ |
577 | BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); | 576 | BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); |
@@ -582,10 +581,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
582 | if (ocfs2_iocb_is_unaligned_aio(iocb)) { | 581 | if (ocfs2_iocb_is_unaligned_aio(iocb)) { |
583 | ocfs2_iocb_clear_unaligned_aio(iocb); | 582 | ocfs2_iocb_clear_unaligned_aio(iocb); |
584 | 583 | ||
585 | if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) && | 584 | mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio); |
586 | waitqueue_active(wq)) { | ||
587 | wake_up_all(wq); | ||
588 | } | ||
589 | } | 585 | } |
590 | 586 | ||
591 | ocfs2_iocb_clear_rw_locked(iocb); | 587 | ocfs2_iocb_clear_rw_locked(iocb); |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index f671e49beb34..6cae155d54df 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
@@ -102,9 +102,4 @@ enum ocfs2_iocb_lock_bits { | |||
102 | #define ocfs2_iocb_is_unaligned_aio(iocb) \ | 102 | #define ocfs2_iocb_is_unaligned_aio(iocb) \ |
103 | test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) | 103 | test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private) |
104 | 104 | ||
105 | #define OCFS2_IOEND_WQ_HASH_SZ 37 | ||
106 | #define ocfs2_ioend_wq(v) (&ocfs2__ioend_wq[((unsigned long)(v)) %\ | ||
107 | OCFS2_IOEND_WQ_HASH_SZ]) | ||
108 | extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; | ||
109 | |||
110 | #endif /* OCFS2_FILE_H */ | 105 | #endif /* OCFS2_FILE_H */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 51632c40e896..1673438789fe 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2061,13 +2061,6 @@ out: | |||
2061 | return ret; | 2061 | return ret; |
2062 | } | 2062 | } |
2063 | 2063 | ||
2064 | static void ocfs2_aiodio_wait(struct inode *inode) | ||
2065 | { | ||
2066 | wait_queue_head_t *wq = ocfs2_ioend_wq(inode); | ||
2067 | |||
2068 | wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0)); | ||
2069 | } | ||
2070 | |||
2071 | static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos) | 2064 | static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos) |
2072 | { | 2065 | { |
2073 | int blockmask = inode->i_sb->s_blocksize - 1; | 2066 | int blockmask = inode->i_sb->s_blocksize - 1; |
@@ -2345,10 +2338,8 @@ relock: | |||
2345 | * Wait on previous unaligned aio to complete before | 2338 | * Wait on previous unaligned aio to complete before |
2346 | * proceeding. | 2339 | * proceeding. |
2347 | */ | 2340 | */ |
2348 | ocfs2_aiodio_wait(inode); | 2341 | mutex_lock(&OCFS2_I(inode)->ip_unaligned_aio); |
2349 | 2342 | /* Mark the iocb as needing an unlock in ocfs2_dio_end_io */ | |
2350 | /* Mark the iocb as needing a decrement in ocfs2_dio_end_io */ | ||
2351 | atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio); | ||
2352 | ocfs2_iocb_set_unaligned_aio(iocb); | 2343 | ocfs2_iocb_set_unaligned_aio(iocb); |
2353 | } | 2344 | } |
2354 | 2345 | ||
@@ -2428,7 +2419,7 @@ out_dio: | |||
2428 | 2419 | ||
2429 | if (unaligned_dio) { | 2420 | if (unaligned_dio) { |
2430 | ocfs2_iocb_clear_unaligned_aio(iocb); | 2421 | ocfs2_iocb_clear_unaligned_aio(iocb); |
2431 | atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio); | 2422 | mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio); |
2432 | } | 2423 | } |
2433 | 2424 | ||
2434 | out: | 2425 | out: |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 621fc73bf23d..9f1580b506a5 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
@@ -44,7 +44,7 @@ struct ocfs2_inode_info | |||
44 | struct rw_semaphore ip_xattr_sem; | 44 | struct rw_semaphore ip_xattr_sem; |
45 | 45 | ||
46 | /* Number of outstanding AIO's which are not page aligned */ | 46 | /* Number of outstanding AIO's which are not page aligned */ |
47 | atomic_t ip_unaligned_aio; | 47 | struct mutex ip_unaligned_aio; |
48 | 48 | ||
49 | /* These fields are protected by ip_lock */ | 49 | /* These fields are protected by ip_lock */ |
50 | spinlock_t ip_lock; | 50 | spinlock_t ip_lock; |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 49d84f80f36c..d17145552097 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1612,14 +1612,9 @@ static int ocfs2_show_options(struct seq_file *s, struct dentry *root) | |||
1612 | return 0; | 1612 | return 0; |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ]; | ||
1616 | |||
1617 | static int __init ocfs2_init(void) | 1615 | static int __init ocfs2_init(void) |
1618 | { | 1616 | { |
1619 | int status, i; | 1617 | int status; |
1620 | |||
1621 | for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++) | ||
1622 | init_waitqueue_head(&ocfs2__ioend_wq[i]); | ||
1623 | 1618 | ||
1624 | status = init_ocfs2_uptodate_cache(); | 1619 | status = init_ocfs2_uptodate_cache(); |
1625 | if (status < 0) | 1620 | if (status < 0) |
@@ -1761,7 +1756,7 @@ static void ocfs2_inode_init_once(void *data) | |||
1761 | ocfs2_extent_map_init(&oi->vfs_inode); | 1756 | ocfs2_extent_map_init(&oi->vfs_inode); |
1762 | INIT_LIST_HEAD(&oi->ip_io_markers); | 1757 | INIT_LIST_HEAD(&oi->ip_io_markers); |
1763 | oi->ip_dir_start_lookup = 0; | 1758 | oi->ip_dir_start_lookup = 0; |
1764 | atomic_set(&oi->ip_unaligned_aio, 0); | 1759 | mutex_init(&oi->ip_unaligned_aio); |
1765 | init_rwsem(&oi->ip_alloc_sem); | 1760 | init_rwsem(&oi->ip_alloc_sem); |
1766 | init_rwsem(&oi->ip_xattr_sem); | 1761 | init_rwsem(&oi->ip_xattr_sem); |
1767 | mutex_init(&oi->ip_io_mutex); | 1762 | mutex_init(&oi->ip_io_mutex); |