"shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr" messages seen in RHEL6

Solution Unverified - Updated -

Environment

  • Red Hat Enterprise Linux 6 (prior to kernel-2.6.32-358.el6)
  • XFS

Issue

  • The following messages are displayed while using the XFS filesystem:
shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr=-9223372036854690538
shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr=-9223372036854743572
shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr=-84
shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr=-9223372036854775758
shrink_slab: xfs_buftarg_shrink+0x0/0x160 [xfs] negative objects to delete nr=-313100388

Resolution

Root Cause

  • The buffer counter of LRU list (btp->bt_lru_nr) can be decremented twice by xfs_buftarg_shrink() and xfs_buf_stale() causing incorrect account usage of the LRU list.

Diagnostic Steps

  • Messages are coming from following code segment:
unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
                        unsigned long lru_pages)
{
        struct shrinker *shrinker;
        unsigned long ret = 0;

        if (scanned == 0)
                scanned = SWAP_CLUSTER_MAX;

        if (!down_read_trylock(&shrinker_rwsem)) {
                /* Assume we'll be able to shrink next time */
                ret = 1;
                goto out;
        }

        list_for_each_entry(shrinker, &shrinker_list, list) {
                unsigned long long delta;
                unsigned long total_scan;
                unsigned long max_pass;

                max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask);
                delta = (4 * scanned) / shrinker->seeks;
                delta *= max_pass;

                max_pass = (*shrinker->shrink)(shrinker, 0, gfp_mask);
                delta = (4 * scanned) / shrinker->seeks;
                delta *= max_pass;
                do_div(delta, lru_pages + 1);
                shrinker->nr += delta;
                if (shrinker->nr < 0) {
                        printk(KERN_ERR "shrink_slab: %pF negative objects to "
                               "delete nr=%ld\n",
                               shrinker->shrink, shrinker->nr);
                        shrinker->nr = max_pass;
                }

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.