summaryrefslogtreecommitdiff
path: root/libbcachefs/fs-io.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-10-12 11:06:50 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2022-10-12 11:06:50 -0400
commit3165f53b28b87b3c46c95763bae5e40a29166e2e (patch)
tree0b9f3262721bf95732c511518d714439347112ee /libbcachefs/fs-io.c
parentab392d3c15be2ad7fb008956ec589cba3bb613e6 (diff)
Update bcachefs sources to 6ee8a33cee bcachefs: Call bch2_btree_update_add_new_node() before dropping write lock
Diffstat (limited to 'libbcachefs/fs-io.c')
-rw-r--r--libbcachefs/fs-io.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/libbcachefs/fs-io.c b/libbcachefs/fs-io.c
index 8e025768..2ea6e79f 100644
--- a/libbcachefs/fs-io.c
+++ b/libbcachefs/fs-io.c
@@ -151,7 +151,7 @@ static void bch2_quota_reservation_put(struct bch_fs *c,
static int bch2_quota_reservation_add(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res,
- unsigned sectors,
+ u64 sectors,
bool check_enospc)
{
int ret;
@@ -3256,6 +3256,62 @@ err:
/* fseek: */
+static int page_data_offset(struct page *page, unsigned offset)
+{
+ struct bch_page_state *s = bch2_page_state(page);
+ unsigned i;
+
+ if (s)
+ for (i = offset >> 9; i < PAGE_SECTORS; i++)
+ if (s->s[i].state >= SECTOR_DIRTY)
+ return i << 9;
+
+ return -1;
+}
+
+static loff_t bch2_seek_pagecache_data(struct inode *vinode,
+ loff_t start_offset,
+ loff_t end_offset)
+{
+ struct folio_batch fbatch;
+ pgoff_t start_index = start_offset >> PAGE_SHIFT;
+ pgoff_t end_index = end_offset >> PAGE_SHIFT;
+ pgoff_t index = start_index;
+ unsigned i;
+ loff_t ret;
+ int offset;
+
+ folio_batch_init(&fbatch);
+
+ while (filemap_get_folios(vinode->i_mapping,
+ &index, end_index, &fbatch)) {
+ for (i = 0; i < folio_batch_count(&fbatch); i++) {
+ struct folio *folio = fbatch.folios[i];
+
+ folio_lock(folio);
+
+ offset = page_data_offset(&folio->page,
+ folio->index == start_index
+ ? start_offset & (PAGE_SIZE - 1)
+ : 0);
+ if (offset >= 0) {
+ ret = clamp(((loff_t) folio->index << PAGE_SHIFT) +
+ offset,
+ start_offset, end_offset);
+ folio_unlock(folio);
+ folio_batch_release(&fbatch);
+ return ret;
+ }
+
+ folio_unlock(folio);
+ }
+ folio_batch_release(&fbatch);
+ cond_resched();
+ }
+
+ return end_offset;
+}
+
static loff_t bch2_seek_data(struct file *file, u64 offset)
{
struct bch_inode_info *inode = file_bch_inode(file);
@@ -3299,13 +3355,9 @@ err:
if (ret)
return ret;
- if (next_data > offset) {
- loff_t pagecache_next_data =
- mapping_seek_hole_data(inode->v.i_mapping, offset,
- next_data, SEEK_DATA);
- if (pagecache_next_data >= 0)
- next_data = min_t(u64, next_data, pagecache_next_data);
- }
+ if (next_data > offset)
+ next_data = bch2_seek_pagecache_data(&inode->v,
+ offset, next_data);
if (next_data >= isize)
return -ENXIO;