From owner-freebsd-hackers@freebsd.org Sat Oct 29 21:37:21 2016 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AEEC4C26CFC for ; Sat, 29 Oct 2016 21:37:21 +0000 (UTC) (envelope-from dumbbell@FreeBSD.org) Received: from mail.made4.biz (mail.made4.biz [IPv6:2001:41d0:2:c018::1:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 78F003D1 for ; Sat, 29 Oct 2016 21:37:21 +0000 (UTC) (envelope-from dumbbell@FreeBSD.org) Received: from 141.7.19.93.rev.sfr.net ([93.19.7.141] helo=magellan.dumbbell.fr) by mail.made4.biz with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.87 (FreeBSD)) (envelope-from ) id 1c0bJW-000Lq2-42 for freebsd-hackers@freebsd.org; Sat, 29 Oct 2016 23:37:19 +0200 To: "freebsd-hackers@freebsd.org" From: =?UTF-8?Q?Jean-S=c3=a9bastien_P=c3=a9dron?= Subject: Linux' struct address_space & FreeBSD's vm_object Message-ID: Date: Sat, 29 Oct 2016 23:37:13 +0200 User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="wrWAIoLvm0igI7WMDSWPohCt1oPvJaThA" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Oct 2016 21:37:21 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --wrWAIoLvm0igI7WMDSWPohCt1oPvJaThA Content-Type: multipart/mixed; boundary="pJfrg5t3ajHA4MuUpoS2t0vSaJq7hhKSj"; protected-headers="v1" From: =?UTF-8?Q?Jean-S=c3=a9bastien_P=c3=a9dron?= To: "freebsd-hackers@freebsd.org" Message-ID: Subject: Linux' struct address_space & FreeBSD's vm_object --pJfrg5t3ajHA4MuUpoS2t0vSaJq7hhKSj Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi! I'm tracking a memory leak in the drm-next-4.7 branch [1]. I found the issue, however, I'm unsure of the solution for now. Let me sum up what I understand (or what I think I understand :): In Linux, they use a `struct vm_area_struct` to represent a mapping of an object. It holds the callback functions (open, close and fault) of the device driver and the private data to be used with those callbacks. All `struct vm_area_struct` are stored in a tree in another structure called `struct address_space` which belongs to the owner of the resource (an inode in the case of DRM). This structure holds references to pages loaded from the inode, so it acts as a page cache. So: struct inode `-- struct address_space |-- tree of pages `-- tree of struct vm_area_struct In DRM, there is a `struct vm_area_struct` for each mapping of each graphics object. But those mapping are all stored in the same `struct address_space` belonging to an "anonymous inode" attached to the device. Furthermore, a DRM driver creates three character devices in /dev for each real device, and all three character devices use this same anonymous inode. Therefore, if I understand correctly, all mappings for all three character devices use the same list of pages. Thus the memory is shared. In DRM, when a mapping must be released, eg. i915_gem_release_mmap() indirectly calls unmap_mapping_range() with the anonymous inode's `struct address_space`. This function removes all mappings of a given graphics object, thus removes all `struct vm_area_struct` from `struct address` which are covered by the specified range. Currently, on FreeBSD, `struct address_space` is replaced by the vm_object returned by cdev_pager_allocate(). The first issue is that we never create the equivalent of `struct address_space` for the global anonymous inode. Therefore the code responsible for removing mappings does nothing and mappings & pages are leaked. Anyway, the d_mmap_single implementation doesn't even try to fill the equivalent of `struct address_space`. So that's my understanding of the issue. First, I'm not 100% sure of what I described and second, I don't see how to implement the same shared page cache in FreeBSD because a device pager vm_object can't be shared by multiple mappings (or can it?). Can you confirm my comprehension? Do you have any ideas to implement that= ? Thank you very much for your time! [1] In the development tree for DRM: https://github.com/FreeBSDDesktop/freebsd-base-graphics --=20 Jean-S=C3=A9bastien P=C3=A9dron --pJfrg5t3ajHA4MuUpoS2t0vSaJq7hhKSj-- --wrWAIoLvm0igI7WMDSWPohCt1oPvJaThA Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQIcBAEBCgAGBQJYFRaJAAoJEDnpl2Gl/ZTMLwgP/1h6/XVuyXqUCDWPClaJxpIv RT1+AEwrF7MWxciskSpSMr2mh54Xdjf2wZh6y3ct/LHpXqVmsXqGMDLjCz1dbc0G yErVXnijI5HuH3Gp+0nRXA2bMv0FxDYrwTtjWnhBvXvDt3N211bFw5iQbbo/6B5+ E75Dy2Y4ux0/CWy22tSyCRFWzEKMckdxK3BTCkKdOqZtLRRrjq6qV+4OYYJxNqdQ XbY6NUKEBXz+jrRjewOuqd3cq9UmEmLYk09x8xwpn8EBKiIRG9Va4kigJTv9ZjJQ ZztHipWQrz9A/rin8CUVuxVhLZos6BDz+a7drtG1ZldUfgofFKK6U7jnxhE4qAt5 Z0NFU5Fd+bu7qhGEtWTjzZywTmPjtboI06BYknRS8ckZnTOlhfb2kVFO7sIOA2yF Ui4yHZAn9DRHvQQv2+HqKIxiplRjCj3Fpu6aXYM6tNmZQG/hok+GNGmGEjFDmJgh PZZr6JHfv/DXn2eUoHJdTq7y0qRTMUHG84ZsRn0lZhgptwFsGcmc6Bhr/BiFODvi Hyq8cbnjsFNDVG98ZWg1ggw26QttgZo4bCWTMGRd26sSw1WW5QZP90f2H/ASgJlU Ymirz+wGEdZ9hYUe3UazYnRSc766bmy553FoAPSDOaxEctMemJBZijJVT4gyrFUy +AWW+jWlhjaIf2cCb8bZ =n94E -----END PGP SIGNATURE----- --wrWAIoLvm0igI7WMDSWPohCt1oPvJaThA--