bch2_trans_update(&trans, &iter, insert,
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
bch2_trans_commit(&trans, &op->res,
- &op->journal_seq,
+ NULL,
BTREE_INSERT_NOFAIL|
m->data_opts.btree_insert_flags);
if (!ret) {
m->op.flags |= BCH_WRITE_PAGES_STABLE|
BCH_WRITE_PAGES_OWNED|
BCH_WRITE_DATA_ENCODED|
- BCH_WRITE_FROM_INTERNAL|
BCH_WRITE_MOVE|
m->data_opts.write_flags;
m->op.compression_type =
struct mm_struct *mm;
unsigned loop:1,
sync:1,
+ flush:1,
free_iov:1;
struct quota_res quota_res;
u64 written;
dio->op.opts.compression != 0);
}
+static void bch2_dio_write_loop_async(struct bch_write_op *);
+static __always_inline long bch2_dio_write_done(struct dio_write *dio);
+
/*
* We're going to return -EIOCBQUEUED, but we haven't finished consuming the
* iov_iter yet, so we need to stash a copy of the iovec: it might be on the
return 0;
}
-static void bch2_dio_write_loop_async(struct bch_write_op *);
+static void bch2_dio_write_flush_done(struct closure *cl)
+{
+ struct dio_write *dio = container_of(cl, struct dio_write, op.cl);
+ struct bch_fs *c = dio->op.c;
+
+ closure_debug_destroy(cl);
+
+ dio->op.error = bch2_journal_error(&c->journal);
+
+ bch2_dio_write_done(dio);
+}
+
+static noinline void bch2_dio_write_flush(struct dio_write *dio)
+{
+ struct bch_fs *c = dio->op.c;
+ struct bch_inode_unpacked inode;
+ int ret;
+
+ dio->flush = 0;
+
+ closure_init(&dio->op.cl, NULL);
+
+ if (!dio->op.error) {
+ ret = bch2_inode_find_by_inum(c, inode_inum(dio->inode), &inode);
+ if (ret)
+ dio->op.error = ret;
+ else
+ bch2_journal_flush_seq_async(&c->journal, inode.bi_journal_seq, &dio->op.cl);
+ }
+
+ if (dio->sync) {
+ closure_sync(&dio->op.cl);
+ closure_debug_destroy(&dio->op.cl);
+ } else {
+ continue_at(&dio->op.cl, bch2_dio_write_flush_done, NULL);
+ }
+}
static __always_inline long bch2_dio_write_done(struct dio_write *dio)
{
struct kiocb *req = dio->req;
struct bch_inode_info *inode = dio->inode;
bool sync = dio->sync;
- long ret = dio->op.error ?: ((long) dio->written << 9);
+ long ret;
+
+ if (unlikely(dio->flush)) {
+ bch2_dio_write_flush(dio);
+ if (!sync)
+ return -EIOCBQUEUED;
+ }
bch2_pagecache_block_put(&inode->ei_pagecache_lock);
bch2_quota_reservation_put(c, inode, &dio->quota_res);
if (dio->free_iov)
kfree(dio->iter.__iov);
+
+ ret = dio->op.error ?: ((long) dio->written << 9);
bio_put(&dio->op.wbio.bio);
/* inode->i_dio_count is our ref on inode and thus bch_fs */
if (sync)
dio->op.flags |= BCH_WRITE_SYNC;
- if ((req->ki_flags & IOCB_DSYNC) &&
- !c->opts.journal_flush_disabled)
- dio->op.flags |= BCH_WRITE_FLUSH;
dio->op.flags |= BCH_WRITE_CHECK_ENOSPC;
ret = bch2_disk_reservation_get(c, &dio->op.res, bio_sectors(bio),
dio->mm = current->mm;
dio->loop = false;
dio->sync = is_sync_kiocb(req) || extending;
+ dio->flush = iocb_is_dsync(req) && !c->opts.journal_flush_disabled;
dio->free_iov = false;
dio->quota_res.sectors = 0;
dio->written = 0;
}
ret = bch2_extent_update(&trans, inode_inum(inode), &iter,
- &reservation.k_i,
- &disk_res, NULL,
+ &reservation.k_i, &disk_res,
0, &i_sectors_delta, true);
if (ret)
goto bkey_err;
struct btree_iter *iter,
struct bkey_i *k,
struct disk_reservation *disk_res,
- u64 *journal_seq,
u64 new_i_size,
s64 *i_sectors_delta_total,
bool check_enospc)
}
ret = bch2_trans_update(trans, iter, k, 0) ?:
- bch2_trans_commit(trans, disk_res, journal_seq,
+ bch2_trans_commit(trans, disk_res, NULL,
BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL);
err:
bch2_cut_back(end_pos, &delete);
ret = bch2_extent_update(trans, inum, iter, &delete,
- &disk_res, NULL,
- 0, i_sectors_delta, false);
+ &disk_res, 0, i_sectors_delta, false);
bch2_disk_reservation_put(c, &disk_res);
}
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
ret = bch2_extent_update(&trans, inum, &iter, sk.k,
- &op->res, &op->journal_seq,
+ &op->res,
op->new_i_size, &op->i_sectors_delta,
op->flags & BCH_WRITE_CHECK_ENOSPC);
bch2_trans_iter_exit(&trans, &iter);
static void __bch2_write(struct bch_write_op *);
-static void __bch2_write_done(struct closure *cl)
+static void bch2_write_done(struct closure *cl)
{
struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
struct bch_fs *c = op->c;
- if (!op->error && (op->flags & BCH_WRITE_FLUSH))
- op->error = bch2_journal_error(&c->journal);
-
bch2_disk_reservation_put(c, &op->res);
percpu_ref_put(&c->writes);
bch2_keylist_free(&op->insert_keys, op->inline_keys);
op->end_io(op);
}
-static __always_inline void bch2_write_done(struct bch_write_op *op)
-{
- if (likely(!(op->flags & BCH_WRITE_FLUSH) || op->error)) {
- __bch2_write_done(&op->cl);
- } else if (!(op->flags & BCH_WRITE_SYNC)) {
- bch2_journal_flush_seq_async(&op->c->journal,
- op->journal_seq,
- &op->cl);
- continue_at(&op->cl, __bch2_write_done, index_update_wq(op));
- } else {
- bch2_journal_flush_seq(&op->c->journal, op->journal_seq);
- __bch2_write_done(&op->cl);
- }
-}
-
static noinline int bch2_write_drop_io_error_ptrs(struct bch_write_op *op)
{
struct keylist *keys = &op->insert_keys;
__bch2_write_index(op);
- if (!(op->flags & BCH_WRITE_DONE)) {
+ if (!(op->flags & BCH_WRITE_DONE))
__bch2_write(op);
- } else if (!op->error && (op->flags & BCH_WRITE_FLUSH)) {
- bch2_journal_flush_seq_async(&op->c->journal,
- op->journal_seq,
- &op->cl);
- continue_at(&op->cl, __bch2_write_done, index_update_wq(op));
- } else {
- __bch2_write_done(&op->cl);
- }
+ else
+ bch2_write_done(&op->cl);
}
}
if (!(op->flags & BCH_WRITE_DONE))
goto again;
- bch2_write_done(op);
+ bch2_write_done(&op->cl);
} else {
continue_at(&op->cl, bch2_write_index, NULL);
}
__bch2_write_index(op);
err:
- bch2_write_done(op);
+ bch2_write_done(&op->cl);
}
/**
enum bch_write_flags {
__BCH_WRITE_ALLOC_NOWAIT,
__BCH_WRITE_CACHED,
- __BCH_WRITE_FLUSH,
__BCH_WRITE_DATA_ENCODED,
__BCH_WRITE_PAGES_STABLE,
__BCH_WRITE_PAGES_OWNED,
#define BCH_WRITE_ALLOC_NOWAIT (1U << __BCH_WRITE_ALLOC_NOWAIT)
#define BCH_WRITE_CACHED (1U << __BCH_WRITE_CACHED)
-#define BCH_WRITE_FLUSH (1U << __BCH_WRITE_FLUSH)
#define BCH_WRITE_DATA_ENCODED (1U << __BCH_WRITE_DATA_ENCODED)
#define BCH_WRITE_PAGES_STABLE (1U << __BCH_WRITE_PAGES_STABLE)
#define BCH_WRITE_PAGES_OWNED (1U << __BCH_WRITE_PAGES_OWNED)
struct bkey_i *, bool *, bool *, s64 *, s64 *);
int bch2_extent_update(struct btree_trans *, subvol_inum,
struct btree_iter *, struct bkey_i *,
- struct disk_reservation *, u64 *, u64, s64 *, bool);
+ struct disk_reservation *, u64, s64 *, bool);
int bch2_fpunch_at(struct btree_trans *, struct btree_iter *,
subvol_inum, u64, s64 *);
op->version = ZERO_VERSION;
op->write_point = (struct write_point_specifier) { 0 };
op->res = (struct disk_reservation) { 0 };
- op->journal_seq = 0;
op->new_i_size = U64_MAX;
op->i_sectors_delta = 0;
}
struct open_buckets open_buckets;
- u64 journal_seq;
u64 new_i_size;
s64 i_sectors_delta;
dst_end.offset - dst_iter.pos.offset));
ret = bch2_extent_update(&trans, dst_inum, &dst_iter,
- new_dst.k, &disk_res, NULL,
+ new_dst.k, &disk_res,
new_i_size, i_sectors_delta,
true);
bch2_disk_reservation_put(c, &disk_res);