[Bug 111601] regression: deadlock-freeze due to kernel commit aa56a292ce623734ddd30f52d73f527d1f3529b5

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Mon Sep 9 20:20:29 UTC 2019


https://bugs.freedesktop.org/show_bug.cgi?id=111601

--- Comment #6 from howaboutsynergy <howaboutsynergy at pm.me> ---
[  310.860735] userptr_mn_invalidate_range_start+0x0/0x210 [i915] callback
failed with -4 in blockable context.

mm/mmu_notifier.c:179:                          pr_info("%pS callback failed
with %d in %sblockable context.\n",

context:
```c
  int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
  {
    struct mmu_notifier *mn;
    int ret = 0;
    int id;

    id = srcu_read_lock(&srcu);
    hlist_for_each_entry_rcu(mn, &range->mm->mmu_notifier_mm->list, hlist) {
      if (mn->ops->invalidate_range_start) {
        int _ret = mn->ops->invalidate_range_start(mn, range);
        if (_ret) {
          pr_info("%pS callback failed with %d in %sblockable context.\n",      
            mn->ops->invalidate_range_start, _ret,
            !mmu_notifier_range_blockable(range) ? "non-" : "");
          ret = _ret;
        }
      }
    }
    srcu_read_unlock(&srcu, id);

    return ret;
  }
  EXPORT_SYMBOL_GPL(__mmu_notifier_invalidate_range_start);
```

the `-4` is:

#define EINTR    4  /* Interrupted system call */                               

context:
```c
static int
userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
                                  const struct mmu_notifier_range *range)
{
        struct i915_mmu_notifier *mn =
                container_of(_mn, struct i915_mmu_notifier, mn);
        struct interval_tree_node *it;
        struct mutex *unlock = NULL;
        unsigned long end;
        int ret = 0;

        if (RB_EMPTY_ROOT(&mn->objects.rb_root))
                return 0;

        /* interval ranges are inclusive, but invalidate range is exclusive */
        end = range->end - 1;

        spin_lock(&mn->lock);
        it = interval_tree_iter_first(&mn->objects, range->start, end);
        while (it) {
                struct drm_i915_gem_object *obj;

                if (!mmu_notifier_range_blockable(range)) {
                        ret = -EAGAIN;
                        break;
                }

                /*
                 * The mmu_object is released late when destroying the
                 * GEM object so it is entirely possible to gain a
                 * reference on an object in the process of being freed
                 * since our serialisation is via the spinlock and not
                 * the struct_mutex - and consequently use it after it
                 * is freed and then double free it. To prevent that
                 * use-after-free we only acquire a reference on the
                 * object if it is not in the process of being destroyed.
                 */
                obj = container_of(it, struct i915_mmu_object, it)->obj;
                if (!kref_get_unless_zero(&obj->base.refcount)) {
                        it = interval_tree_iter_next(it, range->start, end);
                        continue;
                }
                spin_unlock(&mn->lock);

                if (!unlock) {
                        unlock = &mn->mm->i915->drm.struct_mutex;

                        switch (mutex_trylock_recursive(unlock)) {
                        default:
                        case MUTEX_TRYLOCK_FAILED:
                                if (mutex_lock_killable_nested(unlock,
I915_MM_SHRINKER)) {
                                        i915_gem_object_put(obj);
                                        return -EINTR;
                                }
                                /* fall through */
                        case MUTEX_TRYLOCK_SUCCESS:
                                break;

                        case MUTEX_TRYLOCK_RECURSIVE:
                                unlock = ERR_PTR(-EEXIST);
                                break;
                        }
                }

                ret = i915_gem_object_unbind(obj);
                if (ret == 0)
                        ret = __i915_gem_object_put_pages(obj,
I915_MM_SHRINKER);
                i915_gem_object_put(obj);
                if (ret)
                        goto unlock;

                spin_lock(&mn->lock);

                /*
                 * As we do not (yet) protect the mmu from concurrent insertion
                 * over this range, there is no guarantee that this search will
                 * terminate given a pathologic workload.
                 */
                it = interval_tree_iter_first(&mn->objects, range->start, end);
        }
        spin_unlock(&mn->lock);

unlock:
        if (!IS_ERR_OR_NULL(unlock))
                mutex_unlock(unlock);

        return ret;

}
```
drivers/gpu/drm/i915/gem/i915_gem_userptr.c

-- 
You are receiving this mail because:
You are the QA Contact for the bug.
You are the assignee for the bug.
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/intel-gfx-bugs/attachments/20190909/ef6b83f4/attachment.html>


More information about the intel-gfx-bugs mailing list