summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-02-18 13:22:35 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-02-19 18:00:35 -0500
commit02d7c0e4b51b52fccb937617b4b448ed278e17b6 (patch)
tree59678be4ac81a153391a1d759f150138a99ea3df
parent1fe226203d3d85f18cb3557ea7413fd9de12fe30 (diff)
bcachefs: fixes for check_set_has_compressed_data()
-rw-r--r--fs/bcachefs/bcachefs.h1
-rw-r--r--fs/bcachefs/compress.c70
-rw-r--r--fs/bcachefs/fs-io.c2
-rw-r--r--fs/bcachefs/super-io.c1
-rw-r--r--fs/bcachefs/super.c1
-rw-r--r--fs/bcachefs/sysfs.c9
-rw-r--r--fs/bcachefs/xattr.c6
7 files changed, 60 insertions, 30 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index 5a3e99b3b79a..e50aa3dd49bc 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -522,6 +522,7 @@ struct bch_fs {
u64 time_base_lo;
u32 time_base_hi;
u32 time_precision;
+ u64 features;
} sb;
struct bch_sb *disk_sb;
diff --git a/fs/bcachefs/compress.c b/fs/bcachefs/compress.c
index 7726cfd8cfac..18c945985636 100644
--- a/fs/bcachefs/compress.c
+++ b/fs/bcachefs/compress.c
@@ -360,6 +360,9 @@ static unsigned __bio_compress(struct bch_fs *c,
unsigned pad;
int ret = 0;
+ BUG_ON(compression_type >= BCH_COMPRESSION_NR);
+ BUG_ON(!mempool_initialized(&c->compress_workspace[compression_type]));
+
/* If it's only one block, don't bother trying to compress: */
if (bio_sectors(src) <= c->opts.block_size)
return 0;
@@ -465,6 +468,8 @@ unsigned bch2_bio_compress(struct bch_fs *c,
return compression_type;
}
+static int __bch2_fs_compress_init(struct bch_fs *, u64);
+
#define BCH_FEATURE_NONE 0
static const unsigned bch2_compression_opt_to_feature[] = {
@@ -475,29 +480,42 @@ static const unsigned bch2_compression_opt_to_feature[] = {
#undef BCH_FEATURE_NONE
-/* doesn't write superblock: */
-int bch2_check_set_has_compressed_data(struct bch_fs *c,
- unsigned compression_type)
+int __bch2_check_set_has_compressed_data(struct bch_fs *c, u64 f)
{
- unsigned f;
int ret = 0;
- pr_verbose_init(c->opts, "");
+ if ((c->sb.features & f) == f)
+ return 0;
- BUG_ON(compression_type >= ARRAY_SIZE(bch2_compression_opt_to_feature));
+ mutex_lock(&c->sb_lock);
- if (!compression_type)
- goto out;
+ if ((c->sb.features & f) == f) {
+ mutex_unlock(&c->sb_lock);
+ return 0;
+ }
- f = bch2_compression_opt_to_feature[compression_type];
- if (bch2_sb_test_feature(c->disk_sb, f))
- goto out;
+ ret = __bch2_fs_compress_init(c, c->sb.features|f);
+ if (ret) {
+ mutex_unlock(&c->sb_lock);
+ return ret;
+ }
- bch2_sb_set_feature(c->disk_sb, f);
- ret = bch2_fs_compress_init(c);
-out:
- pr_verbose_init(c->opts, "ret %i", ret);
- return ret;
+ c->disk_sb->features[0] |= cpu_to_le64(f);
+ bch2_write_super(c);
+ mutex_unlock(&c->sb_lock);
+
+ return 0;
+}
+
+int bch2_check_set_has_compressed_data(struct bch_fs *c,
+ unsigned compression_type)
+{
+ BUG_ON(compression_type >= ARRAY_SIZE(bch2_compression_opt_to_feature));
+
+ return compression_type
+ ? __bch2_check_set_has_compressed_data(c,
+ 1ULL << bch2_compression_opt_to_feature[compression_type])
+ : 0;
}
void bch2_fs_compress_exit(struct bch_fs *c)
@@ -531,7 +549,7 @@ static int mempool_init_kvpmalloc_pool(mempool_t *pool, int min_nr, size_t size)
: 0;
}
-int bch2_fs_compress_init(struct bch_fs *c)
+static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
{
size_t max_extent = c->sb.encoded_extent_max << 9;
size_t order = get_order(max_extent);
@@ -561,7 +579,7 @@ int bch2_fs_compress_init(struct bch_fs *c)
for (i = compression_types;
i < compression_types + ARRAY_SIZE(compression_types);
i++)
- if (bch2_sb_test_feature(c->disk_sb, i->feature))
+ if (features & (1 << i->feature))
goto have_compressed;
goto out;
@@ -587,7 +605,7 @@ have_compressed:
decompress_workspace_size =
max(decompress_workspace_size, i->decompress_workspace);
- if (!bch2_sb_test_feature(c->disk_sb, i->feature))
+ if (!(features & (1 << i->feature)))
continue;
if (i->decompress_workspace)
@@ -609,3 +627,17 @@ out:
pr_verbose_init(c->opts, "ret %i", ret);
return ret;
}
+
+int bch2_fs_compress_init(struct bch_fs *c)
+{
+ u64 f = c->sb.features;
+
+ if (c->opts.compression)
+ f |= 1ULL << bch2_compression_opt_to_feature[c->opts.compression];
+
+ if (c->opts.background_compression)
+ f |= 1ULL << bch2_compression_opt_to_feature[c->opts.background_compression];
+
+ return __bch2_fs_compress_init(c, f);
+
+}
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 00475b99dff8..d7fb28cc95c7 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -2351,7 +2351,7 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode,
loff_t block_start, block_end;
loff_t end = offset + len;
unsigned sectors;
- unsigned replicas = READ_ONCE(c->opts.data_replicas);
+ unsigned replicas = io_opts(c, inode).data_replicas;
int ret;
bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN,
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index c747391707b3..1c4f67cc4bd4 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -400,6 +400,7 @@ static void bch2_sb_update(struct bch_fs *c)
c->sb.time_base_lo = le64_to_cpu(src->time_base_lo);
c->sb.time_base_hi = le32_to_cpu(src->time_base_hi);
c->sb.time_precision = le32_to_cpu(src->time_precision);
+ c->sb.features = le64_to_cpu(src->features[0]);
for_each_member_device(ca, c, i)
ca->mi = bch2_mi_to_cpu(mi->members + i);
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 58bcd7d1ee06..777d60d3a4de 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -626,7 +626,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_fs_btree_cache_init(c) ||
bch2_fs_encryption_init(c) ||
bch2_fs_compress_init(c) ||
- bch2_check_set_has_compressed_data(c, c->opts.compression) ||
bch2_fs_fsio_init(c))
goto err;
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index 2e958a8ef381..722aa2642b92 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -546,9 +546,8 @@ STORE(bch2_fs_opts_dir)
if (ret < 0)
return ret;
- mutex_lock(&c->sb_lock);
-
- if (id == Opt_compression) {
+ if (id == Opt_compression ||
+ id == Opt_background_compression) {
int ret = bch2_check_set_has_compressed_data(c, v);
if (ret) {
mutex_unlock(&c->sb_lock);
@@ -557,14 +556,14 @@ STORE(bch2_fs_opts_dir)
}
if (opt->set_sb != SET_NO_SB_OPT) {
+ mutex_lock(&c->sb_lock);
opt->set_sb(c->disk_sb, v);
bch2_write_super(c);
+ mutex_unlock(&c->sb_lock);
}
bch2_opt_set_by_id(&c->opts, id, v);
- mutex_unlock(&c->sb_lock);
-
return size;
}
SYSFS_OPS(bch2_fs_opts_dir);
diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c
index 1d6cbe72e05b..c286f3f8859a 100644
--- a/fs/bcachefs/xattr.c
+++ b/fs/bcachefs/xattr.c
@@ -441,11 +441,9 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
if (ret < 0)
return ret;
- if (s.id == Opt_compression) {
- mutex_lock(&c->sb_lock);
+ if (s.id == Opt_compression ||
+ s.id == Opt_background_compression) {
ret = bch2_check_set_has_compressed_data(c, s.v);
- mutex_unlock(&c->sb_lock);
-
if (ret)
return ret;
}