From patchwork Fri Jan 24 12:56:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 11350197 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 25BB8109A for ; Fri, 24 Jan 2020 12:56:44 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0D94A20708 for ; Fri, 24 Jan 2020 12:56:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0D94A20708 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=chris-wilson.co.uk Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7E61072A49; Fri, 24 Jan 2020 12:56:40 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8CB146FA54; Fri, 24 Jan 2020 12:56:38 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 19995095-1500050 for multiple; Fri, 24 Jan 2020 12:56:28 +0000 From: Chris Wilson To: dri-devel@lists.freedesktop.org Subject: [PATCH 1/2] drm: Release filp before global lock Date: Fri, 24 Jan 2020 12:56:26 +0000 Message-Id: <20200124125627.125042-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.25.0 MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Hellstr=C3=B6m?= Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The file is not part of the global drm resource and can be released prior to take the global mutex to drop the open_count (and potentially close) the drm device. As the global mutex is indeed global, not only within the device but across devices, a slow file release mechanism can bottleneck the entire system. However, inside drm_close_helper() there are a number of dev->driver callbacks that take the drm_device as the first parameter... Worryingly some of those callbacks may be (implicitly) depending on the global mutex. v2: Drop the debug message for the open-count, it's included with the drm_file_free() debug message -- and for good measure make that up as reading outside of the mutex. v3: Separate the calling of the filp cleanup outside of drm_global_mutex into a new drm_release_noglobal() hook, so that we can phase the transition. drm/savage relies on the global mutex, and there may be more, so be cautious. Signed-off-by: Chris Wilson Cc: Thomas Hellström (VMware) Acked-by: Thomas Hellström (VMware) --- drivers/gpu/drm/drm_file.c | 36 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.c | 2 +- include/drm/drm_file.h | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 92d16724f949..e25306c49cc6 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -220,7 +220,7 @@ void drm_file_free(struct drm_file *file) DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", task_pid_nr(current), (long)old_encode_dev(file->minor->kdev->devt), - dev->open_count); + READ_ONCE(dev->open_count)); if (drm_core_check_feature(dev, DRIVER_LEGACY) && dev->driver->preclose) @@ -455,6 +455,40 @@ int drm_release(struct inode *inode, struct file *filp) } EXPORT_SYMBOL(drm_release); +/** + * drm_release_noglobal - release method for DRM file + * @inode: device inode + * @filp: file pointer. + * + * This function may be used by drivers as their &file_operations.release + * method. It frees any resources associated with the open file prior to taking + * the drm_global_mutex, which then calls the &drm_driver.postclose driver + * callback. If this is the last open file for the DRM device also proceeds to + * call the &drm_driver.lastclose driver callback. + * + * RETURNS: + * + * Always succeeds and returns 0. + */ +int drm_release_noglobal(struct inode *inode, struct file *filp) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_minor *minor = file_priv->minor; + struct drm_device *dev = minor->dev; + + drm_close_helper(filp); + + mutex_lock(&drm_global_mutex); + if (!--dev->open_count) + drm_lastclose(dev); + mutex_unlock(&drm_global_mutex); + + drm_minor_release(minor); + + return 0; +} +EXPORT_SYMBOL(drm_release_noglobal); + /** * drm_read - read method for DRM file * @filp: file pointer diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9b42e962032..5a5846d892f4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2673,7 +2673,7 @@ const struct dev_pm_ops i915_pm_ops = { static const struct file_operations i915_driver_fops = { .owner = THIS_MODULE, .open = drm_open, - .release = drm_release, + .release = drm_release_noglobal, .unlocked_ioctl = drm_ioctl, .mmap = i915_gem_mmap, .poll = drm_poll, diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 8b099b347817..19df8028a6c4 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -374,6 +374,7 @@ int drm_open(struct inode *inode, struct file *filp); ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); int drm_release(struct inode *inode, struct file *filp); +int drm_release_noglobal(struct inode *inode, struct file *filp); __poll_t drm_poll(struct file *filp, struct poll_table_struct *wait); int drm_event_reserve_init_locked(struct drm_device *dev, struct drm_file *file_priv,