}
 
        xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
-
        acl = bch2_acl_from_disk(xattr_val(xattr.v),
                        le16_to_cpu(xattr.v->x_val_len));
 
        if (!IS_ERR(acl))
                set_cached_acl(&inode->v, type, acl);
+       bch2_trans_iter_put(&trans, iter);
 out:
        bch2_trans_exit(&trans);
        return acl;
        if (type == ACL_TYPE_ACCESS) {
                ret = posix_acl_update_mode(idmap, &inode->v, &mode, &acl);
                if (ret)
-                       goto err;
+                       goto btree_err;
        }
 
        hash_info = bch2_hash_info_init(c, &inode_u);
                                  &inode->ei_journal_seq,
                                  BTREE_INSERT_NOUNLOCK);
 btree_err:
+       bch2_trans_iter_put(&trans, inode_iter);
+
        if (ret == -EINTR)
                goto retry;
        if (unlikely(ret))
        struct bkey_s_c_xattr xattr;
        struct bkey_i_xattr *new;
        struct posix_acl *acl;
-       int ret = 0;
+       int ret;
 
        iter = bch2_hash_lookup(trans, bch2_xattr_hash_desc,
                        &hash_info, inode->bi_inum,
                        &X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0),
                        BTREE_ITER_INTENT);
-       if (IS_ERR(iter))
-               return PTR_ERR(iter) != -ENOENT ? PTR_ERR(iter) : 0;
+       ret = PTR_ERR_OR_ZERO(iter);
+       if (ret)
+               return ret == -ENOENT ? 0 : ret;
 
        xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
-
        acl = bch2_acl_from_disk(xattr_val(xattr.v),
                        le16_to_cpu(xattr.v->x_val_len));
-       if (IS_ERR_OR_NULL(acl))
-               return PTR_ERR(acl);
+       ret = PTR_ERR_OR_ZERO(acl);
+       if (ret || !acl)
+               goto err;
 
        ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
        if (ret)
        *new_acl = acl;
        acl = NULL;
 err:
+       bch2_trans_iter_put(trans, iter);
        kfree(acl);
        return ret;
 }
 
        int ret = 0;
 
        bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
-
        iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc, POS_MIN,
                                   BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
 
                }
        }
 err:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
        int ret = 0;
 
        bch2_trans_init(&trans, c, 0, 0);
-
        iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc,
                                   POS(ca->dev_idx, 0),
                                   BTREE_ITER_CACHED|
                                (!fifo_empty(&ca->free_inc)
                                 ? BTREE_INSERT_NOWAIT : 0));
 
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
 
        /* If we used NOWAIT, don't return the error: */
 
 
                bch2_trans_cond_resched(&trans);
        }
+       bch2_trans_iter_put(&trans, iter);
+
        ret = bch2_trans_exit(&trans) ?: ret;
        if (ret)
                return ret;
 
                bch2_btree_iter_next(iter);
        }
+       bch2_trans_iter_put(&trans, iter);
 
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&sk, c);
        struct btree *b;
        bool kthread = (current->flags & PF_KTHREAD) != 0;
        unsigned i;
+       int ret = 0;
 
        /* Sliding window of adjacent btree nodes */
        struct btree *merge[GC_MERGE_NODES];
                lock_seq[0] = merge[0]->c.lock.state.seq;
 
                if (kthread && kthread_should_stop()) {
-                       bch2_trans_exit(&trans);
-                       return -ESHUTDOWN;
+                       ret = -ESHUTDOWN;
+                       break;
                }
 
                bch2_trans_cond_resched(&trans);
                        memset(merge + 1, 0,
                               (GC_MERGE_NODES - 1) * sizeof(merge[0]));
        }
-       return bch2_trans_exit(&trans);
+       bch2_trans_iter_put(&trans, iter);
+
+       return bch2_trans_exit(&trans) ?: ret;
 }
 
 /**
 
        if (ret)
                goto err;
 out:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&k, c);
        bio_put(&wbio->wbio.bio);
 
 #include "btree_locking.h"
 #include "btree_update.h"
 #include "debug.h"
+#include "error.h"
 #include "extents.h"
 #include "journal.h"
 #include "trace.h"
        for (i = 0; i < ARRAY_SIZE(iter->l); i++)
                iter->l[i].b            = NULL;
        iter->l[iter->level].b          = BTREE_ITER_NO_NODE_INIT;
+       iter->ip_allocated = _RET_IP_;
 
        return iter;
 }
                       (void *) &trans->fs_usage_deltas->memset_start);
        }
 
+       bch2_trans_cond_resched(trans);
+
        if (!(flags & TRANS_RESET_NOTRAVERSE))
                bch2_btree_iter_traverse_all(trans);
 }
        bch2_trans_unlock(trans);
 
 #ifdef CONFIG_BCACHEFS_DEBUG
+       if (trans->iters_live) {
+               struct btree_iter *iter;
+
+               bch_err(c, "btree iterators leaked!");
+               trans_for_each_iter(trans, iter)
+                       if (btree_iter_live(trans, iter))
+                               printk(KERN_ERR "  btree %s allocated at %pS\n",
+                                      bch2_btree_ids[iter->btree_id],
+                                      (void *) iter->ip_allocated);
+               /* Be noisy about this: */
+               bch2_fatal_error(c);
+       }
+
        mutex_lock(&trans->c->btree_trans_lock);
        list_del(&trans->list);
        mutex_unlock(&trans->c->btree_trans_lock);
 
                if (!i->size)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
 
        return err < 0 ? err : i->ret;
                if (!i->size)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
 
        return err < 0 ? err : i->ret;
 
 
        k = bch2_btree_iter_peek_slot(iter);
        inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
+       bch2_trans_iter_put(&trans, iter);
 out:
        bch2_trans_exit(&trans);
        return inum;
                        break;
                ctx->pos = dirent.k->p.offset + 1;
        }
+       bch2_trans_iter_put(&trans, iter);
+
        ret = bch2_trans_exit(&trans) ?: ret;
 
        return ret;
 
                if (ret)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&sk, c);
        int ret = 0;
 
        bch2_trans_init(&trans, c, 0, 0);
-
        iter = bch2_trans_get_iter(&trans, BTREE_ID_stripes, POS(0, U64_MAX), 0);
 
        k = bch2_btree_iter_prev(iter);
        if (!IS_ERR_OR_NULL(k.k))
                idx = k.k->p.offset + 1;
+
+       bch2_trans_iter_put(&trans, iter);
        ret = bch2_trans_exit(&trans);
        if (ret)
                return ret;
 
                        break;
                }
        }
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
 
        return ret;
 
        BUG_ON(ret);
 
        bch2_trans_init(&trans, c, 0, 0);
-
        iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS_MIN,
                                   BTREE_ITER_SLOTS);
 
 
        bch2_pagecache_add_put(&inode->ei_pagecache_lock);
 
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        kfree(readpages_iter.pages);
 }
 
        bchfs_read(&trans, iter, rbio, inum, NULL);
 
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
 }
 
                        break;
                }
        }
+       bch2_trans_iter_put(&trans, iter);
 
        return bch2_trans_exit(&trans) ?: ret;
 }
        bch2_trans_init(&trans, c, 0, 0);
        iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, 0);
        ret = PTR_ERR_OR_ZERO(iter);
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
 
        if (ret)
        struct btree_iter *src, *dst, *del;
        loff_t shift, new_size;
        u64 src_start;
-       int ret;
+       int ret = 0;
 
        if ((offset | len) & (block_bytes(c) - 1))
                return -EINVAL;
 
-       bch2_bkey_buf_init(©);
-       bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
-
        /*
         * We need i_mutex to keep the page cache consistent with the extents
         * btree, and the btree consistent with i_size - we don't need outside
                        goto err;
        }
 
+       bch2_bkey_buf_init(©);
+       bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
        src = bch2_trans_get_iter(&trans, BTREE_ID_extents,
                        POS(inode->v.i_ino, src_start >> 9),
                        BTREE_ITER_INTENT);
        dst = bch2_trans_copy_iter(&trans, src);
        del = bch2_trans_copy_iter(&trans, src);
 
-       while (1) {
+       while (ret == 0 || ret == -EINTR) {
                struct disk_reservation disk_res =
                        bch2_disk_reservation_init(c, 0);
                struct bkey_i delete;
                        ? bch2_btree_iter_peek_prev(src)
                        : bch2_btree_iter_peek(src);
                if ((ret = bkey_err(k)))
-                       goto bkey_err;
+                       continue;
 
                if (!k.k || k.k->p.inode != inode->v.i_ino)
                        break;
 
                ret = bch2_extent_atomic_end(dst, copy.k, &atomic_end);
                if (ret)
-                       goto bkey_err;
+                       continue;
 
                if (bkey_cmp(atomic_end, copy.k->k.p)) {
                        if (insert) {
                                          &inode->ei_journal_seq,
                                          BTREE_INSERT_NOFAIL);
                bch2_disk_reservation_put(c, &disk_res);
-bkey_err:
+
                if (!ret)
                        bch2_btree_iter_set_pos(src, next_pos);
-
-               if (ret == -EINTR)
-                       ret = 0;
-               if (ret)
-                       goto err;
-
-               bch2_trans_cond_resched(&trans);
        }
-       bch2_trans_unlock(&trans);
+       bch2_trans_iter_put(&trans, del);
+       bch2_trans_iter_put(&trans, dst);
+       bch2_trans_iter_put(&trans, src);
+       bch2_trans_exit(&trans);
+       bch2_bkey_buf_exit(©, c);
+
+       if (ret)
+               goto err;
 
        if (!insert) {
                i_size_write(&inode->v, new_size);
                mutex_unlock(&inode->ei_update_lock);
        }
 err:
-       bch2_trans_exit(&trans);
-       bch2_bkey_buf_exit(©, c);
        bch2_pagecache_block_put(&inode->ei_pagecache_lock);
        inode_unlock(&inode->v);
        return ret;
                        BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
        end_pos = POS(inode->v.i_ino, block_end >> 9);
 
-       while (bkey_cmp(iter->pos, end_pos) < 0) {
+       while (!ret && bkey_cmp(iter->pos, end_pos) < 0) {
                s64 i_sectors_delta = 0;
                struct disk_reservation disk_res = { 0 };
                struct quota_res quota_res = { 0 };
                bch2_disk_reservation_put(c, &disk_res);
                if (ret == -EINTR)
                        ret = 0;
-               if (ret)
-                       goto err;
        }
+       bch2_trans_iter_put(&trans, iter);
+
+       if (ret)
+               goto err;
 
        /*
         * Do we need to extend the file?
                        ret = PTR_ERR_OR_ZERO(inode_iter);
                } while (ret == -EINTR);
 
+               bch2_trans_iter_put(&trans, inode_iter);
                bch2_trans_unlock(&trans);
 
                if (ret)
                } else if (k.k->p.offset >> 9 > isize)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 
        ret = bch2_trans_exit(&trans) ?: ret;
        if (ret)
                        offset = max(offset, bkey_start_offset(k.k) << 9);
                }
        }
+       bch2_trans_iter_put(&trans, iter);
 
        ret = bch2_trans_exit(&trans) ?: ret;
        if (ret)
 
                                  BTREE_INSERT_NOUNLOCK|
                                  BTREE_INSERT_NOFAIL);
 btree_err:
+       bch2_trans_iter_put(&trans, inode_iter);
+
        if (ret == -EINTR)
                goto retry;
        if (unlikely(ret))
                ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k),
                                       FIEMAP_EXTENT_LAST);
 
+       bch2_trans_iter_put(&trans, iter);
        ret = bch2_trans_exit(&trans) ?: ret;
        bch2_bkey_buf_exit(&cur, c);
        bch2_bkey_buf_exit(&prev, c);
 
                     BCH_INODE_I_SECTORS_DIRTY|
                     BCH_INODE_UNLINKED)) {
                        ret = check_inode(&trans, NULL, iter, inode, NULL);
-                       BUG_ON(ret == -EINTR);
                        if (ret)
                                break;
                }
        }
+       bch2_trans_iter_put(&trans, iter);
+
        BUG_ON(ret == -EINTR);
 
        return bch2_trans_exit(&trans) ?: ret;
 
 
        ret = bch2_trans_commit(&trans, NULL, NULL,
                                BTREE_INSERT_NOFAIL);
+       bch2_trans_iter_put(&trans, iter);
 err:
        if (ret == -EINTR)
                goto retry;
 
 
        ret = bch2_fpunch_at(&trans, iter, POS(inum, end),
                             journal_seq, i_sectors_delta);
+
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
 
        if (ret == -EINTR)
                        bch2_keylist_pop_front(keys);
        } while (!bch2_keylist_empty(keys));
 
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&sk, c);
 
                goto err;
 out:
        bch2_rbio_done(rbio);
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&sk, c);
        return;
                k = bch2_btree_iter_peek_slot(iter);
                ret = bkey_err(k);
                if (ret)
-                       goto err;
+                       break;
 
                offset_into_extent = iter->pos.offset -
                        bkey_start_offset(k.k);
                ret = bch2_read_indirect_extent(&trans, &data_btree,
                                        &offset_into_extent, &sk);
                if (ret)
-                       goto err;
+                       break;
 
                k = bkey_i_to_s_c(sk.k);
 
                ret = __bch2_read_extent(&trans, rbio, bvec_iter, iter->pos,
                                         data_btree, k,
                                         offset_into_extent, failed, flags);
-               switch (ret) {
-               case READ_RETRY:
-                       goto retry;
-               case READ_ERR:
-                       goto err;
-               };
+               if (ret)
+                       break;
 
                if (flags & BCH_READ_LAST_FRAGMENT)
                        break;
                swap(bvec_iter.bi_size, bytes);
                bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
        }
-out:
-       bch2_trans_exit(&trans);
-       bch2_bkey_buf_exit(&sk, c);
-       return;
-err:
-       if (ret == -EINTR)
+       bch2_trans_iter_put(&trans, iter);
+
+       if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID)
                goto retry;
 
-       bch_err_inum_ratelimited(c, inode,
-                                "read error %i from btree lookup", ret);
-       rbio->bio.bi_status = BLK_STS_IOERR;
-       bch2_rbio_done(rbio);
-       goto out;
+       if (ret) {
+               bch_err_inum_ratelimited(c, inode,
+                                        "read error %i from btree lookup", ret);
+               rbio->bio.bi_status = BLK_STS_IOERR;
+               bch2_rbio_done(rbio);
+       }
+       bch2_trans_exit(&trans);
+       bch2_bkey_buf_exit(&sk, c);
 }
 
 void bch2_fs_io_exit(struct bch_fs *c)
 
                if (ret)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 
        ret = bch2_trans_exit(&trans) ?: ret;
        bch2_bkey_buf_exit(&sk, c);
                                            dev_idx, flags, true);
                        if (ret) {
                                bch_err(c, "Cannot drop device without losing data");
-                               goto err;
+                               break;
                        }
 
                        ret = bch2_btree_node_update_key(c, iter, b, k.k);
                        if (ret == -EINTR) {
                                b = bch2_btree_iter_peek_node(iter);
+                               ret = 0;
                                goto retry;
                        }
                        if (ret) {
                                bch_err(c, "Error updating btree node key: %i", ret);
-                               goto err;
+                               break;
                        }
                }
                bch2_trans_iter_free(&trans, iter);
+
+               if (ret)
+                       goto err;
        }
 
        /* flush relevant btree updates */
 
                goto next;
        }
 out:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        bch2_bkey_buf_exit(&_insert, c);
        bch2_bkey_buf_exit(&_new, c);
                bch2_trans_cond_resched(&trans);
        }
 out:
+
+       bch2_trans_iter_put(&trans, iter);
        ret = bch2_trans_exit(&trans) ?: ret;
        bch2_bkey_buf_exit(&sk, c);
 
 
                if (ret)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 
        return bch2_trans_exit(&trans) ?: ret;
 }
                                        KEY_TYPE_QUOTA_NOCHECK);
                }
        }
+       bch2_trans_iter_put(&trans, iter);
+
        return bch2_trans_exit(&trans) ?: ret;
 }
 
        if (qdq->d_fieldmask & QC_INO_HARD)
                new_quota->v.c[Q_INO].hardlimit = cpu_to_le64(qdq->d_ino_hardlimit);
 
-       return bch2_trans_update(trans, iter, &new_quota->k_i, 0);
+       ret = bch2_trans_update(trans, iter, &new_quota->k_i, 0);
+       bch2_trans_iter_put(trans, iter);
+       return ret;
 }
 
 static int bch2_set_quota(struct super_block *sb, struct kqid qid,
 
        dst_iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, dst_start,
                                       BTREE_ITER_INTENT);
 
-       while (1) {
+       while (ret == 0 || ret == -EINTR) {
                bch2_trans_begin(&trans);
 
-               trans.mem_top = 0;
-
                if (fatal_signal_pending(current)) {
                        ret = -EINTR;
-                       goto err;
+                       break;
                }
 
                src_k = get_next_src(src_iter, src_end);
                ret = bkey_err(src_k);
                if (ret)
-                       goto btree_err;
+                       continue;
 
                src_done = bpos_min(src_iter->pos, src_end).offset -
                        src_start.offset;
                if (bkey_cmp(dst_iter->pos, dst_want) < 0) {
                        ret = bch2_fpunch_at(&trans, dst_iter, dst_want,
                                             journal_seq, i_sectors_delta);
-                       if (ret)
-                               goto btree_err;
                        continue;
                }
 
                        ret = bch2_make_extent_indirect(&trans, src_iter,
                                                new_src.k);
                        if (ret)
-                               goto btree_err;
+                               continue;
 
                        BUG_ON(src_k.k->type != KEY_TYPE_reflink_p);
                }
                                         NULL, journal_seq,
                                         new_i_size, i_sectors_delta);
                if (ret)
-                       goto btree_err;
+                       continue;
 
                dst_done = dst_iter->pos.offset - dst_start.offset;
                src_want = POS(src_start.inode, src_start.offset + dst_done);
                bch2_btree_iter_set_pos(src_iter, src_want);
-btree_err:
-               if (ret == -EINTR)
-                       ret = 0;
-               if (ret)
-                       goto err;
        }
+       bch2_trans_iter_put(&trans, dst_iter);
+       bch2_trans_iter_put(&trans, src_iter);
 
-       BUG_ON(bkey_cmp(dst_iter->pos, dst_end));
-err:
+       BUG_ON(!ret && bkey_cmp(dst_iter->pos, dst_end));
        BUG_ON(bkey_cmp(dst_iter->pos, dst_end) > 0);
 
        dst_done = dst_iter->pos.offset - dst_start.offset;
                        ret2  = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
                                bch2_trans_commit(&trans, NULL, journal_seq, 0);
                }
+
+               bch2_trans_iter_put(&trans, inode_iter);
        } while (ret2 == -EINTR);
 
        ret = bch2_trans_exit(&trans) ?: ret;
 
                goto err;
        }
 err:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
                goto err;
        }
 err:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
 static int test_iterate(struct bch_fs *c, u64 nr)
 {
        struct btree_trans trans;
-       struct btree_iter *iter;
+       struct btree_iter *iter = NULL;
        struct bkey_s_c k;
        u64 i;
        int ret = 0;
 
        BUG_ON(i);
 err:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
 static int test_iterate_extents(struct bch_fs *c, u64 nr)
 {
        struct btree_trans trans;
-       struct btree_iter *iter;
+       struct btree_iter *iter = NULL;
        struct bkey_s_c k;
        u64 i;
        int ret = 0;
 
        BUG_ON(i);
 err:
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
                BUG_ON(k.k->p.offset != i);
                i += 2;
        }
-       bch2_trans_iter_free(&trans, iter);
+       bch2_trans_iter_put(&trans, iter);
 
        BUG_ON(i != nr * 2);
 
                if (i == nr * 2)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 err:
        bch2_trans_exit(&trans);
        return ret;
                BUG_ON(k.k->size != 8);
                i += 16;
        }
-       bch2_trans_iter_free(&trans, iter);
+       bch2_trans_iter_put(&trans, iter);
 
        BUG_ON(i != nr);
 
                if (i == nr)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
 err:
        bch2_trans_exit(&trans);
        return 0;
        k = bch2_btree_iter_peek(iter);
        BUG_ON(k.k);
 
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
        return 0;
 }
        k = bch2_btree_iter_peek(iter);
        BUG_ON(k.k);
 
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
        return 0;
 }
                }
        }
 
-       bch2_trans_iter_free(&trans, iter);
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
                }
        }
 
-       bch2_trans_iter_free(&trans, iter);
+       bch2_trans_iter_put(&trans, iter);
        bch2_trans_exit(&trans);
        return ret;
 }
                if (++i == nr)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
        return ret;
 }
 
        for_each_btree_key(&trans, iter, BTREE_ID_xattrs, POS_MIN, 0, k, ret)
                ;
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
        return ret;
 }
                        break;
                }
        }
+       bch2_trans_iter_put(&trans, iter);
+
        bch2_trans_exit(&trans);
        return ret;
 }
 
                                inode->v.i_ino,
                                &X_SEARCH(type, name, strlen(name)),
                                0);
-       if (IS_ERR(iter)) {
-               bch2_trans_exit(&trans);
-               BUG_ON(PTR_ERR(iter) == -EINTR);
-
-               return PTR_ERR(iter) == -ENOENT ? -ENODATA : PTR_ERR(iter);
-       }
+       ret = PTR_ERR_OR_ZERO(iter);
+       if (ret)
+               goto err;
 
        xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
        ret = le16_to_cpu(xattr.v->x_val_len);
                else
                        memcpy(buffer, xattr_val(xattr.v), ret);
        }
-
+       bch2_trans_iter_put(&trans, iter);
+err:
        bch2_trans_exit(&trans);
-       return ret;
+
+       BUG_ON(ret == -EINTR);
+       return ret == -ENOENT ? -ENODATA : ret;
 }
 
 int bch2_xattr_set(struct btree_trans *trans, u64 inum,
                if (ret)
                        break;
        }
+       bch2_trans_iter_put(&trans, iter);
+
        ret = bch2_trans_exit(&trans) ?: ret;
 
        if (ret)