From 8630059e6ac363bea39e54df3f8115da5a5c2c5d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 14 Jan 2019 00:48:54 -0500 Subject: [PATCH] Update bcachefs sources to bcca1c557b bcachefs: fixes for getting stuck flushing journal pins --- .bcachefs_revision | 2 +- libbcachefs/fs-io.c | 15 ++++++------ libbcachefs/journal_reclaim.c | 43 ++++++++++++++++------------------- linux/sched.c | 2 +- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index 3bcc585a..088f645c 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -ef60854e9912d24c0ba83e0760552c98257d2b07 +bcca1c557b1897ecc3aeb1f89ab91865487d91ab diff --git a/libbcachefs/fs-io.c b/libbcachefs/fs-io.c index fdc24be1..c1739f53 100644 --- a/libbcachefs/fs-io.c +++ b/libbcachefs/fs-io.c @@ -56,7 +56,7 @@ struct bch_writepage_io { struct dio_write { struct closure cl; struct kiocb *req; - struct task_struct *task; + struct mm_struct *mm; unsigned loop:1, sync:1, free_iov:1; @@ -1753,6 +1753,7 @@ static void bch2_dio_write_loop_async(struct closure *); static long bch2_dio_write_loop(struct dio_write *dio) { + bool kthread = (current->flags & PF_KTHREAD) != 0; struct kiocb *req = dio->req; struct address_space *mapping = req->ki_filp->f_mapping; struct bch_inode_info *inode = dio->iop.inode; @@ -1777,13 +1778,13 @@ static long bch2_dio_write_loop(struct dio_write *dio) while (1) { BUG_ON(current->pagecache_lock); current->pagecache_lock = &mapping->add_lock; - if (current != dio->task) - use_mm(dio->task->mm); + if (kthread) + use_mm(dio->mm); ret = bio_iov_iter_get_pages(bio, &dio->iter); - if (current != dio->task) - unuse_mm(dio->task->mm); + if (kthread) + unuse_mm(dio->mm); current->pagecache_lock = NULL; if (unlikely(ret < 0)) @@ -1894,7 +1895,7 @@ static int bch2_direct_IO_write(struct kiocb *req, dio = container_of(bio, struct dio_write, iop.op.wbio.bio); closure_init(&dio->cl, NULL); dio->req = req; - dio->task = current; + dio->mm = current->mm; dio->loop = false; dio->sync = is_sync_kiocb(req) || offset + iter->count > inode->v.i_size; @@ -1902,7 +1903,7 @@ static int bch2_direct_IO_write(struct kiocb *req, dio->quota_res.sectors = 0; dio->iter = *iter; bch2_fswrite_op_init(&dio->iop, c, inode, io_opts(c, inode), true); - dio->iop.op.write_point = writepoint_hashed((unsigned long) dio->task); + dio->iop.op.write_point = writepoint_hashed((unsigned long) current); dio->iop.op.flags |= BCH_WRITE_NOPUT_RESERVATION; if ((req->ki_flags & IOCB_DSYNC) && diff --git a/libbcachefs/journal_reclaim.c b/libbcachefs/journal_reclaim.c index d8d1b6b0..4a997366 100644 --- a/libbcachefs/journal_reclaim.c +++ b/libbcachefs/journal_reclaim.c @@ -64,6 +64,9 @@ static inline void __journal_pin_drop(struct journal *j, if (atomic_dec_and_test(&pin_list->count) && pin_list == &fifo_peek_front(&j->pin)) bch2_journal_reclaim_fast(j); + else if (fifo_used(&j->pin) == 1 && + atomic_read(&pin_list->count) == 1) + journal_wake(j); } void bch2_journal_pin_drop(struct journal *j, @@ -336,56 +339,48 @@ void bch2_journal_reclaim_work(struct work_struct *work) msecs_to_jiffies(j->reclaim_delay_ms)); } -static int journal_flush_done(struct journal *j, u64 seq_to_flush, - struct journal_entry_pin **pin, - u64 *pin_seq) +static int journal_flush_done(struct journal *j, u64 seq_to_flush) { + struct journal_entry_pin *pin; + u64 pin_seq; int ret; - *pin = NULL; - ret = bch2_journal_error(j); if (ret) return ret; + mutex_lock(&j->reclaim_lock); spin_lock(&j->lock); + + while ((pin = journal_get_next_pin(j, seq_to_flush, &pin_seq))) { + journal_pin_mark_flushing(j, pin, pin_seq); + spin_unlock(&j->lock); + + journal_pin_flush(j, pin, pin_seq); + + spin_lock(&j->lock); + } /* * If journal replay hasn't completed, the unreplayed journal entries * hold refs on their corresponding sequence numbers */ - ret = (*pin = journal_get_next_pin(j, seq_to_flush, pin_seq)) != NULL || - !test_bit(JOURNAL_REPLAY_DONE, &j->flags) || + ret = !test_bit(JOURNAL_REPLAY_DONE, &j->flags) || journal_last_seq(j) > seq_to_flush || (fifo_used(&j->pin) == 1 && atomic_read(&fifo_peek_front(&j->pin).count) == 1); - if (*pin) - journal_pin_mark_flushing(j, *pin, *pin_seq); spin_unlock(&j->lock); + mutex_unlock(&j->reclaim_lock); return ret; } void bch2_journal_flush_pins(struct journal *j, u64 seq_to_flush) { - struct journal_entry_pin *pin; - u64 pin_seq; - if (!test_bit(JOURNAL_STARTED, &j->flags)) return; - mutex_lock(&j->reclaim_lock); - - while (1) { - wait_event(j->wait, journal_flush_done(j, seq_to_flush, - &pin, &pin_seq)); - if (!pin) - break; - - journal_pin_flush(j, pin, pin_seq); - } - - mutex_unlock(&j->reclaim_lock); + closure_wait_event(&j->async_wait, journal_flush_done(j, seq_to_flush)); } int bch2_journal_flush_device_pins(struct journal *j, int dev_idx) diff --git a/linux/sched.c b/linux/sched.c index b3fc7739..353c11db 100644 --- a/linux/sched.c +++ b/linux/sched.c @@ -37,7 +37,7 @@ void schedule(void) rcu_quiescent_state(); - while ((v = current->state) != TASK_RUNNING) + while ((v = READ_ONCE(current->state)) != TASK_RUNNING) futex(¤t->state, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, v, NULL, NULL, 0); }