mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
nvmap: Use same nvmap client for namespaces in a process
Some of the libraries may be linked into different namespaces, but they belong to same process. So each namespace can open the /dev/nvmap node and call nvmap ioctls, instead of reusing the already opened /dev/nvmap FD. Because of this, memory handles created by one namespace can't be used by other namespaces, even though they belong to same process. Fix this issue by following: - When /dev/nvmap node is opened, check if there is already any nvmap client with same pid, if yes use that client; otherwise, create new nvmap client. - Track the number of namespaces via count field. - When /dev/nvmap node is closed, destroy the nvmap client only when count reaches to 0. Bug 3689604 Change-Id: I4c91db36b88e78b7526dd63b006e562c8f66c7ae Signed-off-by: Ketan Patil <ketanp@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2819915 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-by: Ivan Raul Guadarrama <iguadarrama@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
ac3205e61e
commit
ad02c6afa5
@@ -198,18 +198,12 @@ struct nvmap_client *__nvmap_create_client(struct nvmap_device *dev,
|
|||||||
{
|
{
|
||||||
struct nvmap_client *client;
|
struct nvmap_client *client;
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
|
pid_t pid;
|
||||||
|
bool is_existing_client = false;
|
||||||
|
|
||||||
if (WARN_ON(!dev))
|
if (WARN_ON(!dev))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
|
||||||
if (!client)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
client->name = name;
|
|
||||||
client->kernel_client = true;
|
|
||||||
client->handle_refs = RB_ROOT;
|
|
||||||
|
|
||||||
get_task_struct(current->group_leader);
|
get_task_struct(current->group_leader);
|
||||||
task_lock(current->group_leader);
|
task_lock(current->group_leader);
|
||||||
/* don't bother to store task struct for kernel threads,
|
/* don't bother to store task struct for kernel threads,
|
||||||
@@ -221,12 +215,42 @@ struct nvmap_client *__nvmap_create_client(struct nvmap_device *dev,
|
|||||||
task = current->group_leader;
|
task = current->group_leader;
|
||||||
}
|
}
|
||||||
task_unlock(current->group_leader);
|
task_unlock(current->group_leader);
|
||||||
|
|
||||||
|
pid = task ? task->pid : 0;
|
||||||
|
|
||||||
|
mutex_lock(&dev->clients_lock);
|
||||||
|
list_for_each_entry(client, &nvmap_dev->clients, list) {
|
||||||
|
if (nvmap_client_pid(client) == pid) {
|
||||||
|
/* Increment counter to track number of namespaces of a process */
|
||||||
|
atomic_add(1, &client->count);
|
||||||
|
is_existing_client = true;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock:
|
||||||
|
if (is_existing_client) {
|
||||||
|
mutex_unlock(&dev->clients_lock);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||||
|
if (!client)
|
||||||
|
return NULL;
|
||||||
|
client->name = name;
|
||||||
|
client->handle_refs = RB_ROOT;
|
||||||
client->task = task;
|
client->task = task;
|
||||||
|
|
||||||
mutex_init(&client->ref_lock);
|
mutex_init(&client->ref_lock);
|
||||||
atomic_set(&client->count, 1);
|
atomic_set(&client->count, 1);
|
||||||
|
client->kernel_client = false;
|
||||||
|
nvmap_id_array_init(&client->id_array);
|
||||||
|
|
||||||
|
#ifdef NVMAP_CONFIG_HANDLE_AS_ID
|
||||||
|
client->ida = &client->id_array;
|
||||||
|
#else
|
||||||
|
client->ida = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_lock(&dev->clients_lock);
|
|
||||||
list_add(&client->list, &dev->clients);
|
list_add(&client->list, &dev->clients);
|
||||||
if (!IS_ERR_OR_NULL(dev->handles_by_pid)) {
|
if (!IS_ERR_OR_NULL(dev->handles_by_pid)) {
|
||||||
pid_t pid = nvmap_client_pid(client);
|
pid_t pid = nvmap_client_pid(client);
|
||||||
@@ -243,6 +267,11 @@ static void destroy_client(struct nvmap_client *client)
|
|||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
nvmap_id_array_exit(&client->id_array);
|
||||||
|
#ifdef NVMAP_CONFIG_HANDLE_AS_ID
|
||||||
|
client->ida = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_lock(&nvmap_dev->clients_lock);
|
mutex_lock(&nvmap_dev->clients_lock);
|
||||||
if (!IS_ERR_OR_NULL(nvmap_dev->handles_by_pid)) {
|
if (!IS_ERR_OR_NULL(nvmap_dev->handles_by_pid)) {
|
||||||
pid_t pid = nvmap_client_pid(client);
|
pid_t pid = nvmap_client_pid(client);
|
||||||
@@ -298,16 +327,6 @@ static int nvmap_open(struct inode *inode, struct file *filp)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
trace_nvmap_open(priv, priv->name);
|
trace_nvmap_open(priv, priv->name);
|
||||||
|
|
||||||
priv->kernel_client = false;
|
|
||||||
|
|
||||||
nvmap_id_array_init(&priv->id_array);
|
|
||||||
|
|
||||||
#ifdef NVMAP_CONFIG_HANDLE_AS_ID
|
|
||||||
priv->ida = &priv->id_array;
|
|
||||||
#else
|
|
||||||
priv->ida = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
filp->private_data = priv;
|
filp->private_data = priv;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -319,14 +338,11 @@ static int nvmap_release(struct inode *inode, struct file *filp)
|
|||||||
if(!priv)
|
if(!priv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nvmap_id_array_exit(&priv->id_array);
|
|
||||||
|
|
||||||
#ifdef NVMAP_CONFIG_HANDLE_AS_ID
|
|
||||||
priv->ida = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
trace_nvmap_release(priv, priv->name);
|
trace_nvmap_release(priv, priv->name);
|
||||||
|
/*
|
||||||
|
* count field tracks the number of namespaces within a process.
|
||||||
|
* Destroy the client only after all namespaces close the /dev/nvmap node.
|
||||||
|
*/
|
||||||
if (!atomic_dec_return(&priv->count))
|
if (!atomic_dec_return(&priv->count))
|
||||||
destroy_client(priv);
|
destroy_client(priv);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user