summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-01-19 13:29:00 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-01-30 20:41:29 -0500
commite7e7616e13f7eb452a8e03cb50e9cb879f271560 (patch)
tree882c9ba7bd00dd2482c0a094cea8ebbded74573c
parente2554ba25f220c681718f1faa8f7855b48b7f154 (diff)
bcachefs: organize fs-io.c a bit better
-rw-r--r--fs/bcachefs/fs-io.c256
1 files changed, 136 insertions, 120 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 2944bff39166..e1ad5aaa20eb 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -576,6 +576,95 @@ int bch2_set_page_dirty(struct page *page)
return __set_page_dirty_nobuffers(page);
}
+int 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 bch_fs *c = inode->v.i_sb->s_fs_info;
+ int ret = VM_FAULT_LOCKED;
+
+ sb_start_pagefault(inode->v.i_sb);
+ file_update_time(file);
+
+ /*
+ * Not strictly necessary, but helps avoid dio writes livelocking in
+ * write_invalidate_inode_pages_range() - can drop this if/when we get
+ * 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);
+
+ lock_page(page);
+ if (page->mapping != mapping ||
+ page_offset(page) > i_size_read(&inode->v)) {
+ unlock_page(page);
+ ret = VM_FAULT_NOPAGE;
+ goto out;
+ }
+
+ if (bch2_get_page_reservation(c, page, true)) {
+ unlock_page(page);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }
+
+ if (!PageDirty(page))
+ set_page_dirty(page);
+ wait_for_stable_page(page);
+out:
+ if (current->pagecache_lock != &mapping->add_lock)
+ pagecache_add_put(&mapping->add_lock);
+ sb_end_pagefault(inode->v.i_sb);
+ return ret;
+}
+
+void bch2_invalidatepage(struct page *page, unsigned int offset,
+ unsigned int length)
+{
+ EBUG_ON(!PageLocked(page));
+ EBUG_ON(PageWriteback(page));
+
+ if (offset || length < PAGE_SIZE)
+ return;
+
+ bch2_clear_page_bits(page);
+}
+
+int bch2_releasepage(struct page *page, gfp_t gfp_mask)
+{
+ EBUG_ON(!PageLocked(page));
+ EBUG_ON(PageWriteback(page));
+
+ if (PageDirty(page))
+ return 0;
+
+ bch2_clear_page_bits(page);
+ return 1;
+}
+
+#ifdef CONFIG_MIGRATION
+int bch2_migrate_page(struct address_space *mapping, struct page *newpage,
+ struct page *page, enum migrate_mode mode)
+{
+ int ret;
+
+ ret = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+ if (ret != MIGRATEPAGE_SUCCESS)
+ return ret;
+
+ if (PagePrivate(page)) {
+ *page_state(newpage) = *page_state(page);
+ ClearPagePrivate(page);
+ }
+
+ migrate_page_copy(newpage, page);
+ return MIGRATEPAGE_SUCCESS;
+}
+#endif
+
/* readpages/writepages: */
static bool bio_can_add_page_contig(struct bio *bio, struct page *page)
@@ -612,6 +701,8 @@ static int bio_add_page_contig(struct bio *bio, struct page *page)
return 0;
}
+/* readpage(s): */
+
static void bch2_readpages_end_io(struct bio *bio)
{
struct bio_vec *bv;
@@ -922,6 +1013,40 @@ int bch2_readpage(struct file *file, struct page *page)
return 0;
}
+static void bch2_read_single_page_end_io(struct bio *bio)
+{
+ complete(bio->bi_private);
+}
+
+static int bch2_read_single_page(struct page *page,
+ struct address_space *mapping)
+{
+ struct bch_inode_info *inode = to_bch_ei(mapping->host);
+ struct bch_fs *c = inode->v.i_sb->s_fs_info;
+ struct bch_read_bio *rbio;
+ int ret;
+ DECLARE_COMPLETION_ONSTACK(done);
+
+ rbio = rbio_init(bio_alloc_bioset(GFP_NOFS, 1, &c->bio_read),
+ io_opts(c, inode));
+ rbio->bio.bi_private = &done;
+ rbio->bio.bi_end_io = bch2_read_single_page_end_io;
+
+ __bchfs_readpage(c, rbio, inode->v.i_ino, page);
+ wait_for_completion(&done);
+
+ ret = blk_status_to_errno(rbio->bio.bi_status);
+ bio_put(&rbio->bio);
+
+ if (ret < 0)
+ return ret;
+
+ SetPageUptodate(page);
+ return 0;
+}
+
+/* writepages: */
+
struct bch_writepage_state {
struct bch_writepage_io *io;
struct bch_io_opts opts;
@@ -1273,37 +1398,7 @@ int bch2_writepage(struct page *page, struct writeback_control *wbc)
return ret;
}
-static void bch2_read_single_page_end_io(struct bio *bio)
-{
- complete(bio->bi_private);
-}
-
-static int bch2_read_single_page(struct page *page,
- struct address_space *mapping)
-{
- struct bch_inode_info *inode = to_bch_ei(mapping->host);
- struct bch_fs *c = inode->v.i_sb->s_fs_info;
- struct bch_read_bio *rbio;
- int ret;
- DECLARE_COMPLETION_ONSTACK(done);
-
- rbio = rbio_init(bio_alloc_bioset(GFP_NOFS, 1, &c->bio_read),
- io_opts(c, inode));
- rbio->bio.bi_private = &done;
- rbio->bio.bi_end_io = bch2_read_single_page_end_io;
-
- __bchfs_readpage(c, rbio, inode->v.i_ino, page);
- wait_for_completion(&done);
-
- ret = blk_status_to_errno(rbio->bio.bi_status);
- bio_put(&rbio->bio);
-
- if (ret < 0)
- return ret;
-
- SetPageUptodate(page);
- return 0;
-}
+/* buffered writes: */
int bch2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
@@ -1415,7 +1510,7 @@ int bch2_write_end(struct file *filp, struct address_space *mapping,
return copied;
}
-/* O_DIRECT */
+/* O_DIRECT reads */
static void bch2_dio_read_complete(struct closure *cl)
{
@@ -1529,6 +1624,8 @@ start:
}
}
+/* O_DIRECT writes */
+
static void bch2_dio_write_loop_async(struct closure *);
static long bch2_dio_write_loop(struct dio_write *dio)
@@ -1765,94 +1862,7 @@ ssize_t bch2_write_iter(struct kiocb *iocb, struct iov_iter *from)
return ret;
}
-int 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 bch_fs *c = inode->v.i_sb->s_fs_info;
- int ret = VM_FAULT_LOCKED;
-
- sb_start_pagefault(inode->v.i_sb);
- file_update_time(file);
-
- /*
- * Not strictly necessary, but helps avoid dio writes livelocking in
- * write_invalidate_inode_pages_range() - can drop this if/when we get
- * 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);
-
- lock_page(page);
- if (page->mapping != mapping ||
- page_offset(page) > i_size_read(&inode->v)) {
- unlock_page(page);
- ret = VM_FAULT_NOPAGE;
- goto out;
- }
-
- if (bch2_get_page_reservation(c, page, true)) {
- unlock_page(page);
- ret = VM_FAULT_SIGBUS;
- goto out;
- }
-
- if (!PageDirty(page))
- set_page_dirty(page);
- wait_for_stable_page(page);
-out:
- if (current->pagecache_lock != &mapping->add_lock)
- pagecache_add_put(&mapping->add_lock);
- sb_end_pagefault(inode->v.i_sb);
- return ret;
-}
-
-void bch2_invalidatepage(struct page *page, unsigned int offset,
- unsigned int length)
-{
- EBUG_ON(!PageLocked(page));
- EBUG_ON(PageWriteback(page));
-
- if (offset || length < PAGE_SIZE)
- return;
-
- bch2_clear_page_bits(page);
-}
-
-int bch2_releasepage(struct page *page, gfp_t gfp_mask)
-{
- EBUG_ON(!PageLocked(page));
- EBUG_ON(PageWriteback(page));
-
- if (PageDirty(page))
- return 0;
-
- bch2_clear_page_bits(page);
- return 1;
-}
-
-#ifdef CONFIG_MIGRATION
-int bch2_migrate_page(struct address_space *mapping, struct page *newpage,
- struct page *page, enum migrate_mode mode)
-{
- int ret;
-
- ret = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
- if (ret != MIGRATEPAGE_SUCCESS)
- return ret;
-
- if (PagePrivate(page)) {
- *page_state(newpage) = *page_state(page);
- ClearPagePrivate(page);
- }
-
- migrate_page_copy(newpage, page);
- return MIGRATEPAGE_SUCCESS;
-}
-#endif
+/* fsync: */
int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
@@ -1870,6 +1880,8 @@ int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
return bch2_journal_flush_seq(&c->journal, inode->ei_journal_seq);
}
+/* truncate: */
+
static int __bch2_truncate_page(struct bch_inode_info *inode,
pgoff_t index, loff_t start, loff_t end)
{
@@ -2023,6 +2035,8 @@ err_put_pagecache:
return ret;
}
+/* fallocate: */
+
static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len)
{
struct bch_fs *c = inode->v.i_sb->s_fs_info;
@@ -2385,6 +2399,8 @@ long bch2_fallocate_dispatch(struct file *file, int mode,
return -EOPNOTSUPP;
}
+/* fseek: */
+
static bool page_is_data(struct page *page)
{
/* XXX: should only have to check PageDirty */