diff options
-rw-r--r-- | drivers/md/bcache/bcache.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/chardev.c | 4 | ||||
-rw-r--r-- | drivers/md/bcache/fs.c | 121 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 35 | ||||
-rw-r--r-- | drivers/md/bcache/super.h | 9 | ||||
-rw-r--r-- | drivers/md/bcache/super_types.h | 10 |
6 files changed, 133 insertions, 48 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 3327dc490a5f..224858445b5e 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -414,6 +414,8 @@ struct cache_set { struct cache_member_rcu *members; unsigned long cache_slots_used[BITS_TO_LONGS(MAX_CACHES_PER_SET)]; + struct cache_set_opts opts; + struct cache_sb sb; unsigned short block_bits; /* ilog2(block_size) */ diff --git a/drivers/md/bcache/chardev.c b/drivers/md/bcache/chardev.c index cffba0dc937d..5c6b2e6aeb91 100644 --- a/drivers/md/bcache/chardev.c +++ b/drivers/md/bcache/chardev.c @@ -52,7 +52,9 @@ static long bch_ioctl_assemble(struct bch_ioctl_assemble __user *user_arg) } } - err = bch_register_cache_set(devs, arg.nr_devs, NULL); + err = bch_register_cache_set(devs, arg.nr_devs, + cache_set_opts_empty(), + NULL); if (err) { pr_err("Could not register cache set: %s", err); ret = -EINVAL; diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c index 502a983dcc3f..80884f3adc96 100644 --- a/drivers/md/bcache/fs.c +++ b/drivers/md/bcache/fs.c @@ -1843,23 +1843,8 @@ static int bch_sync_fs(struct super_block *sb, int wait) return 0; } -static const struct super_operations bch_super_operations = { - .alloc_inode = bch_alloc_inode, - .destroy_inode = bch_destroy_inode, - .write_inode = bch_write_inode, - .evict_inode = bch_evict_inode, - .sync_fs = bch_sync_fs, - .statfs = bch_statfs, - .show_options = generic_show_options, -#if 0 - .put_super = bch_put_super, - .freeze_fs = bch_freeze, - .unfreeze_fs = bch_unfreeze, - .remount_fs = bch_remount, -#endif -}; - -static struct cache_set *bch_open_as_blockdevs(const char *_dev_name) +static struct cache_set *bch_open_as_blockdevs(const char *_dev_name, + struct cache_set_opts opts) { size_t nr_devs = 0, i = 0; char *dev_name, *s, **devs; @@ -1882,7 +1867,7 @@ static struct cache_set *bch_open_as_blockdevs(const char *_dev_name) (s = strchr(s, ':')) && (*s++ = '\0')) devs[i++] = s; - err = bch_register_cache_set(devs, nr_devs, &c); + err = bch_register_cache_set(devs, nr_devs, opts, &c); if (err) { pr_err("register_cache_set err %s", err); goto out; @@ -1914,12 +1899,15 @@ static const match_table_t tokens = { {Opt_err, NULL} }; -static int parse_options(struct cache_set *c, struct super_block *sb, - char *options) +static int parse_options(struct cache_set_opts *opts, int flags, char *options) { char *p; substring_t args[MAX_OPT_ARGS]; + *opts = cache_set_opts_empty(); + + opts->read_only = (flags & MS_RDONLY) != 0; + if (!options) return 1; @@ -1932,43 +1920,102 @@ static int parse_options(struct cache_set *c, struct super_block *sb, token = match_token(p, tokens, args); switch (token) { case Opt_err_panic: - /* - * XXX: this will get written to the superblock, don't - * want this option to be persistent - */ - SET_CACHE_ERROR_ACTION(&c->sb, BCH_ON_ERROR_PANIC); + opts->on_error_action = BCH_ON_ERROR_PANIC; break; case Opt_err_ro: - SET_CACHE_ERROR_ACTION(&c->sb, BCH_ON_ERROR_RO); + opts->on_error_action = BCH_ON_ERROR_RO; break; case Opt_err_cont: - SET_CACHE_ERROR_ACTION(&c->sb, BCH_ON_ERROR_CONTINUE); + opts->on_error_action = BCH_ON_ERROR_CONTINUE; break; case Opt_user_xattr: case Opt_nouser_xattr: break; case Opt_acl: - sb->s_flags |= MS_POSIXACL; + opts->posix_acl = true; break; case Opt_noacl: - sb->s_flags &= ~MS_POSIXACL; + opts->posix_acl = false; break; default: return 0; } } + return 1; } +static int bch_remount(struct super_block *sb, int *flags, char *data) +{ + struct cache_set *c = sb->s_fs_info; + struct cache_set_opts opts; + int ret = 0; + + if (!parse_options(&opts, *flags, data)) + return EINVAL; + + mutex_lock(&bch_register_lock); + + if (opts.read_only >= 0 && + opts.read_only != c->opts.read_only) { + const char *err = NULL; + + if (opts.read_only) { + bch_cache_set_read_only(c); + + sb->s_flags |= MS_RDONLY; + } else { + err = bch_cache_set_read_write(c); + if (err) { + pr_info("error going rw"); + ret = -EINVAL; + goto unlock; + } + + sb->s_flags &= ~MS_RDONLY; + } + + c->opts.read_only = opts.read_only; + } + + if (opts.on_error_action >= 0) + c->opts.on_error_action = opts.on_error_action; + +unlock: + mutex_unlock(&bch_register_lock); + + return ret; +} + +static const struct super_operations bch_super_operations = { + .alloc_inode = bch_alloc_inode, + .destroy_inode = bch_destroy_inode, + .write_inode = bch_write_inode, + .evict_inode = bch_evict_inode, + .sync_fs = bch_sync_fs, + .statfs = bch_statfs, + .show_options = generic_show_options, + .remount_fs = bch_remount, +#if 0 + .put_super = bch_put_super, + .freeze_fs = bch_freeze, + .unfreeze_fs = bch_unfreeze, +#endif +}; + static struct dentry *bch_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { struct cache_set *c; struct super_block *sb; struct inode *inode; + struct cache_set_opts opts; int ret; - c = bch_open_as_blockdevs(dev_name); + if (!parse_options(&opts, flags, data)) + return ERR_PTR(-EINVAL); + + c = bch_open_as_blockdevs(dev_name, opts); if (!c) return ERR_PTR(-ENOENT); @@ -1978,7 +2025,7 @@ static struct dentry *bch_mount(struct file_system_type *fs_type, goto err; } - /* XXX: */ + /* XXX: blocksize */ sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; sb->s_maxbytes = MAX_LFS_FILESIZE; @@ -1988,17 +2035,15 @@ static struct dentry *bch_mount(struct file_system_type *fs_type, sb->s_time_gran = 1; sb->s_fs_info = c; - sb->s_flags |= MS_POSIXACL; + if (opts.posix_acl < 0) + sb->s_flags |= MS_POSIXACL; + else + sb->s_flags |= opts.posix_acl ? MS_POSIXACL : 0; - /* XXX */ + /* XXX: do we even need s_bdev? */ sb->s_bdev = c->cache[0]->disk_sb.bdev; sb->s_bdi = &c->bdi; - if (!parse_options(c, sb, (char *) data)) { - ret = -EINVAL; - goto err_put_super; - } - inode = bch_vfs_inode_get(sb, BCACHE_ROOT_INO); if (IS_ERR(inode)) { ret = PTR_ERR(inode); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index a434a6f07726..4b0e4167e3c8 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -809,7 +809,7 @@ static void bch_cache_set_read_only_work(struct work_struct *work) void bch_cache_set_fail(struct cache_set *c) { - switch (CACHE_ERROR_ACTION(&c->sb)) { + switch (c->opts.on_error_action) { case BCH_ON_ERROR_CONTINUE: break; case BCH_ON_ERROR_RO: @@ -975,7 +975,8 @@ static unsigned cache_set_nr_online_devices(struct cache_set *c) #define alloc_bucket_pages(gfp, ca) \ ((void *) __get_free_pages(__GFP_ZERO|gfp, ilog2(bucket_pages(ca)))) -static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) +static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, + struct cache_set_opts opts) { struct cache_set *c; unsigned iter_size; @@ -1005,6 +1006,16 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) if (cache_sb_to_cache_set(c, sb)) goto err; + c->opts = (struct cache_set_opts) { + .read_only = 0, + .on_error_action = CACHE_ERROR_ACTION(&c->sb), + }; + + if (opts.read_only >= 0) + c->opts.read_only = opts.read_only; + if (opts.on_error_action >= 0) + c->opts.on_error_action = opts.on_error_action; + c->minor = -1; c->block_bits = ilog2(c->sb.block_size); @@ -1315,9 +1326,13 @@ static const char *run_cache_set(struct cache_set *c) closure_sync(&cl); - err = __bch_cache_set_read_write(c); - if (err) - goto err; + if (c->opts.read_only) { + bch_cache_set_read_only(c); + } else { + err = __bch_cache_set_read_write(c); + if (err) + goto err; + } now = get_seconds(); mi = cache_member_info_get(c); @@ -1966,7 +1981,8 @@ static struct cache_set *cache_set_lookup(uuid_le uuid) return NULL; } -static const char *register_cache(struct bcache_superblock *sb) +static const char *register_cache(struct bcache_superblock *sb, + struct cache_set_opts opts) { char name[BDEVNAME_SIZE]; const char *err = "cannot allocate memory"; @@ -1989,7 +2005,7 @@ static const char *register_cache(struct bcache_superblock *sb) goto out; } - c = bch_cache_set_alloc(sb->sb); + c = bch_cache_set_alloc(sb->sb, opts); if (!c) goto err; @@ -2136,6 +2152,7 @@ err: } const char *bch_register_cache_set(char * const *devices, unsigned nr_devices, + struct cache_set_opts opts, struct cache_set **ret) { const char *err; @@ -2173,7 +2190,7 @@ const char *bch_register_cache_set(char * const *devices, unsigned nr_devices, goto err; err = "cannot allocate memory"; - c = bch_cache_set_alloc(sb[0].sb); + c = bch_cache_set_alloc(sb[0].sb, opts); if (!c) goto err_unlock; @@ -2231,7 +2248,7 @@ const char *bch_register_one(const char *path) err = bch_register_bdev(&sb); mutex_unlock(&bch_register_lock); } else { - err = register_cache(&sb); + err = register_cache(&sb, cache_set_opts_empty()); } free_super(&sb); diff --git a/drivers/md/bcache/super.h b/drivers/md/bcache/super.h index 1e4f9d6d73c0..f3e0bd52d44d 100644 --- a/drivers/md/bcache/super.h +++ b/drivers/md/bcache/super.h @@ -160,8 +160,17 @@ void bch_cache_release(struct kobject *); void bch_cache_set_unregister(struct cache_set *); void bch_cache_set_stop(struct cache_set *); +static inline struct cache_set_opts cache_set_opts_empty(void) +{ + struct cache_set_opts ret; + + memset(&ret, 255, sizeof(ret)); + return ret; +} + const char *bch_register_one(const char *path); const char *bch_register_cache_set(char * const *, unsigned, + struct cache_set_opts, struct cache_set **); void bch_cache_set_read_only(struct cache_set *); diff --git a/drivers/md/bcache/super_types.h b/drivers/md/bcache/super_types.h index d89f780f544f..25f0e203acf1 100644 --- a/drivers/md/bcache/super_types.h +++ b/drivers/md/bcache/super_types.h @@ -8,4 +8,14 @@ struct bcache_superblock { unsigned page_order; }; +struct cache_set_opts { + /* For each opt, -1 = undefined */ + + int read_only:2; + int on_error_action:3; + + /* filesystem options: */ + int posix_acl:2; +}; + #endif /* _BCACHE_SUPER_TYPES_H */ |