diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-01-07 19:02:15 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-01-10 03:04:44 -0500 |
commit | 3adb323966f54f9e371ec1c59c84b239b42bdc6c (patch) | |
tree | de2d88e22f6a4dc7def3a51afc75549b023d703e | |
parent | 6431e47fd52828ed94cfbf0ebed3a0a9f99326d9 (diff) |
bcachefs: fix mounting read only block devices
-rw-r--r-- | fs/bcachefs/opts.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/super-io.c | 22 | ||||
-rw-r--r-- | fs/bcachefs/super-io.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 10 |
4 files changed, 24 insertions, 12 deletions
diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 126056e60543..bc8fd46aeb23 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -171,7 +171,7 @@ static const struct bch_opts bch2_opts_default = { #define opt_defined(_opts, _name) ((_opts)._name##_defined) #define opt_get(_opts, _name) \ - (opt_defined(_opts, _name) ? _opts._name : bch2_opts_default._name) + (opt_defined(_opts, _name) ? (_opts)._name : bch2_opts_default._name) #define opt_set(_opts, _name, _v) \ do { \ diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index e49437c276ac..6c7f4166d3dd 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -531,10 +531,10 @@ reread: return NULL; } -int bch2_read_super(const char *path, struct bch_opts opts, +int bch2_read_super(const char *path, struct bch_opts *opts, struct bch_sb_handle *sb) { - u64 offset = opt_get(opts, sb); + u64 offset = opt_get(*opts, sb); struct bch_sb_layout layout; const char *err; __le64 *i; @@ -543,13 +543,23 @@ int bch2_read_super(const char *path, struct bch_opts opts, memset(sb, 0, sizeof(*sb)); sb->mode = FMODE_READ; - if (!opt_get(opts, noexcl)) + if (!opt_get(*opts, noexcl)) sb->mode |= FMODE_EXCL; - if (!opt_get(opts, nochanges)) + if (!opt_get(*opts, nochanges)) sb->mode |= FMODE_WRITE; sb->bdev = blkdev_get_by_path(path, sb->mode, sb); + if (IS_ERR(sb->bdev) && + PTR_ERR(sb->bdev) == -EACCES && + opt_get(*opts, read_only)) { + sb->mode &= ~FMODE_WRITE; + + sb->bdev = blkdev_get_by_path(path, sb->mode, sb); + if (!IS_ERR(sb->bdev)) + opt_set(*opts, nochanges, true); + } + if (IS_ERR(sb->bdev)) return PTR_ERR(sb->bdev); @@ -568,7 +578,7 @@ int bch2_read_super(const char *path, struct bch_opts opts, if (!err) goto got_super; - if (opt_defined(opts, sb)) + if (opt_defined(*opts, sb)) goto err; pr_err("error reading default superblock: %s", err); @@ -601,7 +611,7 @@ int bch2_read_super(const char *path, struct bch_opts opts, i < layout.sb_offset + layout.nr_superblocks; i++) { offset = le64_to_cpu(*i); - if (offset == opt_get(opts, sb)) + if (offset == opt_get(*opts, sb)) continue; err = read_one_super(sb, offset); diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h index 32ac0e875fa0..69366a6f9581 100644 --- a/fs/bcachefs/super-io.h +++ b/fs/bcachefs/super-io.h @@ -94,7 +94,7 @@ int bch2_super_realloc(struct bch_sb_handle *, unsigned); const char *bch2_sb_validate(struct bch_sb_handle *); -int bch2_read_super(const char *, struct bch_opts, struct bch_sb_handle *); +int bch2_read_super(const char *, struct bch_opts *, struct bch_sb_handle *); void bch2_write_super(struct bch_fs *); /* BCH_SB_FIELD_journal: */ diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 6f541ddd6aa0..4cc4301ceae7 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1432,6 +1432,7 @@ err: /* Add new device to running filesystem: */ int bch2_dev_add(struct bch_fs *c, const char *path) { + struct bch_opts opts = bch2_opts_empty(); struct bch_sb_handle sb; const char *err; struct bch_dev *ca = NULL; @@ -1440,7 +1441,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path) unsigned dev_idx, nr_devices, u64s; int ret; - ret = bch2_read_super(path, bch2_opts_empty(), &sb); + ret = bch2_read_super(path, &opts, &sb); if (ret) return ret; @@ -1542,6 +1543,7 @@ err: /* Hot add existing device to running filesystem: */ int bch2_dev_online(struct bch_fs *c, const char *path) { + struct bch_opts opts = bch2_opts_empty(); struct bch_sb_handle sb = { NULL }; struct bch_dev *ca; unsigned dev_idx; @@ -1550,7 +1552,7 @@ int bch2_dev_online(struct bch_fs *c, const char *path) mutex_lock(&c->state_lock); - ret = bch2_read_super(path, bch2_opts_empty(), &sb); + ret = bch2_read_super(path, &opts, &sb); if (ret) { mutex_unlock(&c->state_lock); return ret; @@ -1708,7 +1710,7 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, goto err; for (i = 0; i < nr_devices; i++) { - ret = bch2_read_super(devices[i], opts, &sb[i]); + ret = bch2_read_super(devices[i], &opts, &sb[i]); if (ret) goto err; @@ -1842,7 +1844,7 @@ const char *bch2_fs_open_incremental(const char *path) struct bch_opts opts = bch2_opts_empty(); const char *err; - if (bch2_read_super(path, opts, &sb)) + if (bch2_read_super(path, &opts, &sb)) return "error reading superblock"; err = __bch2_fs_open_incremental(&sb, opts); |