Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp3302906img; Mon, 25 Mar 2019 07:41:49 -0700 (PDT) X-Google-Smtp-Source: APXvYqw3XIycgfMwzsCHkmNtc+VzKdKHacjpDXkJL4Oj88utNHfdmyP75uVhxmEzoD9bARJOPHFV X-Received: by 2002:a17:902:bb92:: with SMTP id m18mr8193553pls.316.1553524909597; Mon, 25 Mar 2019 07:41:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553524909; cv=none; d=google.com; s=arc-20160816; b=nydB51mKFHtp3hsASUp3QQqPigP3mHkq4wZY8UddyNOvcO1WCqdPMh4rRFlK2f0sTj JL95Rw0dNMuFcUsk4+oDAln6SeGXrBqt8JEBZzR+FYAfbVVI/HtpTs9LrUQSBfebSJwf iHEhVU4Ly/YRD+7Rh1XfYuvuA1eDyIy2DgyrT5jPAaLl0y449olazBPQ5TYKqWSA3YZQ lcGm8TCqpKtK/ZZmPfUffKJiFwzPBTCMUYEf0e7OmsUAtRaBnzd9E6cLf55A3F0VHvfd iHu4onMNFx0KZ/w+1Y1bikeIiPGVlLsFR5TePcbdkSIfwE04vkntyvimudoWPk3dLh/M /Qwg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=3Ti6IjAWZ9nxGji48U2finShhN9k8Ywg/5Fu3MYAh2E=; b=QxXOIT3WuJKIsxUoooIPSNUSNDeiC7vZmkAXEYUUG31rRWQ1Nf8qRy6bPB4hK13Xmz o66wlSOQ5tspUTRjBOt56cQIbMNDcOLus81BUxDDEwY6/12o2arFgjrwdfgnbczHmzQe EMhKhjHxSlf+sssih5zCYXpD29hY2ZTwIDIVcJhRFtLPNP7G7RMZxSkRpH+RqbOvJeE9 v/2oYA0g4NyiB2a+P2MoOnzdwylWB/BH/9IlXqfVCbykW4xB7ys2CFf3LwEXe7TBzAOk 4hgjvgp5JPUEnytrc5lAydqI1fPzJGfhoDSm9Sd6cTxnB6a4rY4O49i+GzvZ+zZuKdvs MIGA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w1si14163858plz.106.2019.03.25.07.41.34; Mon, 25 Mar 2019 07:41:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729506AbfCYOkj (ORCPT + 99 others); Mon, 25 Mar 2019 10:40:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39788 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729403AbfCYOkX (ORCPT ); Mon, 25 Mar 2019 10:40:23 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CEC44821E5; Mon, 25 Mar 2019 14:40:22 +0000 (UTC) Received: from localhost.localdomain.com (unknown [10.20.6.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2ABDC1001DC8; Mon, 25 Mar 2019 14:40:22 +0000 (UTC) From: jglisse@redhat.com To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= , Andrew Morton , John Hubbard , Dan Williams Subject: [PATCH v2 10/11] mm/hmm: add helpers for driver to safely take the mmap_sem v2 Date: Mon, 25 Mar 2019 10:40:10 -0400 Message-Id: <20190325144011.10560-11-jglisse@redhat.com> In-Reply-To: <20190325144011.10560-1-jglisse@redhat.com> References: <20190325144011.10560-1-jglisse@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 25 Mar 2019 14:40:22 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jérôme Glisse The device driver context which holds reference to mirror and thus to core hmm struct might outlive the mm against which it was created. To avoid every driver to check for that case provide an helper that check if mm is still alive and take the mmap_sem in read mode if so. If the mm have been destroy (mmu_notifier release call back did happen) then we return -EINVAL so that calling code knows that it is trying to do something against a mm that is no longer valid. Changes since v1: - removed bunch of useless check (if API is use with bogus argument better to fail loudly so user fix their code) Signed-off-by: Jérôme Glisse Reviewed-by: Ralph Campbell Cc: Andrew Morton Cc: John Hubbard Cc: Dan Williams --- include/linux/hmm.h | 50 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/include/linux/hmm.h b/include/linux/hmm.h index f3b919b04eda..5f9deaeb9d77 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -438,6 +438,50 @@ struct hmm_mirror { int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); void hmm_mirror_unregister(struct hmm_mirror *mirror); +/* + * hmm_mirror_mm_down_read() - lock the mmap_sem in read mode + * @mirror: the HMM mm mirror for which we want to lock the mmap_sem + * Returns: -EINVAL if the mm is dead, 0 otherwise (lock taken). + * + * The device driver context which holds reference to mirror and thus to core + * hmm struct might outlive the mm against which it was created. To avoid every + * driver to check for that case provide an helper that check if mm is still + * alive and take the mmap_sem in read mode if so. If the mm have been destroy + * (mmu_notifier release call back did happen) then we return -EINVAL so that + * calling code knows that it is trying to do something against a mm that is + * no longer valid. + */ +static inline int hmm_mirror_mm_down_read(struct hmm_mirror *mirror) +{ + struct mm_struct *mm; + + /* Sanity check ... */ + if (!mirror || !mirror->hmm) + return -EINVAL; + /* + * Before trying to take the mmap_sem make sure the mm is still + * alive as device driver context might outlive the mm lifetime. + * + * FIXME: should we also check for mm that outlive its owning + * task ? + */ + mm = READ_ONCE(mirror->hmm->mm); + if (mirror->hmm->dead || !mm) + return -EINVAL; + + down_read(&mm->mmap_sem); + return 0; +} + +/* + * hmm_mirror_mm_up_read() - unlock the mmap_sem from read mode + * @mirror: the HMM mm mirror for which we want to lock the mmap_sem + */ +static inline void hmm_mirror_mm_up_read(struct hmm_mirror *mirror) +{ + up_read(&mirror->hmm->mm->mmap_sem); +} + /* * To snapshot the CPU page table you first have to call hmm_range_register() @@ -463,7 +507,7 @@ void hmm_mirror_unregister(struct hmm_mirror *mirror); * if (ret) * return ret; * - * down_read(mm->mmap_sem); + * hmm_mirror_mm_down_read(mirror); * again: * * if (!hmm_range_wait_until_valid(&range, TIMEOUT)) { @@ -476,13 +520,13 @@ void hmm_mirror_unregister(struct hmm_mirror *mirror); * * ret = hmm_range_snapshot(&range); or hmm_range_fault(&range); * if (ret == -EAGAIN) { - * down_read(mm->mmap_sem); + * hmm_mirror_mm_down_read(mirror); * goto again; * } else if (ret == -EBUSY) { * goto again; * } * - * up_read(&mm->mmap_sem); + * hmm_mirror_mm_up_read(mirror); * if (ret) { * hmm_range_unregister(range); * return ret; -- 2.17.2