]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/io.c
Update bcachefs sources to 50d6a25d9c bcachefs: Erasure coding fixes
[bcachefs-tools-debian] / libbcachefs / io.c
index c4c28559a49c43d80f51d8c2a61800da99bfa7c9..5a3c9eff1b50dbd8a6106098e0e7b15a272dbbb0 100644 (file)
@@ -187,7 +187,6 @@ void bch2_bio_alloc_pages_pool(struct bch_fs *c, struct bio *bio,
 int bch2_sum_sector_overwrites(struct btree_trans *trans,
                               struct btree_iter *extent_iter,
                               struct bkey_i *new,
-                              bool *maybe_extending,
                               bool *usage_increasing,
                               s64 *i_sectors_delta,
                               s64 *disk_sectors_delta)
@@ -199,7 +198,6 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
        bool new_compressed = bch2_bkey_sectors_compressed(bkey_i_to_s_c(new));
        int ret = 0;
 
-       *maybe_extending        = true;
        *usage_increasing       = false;
        *i_sectors_delta        = 0;
        *disk_sectors_delta     = 0;
@@ -226,31 +224,8 @@ int bch2_sum_sector_overwrites(struct btree_trans *trans,
                     (!new_compressed && bch2_bkey_sectors_compressed(old))))
                        *usage_increasing = true;
 
-               if (bkey_cmp(old.k->p, new->k.p) >= 0) {
-                       /*
-                        * Check if there's already data above where we're
-                        * going to be writing to - this means we're definitely
-                        * not extending the file:
-                        *
-                        * Note that it's not sufficient to check if there's
-                        * data up to the sector offset we're going to be
-                        * writing to, because i_size could be up to one block
-                        * less:
-                        */
-                       if (!bkey_cmp(old.k->p, new->k.p)) {
-                               old = bch2_btree_iter_next(&iter);
-                               ret = bkey_err(old);
-                               if (ret)
-                                       break;
-                       }
-
-                       if (old.k && !bkey_err(old) &&
-                           old.k->p.inode == extent_iter->pos.inode &&
-                           bkey_extent_is_data(old.k))
-                               *maybe_extending = false;
-
+               if (bkey_cmp(old.k->p, new->k.p) >= 0)
                        break;
-               }
        }
 
        bch2_trans_iter_exit(trans, &iter);
