<div></div><div style="color:#000; font-size: 14px;font-family: arial;"><div><br></div><div>Sorry, I have a mistake.</div><div>the function complete will record the flag to indicate it have been executed.</div><div><br></div><div>So the walking path of sync io is corrent to use function <span style="line-height: 1.7;">wait_for_completion_io.</span></div><div><span style="line-height: 1.7;">Athrough sync io may be finished,  the thread do not be hanged.</span></div><div><br></div><div>Apologize for my mistake.</div><div><br></div></div><blockquote id="isReplyContent" style="padding-left:1ex; margin: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid"><br> There's a race condition between the atomic_dec_and_test(&io->count)<br>in dec_count() and the waking of the sync_io() thread.  If the thread<br>is spuriously woken immediately after the decrement it may exit,<br>making the on the stack io struct invalid, yet the dec_count could<br>still be using it.<br><br>There are smaller fixes than the one here (eg, just take the io object<br>off the stack).  But I feel this code could use a clean up.<br><br>- simplify dec_count().<br><br>  - It always calls a callback fn now.<br>  - It always frees the io object back to the pool.<br><br>- sync_io()<br><br>  - Take the io object off the stack and allocate it from the pool the<br>    same as async_io.<br>  - Use a completion object rather than an explicit io_schedule()<br>    loop.  The callback triggers the completion.<br><br>Signed-off-by: Minfei Huang <<a href="mailto:huangminfei@ucloud.cn">huangminfei@ucloud.cn</a>><br>---<br> drivers/md/dm-io.c |   22 +++++++++-------------<br> 1 files changed, 9 insertions(+), 13 deletions(-)<br><br>diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c<br>index 3842ac7..05583da 100644<br>--- a/drivers/md/dm-io.c<br>+++ b/drivers/md/dm-io.c<br>@@ -10,6 +10,7 @@<br> #include <linux/device-mapper.h><br> <br> #include <linux/bio.h><br>+#include <linux/completion.h><br> #include <linux/mempool.h><br> #include <linux/module.h><br> #include <linux/sched.h><br>@@ -32,7 +33,7 @@ struct dm_io_client {<br> struct io {<br>     unsigned long error_bits;<br>     atomic_t count;<br>-    struct task_struct *sleeper;<br>+    struct completion *wait;<br>     struct dm_io_client *client;<br>     io_notify_fn callback;<br>     void *context;<br>@@ -121,8 +122,8 @@ static void dec_count(struct io *io, unsigned int region, int error)<br>             invalidate_kernel_vmap_range(io->vma_invalidate_address,<br>                              io->vma_invalidate_size);<br> <br>-        if (io->sleeper)<br>-            wake_up_process(io->sleeper);<br>+        if (io->wait)<br>+            complete(io->wait);<br> <br>         else {<br>             unsigned long r = io->error_bits;<br>@@ -387,6 +388,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,<br>      */<br>     volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1];<br>     struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io));<br>+    DECLARE_COMPLETION_ONSTACK(wait);<br> <br>     if (num_regions > 1 && (rw & RW_MASK) != WRITE) {<br>         WARN_ON(1);<br>@@ -395,7 +397,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,<br> <br>     io->error_bits = 0;<br>     atomic_set(&io->count, 1); /* see dispatch_io() */<br>-    io->sleeper = current;<br>+    io->wait = &wait;<br>     io->client = client;<br> <br>     io->vma_invalidate_address = dp->vma_invalidate_address;<br>@@ -403,15 +405,9 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,<br> <br>     dispatch_io(rw, num_regions, where, dp, io, 1);<br> <br>-    while (1) {<br>-        set_current_state(TASK_UNINTERRUPTIBLE);<br>-<br>-        if (!atomic_read(&io->count))<br>-            break;<br>-<br>-        io_schedule();<br>+    while (atomic_read(&io->count) != 0) {<br>+        wait_for_completion_io_timeout(&wait, 5);<br>     }<br>-    set_current_state(TASK_RUNNING);<br> <br>     if (error_bits)<br>         *error_bits = io->error_bits;<br>@@ -434,7 +430,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,<br>     io = mempool_alloc(client->pool, GFP_NOIO);<br>     io->error_bits = 0;<br>     atomic_set(&io->count, 1); /* see dispatch_io() */<br>-    io->sleeper = NULL;<br>+    io->wait = NULL;<br>     io->client = client;<br>     io->callback = fn;<br>     io->context = context;<br>-- <br>1.7.1<br><br></blockquote>