]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/io_read.h
Move c_src dirs back to toplevel
[bcachefs-tools-debian] / libbcachefs / io_read.h
diff --git a/libbcachefs/io_read.h b/libbcachefs/io_read.h
new file mode 100644 (file)
index 0000000..d9c18bb
--- /dev/null
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _BCACHEFS_IO_READ_H
+#define _BCACHEFS_IO_READ_H
+
+#include "bkey_buf.h"
+
+struct bch_read_bio {
+       struct bch_fs           *c;
+       u64                     start_time;
+       u64                     submit_time;
+
+       /*
+        * Reads will often have to be split, and if the extent being read from
+        * was checksummed or compressed we'll also have to allocate bounce
+        * buffers and copy the data back into the original bio.
+        *
+        * If we didn't have to split, we have to save and restore the original
+        * bi_end_io - @split below indicates which:
+        */
+       union {
+       struct bch_read_bio     *parent;
+       bio_end_io_t            *end_io;
+       };
+
+       /*
+        * Saved copy of bio->bi_iter, from submission time - allows us to
+        * resubmit on IO error, and also to copy data back to the original bio
+        * when we're bouncing:
+        */
+       struct bvec_iter        bvec_iter;
+
+       unsigned                offset_into_extent;
+
+       u16                     flags;
+       union {
+       struct {
+       u16                     bounce:1,
+                               split:1,
+                               kmalloc:1,
+                               have_ioref:1,
+                               narrow_crcs:1,
+                               hole:1,
+                               retry:2,
+                               context:2;
+       };
+       u16                     _state;
+       };
+
+       struct bch_devs_list    devs_have;
+
+       struct extent_ptr_decoded pick;
+
+       /*
+        * pos we read from - different from data_pos for indirect extents:
+        */
+       u32                     subvol;
+       struct bpos             read_pos;
+
+       /*
+        * start pos of data we read (may not be pos of data we want) - for
+        * promote, narrow extents paths:
+        */
+       enum btree_id           data_btree;
+       struct bpos             data_pos;
+       struct bversion         version;
+
+       struct promote_op       *promote;
+
+       struct bch_io_opts      opts;
+
+       struct work_struct      work;
+
+       struct bio              bio;
+};
+
+#define to_rbio(_bio)          container_of((_bio), struct bch_read_bio, bio)
+
+struct bch_devs_mask;
+struct cache_promote_op;
+struct extent_ptr_decoded;
+
+int __bch2_read_indirect_extent(struct btree_trans *, unsigned *,
+                               struct bkey_buf *);
+
+static inline int bch2_read_indirect_extent(struct btree_trans *trans,
+                                           enum btree_id *data_btree,
+                                           unsigned *offset_into_extent,
+                                           struct bkey_buf *k)
+{
+       if (k->k->k.type != KEY_TYPE_reflink_p)
+               return 0;
+
+       *data_btree = BTREE_ID_reflink;
+       return __bch2_read_indirect_extent(trans, offset_into_extent, k);
+}
+
+enum bch_read_flags {
+       BCH_READ_RETRY_IF_STALE         = 1 << 0,
+       BCH_READ_MAY_PROMOTE            = 1 << 1,
+       BCH_READ_USER_MAPPED            = 1 << 2,
+       BCH_READ_NODECODE               = 1 << 3,
+       BCH_READ_LAST_FRAGMENT          = 1 << 4,
+
+       /* internal: */
+       BCH_READ_MUST_BOUNCE            = 1 << 5,
+       BCH_READ_MUST_CLONE             = 1 << 6,
+       BCH_READ_IN_RETRY               = 1 << 7,
+};
+
+int __bch2_read_extent(struct btree_trans *, struct bch_read_bio *,
+                      struct bvec_iter, struct bpos, enum btree_id,
+                      struct bkey_s_c, unsigned,
+                      struct bch_io_failures *, unsigned);
+
+static inline void bch2_read_extent(struct btree_trans *trans,
+                       struct bch_read_bio *rbio, struct bpos read_pos,
+                       enum btree_id data_btree, struct bkey_s_c k,
+                       unsigned offset_into_extent, unsigned flags)
+{
+       __bch2_read_extent(trans, rbio, rbio->bio.bi_iter, read_pos,
+                          data_btree, k, offset_into_extent, NULL, flags);
+}
+
+void __bch2_read(struct bch_fs *, struct bch_read_bio *, struct bvec_iter,
+                subvol_inum, struct bch_io_failures *, unsigned flags);
+
+static inline void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
+                            subvol_inum inum)
+{
+       struct bch_io_failures failed = { .nr = 0 };
+
+       BUG_ON(rbio->_state);
+
+       rbio->c = c;
+       rbio->start_time = local_clock();
+       rbio->subvol = inum.subvol;
+
+       __bch2_read(c, rbio, rbio->bio.bi_iter, inum, &failed,
+                   BCH_READ_RETRY_IF_STALE|
+                   BCH_READ_MAY_PROMOTE|
+                   BCH_READ_USER_MAPPED);
+}
+
+static inline struct bch_read_bio *rbio_init(struct bio *bio,
+                                            struct bch_io_opts opts)
+{
+       struct bch_read_bio *rbio = to_rbio(bio);
+
+       rbio->_state    = 0;
+       rbio->promote   = NULL;
+       rbio->opts      = opts;
+       return rbio;
+}
+
+void bch2_fs_io_read_exit(struct bch_fs *);
+int bch2_fs_io_read_init(struct bch_fs *);
+
+#endif /* _BCACHEFS_IO_READ_H */