From 9d8022db1ccfff6aaf1de6158c2a26b667c70a15 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 6 Apr 2021 14:00:56 -0400 Subject: [PATCH] bcachefs: Eliminate more PAGE_SIZE uses In userspace, we don't really have a well defined PAGE_SIZE and shouln't be relying on it. This is some more incremental work to remove references to it. Signed-off-by: Kent Overstreet Signed-off-by: Kent Overstreet --- fs/bcachefs/debug.c | 4 ++-- fs/bcachefs/super-io.c | 31 +++++++++++++++---------------- fs/bcachefs/super.c | 3 +-- fs/bcachefs/super_types.h | 2 +- fs/bcachefs/util.c | 2 +- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 111310344cec..eb8c57d253fb 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -150,7 +150,7 @@ struct dump_iter { struct bch_fs *c; enum btree_id id; - char buf[PAGE_SIZE]; + char buf[1 << 12]; size_t bytes; /* what's currently in buf */ char __user *ubuf; /* destination user buffer */ @@ -230,7 +230,7 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf, while (k.k && !(err = bkey_err(k))) { bch2_bkey_val_to_text(&PBUF(i->buf), i->c, k); i->bytes = strlen(i->buf); - BUG_ON(i->bytes >= PAGE_SIZE); + BUG_ON(i->bytes >= sizeof(i->buf)); i->buf[i->bytes] = '\n'; i->bytes++; diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index e397a2a70c9c..bf36a5743607 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -53,8 +53,7 @@ static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb_handle *sb, unsigned old_u64s = f ? le32_to_cpu(f->u64s) : 0; unsigned sb_u64s = le32_to_cpu(sb->sb->u64s) + u64s - old_u64s; - BUG_ON(get_order(__vstruct_bytes(struct bch_sb, sb_u64s)) > - sb->page_order); + BUG_ON(__vstruct_bytes(struct bch_sb, sb_u64s) > sb->buffer_size); if (!f && !u64s) { /* nothing to do: */ @@ -105,18 +104,23 @@ void bch2_free_super(struct bch_sb_handle *sb) blkdev_put(sb->bdev, sb->holder); kfree(sb->holder); - free_pages((unsigned long) sb->sb, sb->page_order); + kfree(sb->sb); memset(sb, 0, sizeof(*sb)); } int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) { size_t new_bytes = __vstruct_bytes(struct bch_sb, u64s); - unsigned order = get_order(new_bytes); + size_t new_buffer_size; struct bch_sb *new_sb; struct bio *bio; - if (sb->sb && sb->page_order >= order) + if (sb->bdev) + new_bytes = max_t(size_t, new_bytes, bdev_logical_block_size(sb->bdev)); + + new_buffer_size = roundup_pow_of_two(new_bytes); + + if (sb->sb && sb->buffer_size >= new_buffer_size) return 0; if (sb->have_layout) { @@ -129,14 +133,14 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) } } - if (sb->page_order >= order && sb->sb) + if (sb->buffer_size >= new_buffer_size && sb->sb) return 0; if (dynamic_fault("bcachefs:add:super_realloc")) return -ENOMEM; if (sb->have_bio) { - unsigned nr_bvecs = 1 << order; + unsigned nr_bvecs = DIV_ROUND_UP(new_buffer_size, PAGE_SIZE); bio = bio_kmalloc(nr_bvecs, GFP_KERNEL); if (!bio) @@ -149,17 +153,12 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s) sb->bio = bio; } - new_sb = (void *) __get_free_pages(GFP_NOFS|__GFP_ZERO, order); + new_sb = krealloc(sb->sb, new_buffer_size, GFP_NOFS|__GFP_ZERO); if (!new_sb) return -ENOMEM; - if (sb->sb) - memcpy(new_sb, sb->sb, PAGE_SIZE << sb->page_order); - - free_pages((unsigned long) sb->sb, sb->page_order); sb->sb = new_sb; - - sb->page_order = order; + sb->buffer_size = new_buffer_size; return 0; } @@ -480,7 +479,7 @@ static const char *read_one_super(struct bch_sb_handle *sb, u64 offset) reread: bio_reset(sb->bio, sb->bdev, REQ_OP_READ|REQ_SYNC|REQ_META); sb->bio->bi_iter.bi_sector = offset; - bch2_bio_map(sb->bio, sb->sb, PAGE_SIZE << sb->page_order); + bch2_bio_map(sb->bio, sb->sb, sb->buffer_size); if (submit_bio_wait(sb->bio)) return "IO error"; @@ -498,7 +497,7 @@ reread: if (bytes > 512 << sb->sb->layout.sb_max_size_bits) return "Bad superblock: too big"; - if (get_order(bytes) > sb->page_order) { + if (bytes > sb->buffer_size) { if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s))) return "cannot allocate memory"; goto reread; diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 529d33f4a6d7..385b41f16754 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -509,8 +509,7 @@ static void __bch2_fs_free(struct bch_fs *c) if (c->wq) destroy_workqueue(c->wq); - free_pages((unsigned long) c->disk_sb.sb, - c->disk_sb.page_order); + bch2_free_super(&c->disk_sb); kvpfree(c, sizeof(*c)); module_put(THIS_MODULE); } diff --git a/fs/bcachefs/super_types.h b/fs/bcachefs/super_types.h index e3a989e3e9d9..b14b2d82c655 100644 --- a/fs/bcachefs/super_types.h +++ b/fs/bcachefs/super_types.h @@ -7,7 +7,7 @@ struct bch_sb_handle { struct block_device *bdev; struct bio *bio; void *holder; - unsigned page_order; + size_t buffer_size; fmode_t mode; unsigned have_layout:1; unsigned have_bio:1; diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index 6e665f7f25a3..f183c9d80e2c 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -154,7 +154,7 @@ void bch2_flags_to_text(struct printbuf *out, u64 bch2_read_flag_list(char *opt, const char * const list[]) { u64 ret = 0; - char *p, *s, *d = kstrndup(opt, PAGE_SIZE - 1, GFP_KERNEL); + char *p, *s, *d = kstrdup(opt, GFP_KERNEL); if (!d) return -ENOMEM;