]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/io_write.c
Update bcachefs sources to 9a555a741e80 bcachefs: omit alignment attribute on big...
[bcachefs-tools-debian] / libbcachefs / io_write.c
index abad1d9d20665c267208498a16475c46c6a4c5f5..3fa2cb1d5b13aa3efeb07571879d3e1cb7ed066a 100644 (file)
@@ -88,7 +88,7 @@ void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw)
 
        bch2_congested_acct(ca, io_latency, now, rw);
 
-       __bch2_time_stats_update(&ca->io_latency[rw], submit_time, now);
+       __time_stats_update(&ca->io_latency[rw].stats, submit_time, now);
 }
 
 #endif
@@ -362,9 +362,7 @@ static int bch2_write_index_default(struct bch_write_op *op)
                                     bkey_start_pos(&sk.k->k),
                                     BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
 
-               ret =   bch2_bkey_set_needs_rebalance(c, sk.k,
-                                       op->opts.background_target,
-                                       op->opts.background_compression) ?:
+               ret =   bch2_bkey_set_needs_rebalance(c, sk.k, &op->opts) ?:
                        bch2_extent_update(trans, inum, &iter, sk.k,
                                        &op->res,
                                        op->new_i_size, &op->i_sectors_delta,
@@ -396,16 +394,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(!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,
@@ -461,7 +457,7 @@ static void bch2_write_done(struct closure *cl)
 
        EBUG_ON(op->open_buckets.nr);
 
-       bch2_time_stats_update(&c->times[BCH_TIME_data_write], op->start_time);
+       time_stats_update(&c->times[BCH_TIME_data_write], op->start_time);
        bch2_disk_reservation_put(c, &op->res);
 
        if (!(op->flags & BCH_WRITE_MOVE))
@@ -1108,16 +1104,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);
        }
 }
 
@@ -1127,25 +1121,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;
 
@@ -1166,11 +1155,9 @@ 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 bkey_i *orig;
-       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, BCH_TRANS_COMMIT_no_enospc, ({
@@ -1213,26 +1200,27 @@ static CLOSURE_CALLBACK(bch2_nocow_write_done)
        bch2_write_done(cl);
 }
 
+struct bucket_to_lock {
+       struct bpos             b;
+       unsigned                gen;
+       struct nocow_lock_bucket *l;
+};
+
 static void bch2_nocow_write(struct bch_write_op *op)
 {
        struct bch_fs *c = op->c;
        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;
-               struct nocow_lock_bucket *l;
-       } buckets[BCH_REPLICAS_MAX];
-       unsigned nr_buckets = 0;
+       DARRAY_PREALLOCATED(struct bucket_to_lock, 3) buckets;
        u32 snapshot;
-       int ret, i;
+       struct bucket_to_lock *stale_at;
+       int ret;
 
        if (op->flags & BCH_WRITE_MOVE)
                return;
 
+       darray_init(&buckets);
        trans = bch2_trans_get(c);
 retry:
        bch2_trans_begin(trans);
@@ -1247,7 +1235,7 @@ retry:
        while (1) {
                struct bio *bio = &op->wbio.bio;
 
-               nr_buckets = 0;
+               buckets.nr = 0;
 
                k = bch2_btree_iter_peek_slot(&iter);
                ret = bkey_err(k);
@@ -1260,26 +1248,26 @@ retry:
                        break;
 
                if (bch2_keylist_realloc(&op->insert_keys,
-                                       op->inline_keys,
-                                       ARRAY_SIZE(op->inline_keys),
-                                       k.k->u64s))
+                                        op->inline_keys,
+                                        ARRAY_SIZE(op->inline_keys),
+                                        k.k->u64s))
                        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;
-                       buckets[nr_buckets].l =
-                               bucket_nocow_lock(&c->nocow_locks,
-                                                 bucket_to_u64(buckets[nr_buckets].b));
-
-                       prefetch(buckets[nr_buckets].l);
+                       struct bpos b = PTR_BUCKET_POS(c, ptr);
+                       struct nocow_lock_bucket *l =
+                               bucket_nocow_lock(&c->nocow_locks, bucket_to_u64(b));
+                       prefetch(l);
 
                        if (unlikely(!bch2_dev_get_ioref(bch_dev_bkey_exists(c, ptr->dev), WRITE)))
                                goto err_get_ioref;
 
-                       nr_buckets++;
+                       /* XXX allocating memory with btree locks held - rare */
+                       darray_push_gfp(&buckets, ((struct bucket_to_lock) {
+                                                  .b = b, .gen = ptr->gen, .l = l,
+                                                  }), GFP_KERNEL|__GFP_NOFAIL);
 
                        if (ptr->unwritten)
                                op->flags |= BCH_WRITE_CONVERT_UNWRITTEN;
@@ -1293,21 +1281,21 @@ retry:
                if (op->flags & BCH_WRITE_CONVERT_UNWRITTEN)
                        bch2_cut_back(POS(op->pos.inode, op->pos.offset + bio_sectors(bio)), op->insert_keys.top);
 
-               for (i = 0; i < nr_buckets; i++) {
-                       struct bch_dev *ca = bch_dev_bkey_exists(c, buckets[i].b.inode);
-                       struct nocow_lock_bucket *l = buckets[i].l;
-                       bool stale;
+               darray_for_each(buckets, i) {
+                       struct bch_dev *ca = bch_dev_bkey_exists(c, i->b.inode);
 
-                       __bch2_bucket_nocow_lock(&c->nocow_locks, l,
-                                                bucket_to_u64(buckets[i].b),
+                       __bch2_bucket_nocow_lock(&c->nocow_locks, i->l,
+                                                bucket_to_u64(i->b),
                                                 BUCKET_NOCOW_LOCK_UPDATE);
 
                        rcu_read_lock();
-                       stale = gen_after(*bucket_gen(ca, buckets[i].b.offset), buckets[i].gen);
+                       bool stale = gen_after(*bucket_gen(ca, i->b.offset), i->gen);
                        rcu_read_unlock();
 
-                       if (unlikely(stale))
+                       if (unlikely(stale)) {
+                               stale_at = i;
                                goto err_bucket_stale;
+                       }
                }
 
                bio = &op->wbio.bio;
@@ -1343,15 +1331,14 @@ err:
 
        if (ret) {
                bch_err_inum_offset_ratelimited(c,
-                               op->pos.inode,
-                               op->pos.offset << 9,
-                               "%s: btree lookup error %s",
-                               __func__, bch2_err_str(ret));
+                       op->pos.inode, op->pos.offset << 9,
+                       "%s: btree lookup error %s", __func__, bch2_err_str(ret));
                op->error = ret;
                op->flags |= BCH_WRITE_DONE;
        }
 
        bch2_trans_put(trans);
+       darray_exit(&buckets);
 
        /* fallback to cow write path? */
        if (!(op->flags & BCH_WRITE_DONE)) {
@@ -1371,24 +1358,21 @@ err:
        }
        return;
 err_get_ioref:
-       for (i = 0; i < nr_buckets; i++)
-               percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref);
+       darray_for_each(buckets, i)
+               percpu_ref_put(&bch_dev_bkey_exists(c, i->b.inode)->io_ref);
 
        /* Fall back to COW path: */
        goto out;
 err_bucket_stale:
-       while (i >= 0) {
-               bch2_bucket_nocow_unlock(&c->nocow_locks,
-                                        buckets[i].b,
-                                        BUCKET_NOCOW_LOCK_UPDATE);
-               --i;
+       darray_for_each(buckets, i) {
+               bch2_bucket_nocow_unlock(&c->nocow_locks, i->b, BUCKET_NOCOW_LOCK_UPDATE);
+               if (i == stale_at)
+                       break;
        }
-       for (i = 0; i < nr_buckets; i++)
-               percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref);
 
        /* We can retry this: */
        ret = -BCH_ERR_transaction_restart;
-       goto out;
+       goto err_get_ioref;
 }
 
 static void __bch2_write(struct bch_write_op *op)
@@ -1461,10 +1445,11 @@ 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));
+                               if (!(op->flags & BCH_WRITE_ALLOC_NOWAIT))
+                                       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;
                        }
@@ -1579,6 +1564,7 @@ CLOSURE_CALLBACK(bch2_write)
        BUG_ON(!op->write_point.v);
        BUG_ON(bkey_eq(op->pos, POS_MAX));
 
+       op->nr_replicas_required = min_t(unsigned, op->nr_replicas_required, op->nr_replicas);
        op->start_time = local_clock();
        bch2_keylist_init(&op->insert_keys, op->inline_keys);
        wbio_init(bio)->put_bio = false;