@@ -267,10 +242,10 @@ int bch2_extent_update(struct btree_trans *trans,
                       s64 *i_sectors_delta_total,
                       bool check_enospc)
 {
-       /* this must live until after bch2_trans_commit(): */
-       struct bkey_inode_buf inode_p;
+       struct btree_iter inode_iter;
+       struct bch_inode_unpacked inode_u;
        struct bpos next_pos;
-       bool extending = false, usage_increasing;
+       bool usage_increasing;
        s64 i_sectors_delta = 0, disk_sectors_delta = 0;
        int ret;
 
@@ -288,89 +263,51 @@ int bch2_extent_update(struct btree_trans *trans,
        if (ret)
                return ret;
 
+       new_i_size = min(k->k.p.offset << 9, new_i_size);
+       next_pos = k->k.p;
+
        ret = bch2_sum_sector_overwrites(trans, iter, k,
-                       &extending,
                        &usage_increasing,
                        &i_sectors_delta,
                        &disk_sectors_delta);
        if (ret)
                return ret;
 
-       if (!usage_increasing)
-               check_enospc = false;
-
        if (disk_res &&
            disk_sectors_delta > (s64) disk_res->sectors) {
                ret = bch2_disk_reservation_add(trans->c, disk_res,
                                        disk_sectors_delta - disk_res->sectors,
-                                       !check_enospc
+                                       !check_enospc || !usage_increasing
                                        ? BCH_DISK_RESERVATION_NOFAIL : 0);
                if (ret)
                        return ret;
        }
 
-       new_i_size = extending
-               ? min(k->k.p.offset << 9, new_i_size)
-               : 0;
-
-       if (i_sectors_delta || new_i_size) {
-               struct btree_iter inode_iter;
-               struct bch_inode_unpacked inode_u;
-
-               ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inum,
-                                     BTREE_ITER_INTENT);
-               if (ret)
-                       return ret;
-
-               /*
-                * XXX:
-                * writeback can race a bit with truncate, because truncate
-                * first updates the inode then truncates the pagecache. This is
-                * ugly, but lets us preserve the invariant that the in memory
-                * i_size is always >= the on disk i_size.
-                *
-               BUG_ON(new_i_size > inode_u.bi_size &&
-                      (inode_u.bi_flags & BCH_INODE_I_SIZE_DIRTY));
-                */
-               BUG_ON(new_i_size > inode_u.bi_size && !extending);
-
-               if (!(inode_u.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
-                   new_i_size > inode_u.bi_size)
-                       inode_u.bi_size = new_i_size;
-               else
-                       new_i_size = 0;
-
-               inode_u.bi_sectors += i_sectors_delta;
-
-               if (i_sectors_delta || new_i_size) {
-                       bch2_inode_pack(trans->c, &inode_p, &inode_u);
-
-                       inode_p.inode.k.p.snapshot = iter->snapshot;
-
-                       ret = bch2_trans_update(trans, &inode_iter,
-                                         &inode_p.inode.k_i, 0);
-               }
-
-               bch2_trans_iter_exit(trans, &inode_iter);
+       ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inum,
+                             BTREE_ITER_INTENT);
+       if (ret)
+               return ret;
 
-               if (ret)
-                       return ret;
-       }
+       if (!(inode_u.bi_flags & BCH_INODE_I_SIZE_DIRTY) &&
+           new_i_size > inode_u.bi_size)
+               inode_u.bi_size = new_i_size;
 
-       next_pos = k->k.p;
+       inode_u.bi_sectors += i_sectors_delta;
 
        ret =   bch2_trans_update(trans, iter, k, 0) ?:
+               bch2_inode_write(trans, &inode_iter, &inode_u) ?:
                bch2_trans_commit(trans, disk_res, journal_seq,
                                BTREE_INSERT_NOCHECK_RW|
                                BTREE_INSERT_NOFAIL);
-       BUG_ON(ret == -ENOSPC);
+       bch2_trans_iter_exit(trans, &inode_iter);
+
        if (ret)
                return ret;
 
-       bch2_btree_iter_set_pos(iter, next_pos);
-
        if (i_sectors_delta_total)
                *i_sectors_delta_total += i_sectors_delta;
+       bch2_btree_iter_set_pos(iter, next_pos);
+
        return 0;
 }
 
