]> git.hungrycats.org Git - linux/commitdiff
wip: cand37 = cand36 + per-inode ring of delalloc clears made without EXTENT_CLEAR_ME...
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Thu, 10 Sep 2026 07:11:12 +0000 (03:11 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Thu, 10 Sep 2026 07:11:12 +0000 (03:11 -0400)
fs/btrfs/btrfs_inode.h
fs/btrfs/inode.c

index 37502d620cfdb0d8244fd1dbdd7a06960525e44e..66afd04f2b206dfcb84bf39955e663f4fe5bdab9 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef BTRFS_INODE_H
 #define BTRFS_INODE_H
 
+#include <linux/stackdepot.h>
+#include <linux/stacktrace.h>
 #include <linux/hash.h>
 #include <linux/refcount.h>
 #include <linux/spinlock.h>
@@ -399,6 +401,13 @@ struct btrfs_inode {
 
        /* Hook into fs_info->delayed_iputs */
        struct list_head delayed_iput;
+#ifdef CONFIG_BTRFS_DEBUG
+       /* DEBUG (cand37): last delalloc clears WITHOUT EXTENT_CLEAR_META_RESV */
+       depot_stack_handle_t dbg_noresv[4];
+       u64 dbg_noresv_start[4];
+       u64 dbg_noresv_len[4];
+       unsigned int dbg_noresv_n;
+#endif
 
        struct rw_semaphore i_mmap_lock;
 
index 5e5baad1042c4396b6e025af0d914371bcb9f2c6..c9ab290f1f05c03385532d332150c273e4668033 100644 (file)
@@ -2631,6 +2631,18 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode,
                spin_lock(&inode->lock);
                btrfs_mod_outstanding_extents(inode, -num_extents);
                spin_unlock(&inode->lock);
+#ifdef CONFIG_BTRFS_DEBUG
+               /* DEBUG (cand37): remember who cleared delalloc without releasing metadata */
+               if (!(bits & EXTENT_CLEAR_META_RESV)) {
+                       unsigned long entries[12];
+                       unsigned int nr = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
+                       unsigned int i = inode->dbg_noresv_n++ % 4;
+
+                       inode->dbg_noresv_start[i] = state->start;
+                       inode->dbg_noresv_len[i] = len;
+                       inode->dbg_noresv[i] = stack_depot_save(entries, nr, GFP_NOWAIT);
+               }
+#endif
 
                /*
                 * We don't reserve metadata space for space cache inodes so we
@@ -8071,6 +8083,10 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
         * from disk (btrfs_read_locked_inode()).
         */
        ei->csum_bytes = 0;
+#ifdef CONFIG_BTRFS_DEBUG
+       ei->dbg_noresv_n = 0;
+       memset(ei->dbg_noresv, 0, sizeof(ei->dbg_noresv));
+#endif
        ei->dir_index = 0;
        ei->last_unlink_trans = 0;
        ei->last_reflink_trans = 0;
@@ -8150,6 +8166,23 @@ void btrfs_destroy_inode(struct inode *vfs_inode)
                           inode->outstanding_extents, inode->csum_bytes,
                           inode->delalloc_bytes, inode->new_delalloc_bytes,
                           inode->flags);
+#ifdef CONFIG_BTRFS_DEBUG
+       if (root && !S_ISDIR(vfs_inode->i_mode) && inode->csum_bytes) {
+               unsigned int n = inode->dbg_noresv_n, cnt = min(n, 4u);
+
+               btrfs_warn(root->fs_info, "  %u delalloc clears without META_RESV on ino %llu, last %u (oldest first):",
+                          n, btrfs_ino(inode), cnt);
+               for (unsigned int k = 0; k < cnt; k++) {
+                       unsigned int idx = (n - cnt + k) % 4;
+
+                       btrfs_warn(root->fs_info, "  noresv[%u] start %llu len %llu:",
+                                  n - cnt + k, inode->dbg_noresv_start[idx],
+                                  inode->dbg_noresv_len[idx]);
+                       if (inode->dbg_noresv[idx])
+                               stack_depot_print(inode->dbg_noresv[idx]);
+               }
+       }
+#endif
        WARN_ON(inode->block_rsv.reserved);
        WARN_ON(inode->block_rsv.size);
        WARN_ON(inode->outstanding_extents);