summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/fs-io.c88
-rw-r--r--fs/bcachefs/fs-io.h4
-rw-r--r--fs/bcachefs/fs.c6
3 files changed, 64 insertions, 34 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 90a9bfa41787..101661d0ea9f 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -507,12 +507,25 @@ static void bch2_set_page_dirty(struct bch_fs *c,
__set_page_dirty_nobuffers(page);
}
+vm_fault_t bch2_page_fault(struct vm_fault *vmf)
+{
+ struct file *file = vmf->vma->vm_file;
+ struct address_space *mapping = file->f_mapping;
+ int ret;
+
+ pagecache_add_get(&mapping->add_lock);
+ ret = filemap_fault(vmf);
+ pagecache_add_put(&mapping->add_lock);
+
+ return ret;
+}
+
vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct file *file = vmf->vma->vm_file;
struct bch_inode_info *inode = file_bch_inode(file);
- struct address_space *mapping = inode->v.i_mapping;
+ struct address_space *mapping = file->f_mapping;
struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch2_page_reservation res;
unsigned len;
@@ -530,8 +543,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
* a write_invalidate_inode_pages_range() that works without dropping
* page lock before invalidating page
*/
- if (current->pagecache_lock != &mapping->add_lock)
- pagecache_add_get(&mapping->add_lock);
+ pagecache_add_get(&mapping->add_lock);
lock_page(page);
isize = i_size_read(&inode->v);
@@ -551,14 +563,13 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
}
bch2_set_page_dirty(c, inode, page, &res, 0, len);
+ bch2_page_reservation_put(c, inode, &res);
+
wait_for_stable_page(page);
out:
- if (current->pagecache_lock != &mapping->add_lock)
- pagecache_add_put(&mapping->add_lock);
+ pagecache_add_put(&mapping->add_lock);
sb_end_pagefault(inode->v.i_sb);
- bch2_page_reservation_put(c, inode, &res);
-
return ret;
}
@@ -888,8 +899,7 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_SLOTS);
- if (current->pagecache_lock != &mapping->add_lock)
- pagecache_add_get(&mapping->add_lock);
+ pagecache_add_get(&mapping->add_lock);
while ((page = readpage_iter_next(&readpages_iter))) {
pgoff_t index = readpages_iter.offset + readpages_iter.idx;
@@ -912,8 +922,7 @@ int bch2_readpages(struct file *file, struct address_space *mapping,
&readpages_iter);
}
- if (current->pagecache_lock != &mapping->add_lock)
- pagecache_add_put(&mapping->add_lock);
+ pagecache_add_put(&mapping->add_lock);
bch2_trans_exit(&trans);
kfree(readpages_iter.pages);
@@ -1730,6 +1739,42 @@ start:
}
}
+ssize_t bch2_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ size_t count = iov_iter_count(iter);
+ ssize_t ret;
+
+ if (!count)
+ return 0; /* skip atime */
+
+ if (iocb->ki_flags & IOCB_DIRECT) {
+ struct blk_plug plug;
+
+ ret = filemap_write_and_wait_range(mapping,
+ iocb->ki_pos,
+ iocb->ki_pos + count - 1);
+ if (ret < 0)
+ return ret;
+
+ file_accessed(file);
+
+ blk_start_plug(&plug);
+ ret = bch2_direct_IO_read(iocb, iter);
+ blk_finish_plug(&plug);
+
+ if (ret >= 0)
+ iocb->ki_pos += ret;
+ } else {
+ pagecache_add_get(&mapping->add_lock);
+ ret = generic_file_read_iter(iocb, iter);
+ pagecache_add_put(&mapping->add_lock);
+ }
+
+ return ret;
+}
+
/* O_DIRECT writes */
static long bch2_dio_write_loop(struct dio_write *dio)
@@ -1762,16 +1807,16 @@ static long bch2_dio_write_loop(struct dio_write *dio)
while (1) {
offset = req->ki_pos + (dio->op.written << 9);
- BUG_ON(current->pagecache_lock);
- current->pagecache_lock = &mapping->add_lock;
if (kthread)
use_mm(dio->mm);
+ BUG_ON(current->faults_disabled_mapping);
+ current->faults_disabled_mapping = mapping;
ret = bio_iov_iter_get_pages(bio, &dio->iter);
+ current->faults_disabled_mapping = NULL;
if (kthread)
unuse_mm(dio->mm);
- current->pagecache_lock = NULL;
if (unlikely(ret < 0))
goto err;
@@ -1980,21 +2025,6 @@ err_put_bio:
goto err;
}
-ssize_t bch2_direct_IO(struct kiocb *req, struct iov_iter *iter)
-{
- struct blk_plug plug;
- ssize_t ret;
-
- if (iov_iter_rw(iter) == WRITE)
- return -EINVAL;
-
- blk_start_plug(&plug);
- ret = bch2_direct_IO_read(req, iter);
- blk_finish_plug(&plug);
-
- return ret;
-}
-
ssize_t bch2_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
diff --git a/fs/bcachefs/fs-io.h b/fs/bcachefs/fs-io.h
index ae171a290d58..7063556d289b 100644
--- a/fs/bcachefs/fs-io.h
+++ b/fs/bcachefs/fs-io.h
@@ -27,8 +27,7 @@ int bch2_write_begin(struct file *, struct address_space *, loff_t,
int bch2_write_end(struct file *, struct address_space *, loff_t,
unsigned, unsigned, struct page *, void *);
-ssize_t bch2_direct_IO(struct kiocb *, struct iov_iter *);
-
+ssize_t bch2_read_iter(struct kiocb *, struct iov_iter *);
ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
int bch2_fsync(struct file *, loff_t, loff_t, int);
@@ -41,6 +40,7 @@ loff_t bch2_remap_file_range(struct file *, loff_t, struct file *,
loff_t bch2_llseek(struct file *, loff_t, int);
+vm_fault_t bch2_page_fault(struct vm_fault *);
vm_fault_t bch2_page_mkwrite(struct vm_fault *);
void bch2_invalidatepage(struct page *, unsigned int, unsigned int);
int bch2_releasepage(struct page *, gfp_t);
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index f9b3650b2f37..671993362e97 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -872,7 +872,7 @@ retry:
}
static const struct vm_operations_struct bch_vm_ops = {
- .fault = filemap_fault,
+ .fault = bch2_page_fault,
.map_pages = filemap_map_pages,
.page_mkwrite = bch2_page_mkwrite,
};
@@ -906,7 +906,7 @@ static int bch2_vfs_readdir(struct file *file, struct dir_context *ctx)
static const struct file_operations bch_file_operations = {
.llseek = bch2_llseek,
- .read_iter = generic_file_read_iter,
+ .read_iter = bch2_read_iter,
.write_iter = bch2_write_iter,
.mmap = bch2_mmap,
.open = generic_file_open,
@@ -994,7 +994,7 @@ static const struct address_space_operations bch_address_space_operations = {
.write_end = bch2_write_end,
.invalidatepage = bch2_invalidatepage,
.releasepage = bch2_releasepage,
- .direct_IO = bch2_direct_IO,
+ .direct_IO = noop_direct_IO,
#ifdef CONFIG_MIGRATION
.migratepage = bch2_migrate_page,
#endif