diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2017-08-31 06:01:26 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-09-11 13:34:57 -0400 |
commit | 17451138cf60f5d64eed88cc5defd44981926d9d (patch) | |
tree | ea335a05d9e038876d42bcd8a73c56e3b60af1a5 /drivers/gpu/nvgpu/common/linux/ioctl_channel.c | |
parent | de0ce3e017decadd3a5049477f17ba770ddf074c (diff) |
gpu: nvgpu: hold ch ref when getting ch from fd
Fix a race condition in gk20a_get_channel_from_file() that returns a
channel pointer from an fd: take a reference to the channel before
putting the file ref back. Now the caller is responsible of releasing
the channel reference eventually.
Also document why dbg_session_channel_data has to hold a ref to the
channel file instead of just the channel: that might deadlock if the fds
were closed in "wrong" order.
Change-Id: I8e91b809f5f7b1cb0c1487bd955ad6d643727a53
Signed-off-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1549290
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/ioctl_channel.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/ioctl_channel.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_channel.c b/drivers/gpu/nvgpu/common/linux/ioctl_channel.c index ab02dc42..5e09c677 100644 --- a/drivers/gpu/nvgpu/common/linux/ioctl_channel.c +++ b/drivers/gpu/nvgpu/common/linux/ioctl_channel.c | |||
@@ -260,8 +260,15 @@ static int gk20a_init_error_notifier(struct channel_gk20a *ch, | |||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | /* | ||
264 | * This returns the channel with a reference. The caller must | ||
265 | * gk20a_channel_put() the ref back after use. | ||
266 | * | ||
267 | * NULL is returned if the channel was not found. | ||
268 | */ | ||
263 | struct channel_gk20a *gk20a_get_channel_from_file(int fd) | 269 | struct channel_gk20a *gk20a_get_channel_from_file(int fd) |
264 | { | 270 | { |
271 | struct channel_gk20a *ch; | ||
265 | struct channel_priv *priv; | 272 | struct channel_priv *priv; |
266 | struct file *f = fget(fd); | 273 | struct file *f = fget(fd); |
267 | 274 | ||
@@ -274,8 +281,9 @@ struct channel_gk20a *gk20a_get_channel_from_file(int fd) | |||
274 | } | 281 | } |
275 | 282 | ||
276 | priv = (struct channel_priv *)f->private_data; | 283 | priv = (struct channel_priv *)f->private_data; |
284 | ch = gk20a_channel_get(priv->c); | ||
277 | fput(f); | 285 | fput(f); |
278 | return priv->c; | 286 | return ch; |
279 | } | 287 | } |
280 | 288 | ||
281 | int gk20a_channel_release(struct inode *inode, struct file *filp) | 289 | int gk20a_channel_release(struct inode *inode, struct file *filp) |