@@ -379,7 +316,7 @@ int bch2_extent_update(struct btree_trans *trans,
  */
 int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
                   subvol_inum inum, u64 end,
-                  u64 *journal_seq, s64 *i_sectors_delta)
+                  s64 *i_sectors_delta)
 {
        struct bch_fs *c        = trans->c;
        unsigned max_sectors    = KEY_SIZE_MAX & (~0 << c->block_bits);
@@ -388,26 +325,31 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
        int ret = 0, ret2 = 0;
        u32 snapshot;
 
-       while (1) {
+       while (!ret || ret == -EINTR) {
                struct disk_reservation disk_res =
                        bch2_disk_reservation_init(c, 0);
                struct bkey_i delete;
 
+               if (ret)
+                       ret2 = ret;
+
                bch2_trans_begin(trans);
 
                ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
                if (ret)
-                       goto btree_err;
+                       continue;
 
                bch2_btree_iter_set_snapshot(iter, snapshot);
 
                k = bch2_btree_iter_peek(iter);
-               if (bkey_cmp(iter->pos, end_pos) >= 0)
+               if (bkey_cmp(iter->pos, end_pos) >= 0) {
+                       bch2_btree_iter_set_pos(iter, end_pos);
                        break;
+               }
 
                ret = bkey_err(k);
                if (ret)
-                       goto btree_err;
+                       continue;
 
                bkey_init(&delete.k);
                delete.k.p = iter->pos;
@@ -417,26 +359,16 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
                bch2_cut_back(end_pos, &delete);
 
                ret = bch2_extent_update(trans, inum, iter, &delete,
-                               &disk_res, journal_seq,
+                               &disk_res, NULL,
                                0, i_sectors_delta, false);
                bch2_disk_reservation_put(c, &disk_res);
-btree_err:
-               if (ret == -EINTR) {
-                       ret2 = ret;
-                       ret = 0;
-               }
-               if (ret)
-                       break;
        }
 
-       if (bkey_cmp(iter->pos, end_pos) > 0)
-               bch2_btree_iter_set_pos(iter, end_pos);
-
        return ret ?: ret2;
 }
 
 int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
-               u64 *journal_seq, s64 *i_sectors_delta)
+               s64 *i_sectors_delta)
 {
        struct btree_trans trans;
        struct btree_iter iter;
@@ -447,8 +379,7 @@ int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
                             POS(inum.inum, start),
                             BTREE_ITER_INTENT);
 
-       ret = bch2_fpunch_at(&trans, &iter, inum, end,
-                            journal_seq, i_sectors_delta);
+       ret = bch2_fpunch_at(&trans, &iter, inum, end, i_sectors_delta);
 
        bch2_trans_iter_exit(&trans, &iter);
        bch2_trans_exit(&trans);
@@ -460,6 +391,7 @@ int bch2_write_index_default(struct bch_write_op *op)
 {
        struct bch_fs *c = op->c;
        struct bkey_buf sk;
+       struct open_bucket *ec_ob = ec_open_bucket(c, &op->open_buckets);
        struct keylist *keys = &op->insert_keys;
        struct bkey_i *k = bch2_keylist_front(keys);
        struct btree_trans trans;
@@ -503,6 +435,9 @@ int bch2_write_index_default(struct bch_write_op *op)
                if (ret)
                        break;
 
+               if (ec_ob)
+                       bch2_ob_add_backpointer(c, ec_ob, &sk.k->k);
+
                if (bkey_cmp(iter.pos, k->k.p) >= 0)
                        bch2_keylist_pop_front(&op->insert_keys);
                else
@@ -949,7 +884,6 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
        struct bio *src = &op->wbio.bio, *dst = src;
        struct bvec_iter saved_iter;
        void *ec_buf;
-       struct bpos ec_pos = op->pos;
        unsigned total_output = 0, total_input = 0;
        bool bounce = false;
        bool page_alloc_failed = false;
@@ -1119,9 +1053,6 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
 
        dst->bi_iter.bi_size = total_output;
 do_write:
-       /* might have done a realloc... */
-       bch2_ec_add_backpointer(c, wp, ec_pos, total_input >> 9);
-
        *_dst = dst;
        return more;
 csum_err:
@@ -2108,7 +2039,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
        EBUG_ON(offset_into_extent + bvec_iter_sectors(iter) > k.k->size);
 
        if (crc_is_compressed(pick.crc) ||
-           (pick.crc.csum_type != BCH_CSUM_NONE &&
+           (pick.crc.csum_type != BCH_CSUM_none &&
             (bvec_iter_sectors(iter) != pick.crc.uncompressed_size ||
              (bch2_csum_type_is_encryption(pick.crc.csum_type) &&
               (flags & BCH_READ_USER_MAPPED)) ||
@@ -2392,6 +2323,10 @@ retry:
 
                swap(bvec_iter.bi_size, bytes);
                bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
+
+               ret = btree_trans_too_many_iters(&trans);
+               if (ret)
+                       break;
        }
 err:
        bch2_trans_iter_exit(&trans, &iter);