summaryrefslogtreecommitdiff
path: root/fs/btrfs
diff options
context:
space:
mode:
authorTimofey Titovets <nefelim4ag@gmail.com>2017-09-28 17:33:39 +0300
committerDavid Sterba <dsterba@suse.com>2017-11-01 22:45:36 +0300
commit1fe4f6fa5ae7dd1e63145e1ced7b9b38854da9f4 (patch)
treedbe0f0b44b9814655e5b64e8b0cc72db375227b9 /fs/btrfs
parenta440d48c7f93af5bae86af676cc6cd4e9fd6015f (diff)
downloadlinux-1fe4f6fa5ae7dd1e63145e1ced7b9b38854da9f4.tar.xz
Btrfs: heuristic: add detection of repeated data patterns
Walk over data sample and use memcmp to detect repeated patterns, like zeros, but a bit more general. Signed-off-by: Timofey Titovets <nefelim4ag@gmail.com> Reviewed-by: David Sterba <dsterba@suse.com> [ minor coding style fixes ] Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/compression.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 0e1561cc9578..0d445c815ca2 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -1222,6 +1222,14 @@ int btrfs_decompress_buf2page(const char *buf, unsigned long buf_start,
return 1;
}
+static bool sample_repeated_patterns(struct heuristic_ws *ws)
+{
+ const u32 half_of_sample = ws->sample_size / 2;
+ const u8 *data = ws->sample;
+
+ return memcmp(&data[0], &data[half_of_sample], half_of_sample) == 0;
+}
+
static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
struct heuristic_ws *ws)
{
@@ -1301,6 +1309,11 @@ int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end)
heuristic_collect_sample(inode, start, end, ws);
+ if (sample_repeated_patterns(ws)) {
+ ret = 1;
+ goto out;
+ }
+
memset(ws->bucket, 0, sizeof(*ws->bucket)*BUCKET_SIZE);
for (i = 0; i < ws->sample_size; i++) {
@@ -1308,8 +1321,8 @@ int btrfs_compress_heuristic(struct inode *inode, u64 start, u64 end)
ws->bucket[byte].count++;
}
+out:
__free_workspace(0, ws_list, true);
-
return ret;
}