Commit dbbfca9f authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Split up fs-io.[ch]

fs-io.c is too big - time for some reorganization
 - fs-dio.c: direct io
 - fs-pagecache.c: pagecache data structures (bch_folio), utility code
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1e81f89b
......@@ -38,6 +38,9 @@ bcachefs-y := \
fs-common.o \
fs-ioctl.o \
fs-io.o \
fs-io-buffered.o \
fs-io-direct.o \
fs-io-pagecache.o \
fsck.o \
inode.o \
io.o \
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_FS_IO_BUFFERED_H
#define _BCACHEFS_FS_IO_BUFFERED_H
#ifndef NO_BCACHEFS_FS
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 *);
int bch2_write_begin(struct file *, struct address_space *, loff_t,
unsigned, struct page **, void **);
int bch2_write_end(struct file *, struct address_space *, loff_t,
unsigned, unsigned, struct page *, void *);
ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
void bch2_fs_fs_io_buffered_exit(struct bch_fs *);
int bch2_fs_fs_io_buffered_init(struct bch_fs *);
#else
static inline void bch2_fs_fs_io_buffered_exit(struct bch_fs *c) {}
static inline int bch2_fs_fs_io_buffered_init(struct bch_fs *c) { return 0; }
#endif
#endif /* _BCACHEFS_FS_IO_BUFFERED_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_FS_IO_DIRECT_H
#define _BCACHEFS_FS_IO_DIRECT_H
#ifndef NO_BCACHEFS_FS
ssize_t bch2_direct_write(struct kiocb *, struct iov_iter *);
ssize_t bch2_read_iter(struct kiocb *, struct iov_iter *);
void bch2_fs_fs_io_direct_exit(struct bch_fs *);
int bch2_fs_fs_io_direct_init(struct bch_fs *);
#else
static inline void bch2_fs_fs_io_direct_exit(struct bch_fs *c) {}
static inline int bch2_fs_fs_io_direct_init(struct bch_fs *c) { return 0; }
#endif
#endif /* _BCACHEFS_FS_IO_DIRECT_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_FS_IO_PAGECACHE_H
#define _BCACHEFS_FS_IO_PAGECACHE_H
#include <linux/pagemap.h>
typedef DARRAY(struct folio *) folios;
int bch2_filemap_get_contig_folios_d(struct address_space *, loff_t,
u64, int, gfp_t, folios *);
int bch2_write_invalidate_inode_pages_range(struct address_space *, loff_t, loff_t);
/*
* Use u64 for the end pos and sector helpers because if the folio covers the
* max supported range of the mapping, the start offset of the next folio
* overflows loff_t. This breaks much of the range based processing in the
* buffered write path.
*/
static inline u64 folio_end_pos(struct folio *folio)
{
return folio_pos(folio) + folio_size(folio);
}
static inline size_t folio_sectors(struct folio *folio)
{
return PAGE_SECTORS << folio_order(folio);
}
static inline loff_t folio_sector(struct folio *folio)
{
return folio_pos(folio) >> 9;
}
static inline u64 folio_end_sector(struct folio *folio)
{
return folio_end_pos(folio) >> 9;
}
#define BCH_FOLIO_SECTOR_STATE() \
x(unallocated) \
x(reserved) \
x(dirty) \
x(dirty_reserved) \
x(allocated)
enum bch_folio_sector_state {
#define x(n) SECTOR_##n,
BCH_FOLIO_SECTOR_STATE()
#undef x
};
struct bch_folio_sector {
/* Uncompressed, fully allocated replicas (or on disk reservation): */
unsigned nr_replicas:4;
/* Owns PAGE_SECTORS * replicas_reserved sized in memory reservation: */
unsigned replicas_reserved:4;
/* i_sectors: */
enum bch_folio_sector_state state:8;
};
struct bch_folio {
spinlock_t lock;
atomic_t write_count;
/*
* Is the sector state up to date with the btree?
* (Not the data itself)
*/
bool uptodate;
struct bch_folio_sector s[];
};
/* Helper for when we need to add debug instrumentation: */
static inline void bch2_folio_sector_set(struct folio *folio,
struct bch_folio *s,
unsigned i, unsigned n)
{
s->s[i].state = n;
}
/* file offset (to folio offset) to bch_folio_sector index */
static inline int folio_pos_to_s(struct folio *folio, loff_t pos)
{
u64 f_offset = pos - folio_pos(folio);
BUG_ON(pos < folio_pos(folio) || pos >= folio_end_pos(folio));
return f_offset >> SECTOR_SHIFT;
}
/* for newly allocated folios: */
static inline void __bch2_folio_release(struct folio *folio)
{
kfree(folio_detach_private(folio));
}
static inline void bch2_folio_release(struct folio *folio)
{
EBUG_ON(!folio_test_locked(folio));
__bch2_folio_release(folio);
}
static inline struct bch_folio *__bch2_folio(struct folio *folio)
{
return folio_has_private(folio)
? (struct bch_folio *) folio_get_private(folio)
: NULL;
}
static inline struct bch_folio *bch2_folio(struct folio *folio)
{
EBUG_ON(!folio_test_locked(folio));
return __bch2_folio(folio);
}
struct bch_folio *__bch2_folio_create(struct folio *, gfp_t);
struct bch_folio *bch2_folio_create(struct folio *, gfp_t);
struct bch2_folio_reservation {
struct disk_reservation disk;
struct quota_res quota;
};
static inline unsigned inode_nr_replicas(struct bch_fs *c, struct bch_inode_info *inode)
{
/* XXX: this should not be open coded */
return inode->ei_inode.bi_data_replicas
? inode->ei_inode.bi_data_replicas - 1
: c->opts.data_replicas;
}
static inline void bch2_folio_reservation_init(struct bch_fs *c,
struct bch_inode_info *inode,
struct bch2_folio_reservation *res)
{
memset(res, 0, sizeof(*res));
res->disk.nr_replicas = inode_nr_replicas(c, inode);
}
int bch2_folio_set(struct bch_fs *, subvol_inum, struct folio **, unsigned);
void bch2_bio_page_state_set(struct bio *, struct bkey_s_c);
void bch2_mark_pagecache_unallocated(struct bch_inode_info *, u64, u64);
void bch2_mark_pagecache_reserved(struct bch_inode_info *, u64, u64);
int bch2_get_folio_disk_reservation(struct bch_fs *,
struct bch_inode_info *,
struct folio *, bool);
void bch2_folio_reservation_put(struct bch_fs *,
struct bch_inode_info *,
struct bch2_folio_reservation *);
int bch2_folio_reservation_get(struct bch_fs *,
struct bch_inode_info *,
struct folio *,
struct bch2_folio_reservation *,
unsigned, unsigned);
void bch2_set_folio_dirty(struct bch_fs *,
struct bch_inode_info *,
struct folio *,
struct bch2_folio_reservation *,
unsigned, unsigned);
vm_fault_t bch2_page_fault(struct vm_fault *);
vm_fault_t bch2_page_mkwrite(struct vm_fault *);
void bch2_invalidate_folio(struct folio *, size_t, size_t);
bool bch2_release_folio(struct folio *, gfp_t);
loff_t bch2_seek_pagecache_data(struct inode *, loff_t, loff_t, unsigned, bool);
loff_t bch2_seek_pagecache_hole(struct inode *, loff_t, loff_t, unsigned, bool);
int bch2_clamp_data_hole(struct inode *, u64 *, u64 *, unsigned, bool);
#endif /* _BCACHEFS_FS_IO_PAGECACHE_H */
This diff is collapsed.
......@@ -5,28 +5,163 @@
#ifndef NO_BCACHEFS_FS
#include "buckets.h"
#include "fs.h"
#include "io_types.h"
#include "quota.h"
#include <linux/uio.h>
struct quota_res;
struct folio_vec {
struct folio *fv_folio;
size_t fv_offset;
size_t fv_len;
};
static inline struct folio_vec biovec_to_foliovec(struct bio_vec bv)
{
struct folio *folio = page_folio(bv.bv_page);
size_t offset = (folio_page_idx(folio, bv.bv_page) << PAGE_SHIFT) +
bv.bv_offset;
size_t len = min_t(size_t, folio_size(folio) - offset, bv.bv_len);
return (struct folio_vec) {
.fv_folio = folio,
.fv_offset = offset,
.fv_len = len,
};
}
static inline struct folio_vec bio_iter_iovec_folio(struct bio *bio,
struct bvec_iter iter)
{
return biovec_to_foliovec(bio_iter_iovec(bio, iter));
}
#define __bio_for_each_folio(bvl, bio, iter, start) \
for (iter = (start); \
(iter).bi_size && \
((bvl = bio_iter_iovec_folio((bio), (iter))), 1); \
bio_advance_iter_single((bio), &(iter), (bvl).fv_len))
/**
* bio_for_each_folio - iterate over folios within a bio
*
* Like other non-_all versions, this iterates over what bio->bi_iter currently
* points to. This version is for drivers, where the bio may have previously
* been split or cloned.
*/
#define bio_for_each_folio(bvl, bio, iter) \
__bio_for_each_folio(bvl, bio, iter, (bio)->bi_iter)
struct quota_res {
u64 sectors;
};
#ifdef CONFIG_BCACHEFS_QUOTA
static inline void __bch2_quota_reservation_put(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res)
{
BUG_ON(res->sectors > inode->ei_quota_reserved);
bch2_quota_acct(c, inode->ei_qid, Q_SPC,
-((s64) res->sectors), KEY_TYPE_QUOTA_PREALLOC);
inode->ei_quota_reserved -= res->sectors;
res->sectors = 0;
}
static inline void bch2_quota_reservation_put(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res)
{
if (res->sectors) {
mutex_lock(&inode->ei_quota_lock);
__bch2_quota_reservation_put(c, inode, res);
mutex_unlock(&inode->ei_quota_lock);
}
}
static inline int bch2_quota_reservation_add(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res,
u64 sectors,
bool check_enospc)
{
int ret;
if (test_bit(EI_INODE_SNAPSHOT, &inode->ei_flags))
return 0;
mutex_lock(&inode->ei_quota_lock);
ret = bch2_quota_acct(c, inode->ei_qid, Q_SPC, sectors,
check_enospc ? KEY_TYPE_QUOTA_PREALLOC : KEY_TYPE_QUOTA_NOCHECK);
if (likely(!ret)) {
inode->ei_quota_reserved += sectors;
res->sectors += sectors;
}
mutex_unlock(&inode->ei_quota_lock);
return ret;
}
int __must_check bch2_write_inode_size(struct bch_fs *,
struct bch_inode_info *,
loff_t, unsigned);
#else
static inline void __bch2_quota_reservation_put(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res) {}
int bch2_read_folio(struct file *, struct folio *);
static inline void bch2_quota_reservation_put(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res) {}
int bch2_writepages(struct address_space *, struct writeback_control *);
void bch2_readahead(struct readahead_control *);
static inline int bch2_quota_reservation_add(struct bch_fs *c,
struct bch_inode_info *inode,
struct quota_res *res,
unsigned sectors,
bool check_enospc)
{
return 0;
}
int bch2_write_begin(struct file *, struct address_space *, loff_t,
unsigned, struct page **, void **);
int bch2_write_end(struct file *, struct address_space *, loff_t,
unsigned, unsigned, struct page *, void *);
#endif
ssize_t bch2_read_iter(struct kiocb *, struct iov_iter *);
ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
void __bch2_i_sectors_acct(struct bch_fs *, struct bch_inode_info *,
struct quota_res *, s64);
static inline void bch2_i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
struct quota_res *quota_res, s64 sectors)
{
if (sectors) {
mutex_lock(&inode->ei_quota_lock);
__bch2_i_sectors_acct(c, inode, quota_res, sectors);
mutex_unlock(&inode->ei_quota_lock);
}
}
static inline struct address_space *faults_disabled_mapping(void)
{
return (void *) (((unsigned long) current->faults_disabled_mapping) & ~1UL);
}
static inline void set_fdm_dropped_locks(void)
{
current->faults_disabled_mapping =
(void *) (((unsigned long) current->faults_disabled_mapping)|1);
}
static inline bool fdm_dropped_locks(void)
{
return ((unsigned long) current->faults_disabled_mapping) & 1;
}
void bch2_inode_flush_nocow_writes_async(struct bch_fs *,
struct bch_inode_info *, struct closure *);
int __must_check bch2_write_inode_size(struct bch_fs *,
struct bch_inode_info *,
loff_t, unsigned);
int bch2_fsync(struct file *, loff_t, loff_t, int);
......@@ -39,11 +174,6 @@ 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_invalidate_folio(struct folio *, size_t, size_t);
bool bch2_release_folio(struct folio *, gfp_t);
void bch2_fs_fsio_exit(struct bch_fs *);
int bch2_fs_fsio_init(struct bch_fs *);
#else
......
......@@ -14,6 +14,9 @@
#include "fs-common.h"
#include "fs-io.h"
#include "fs-ioctl.h"
#include "fs-io-buffered.h"
#include "fs-io-direct.h"
#include "fs-io-pagecache.h"
#include "fsck.h"
#include "inode.h"
#include "io.h"
......
......@@ -30,6 +30,8 @@
#include "error.h"
#include "fs.h"
#include "fs-io.h"
#include "fs-io-buffered.h"
#include "fs-io-direct.h"
#include "fsck.h"
#include "inode.h"
#include "io.h"
......@@ -469,6 +471,8 @@ static void __bch2_fs_free(struct bch_fs *c)
bch2_fs_counters_exit(c);
bch2_fs_snapshots_exit(c);
bch2_fs_quota_exit(c);
bch2_fs_fs_io_direct_exit(c);
bch2_fs_fs_io_buffered_exit(c);
bch2_fs_fsio_exit(c);
bch2_fs_ec_exit(c);
bch2_fs_encryption_exit(c);
......@@ -842,7 +846,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_fs_encryption_init(c) ?:
bch2_fs_compress_init(c) ?:
bch2_fs_ec_init(c) ?:
bch2_fs_fsio_init(c);
bch2_fs_fsio_init(c) ?:
bch2_fs_fs_io_buffered_init(c);
bch2_fs_fs_io_direct_init(c);
if (ret)
goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment