]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/fs-io-direct.c
Disable pristine-tar option in gbp.conf, since there is no pristine-tar branch.
[bcachefs-tools-debian] / libbcachefs / fs-io-direct.c
index a5cadc5d78901193affed4820669bca01ffbff09..33cb6da3a5ad28f2c014c2ef12408937933d49c3 100644 (file)
@@ -7,10 +7,12 @@
 #include "fs-io.h"
 #include "fs-io-direct.h"
 #include "fs-io-pagecache.h"
-#include "io.h"
+#include "io_read.h"
+#include "io_write.h"
 
 #include <linux/kthread.h>
 #include <linux/pagemap.h>
+#include <linux/prefetch.h>
 #include <linux/task_io_accounting_ops.h>
 
 /* O_DIRECT reads */
@@ -33,9 +35,9 @@ static void bio_check_or_release(struct bio *bio, bool check_dirty)
        }
 }
 
-static void bch2_dio_read_complete(struct closure *cl)
+static CLOSURE_CALLBACK(bch2_dio_read_complete)
 {
-       struct dio_read *dio = container_of(cl, struct dio_read, cl);
+       closure_type(dio, struct dio_read, cl);
 
        dio->req->ki_complete(dio->req, dio->ret);
        bio_check_or_release(&dio->rbio.bio, dio->should_dirty);
@@ -75,7 +77,8 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
 
        bch2_inode_opts_get(&opts, c, &inode->ei_inode);
 
-       if ((offset|iter->count) & (block_bytes(c) - 1))
+       /* bios must be 512 byte aligned: */
+       if ((offset|iter->count) & (SECTOR_SIZE - 1))
                return -EINVAL;
 
        ret = min_t(loff_t, iter->count,
@@ -85,6 +88,8 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
                return ret;
 
        shorten = iov_iter_count(iter) - round_up(ret, block_bytes(c));
+       if (shorten >= iter->count)
+               shorten = 0;
        iter->count -= shorten;
 
        bio = bio_alloc_bioset(NULL,
@@ -111,6 +116,7 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
        } else {
                atomic_set(&dio->cl.remaining,
                           CLOSURE_REMAINING_INITIALIZER + 1);
+               dio->cl.closure_get_happened = true;
        }
 
        dio->req        = req;
@@ -213,11 +219,11 @@ struct dio_write {
        struct address_space            *mapping;
        struct bch_inode_info           *inode;
        struct mm_struct                *mm;
+       const struct iovec              *iov;
        unsigned                        loop:1,
                                        extending:1,
                                        sync:1,
-                                       flush:1,
-                                       free_iov:1;
+                                       flush:1;
        struct quota_res                quota_res;
        u64                             written;
 
@@ -232,23 +238,21 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum,
                                       u64 offset, u64 size,
                                       unsigned nr_replicas, bool compressed)
 {
-       struct btree_trans trans;
+       struct btree_trans *trans = bch2_trans_get(c);
        struct btree_iter iter;
        struct bkey_s_c k;
        u64 end = offset + size;
        u32 snapshot;
        bool ret = true;
        int err;
-
-       bch2_trans_init(&trans, c, 0, 0);
 retry:
-       bch2_trans_begin(&trans);
+       bch2_trans_begin(trans);
 
-       err = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot);
+       err = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
        if (err)
                goto err;
 
-       for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents,
+       for_each_btree_key_norestart(trans, iter, BTREE_ID_extents,
                           SPOS(inum.inum, offset, snapshot),
                           BTREE_ITER_SLOTS, k, err) {
                if (bkey_ge(bkey_start_pos(k.k), POS(inum.inum, end)))
@@ -263,11 +267,11 @@ retry:
        }
 
        offset = iter.pos.offset;
-       bch2_trans_iter_exit(&trans, &iter);
+       bch2_trans_iter_exit(trans, &iter);
 err:
        if (bch2_err_matches(err, BCH_ERR_transaction_restart))
                goto retry;
-       bch2_trans_exit(&trans);
+       bch2_trans_put(trans);
 
        return err ? false : ret;
 }
@@ -311,12 +315,10 @@ static noinline int bch2_dio_write_copy_iov(struct dio_write *dio)
                return -1;
 
        if (dio->iter.nr_segs > ARRAY_SIZE(dio->inline_vecs)) {
-               iov = kmalloc_array(dio->iter.nr_segs, sizeof(*iov),
+               dio->iov = iov = kmalloc_array(dio->iter.nr_segs, sizeof(*iov),
                                    GFP_KERNEL);
                if (unlikely(!iov))
                        return -ENOMEM;
-
-               dio->free_iov = true;
        }
 
        memcpy(iov, dio->iter.__iov, dio->iter.nr_segs * sizeof(*iov));
@@ -324,9 +326,9 @@ static noinline int bch2_dio_write_copy_iov(struct dio_write *dio)
        return 0;
 }
 
-static void bch2_dio_write_flush_done(struct closure *cl)
+static CLOSURE_CALLBACK(bch2_dio_write_flush_done)
 {
-       struct dio_write *dio = container_of(cl, struct dio_write, op.cl);
+       closure_type(dio, struct dio_write, op.cl);
        struct bch_fs *c = dio->op.c;
 
        closure_debug_destroy(cl);
@@ -351,7 +353,8 @@ static noinline void bch2_dio_write_flush(struct dio_write *dio)
                if (ret) {
                        dio->op.error = ret;
                } else {
-                       bch2_journal_flush_seq_async(&c->journal, inode.bi_journal_seq, &dio->op.cl);
+                       bch2_journal_flush_seq_async(&c->journal, inode.bi_journal_seq,
+                                                    &dio->op.cl);
                        bch2_inode_flush_nocow_writes_async(c, dio->inode, &dio->op.cl);
                }
        }
@@ -379,8 +382,7 @@ static __always_inline long bch2_dio_write_done(struct dio_write *dio)
 
        bch2_pagecache_block_put(inode);
 
-       if (dio->free_iov)
-               kfree(dio->iter.__iov);
+       kfree(dio->iov);
 
        ret = dio->op.error ?: ((long) dio->written << 9);
        bio_put(&dio->op.wbio.bio);
@@ -624,11 +626,11 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
        dio->mapping            = mapping;
        dio->inode              = inode;
        dio->mm                 = current->mm;
+       dio->iov                = NULL;
        dio->loop               = false;
        dio->extending          = extending;
        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;
        dio->iter               = *iter;