Our current DRM design uses a single address_space for all users of the same DRM device. However, there is no way to create an anonymous address_space without an underlying inode. Therefore, we wait for the first ->open() callback on a registered char-dev and take-over the inode of the char-dev. This worked well so far, but has several drawbacks: - We screw with FS internals and rely on some non-obvious invariants like inode->i_mapping being the same as inode->i_data for char-devs. - We don't have any address_space prior to the first ->open() from user-space. This leads to ugly fallback code and we cannot allocate global objects early. As pointed out by Al-Viro, fs/anon_inode.c is *not* supposed to be used by drivers for anonymous inode-allocation. Therefore, this patch follows the proposed alternative solution and adds a pseudo filesystem mount-point to DRM. We can then allocate private inodes including a private address_space for each DRM device at initialization time. Note that we could use: sysfs_get_inode(sysfs_mnt->mnt_sb, drm_device->dev->kobj.sd); to get access to the underlying sysfs-inode of a "struct device" object. However, most of this information is currently hidden and it's not clear whether this address_space is suitable for driver access. Thus, unless linux allows anonymous address_space objects or driver-core provides a public inode per device, we're left with our own private internal mount point. Signed-off-by: David Herrmann <dh.herrmann@xxxxxxxxx> --- drivers/gpu/drm/drm_drv.c | 37 +++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 1 + 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 345be03..48ee03f 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -49,6 +49,8 @@ #include <linux/debugfs.h> #include <linux/slab.h> #include <linux/export.h> +#include <linux/fs.h> +#include <linux/mount.h> #include <drm/drmP.h> #include <drm/drm_core.h> @@ -171,6 +173,30 @@ static const struct drm_ioctl_desc drm_ioctls[] = { #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) +static struct vfsmount *drm_mnt; + +struct inode *drm_alloc_inode(void) +{ + return alloc_anon_inode(drm_mnt->mnt_sb); +} + +static const struct dentry_operations drm_dops = { + .d_dname = simple_dname, +}; + +static struct dentry *drm_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_pseudo(fs_type, "drm:", NULL, &drm_dops, 0x010203ff); +} + +static struct file_system_type drm_fs = { + .name = "drm", + .owner = THIS_MODULE, + .mount = drm_mount, + .kill_sb = kill_anon_super, +}; + /** File operations structure */ static const struct file_operations drm_stub_fops = { .owner = THIS_MODULE, @@ -203,9 +229,19 @@ static int __init drm_core_init(void) goto err_p3; } + drm_mnt = kern_mount(&drm_fs); + if (IS_ERR(drm_mnt)) { + ret = PTR_ERR(drm_mnt); + DRM_ERROR("Cannot mount pseudo fs: %d\n", ret); + goto err_p4; + } + DRM_INFO("Initialized %s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); return 0; + +err_p4: + debugfs_remove(drm_debugfs_root); err_p3: drm_sysfs_destroy(); err_p2: @@ -218,6 +254,7 @@ err_p1: static void __exit drm_core_exit(void) { + kern_unmount(drm_mnt); debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2fe9b5d..02637a5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1258,6 +1258,7 @@ extern long drm_ioctl(struct file *filp, extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern int drm_lastclose(struct drm_device *dev); +extern struct inode *drm_alloc_inode(void); /* Device support (drm_fops.h) */ extern struct mutex drm_global_mutex; -- 1.8.5.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel