diff --git a/.bcachefs_revision b/.bcachefs_revision index 80991d76..20572444 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -b6d54265513ceb7532e3983163338c1ad28a0284 +ae6f512de8cdd129ce873e14eab84b8e0746daed diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c index ec6eb106..b0262499 100644 --- a/libbcachefs/btree_gc.c +++ b/libbcachefs/btree_gc.c @@ -436,7 +436,7 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id, p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), bch2_data_types[ptr_data_type(k->k, &p.ptr)], p.ptr.gen)) { - if (p.ptr.cached) { + if (!p.ptr.cached) { g2->_mark.gen = g->_mark.gen = p.ptr.gen; g2->gen_valid = g->gen_valid = true; set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags); @@ -450,7 +450,7 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id, p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), bch2_data_types[ptr_data_type(k->k, &p.ptr)], p.ptr.gen, g->mark.gen)) { - if (p.ptr.cached) { + if (!p.ptr.cached) { g2->_mark.gen = g->_mark.gen = p.ptr.gen; g2->gen_valid = g->gen_valid = true; g2->_mark.data_type = 0; diff --git a/libbcachefs/chardev.c b/libbcachefs/chardev.c index c6160147..c29f8272 100644 --- a/libbcachefs/chardev.c +++ b/libbcachefs/chardev.c @@ -414,7 +414,8 @@ static long bch2_ioctl_fs_usage(struct bch_fs *c, struct bch_replicas_entry *src_e = cpu_replicas_entry(&c->replicas, i); - if (replicas_usage_next(dst_e) > dst_end) { + /* check that we have enough space for one replicas entry */ + if (dst_e + 1 > dst_end) { ret = -ERANGE; break; } @@ -523,7 +524,7 @@ static long bch2_ioctl_read_super(struct bch_fs *c, ret = copy_to_user((void __user *)(unsigned long)arg.sb, sb, vstruct_bytes(sb)); err: - if (ca) + if (!IS_ERR_OR_NULL(ca)) percpu_ref_put(&ca->ref); mutex_unlock(&c->sb_lock); return ret; diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c index b1bbec3f..4c6568e0 100644 --- a/libbcachefs/fs.c +++ b/libbcachefs/fs.c @@ -30,6 +30,7 @@ #include #include #include +#include #include static struct kmem_cache *bch2_inode_cache; @@ -1311,6 +1312,9 @@ static char **split_devs(const char *_dev_name, unsigned *nr) char *dev_name = NULL, **devs = NULL, *s; size_t i, nr_devs = 0; + if (strlen(_dev_name) == 0) + return NULL; + dev_name = kstrdup(_dev_name, GFP_KERNEL); if (!dev_name) return NULL; diff --git a/libbcachefs/fsck.c b/libbcachefs/fsck.c index 338d50be..d2697864 100644 --- a/libbcachefs/fsck.c +++ b/libbcachefs/fsck.c @@ -512,7 +512,9 @@ static int check_inodes(struct bch_fs *c, bool full) bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); - for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, 0, k, ret) { + for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH, k, ret) { if (k.k->type != KEY_TYPE_inode) continue; @@ -621,7 +623,8 @@ static int check_extents(struct bch_fs *c) iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS(BCACHEFS_ROOT_INO, 0), - BTREE_ITER_INTENT); + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH); retry: while ((k = bch2_btree_iter_peek(iter)).k && !(ret = bkey_err(k))) { @@ -719,7 +722,9 @@ static int check_dirents(struct bch_fs *c) bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); iter = bch2_trans_get_iter(&trans, BTREE_ID_dirents, - POS(BCACHEFS_ROOT_INO, 0), 0); + POS(BCACHEFS_ROOT_INO, 0), + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH); retry: while ((k = bch2_btree_iter_peek(iter)).k && !(ret = bkey_err(k))) { @@ -920,7 +925,9 @@ static int check_xattrs(struct bch_fs *c) bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); iter = bch2_trans_get_iter(&trans, BTREE_ID_xattrs, - POS(BCACHEFS_ROOT_INO, 0), 0); + POS(BCACHEFS_ROOT_INO, 0), + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH); retry: while ((k = bch2_btree_iter_peek(iter)).k && !(ret = bkey_err(k))) { @@ -1108,7 +1115,9 @@ static int check_directory_structure(struct bch_fs *c) bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); - for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, 0, k, ret) { + for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN, + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH, k, ret) { if (k.k->type != KEY_TYPE_inode) continue; @@ -1207,7 +1216,9 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c, bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); for_each_btree_key(&trans, iter, BTREE_ID_inodes, - POS(0, start), 0, k, ret) { + POS(0, start), + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH, k, ret) { if (k.k->type != KEY_TYPE_inode) continue; @@ -1255,7 +1266,9 @@ static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); - for_each_btree_key(&trans, iter, BTREE_ID_dirents, POS_MIN, 0, k, ret) { + for_each_btree_key(&trans, iter, BTREE_ID_dirents, POS_MIN, + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH, k, ret) { switch (k.k->type) { case KEY_TYPE_dirent: d = bkey_s_c_to_dirent(k); @@ -1293,7 +1306,9 @@ static int check_nlinks_update_hardlinks(struct bch_fs *c, bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); for_each_btree_key(&trans, iter, BTREE_ID_inodes, - POS(0, range_start), 0, k, ret) { + POS(0, range_start), + BTREE_ITER_INTENT| + BTREE_ITER_PREFETCH, k, ret) { if (k.k->p.offset >= range_end) break; diff --git a/libbcachefs/opts.c b/libbcachefs/opts.c index 0cfbb56a..64bf5a38 100644 --- a/libbcachefs/opts.c +++ b/libbcachefs/opts.c @@ -315,11 +315,20 @@ int bch2_opts_check_may_set(struct bch_fs *c) int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts, char *options) { + char *copied_opts, *copied_opts_start; char *opt, *name, *val; int ret, id; u64 v; - while ((opt = strsep(&options, ",")) != NULL) { + if (!options) + return 0; + + copied_opts = kstrdup(options, GFP_KERNEL); + if (!copied_opts) + return -1; + copied_opts_start = copied_opts; + + while ((opt = strsep(&copied_opts, ",")) != NULL) { name = strsep(&opt, "="); val = opt; @@ -363,16 +372,24 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts, bch2_opt_set_by_id(opts, id, v); } - return 0; + ret = 0; + goto out; + bad_opt: pr_err("Bad mount option %s", name); - return -1; + ret = -1; + goto out; bad_val: pr_err("Invalid value %s for mount option %s", val, name); - return -1; + ret = -1; + goto out; no_val: pr_err("Mount option %s requires a value", name); - return -1; + ret = -1; + goto out; +out: + kfree(copied_opts_start); + return ret; } /* io opts: */ diff --git a/libbcachefs/super.c b/libbcachefs/super.c index e5936041..3b1e9203 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -110,7 +110,7 @@ struct bch_fs *bch2_dev_to_fs(dev_t dev) list_for_each_entry(c, &bch_fs_list, list) for_each_member_device_rcu(ca, c, i, NULL) - if (ca->disk_sb.bdev->bd_dev == dev) { + if (ca->disk_sb.bdev && ca->disk_sb.bdev->bd_dev == dev) { closure_get(&c->cl); goto found; }