#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>
/* 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;
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
* 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;
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);