linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Hellstrom <thellstrom@vmware.com>
To: Andrey Ryabinin <aryabinin@virtuozzo.com>,
	Matthew Wilcox <willy@infradead.org>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
	linux-mm@kvack.org, hch@lst.de, jszhang@marvell.com,
	joelaf@google.com, chris@chris-wilson.co.uk, joaodias@google.com,
	tglx@linutronix.de, hpa@zytor.com, mingo@elte.hu,
	dri-devel@lists.freedesktop.org, David Airlie <airlied@linux.ie>
Subject: Re: [PATCH] mm: Remove pointless might_sleep() in remove_vm_area().
Date: Mon, 27 Mar 2017 16:10:45 +0200	[thread overview]
Message-ID: <f1c0b9ec-c0c8-502c-c7f0-fe692c73ab04@vmware.com> (raw)
In-Reply-To: <0eceef23-a20c-bca7-2153-b9b5baf1f1d8@virtuozzo.com>

On 03/27/2017 03:26 PM, Andrey Ryabinin wrote:
> [+CC drm folks, see the following threads:
> 	https://urldefense.proofpoint.com/v2/url?u=http-3A__lkml.kernel.org_r_201703232349.BGB95898.QHLVFFOMtFOOJS-40I-2Dlove.SAKURA.ne.jp&d=DwIC-g&c=uilaK90D4TOVoH58JNXRgQ&r=wnSlgOCqfpNS4d02vP68_E9q2BNMCwfD2OZ_6dCFVQQ&m=iraTSVk5qLTsuZU7WSBk97YAYoGmC7W5zjR2wwDRVVk&s=bX-RtB9qE168yR2AjMRvRvln1Pn6r8fmNUDQydGWIdk&e= 
> 	https://urldefense.proofpoint.com/v2/url?u=http-3A__lkml.kernel.org_r_1490352808-2D7187-2D1-2Dgit-2Dsend-2Demail-2Dpenguin-2Dkernel-40I-2Dlove.SAKURA.ne.jp&d=DwIC-g&c=uilaK90D4TOVoH58JNXRgQ&r=wnSlgOCqfpNS4d02vP68_E9q2BNMCwfD2OZ_6dCFVQQ&m=iraTSVk5qLTsuZU7WSBk97YAYoGmC7W5zjR2wwDRVVk&s=jw45iN1ypIQrzl08wkan3QZkuU6Gu0riU4_PvZD8KXQ&e= 
> ]
>
> On 03/24/2017 07:17 PM, Matthew Wilcox wrote:
>> On Fri, Mar 24, 2017 at 06:05:45PM +0300, Andrey Ryabinin wrote:
>>> Just fix the drm code. There is zero point in releasing memory under spinlock.
>> I disagree.  The spinlock has to be held while deleting from the hash
>> table. 
> And what makes you think so?
>
> There are too places where spinlock held during drm_ht_remove();
>
> 1) The first one is an obvious crap in ttm_object_device_release():
>
> void ttm_object_device_release(struct ttm_object_device **p_tdev)
> {
> 	struct ttm_object_device *tdev = *p_tdev;
>
> 	*p_tdev = NULL;
>
> 	spin_lock(&tdev->object_lock);
> 	drm_ht_remove(&tdev->object_hash);
> 	spin_unlock(&tdev->object_lock);
>
> 	kfree(tdev);
> }
>
> Obviously this spin_lock has no use here and it can be removed. There should
> be no concurrent access to tdev at this point, because that would mean immediate
> use-afte-free.
>
> 2) The second case is in ttm_object_file_release() calls drm_ht_remove() under tfile->lock
> And drm_ht_remove() does:
> void drm_ht_remove(struct drm_open_hash *ht)
> {
> 	if (ht->table) {
> 		kvfree(ht->table);
> 		ht->table = NULL;
> 	}
> }
>
> Let's assume that we have some other code accessing ht->table and racing
> against ttm_object_file_release()->drm_ht_remove().
> This would mean that such code must do the following:
>   a) take spin_lock(&tfile->lock)
>   b) check ht->table for being non-NULL and only after that it can dereference ht->table.
>
> But I don't see any code checking ht->table for NULL. So if race against drm_ht_remove()
> is possible, this code is already broken and this spin_lock doesn't save us from NULL-ptr
> deref.
>
> So, either we already protected from such scenarios (e.g. we are the only owners of tdev/tfile in
> ttm_object_device_release()/ttm_object_file_release()) or this code is already terribly
> broken. Anyways we can just move drm_ht_remove() out of spin_lock()/spin_unlock() section.
>
> Did I miss anything? 
>
>
>> Sure, we could change the API to return the object removed, and
>> then force the caller to free the object that was removed from the hash
>> table outside the lock it's holding, but that's a really inelegant API.
>>
> This won't be required if I'm right.
>
Actually, I've already sent out a patch for internal review to remove
the spinlocks around drm_ht_free().
They are both in destructors so it should be harmless in this particular
case. The reason the locks are there is to avoid upsetting static code
analyzers that think the hash table pointer should be protected because
it is elsewhere in the code.

However, while it is common that acquiring a resource (in this case
vmalloc space) might sleep,  Sleeping while releasing it ishould, IMO in
general be avoided if at all possible. It's quite common to take a lock
around kref_put() and if the destructor needs to sleep that requires
unlocking in it, leading to bad looking code that upsets static
analyzers and requires extra locking cycles.

In addition, if the vfree sleeping is triggered by waiting for a thread
currently blocked by, for example a memory allocation, which is blocked
by the kernel running shrinkers, which call vfree() then we're in a
deadlock situation.

So to summarize. Yes, the drm callers can be fixed up, but IMO requiring
vfree() to be non-atomic is IMO not a good idea if avoidable.

Thanks,

Thomas



--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2017-03-27 14:11 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-24 10:53 Tetsuo Handa
2017-03-24 12:22 ` Andrey Ryabinin
2017-03-24 12:40   ` Tetsuo Handa
2017-03-24 15:05     ` Andrey Ryabinin
2017-03-24 16:17       ` Matthew Wilcox
2017-03-27 13:26         ` Andrey Ryabinin
2017-03-27 14:06           ` Matthew Wilcox
2017-03-27 14:10           ` Thomas Hellstrom [this message]
2017-03-27 14:29             ` Tetsuo Handa
2017-03-27 15:02               ` Andrey Ryabinin
2017-03-28 10:07                 ` Tetsuo Handa
2017-03-24 22:47       ` Tetsuo Handa
2017-03-27 10:16         ` Tetsuo Handa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f1c0b9ec-c0c8-502c-c7f0-fe692c73ab04@vmware.com \
    --to=thellstrom@vmware.com \
    --cc=airlied@linux.ie \
    --cc=aryabinin@virtuozzo.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hch@lst.de \
    --cc=hpa@zytor.com \
    --cc=joaodias@google.com \
    --cc=joelaf@google.com \
    --cc=jszhang@marvell.com \
    --cc=linux-mm@kvack.org \
    --cc=mingo@elte.hu \
    --cc=penguin-kernel@I-love.SAKURA.ne.jp \
    --cc=tglx@linutronix.de \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox