Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fb252ca authored by Chris Wilson's avatar Chris Wilson Committed by Greg Kroah-Hartman
Browse files

drm/syncobj: Stop reusing the same struct file for all syncobj -> fd



commit e7cdf5c82f1773c3386b93bbcf13b9bfff29fa31 upstream.

The vk cts test:
dEQP-VK.api.external.semaphore.opaque_fd.export_multiple_times_temporary

triggers a lot of
VFS: Close: file count is 0

Dave pointed out that clearing the syncobj->file from
drm_syncobj_file_release() was sufficient to silence the test, but that
opens a can of worm since we assumed that the syncobj->file was never
unset. Stop trying to reuse the same struct file for every fd pointing
to the drm_syncobj, and allocate one file for each fd instead.

v2: Fixup return handling of drm_syncobj_fd_to_handle
v2.1: [airlied: fix possible syncobj ref race]
v2.2: [jekstrand: back-port to 4.14]

Reported-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Tested-by: default avatarDave Airlie <airlied@redhat.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarJason Ekstrand <jason@jlekstrand.net>
Tested-by: default avatarClayton Craft <clayton.a.craft@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a9b385a5
Loading
Loading
Loading
Loading
+30 −51
Original line number Diff line number Diff line
@@ -328,28 +328,11 @@ static const struct file_operations drm_syncobj_file_fops = {
	.release = drm_syncobj_file_release,
};

static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj)
{
	struct file *file = anon_inode_getfile("syncobj_file",
					       &drm_syncobj_file_fops,
					       syncobj, 0);
	if (IS_ERR(file))
		return PTR_ERR(file);

	drm_syncobj_get(syncobj);
	if (cmpxchg(&syncobj->file, NULL, file)) {
		/* lost the race */
		fput(file);
	}

	return 0;
}

static int drm_syncobj_handle_to_fd(struct drm_file *file_private,
				    u32 handle, int *p_fd)
{
	struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
	int ret;
	struct file *file;
	int fd;

	if (!syncobj)
@@ -361,46 +344,40 @@ static int drm_syncobj_handle_to_fd(struct drm_file *file_private,
		return fd;
	}

	if (!syncobj->file) {
		ret = drm_syncobj_alloc_file(syncobj);
		if (ret)
			goto out_put_fd;
	}
	fd_install(fd, syncobj->file);
	drm_syncobj_put(syncobj);
	*p_fd = fd;
	return 0;
out_put_fd:
	file = anon_inode_getfile("syncobj_file",
				  &drm_syncobj_file_fops,
				  syncobj, 0);
	if (IS_ERR(file)) {
		put_unused_fd(fd);
		drm_syncobj_put(syncobj);
	return ret;
		return PTR_ERR(file);
	}

static struct drm_syncobj *drm_syncobj_fdget(int fd)
{
	struct file *file = fget(fd);

	if (!file)
		return NULL;
	if (file->f_op != &drm_syncobj_file_fops)
		goto err;
	drm_syncobj_get(syncobj);
	fd_install(fd, file);

	return file->private_data;
err:
	fput(file);
	return NULL;
};
	*p_fd = fd;
	return 0;
}

static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
				    int fd, u32 *handle)
{
	struct drm_syncobj *syncobj = drm_syncobj_fdget(fd);
	struct drm_syncobj *syncobj;
	struct file *file;
	int ret;

	if (!syncobj)
	file = fget(fd);
	if (!file)
		return -EINVAL;

	if (file->f_op != &drm_syncobj_file_fops) {
		fput(file);
		return -EINVAL;
	}

	/* take a reference to put in the idr */
	syncobj = file->private_data;
	drm_syncobj_get(syncobj);

	idr_preload(GFP_KERNEL);
@@ -409,12 +386,14 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
	spin_unlock(&file_private->syncobj_table_lock);
	idr_preload_end();

	if (ret < 0) {
		fput(syncobj->file);
		return ret;
	}
	if (ret > 0) {
		*handle = ret;
	return 0;
		ret = 0;
	} else
		drm_syncobj_put(syncobj);

	fput(file);
	return ret;
}

int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
+0 −5
Original line number Diff line number Diff line
@@ -60,11 +60,6 @@ struct drm_syncobj {
	 * locks cb_list and write-locks fence.
	 */
	spinlock_t lock;
	/**
	 * @file:
	 * a file backing for this syncobj.
	 */
	struct file *file;
};

typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj,