Instead of just asserting that we have no delalloc space dangling in an inode that gets freed print the actual offenders for debug mode.
Unified · Split
| @@ -933,6 +933,32 @@ xfs_fs_alloc_inode( · 932 unmodified lines | ||
| 933 | 933 | return NULL; |
| 934 | 934 | } |
| 935 | 935 | |
| 936 | +#ifdef DEBUG | |
| 937 | +static void | |
| 938 | +xfs_check_delalloc( | |
| 939 | + struct xfs_inode *ip, | |
| 940 | + int whichfork) | |
| 941 | +{ | |
| 942 | + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | |
| 943 | + struct xfs_bmbt_irec got; | |
| 944 | + struct xfs_iext_cursor icur; | |
| 945 | + | |
| 946 | + if (!ifp || !xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got)) | |
| 947 | + return; | |
| 948 | + do { | |
| 949 | + if (isnullstartblock(got.br_startblock)) { | |
| 950 | + xfs_warn(ip->i_mount, | |
| 951 | + "ino %llx %s fork has delalloc extent at [0x%llx:0x%llx]", | |
| 952 | + ip->i_ino, | |
| 953 | + whichfork == XFS_DATA_FORK ? "data" : "cow", | |
| 954 | + got.br_startoff, got.br_blockcount); | |
| 955 | + } | |
| 956 | + } while (xfs_iext_next_extent(ifp, &icur, &got)); | |
| 957 | +} | |
| 958 | +#else | |
| 959 | +#define xfs_check_delalloc(ip, whichfork) do { } while (0) | |
| 960 | +#endif | |
| 961 | + | |
| 936 | 962 | /* |
| 937 | 963 | * Now that the generic code is guaranteed not to be accessing |
| 938 | 964 | * the linux inode, we can inactivate and reclaim the inode. |
| @@ -951,7 +977,12 @@ xfs_fs_destroy_inode( · 12 unmodified lines | ||
| 951 | 977 | |
| 952 | 978 | xfs_inactive(ip); |
| 953 | 979 | |
| 954 | − ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); | |
| 980 | + if (!XFS_FORCED_SHUTDOWN(ip->i_mount) && ip->i_delayed_blks) { | |
| 981 | + xfs_check_delalloc(ip, XFS_DATA_FORK); | |
| 982 | + xfs_check_delalloc(ip, XFS_COW_FORK); | |
| 983 | + ASSERT(0); | |
| 984 | + } | |
| 985 | + | |
| 955 | 986 | XFS_STATS_INC(ip->i_mount, vn_reclaim); |
| 956 | 987 | |
| 957 | 988 | /* |