Commit 7be9ab63 authored by Chris Webb's avatar Chris Webb Committed by Kent Overstreet

bcachefs: Return -ENOKEY/EINVAL when mount decryption fails

bch2_fs_encryption_init() correctly passes back -ENOKEY from request_key()
when no unlock key is found, or -EINVAL if superblock decryption fails
because of an invalid key. However, these get absorbed into a generic NULL
return from bch2_fs_alloc() and later returned to user space as -ENOMEM,
leading to a misleading error from mount(1):

  mount(2) system call failed: Out of memory.

Return explicit error pointers out of bch2_fs_alloc() and handle them in
both callers, so the user instead sees

  mount(2) system call failed: Required key not available.

when attempting to mount a filesystem which is still locked.
Signed-off-by: default avatarChris Webb <chris@arachsys.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 076c783c
...@@ -646,12 +646,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -646,12 +646,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
struct bch_fs *c; struct bch_fs *c;
unsigned i, iter_size; unsigned i, iter_size;
const char *err; const char *err;
int ret = 0;
pr_verbose_init(opts, ""); pr_verbose_init(opts, "");
c = kvpmalloc(sizeof(struct bch_fs), GFP_KERNEL|__GFP_ZERO); c = kvpmalloc(sizeof(struct bch_fs), GFP_KERNEL|__GFP_ZERO);
if (!c) if (!c) {
c = ERR_PTR(-ENOMEM);
goto out; goto out;
}
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
...@@ -732,13 +735,16 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -732,13 +735,16 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
mutex_init(&c->sectors_available_lock); mutex_init(&c->sectors_available_lock);
if (percpu_init_rwsem(&c->mark_lock)) if (percpu_init_rwsem(&c->mark_lock)) {
ret = -ENOMEM;
goto err; goto err;
}
mutex_lock(&c->sb_lock); mutex_lock(&c->sb_lock);
if (bch2_sb_to_fs(c, sb)) { if (bch2_sb_to_fs(c, sb)) {
mutex_unlock(&c->sb_lock); mutex_unlock(&c->sb_lock);
ret = -ENOMEM;
goto err; goto err;
} }
...@@ -753,8 +759,10 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -753,8 +759,10 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
c->block_bits = ilog2(c->opts.block_size); c->block_bits = ilog2(c->opts.block_size);
c->btree_foreground_merge_threshold = BTREE_FOREGROUND_MERGE_THRESHOLD(c); c->btree_foreground_merge_threshold = BTREE_FOREGROUND_MERGE_THRESHOLD(c);
if (bch2_fs_init_fault("fs_alloc")) if (bch2_fs_init_fault("fs_alloc")) {
ret = -ENOMEM;
goto err; goto err;
}
iter_size = sizeof(struct sort_iter) + iter_size = sizeof(struct sort_iter) +
(btree_blocks(c) + 1) * 2 * (btree_blocks(c) + 1) * 2 *
...@@ -795,10 +803,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -795,10 +803,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_fs_btree_interior_update_init(c) || bch2_fs_btree_interior_update_init(c) ||
bch2_fs_subvolumes_init(c) || bch2_fs_subvolumes_init(c) ||
bch2_fs_io_init(c) || bch2_fs_io_init(c) ||
bch2_fs_encryption_init(c) ||
bch2_fs_compress_init(c) || bch2_fs_compress_init(c) ||
bch2_fs_ec_init(c) || bch2_fs_ec_init(c) ||
bch2_fs_fsio_init(c)) bch2_fs_fsio_init(c)) {
ret = -ENOMEM;
goto err;
}
ret = bch2_fs_encryption_init(c);
if (ret)
goto err; goto err;
if (c->opts.nochanges) if (c->opts.nochanges)
...@@ -807,8 +820,10 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -807,8 +820,10 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
mi = bch2_sb_get_members(c->disk_sb.sb); mi = bch2_sb_get_members(c->disk_sb.sb);
for (i = 0; i < c->sb.nr_devices; i++) for (i = 0; i < c->sb.nr_devices; i++)
if (bch2_dev_exists(c->disk_sb.sb, mi, i) && if (bch2_dev_exists(c->disk_sb.sb, mi, i) &&
bch2_dev_alloc(c, i)) bch2_dev_alloc(c, i)) {
ret = -ENOMEM;
goto err; goto err;
}
bch2_journal_entry_res_resize(&c->journal, bch2_journal_entry_res_resize(&c->journal,
&c->btree_root_journal_res, &c->btree_root_journal_res,
...@@ -823,14 +838,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -823,14 +838,15 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
mutex_unlock(&bch_fs_list_lock); mutex_unlock(&bch_fs_list_lock);
if (err) { if (err) {
bch_err(c, "bch2_fs_online() error: %s", err); bch_err(c, "bch2_fs_online() error: %s", err);
ret = -ENOMEM;
goto err; goto err;
} }
out: out:
pr_verbose_init(opts, "ret %i", c ? 0 : -ENOMEM); pr_verbose_init(opts, "ret %i", PTR_ERR_OR_ZERO(c));
return c; return c;
err: err:
bch2_fs_free(c); bch2_fs_free(c);
c = NULL; c = ERR_PTR(ret);
goto out; goto out;
} }
...@@ -1943,10 +1959,11 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, ...@@ -1943,10 +1959,11 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices,
i++; i++;
} }
ret = -ENOMEM;
c = bch2_fs_alloc(sb[best_sb].sb, opts); c = bch2_fs_alloc(sb[best_sb].sb, opts);
if (!c) if (IS_ERR(c)) {
ret = PTR_ERR(c);
goto err; goto err;
}
err = "bch2_dev_online() error"; err = "bch2_dev_online() error";
down_write(&c->state_lock); down_write(&c->state_lock);
...@@ -1977,7 +1994,7 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, ...@@ -1977,7 +1994,7 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices,
devices[0], err); devices[0], err);
ret = -EINVAL; ret = -EINVAL;
err: err:
if (c) if (!IS_ERR_OR_NULL(c))
bch2_fs_stop(c); bch2_fs_stop(c);
for (i = 0; i < nr_devices; i++) for (i = 0; i < nr_devices; i++)
bch2_free_super(&sb[i]); bch2_free_super(&sb[i]);
...@@ -2006,12 +2023,12 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, ...@@ -2006,12 +2023,12 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb,
if (err) if (err)
goto err; goto err;
} else { } else {
allocated_fs = true;
c = bch2_fs_alloc(sb->sb, opts); c = bch2_fs_alloc(sb->sb, opts);
err = "cannot allocate memory";
if (!c)
goto err;
allocated_fs = true; err = "bch2_fs_alloc() error";
if (IS_ERR(c))
goto err;
} }
err = "bch2_dev_online() error"; err = "bch2_dev_online() error";
...@@ -2037,7 +2054,7 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, ...@@ -2037,7 +2054,7 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb,
err: err:
mutex_unlock(&bch_fs_list_lock); mutex_unlock(&bch_fs_list_lock);
if (allocated_fs) if (allocated_fs && !IS_ERR(c))
bch2_fs_stop(c); bch2_fs_stop(c);
else if (c) else if (c)
closure_put(&c->cl); closure_put(&c->cl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment