diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2025-09-17 11:38:43 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-09-17 12:38:53 -0400 |
commit | b6bb1e2a1128eaedc97e03fe167c55c0d3710128 (patch) | |
tree | 604d9cd8074292563b00da1849b98748927e654b | |
parent | 5862ca9f026ba27dda979f41b2416d27393156c1 (diff) |
Update bcachefs sources to ff14f7886ed9 bcachefs: compat code for pre 6.17
-rw-r--r-- | .bcachefs_revision | 2 | ||||
-rw-r--r-- | libbcachefs/fs-io-buffered.c | 140 | ||||
-rw-r--r-- | libbcachefs/fs-io-buffered.h | 14 | ||||
-rw-r--r-- | libbcachefs/fs.c | 2 |
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 |