]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/io_write.c
Update bcachefs sources to 72740a707b64 bcachefs: Split brain detection
[bcachefs-tools-debian] / libbcachefs / io_write.c
index fbfc42ff08036a17efec5fe573fede3335cce24d..c5961bac19f0087772b2dbc01b386ea173c6b09f 100644 (file)
@@ -202,6 +202,17 @@ static inline int bch2_extent_update_i_size_sectors(struct btree_trans *trans,
        struct btree_iter iter;
        struct bkey_i *k;
        struct bkey_i_inode_v3 *inode;
+       /*
+        * Crazy performance optimization:
+        * Every extent update needs to also update the inode: the inode trigger
+        * will set bi->journal_seq to the journal sequence number of this
+        * transaction - for fsync.
+        *
+        * But if that's the only reason we're updating the inode (we're not
+        * updating bi_size or bi_sectors), then we don't need the inode update
+        * to be journalled - if we crash, the bi_journal_seq update will be
+        * lost, but that's fine.
+        */
        unsigned inode_update_flags = BTREE_UPDATE_NOJOURNAL;
        int ret;
 
@@ -305,8 +316,8 @@ int bch2_extent_update(struct btree_trans *trans,
                                                  i_sectors_delta) ?:
                bch2_trans_update(trans, iter, k, 0) ?:
                bch2_trans_commit(trans, disk_res, NULL,
-                               BTREE_INSERT_NOCHECK_RW|
-                               BTREE_INSERT_NOFAIL);
+                               BCH_TRANS_COMMIT_no_check_rw|
+                               BCH_TRANS_COMMIT_no_enospc);
        if (unlikely(ret))
                return ret;
 
@@ -385,17 +396,14 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
                               bool nocow)
 {
        struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(k));
-       const struct bch_extent_ptr *ptr;
        struct bch_write_bio *n;
