185 lines
4.8 KiB
C
185 lines
4.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _BCACHEFS_FS_IO_H
|
|
#define _BCACHEFS_FS_IO_H
|
|
|
|
#ifndef NO_BCACHEFS_FS
|
|
|
|
#include "buckets.h"
|
|
#include "fs.h"
|
|
#include "io_write_types.h"
|
|
#include "quota.h"
|
|
|
|
#include <linux/uio.h>
|
|
|
|
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;
|
|
}
|
|
|
|
#else
|
|
|
|
static inline void __bch2_quota_reservation_put(struct bch_fs *c,
|
|
struct bch_inode_info *inode,
|
|
struct quota_res *res) {}
|
|
|
|
static inline void bch2_quota_reservation_put(struct bch_fs *c,
|
|
struct bch_inode_info *inode,
|
|
struct quota_res *res) {}
|
|
|
|
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;
|
|
}
|
|
|
|
#endif
|
|
|
|
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);
|
|
|
|
int bchfs_truncate(struct mnt_idmap *,
|
|
struct bch_inode_info *, struct iattr *);
|
|
long bch2_fallocate_dispatch(struct file *, int, loff_t, loff_t);
|
|
|
|
loff_t bch2_remap_file_range(struct file *, loff_t, struct file *,
|
|
loff_t, loff_t, unsigned);
|
|
|
|
loff_t bch2_llseek(struct file *, loff_t, int);
|
|
|
|
void bch2_fs_fsio_exit(struct bch_fs *);
|
|
int bch2_fs_fsio_init(struct bch_fs *);
|
|
#else
|
|
static inline void bch2_fs_fsio_exit(struct bch_fs *c) {}
|
|
static inline int bch2_fs_fsio_init(struct bch_fs *c) { return 0; }
|
|
#endif
|
|
|
|
#endif /* _BCACHEFS_FS_IO_H */
|