summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-03-29 03:33:23 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:35:57 -0800
commitf936676a04688e71b009ae665c8cf2f13191a776 (patch)
tree7118c1726dd23f281f1bbc56d9245f183c98f5e7
parent6d33b9ee7852c21d6b77712ab73ad2fe8562c08c (diff)
bcachefs: fix fallocate + compression
-rw-r--r--drivers/md/bcache/extents.h23
-rw-r--r--drivers/md/bcache/fs-io.c12
2 files changed, 29 insertions, 6 deletions
diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h
index 42db3d1ca933..e861492c731e 100644
--- a/drivers/md/bcache/extents.h
+++ b/drivers/md/bcache/extents.h
@@ -354,6 +354,29 @@ static inline struct bch_extent_crc64 crc_to_64(const union bch_extent_crc *crc)
}
}
+static inline bool bkey_extent_is_compressed(struct cache_set *c,
+ struct bkey_s_c k)
+{
+ struct bkey_s_c_extent e;
+ const struct bch_extent_ptr *ptr;
+ const union bch_extent_crc *crc;
+
+ switch (k.k->type) {
+ case BCH_EXTENT:
+ case BCH_EXTENT_CACHED:
+ e = bkey_s_c_to_extent(k);
+
+ extent_for_each_ptr_crc(e, ptr, crc)
+ if (bch_extent_ptr_is_dirty(c, e, ptr) &&
+ crc_to_64(crc).compression_type != BCH_COMPRESSION_NONE &&
+ crc_to_64(crc).compressed_size < k.k->size)
+ return true;
+ return true;
+ default:
+ return false;
+ }
+}
+
void extent_adjust_pointers(struct bkey_s_extent, union bch_extent_entry *);
/* Doesn't cleanup redundant crcs */
diff --git a/drivers/md/bcache/fs-io.c b/drivers/md/bcache/fs-io.c
index 5c8ff61cee69..0ffe10fb0b98 100644
--- a/drivers/md/bcache/fs-io.c
+++ b/drivers/md/bcache/fs-io.c
@@ -699,6 +699,10 @@ static void bchfs_read(struct cache_set *c, struct bch_read_bio *rbio, u64 inode
unsigned bytes, sectors;
bool is_last;
+ if (!bkey_extent_is_allocation(k.k) ||
+ bkey_extent_is_compressed(c, k))
+ bch_mark_pages_unalloc(bio);
+
bch_extent_pick_ptr(c, k, &pick);
bch_btree_iter_unlock(&iter);
@@ -715,11 +719,6 @@ static void bchfs_read(struct cache_set *c, struct bch_read_bio *rbio, u64 inode
is_last = bytes == bio->bi_iter.bi_size;
swap(bio->bi_iter.bi_size, bytes);
- if (!(k.k->type == BCH_RESERVATION ||
- (pick.ca &&
- pick.crc.compression_type == BCH_COMPRESSION_NONE)))
- bch_mark_pages_unalloc(bio);
-
if (bkey_extent_is_allocation(k.k))
bch_add_page_sectors(bio, k.k);
@@ -2350,7 +2349,8 @@ static long bch_fallocate(struct inode *inode, int mode,
sectors = reservation.k.size;
- if (!bkey_extent_is_allocation(k.k)) {
+ if (!bkey_extent_is_allocation(k.k) ||
+ bkey_extent_is_compressed(c, k)) {
ret = bch_disk_reservation_get(c, &disk_res, sectors);
if (ret)
goto err_put_sectors_dirty;