diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-07-20 13:00:15 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-03-12 20:11:43 -0500 |
commit | 1808e4055e4abdf3ecccf7b7c009d0e2ba4ad186 (patch) | |
tree | 5927ccaf65d853d8265622a89fd1e93826818b5d | |
parent | ac76c4ceabcc3aaea63f3b246bc21b52113eddb2 (diff) |
bcachefs: Wrap write path in memalloc_nofs_save()
This fixes a lockdep splat where we're allocating memory with vmalloc in
the compression bounce path, which doesn't always obey GFP_NOFS.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/compress.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/io.c | 12 |
2 files changed, 10 insertions, 8 deletions
diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c index 9b3326063be6..d70976af4442 100644 --- a/fs/bcachefs/compress.c +++ b/fs/bcachefs/compress.c @@ -7,7 +7,6 @@ #include "super-io.h" #include <linux/lz4.h> -#include <linux/sched/mm.h> #include <linux/zlib.h> #include <linux/zstd.h> @@ -64,7 +63,7 @@ static struct bbuf __bio_map_or_bounce(struct bch_fs *c, struct bio *bio, struct bbuf ret; struct bio_vec bv; struct bvec_iter iter; - unsigned nr_pages = 0, flags; + unsigned nr_pages = 0; struct page *stack_pages[16]; struct page **pages = NULL; void *data; @@ -104,10 +103,7 @@ static struct bbuf __bio_map_or_bounce(struct bch_fs *c, struct bio *bio, __bio_for_each_segment(bv, bio, iter, start) pages[nr_pages++] = bv.bv_page; - flags = memalloc_nofs_save(); data = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); - memalloc_nofs_restore(flags); - if (pages != stack_pages) kfree(pages); diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index ae1e157c591b..bab018b81d09 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -31,6 +31,7 @@ #include <linux/blkdev.h> #include <linux/random.h> +#include <linux/sched/mm.h> #include <trace/events/bcachefs.h> @@ -1053,7 +1054,10 @@ static void __bch2_write(struct closure *cl) struct write_point *wp; struct bio *bio; bool skip_put = true; + unsigned nofs_flags; int ret; + + nofs_flags = memalloc_nofs_save(); again: memset(&op->failed, 0, sizeof(op->failed)); @@ -1135,13 +1139,15 @@ again: if (!skip_put) continue_at(cl, bch2_write_index, index_update_wq(op)); +out: + memalloc_nofs_restore(nofs_flags); return; err: op->error = ret; op->flags |= BCH_WRITE_DONE; continue_at(cl, bch2_write_index, index_update_wq(op)); - return; + goto out; flush_io: /* * If the write can't all be submitted at once, we generally want to @@ -1152,7 +1158,7 @@ flush_io: */ if (current->flags & PF_WQ_WORKER) { continue_at(cl, bch2_write_index, index_update_wq(op)); - return; + goto out; } closure_sync(cl); @@ -1163,7 +1169,7 @@ flush_io: if (op->error) { op->flags |= BCH_WRITE_DONE; continue_at_nobarrier(cl, bch2_write_done, NULL); - return; + goto out; } } |