summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2025-09-17 11:38:43 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2025-09-17 12:38:53 -0400
commitb6bb1e2a1128eaedc97e03fe167c55c0d3710128 (patch)
tree604d9cd8074292563b00da1849b98748927e654b
parent5862ca9f026ba27dda979f41b2416d27393156c1 (diff)
Update bcachefs sources to ff14f7886ed9 bcachefs: compat code for pre 6.17
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/fs-io-buffered.c140
-rw-r--r--libbcachefs/fs-io-buffered.h14
-rw-r--r--libbcachefs/fs.c2
4 files changed, 157 insertions, 1 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index 482ed028..21d54840 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-c819a775791257e7db76b5b54bf0f704cb472f15
+ff14f7886ed9adc133777d5cdba1e3101856f29a
diff --git a/libbcachefs/fs-io-buffered.c b/libbcachefs/fs-io-buffered.c
index bfa1307b..4761af1f 100644
--- a/libbcachefs/fs-io-buffered.c
+++ b/libbcachefs/fs-io-buffered.c
@@ -729,6 +729,146 @@ int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc
/* buffered writes: */
+int bch2_write_begin(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,17,0)
+ const struct kiocb *iocb,
+#else
+ struct file *file,
+#endif
+ struct address_space *mapping,
+ loff_t pos, unsigned len,
+ struct folio **foliop, void **fsdata)
+{
+ struct bch_inode_info *inode = to_bch_ei(mapping->host);
+ struct bch_fs *c = inode->v.i_sb->s_fs_info;
+ struct bch2_folio_reservation *res;
+ struct folio *folio;
+ unsigned offset;
+ int ret = -ENOMEM;
+
+ res = kmalloc(sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return -ENOMEM;
+
+ bch2_folio_reservation_init(c, inode, res);
+ *fsdata = res;
+
+ bch2_pagecache_add_get(inode);
+
+ folio = __filemap_get_folio(mapping, pos >> PAGE_SHIFT,
+ FGP_WRITEBEGIN | fgf_set_order(len),
+ mapping_gfp_mask(mapping));
+ if (IS_ERR(folio))
+ goto err_unlock;
+
+ offset = pos - folio_pos(folio);
+ len = min_t(size_t, len, folio_end_pos(folio) - pos);
+
+ if (folio_test_uptodate(folio))
+ goto out;
+
+ /* If we're writing entire folio, don't need to read it in first: */
+ if (!offset && len == folio_size(folio))
+ goto out;
+
+ if (!offset && pos + len >= inode->v.i_size) {
+ folio_zero_segment(folio, len, folio_size(folio));
+ flush_dcache_folio(folio);
+ goto out;
+ }
+
+ if (folio_pos(folio) >= inode->v.i_size) {
+ folio_zero_segments(folio, 0, offset, offset + len, folio_size(folio));
+ flush_dcache_folio(folio);
+ goto out;
+ }
+readpage:
+ ret = bch2_read_single_folio(folio, mapping);
+ if (ret)
+ goto err;
+out:
+ ret = bch2_folio_set(c, inode_inum(inode), &folio, 1);
+ if (ret)
+ goto err;
+
+ ret = bch2_folio_reservation_get(c, inode, folio, res, offset, len);
+ if (ret) {
+ if (!folio_test_uptodate(folio)) {
+ /*
+ * If the folio hasn't been read in, we won't know if we
+ * actually need a reservation - we don't actually need
+ * to read here, we just need to check if the folio is
+ * fully backed by uncompressed data:
+ */
+ goto readpage;
+ }
+
+ goto err;
+ }
+
+ *foliop = folio;
+ return 0;
+err:
+ folio_unlock(folio);
+ folio_put(folio);
+err_unlock:
+ bch2_pagecache_add_put(inode);
+ kfree(res);
+ *fsdata = NULL;
+ return bch2_err_class(ret);
+}
+
+int bch2_write_end(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,17,0)
+ const struct kiocb *iocb,
+#else
+ struct file *file,
+#endif
+ struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct folio *folio, void *fsdata)
+{
+ struct bch_inode_info *inode = to_bch_ei(mapping->host);
+ struct bch_fs *c = inode->v.i_sb->s_fs_info;
+ struct bch2_folio_reservation *res = fsdata;
+ unsigned offset = pos - folio_pos(folio);
+
+ BUG_ON(offset + copied > folio_size(folio));
+
+ if (unlikely(copied < len && !folio_test_uptodate(folio))) {
+ /*
+ * The folio needs to be read in, but that would destroy
+ * our partial write - simplest thing is to just force
+ * userspace to redo the write:
+ */
+ folio_zero_range(folio, 0, folio_size(folio));
+ flush_dcache_folio(folio);
+ copied = 0;
+ }
+
+ scoped_guard(spinlock, &inode->v.i_lock)
+ if (pos + copied > inode->v.i_size)
+ i_size_write(&inode->v, pos + copied);
+
+ if (copied) {
+ if (!folio_test_uptodate(folio))
+ folio_mark_uptodate(folio);
+
+ bch2_set_folio_dirty(c, inode, folio, res, offset, copied);
+
+ inode->ei_last_dirtied = (unsigned long) current;
+ }
+
+ folio_unlock(folio);
+ folio_put(folio);
+ bch2_pagecache_add_put(inode);
+
+ bch2_folio_reservation_put(c, inode, res);
+ kfree(res);
+
+ return copied;
+}
+
static noinline void folios_trunc(folios *fs, struct folio **fi)
{
while (fs->data + fs->nr > fi) {
diff --git a/libbcachefs/fs-io-buffered.h b/libbcachefs/fs-io-buffered.h
index df59398b..89b7064d 100644
--- a/libbcachefs/fs-io-buffered.h
+++ b/libbcachefs/fs-io-buffered.h
@@ -4,12 +4,26 @@
#ifndef NO_BCACHEFS_FS
+#include <linux/version.h>
+
int bch2_read_single_folio(struct folio *, struct address_space *);
int bch2_read_folio(struct file *, struct folio *);
int bch2_writepages(struct address_space *, struct writeback_control *);
void bch2_readahead(struct readahead_control *);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,17,0)
+int bch2_write_begin(const struct kiocb *, struct address_space *, loff_t pos,
+ unsigned len, struct folio **, void **);
+int bch2_write_end(const struct kiocb *, struct address_space *, loff_t,
+ unsigned len, unsigned copied, struct folio *, void *);
+#else
+int bch2_write_begin(struct file *, struct address_space *, loff_t pos,
+ unsigned len, struct folio **, void **);
+int bch2_write_end(struct file *, struct address_space *, loff_t,
+ unsigned len, unsigned copied, struct folio *, void *);
+#endif
+
ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
void bch2_fs_fs_io_buffered_exit(struct bch_fs *);
diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c
index 9b309ea6..958849c3 100644
--- a/libbcachefs/fs.c
+++ b/libbcachefs/fs.c
@@ -1808,6 +1808,8 @@ static const struct address_space_operations bch_address_space_operations = {
.writepages = bch2_writepages,
.readahead = bch2_readahead,
.dirty_folio = filemap_dirty_folio,
+ .write_begin = bch2_write_begin,
+ .write_end = bch2_write_end,
.invalidate_folio = bch2_invalidate_folio,
.release_folio = bch2_release_folio,
#ifdef CONFIG_MIGRATION