Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp4872777imu; Tue, 29 Jan 2019 08:55:39 -0800 (PST) X-Google-Smtp-Source: ALg8bN7p+SPMyJSjB5CR3j9o7SIV7IO7mK1p3RY/cXnMmQd1cFV7CLi/+ld4JJKewEt/2RY6z0Nz X-Received: by 2002:a63:4342:: with SMTP id q63mr24438586pga.63.1548780939161; Tue, 29 Jan 2019 08:55:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548780939; cv=none; d=google.com; s=arc-20160816; b=SCfVjjq4GlRagvJUEX6OB5r6cNtIwYvNxmNEmG6ilytv+UkFX829veAdDDxnD3cQmM ol6gC+cxnV1ofq5neyJjP3aFB1tLiU6esNoqAcnrPXTHYuvV9U+LZvbQyp+B0N/UYSxo ZNC3kBjIXRU5lTmIE9Mppf9WwxVP1FKF1BLC3Kvw9j9bUqCpsKYH20msEwvaloe6WG+R LEox6t9VEeuaNmZd5seaL3Wl6sRwmUY5BS+I0zMEj85BXOnBPlo0AWHvjRiuy0QWstoP 4J7evTumhyokEhXHcFMDcn8Xg4Wgq8zp+u+/mQsy9SPAeywbDAtts5vNEiF8kqNE42zM xmpw== 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=uF0Rg6OUe55CoYMP7oripH2m8c1bWkRZFMmBzBzXOKY=; b=q5NpiyX6TD0NBiqU3Cm8zdR0ytQ/WZpkEypagidEj1jZe4uwpCVrDaW/8874Ml1cpj w7cZ8QqdXtFeYvTERfLD7rkmAeUk5Yv0Z+wj5opfMh69NpXHEtzEG37GEnf3i8nJH4JZ rxKxwQoM8gtA6Lu2s5u3l2QPjR7idsfXSi6y5PF6yumcuBHZZH8IfQ4V2tYJTySBAUqR HUSrLwXw5jgkO2lN+F3sn8R5e8kAw/PbqyA9v1wa76qSft3/Jo8lvZVS5e8dXrJ3u06O c9r48pp5gFz8KgSvK3AH37eE+s3hAV3pC0gORfgHyPdw6+xzn1CWcpLFQ2zhvF+ulVgp TUAA== 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 h67si6587063pfb.146.2019.01.29.08.55.22; Tue, 29 Jan 2019 08:55:39 -0800 (PST) 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 S1728860AbfA2Qy5 (ORCPT + 99 others); Tue, 29 Jan 2019 11:54:57 -0500 Received: from mx1.redhat.com ([209.132.183.28]:33150 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728816AbfA2Qyy (ORCPT ); Tue, 29 Jan 2019 11:54:54 -0500 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 9CB7281DE9; Tue, 29 Jan 2019 16:54:53 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-122-2.rdu2.redhat.com [10.10.122.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97C9D102BCEB; Tue, 29 Jan 2019 16:54:52 +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 , Ralph Campbell , John Hubbard Subject: [PATCH 10/10] mm/hmm: add helpers for driver to safely take the mmap_sem Date: Tue, 29 Jan 2019 11:54:28 -0500 Message-Id: <20190129165428.3931-11-jglisse@redhat.com> In-Reply-To: <20190129165428.3931-1-jglisse@redhat.com> References: <20190129165428.3931-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.25]); Tue, 29 Jan 2019 16:54:53 +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. Signed-off-by: Jérôme Glisse Cc: Andrew Morton Cc: Ralph Campbell Cc: John Hubbard --- 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 b3850297352f..4a1454e3efba 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