-       struct bch_dev *ca;
 
        BUG_ON(c->opts.nochanges);
 
        bkey_for_each_ptr(ptrs, ptr) {
-               BUG_ON(ptr->dev >= BCH_SB_MEMBERS_MAX ||
-                      !c->devs[ptr->dev]);
+               BUG_ON(!bch2_dev_exists2(c, ptr->dev));
 
-               ca = bch_dev_bkey_exists(c, ptr->dev);
+               struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
 
                if (to_entry(ptr + 1) < ptrs.end) {
                        n = to_wbio(bio_alloc_clone(NULL, &wbio->bio,
@@ -569,9 +577,9 @@ static inline void wp_update_state(struct write_point *wp, bool running)
        __wp_update_state(wp, state);
 }
 
-static void bch2_write_index(struct closure *cl)
+static CLOSURE_CALLBACK(bch2_write_index)
 {
-       struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
+       closure_type(op, struct bch_write_op, cl);
        struct write_point *wp = op->wp;
        struct workqueue_struct *wq = index_update_wq(op);
        unsigned long flags;
@@ -784,7 +792,7 @@ static int bch2_write_decrypt(struct bch_write_op *op)
         * checksum:
         */
        csum = bch2_checksum_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
-       if (bch2_crc_cmp(op->crc.csum, csum))
+       if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
                return -EIO;
 
        ret = bch2_encrypt_bio(c, op->crc.csum_type, nonce, &op->wbio.bio);
@@ -1098,16 +1106,14 @@ static bool bch2_extent_is_writeable(struct bch_write_op *op,
 static inline void bch2_nocow_write_unlock(struct bch_write_op *op)
 {
        struct bch_fs *c = op->c;
-       const struct bch_extent_ptr *ptr;
-       struct bkey_i *k;
 
        for_each_keylist_key(&op->insert_keys, k) {
                struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(k));
 
                bkey_for_each_ptr(ptrs, ptr)
                        bch2_bucket_nocow_unlock(&c->nocow_locks,
-                                              PTR_BUCKET_POS(c, ptr),
-                                              BUCKET_NOCOW_LOCK_UPDATE);
+                                                PTR_BUCKET_POS(c, ptr),
+                                                BUCKET_NOCOW_LOCK_UPDATE);
        }
 }
 
@@ -1117,25 +1123,20 @@ static int bch2_nocow_write_convert_one_unwritten(struct btree_trans *trans,
                                                  struct bkey_s_c k,
                                                  u64 new_i_size)
 {
-       struct bkey_i *new;
-       struct bkey_ptrs ptrs;
-       struct bch_extent_ptr *ptr;
-       int ret;
-
        if (!bch2_extents_match(bkey_i_to_s_c(orig), k)) {
                /* trace this */
                return 0;
        }
 
-       new = bch2_bkey_make_mut_noupdate(trans, k);
-       ret = PTR_ERR_OR_ZERO(new);
+       struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k);
+       int ret = PTR_ERR_OR_ZERO(new);
        if (ret)
                return ret;
 
        bch2_cut_front(bkey_start_pos(&orig->k), new);
        bch2_cut_back(orig->k.p, new);
 
-       ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
+       struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
        bkey_for_each_ptr(ptrs, ptr)
                ptr->unwritten = 0;
 
@@ -1156,16 +1157,12 @@ static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op)
 {
        struct bch_fs *c = op->c;
        struct btree_trans *trans = bch2_trans_get(c);
-       struct btree_iter iter;
-       struct bkey_i *orig;
-       struct bkey_s_c k;
-       int ret;
 
        for_each_keylist_key(&op->insert_keys, orig) {
-               ret = for_each_btree_key_upto_commit(trans, iter, BTREE_ID_extents,
+               int ret = for_each_btree_key_upto_commit(trans, iter, BTREE_ID_extents,
                                     bkey_start_pos(&orig->k), orig->k.p,
                                     BTREE_ITER_INTENT, k,
-                                    NULL, NULL, BTREE_INSERT_NOFAIL, ({
+                                    NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
                        bch2_nocow_write_convert_one_unwritten(trans, &iter, orig, k, op->new_i_size);
                }));
 
@@ -1197,9 +1194,9 @@ static void __bch2_nocow_write_done(struct bch_write_op *op)
                bch2_nocow_write_convert_unwritten(op);
 }
 
-static void bch2_nocow_write_done(struct closure *cl)
+static CLOSURE_CALLBACK(bch2_nocow_write_done)
 {
-       struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
+       closure_type(op, struct bch_write_op, cl);
 
        __bch2_nocow_write_done(op);
        bch2_write_done(cl);
@@ -1211,8 +1208,6 @@ static void bch2_nocow_write(struct bch_write_op *op)
        struct btree_trans *trans;
        struct btree_iter iter;
        struct bkey_s_c k;
-       struct bkey_ptrs_c ptrs;
-       const struct bch_extent_ptr *ptr;
        struct {
                struct bpos     b;
                unsigned        gen;
@@ -1258,7 +1253,7 @@ retry:
                        break;
 
                /* Get iorefs before dropping btree locks: */
-               ptrs = bch2_bkey_ptrs_c(k);
+               struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
                bkey_for_each_ptr(ptrs, ptr) {
                        buckets[nr_buckets].b = PTR_BUCKET_POS(c, ptr);
                        buckets[nr_buckets].gen = ptr->gen;
@@ -1352,7 +1347,7 @@ err:
                op->insert_keys.top = op->insert_keys.keys;
        } else if (op->flags & BCH_WRITE_SYNC) {
                closure_sync(&op->cl);
-               bch2_nocow_write_done(&op->cl);
+               bch2_nocow_write_done(&op->cl.work);
        } else {
                /*
                 * XXX
@@ -1453,6 +1448,10 @@ err:
                        op->flags |= BCH_WRITE_DONE;
 
                        if (ret < 0) {
+                               bch_err_inum_offset_ratelimited(c,
+                                       op->pos.inode,
+                                       op->pos.offset << 9,
+                                       "%s(): error: %s", __func__, bch2_err_str(ret));
                                op->error = ret;
                                break;
                        }
@@ -1555,9 +1554,9 @@ err:
  * If op->discard is true, instead of inserting the data it invalidates the
  * region of the cache represented by op->bio and op->inode.
  */
-void bch2_write(struct closure *cl)
+CLOSURE_CALLBACK(bch2_write)
 {
-       struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
+       closure_type(op, struct bch_write_op, cl);
        struct bio *bio = &op->wbio.bio;
        struct bch_fs *c = op->c;
        unsigned data_len;