msm: kgsl: Fail if sysfs or debugfs initialization fails

While creating a new process struct for kgsl, clean up resources
and bail if sysfs or debugfs initialization fails. This prevents
errors further down the line.

CRs-fixed: 509931
Change-Id: If0857628a56eecf4855013aaf313de28ac9ad108
Signed-off-by: Harsh Vardhan Dwivedi <hdwivedi@codeaurora.org>
Signed-off-by: Carter Cooper <ccooper@codeaurora.org>
This commit is contained in:
Carter Cooper 2013-07-10 14:01:22 -06:00 committed by Iliyan Malchev
parent 96fbf74221
commit dfeec65dc1
5 changed files with 75 additions and 28 deletions

View file

@ -755,7 +755,7 @@ static void kgsl_destroy_process_private(struct kref *kref)
list_del(&private->list);
mutex_unlock(&kgsl_driver.process_mutex);
if (private->kobj.parent)
if (private->kobj.state_in_sysfs)
kgsl_process_uninit_sysfs(private);
if (private->debug_root)
debugfs_remove_recursive(private->debug_root);
@ -869,21 +869,23 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
pt_name = task_tgid_nr(current);
private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
if (private->pagetable == NULL) {
mutex_unlock(&private->process_private_mutex);
kgsl_put_process_private(cur_dev_priv->device,
private);
return NULL;
}
if (private->pagetable == NULL)
goto error;
}
kgsl_process_init_sysfs(private);
kgsl_process_init_debugfs(private);
if (kgsl_process_init_sysfs(cur_dev_priv->device, private))
goto error;
if (kgsl_process_init_debugfs(private))
goto error;
done:
mutex_unlock(&private->process_private_mutex);
return private;
error:
mutex_unlock(&private->process_private_mutex);
kgsl_put_process_private(cur_dev_priv->device, private);
return NULL;
}
int kgsl_close_device(struct kgsl_device *device)

View file

@ -322,25 +322,53 @@ static const struct file_operations process_mem_fops = {
.release = single_release,
};
void
/**
* kgsl_process_init_debugfs() - Initialize debugfs for a process
* @private: Pointer to process private structure created for the process
*
* @returns: 0 on success, error code otherwise
*
* kgsl_process_init_debugfs() is called at the time of creating the
* process struct when a process opens kgsl device for the first time.
* The function creates the debugfs files for the process. If debugfs is
* disabled in the kernel, we ignore that error and return as successful.
*/
int
kgsl_process_init_debugfs(struct kgsl_process_private *private)
{
unsigned char name[16];
struct dentry *mem_dentry;
int ret = 0;
struct dentry *dentry;
snprintf(name, sizeof(name), "%d", private->pid);
private->debug_root = debugfs_create_dir(name, proc_d_debugfs);
if (private->debug_root) {
private->debug_root->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid;
private->debug_root->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid;
}
mem_dentry = debugfs_create_file("mem", 0400, private->debug_root, private,
if (!private->debug_root)
return -EINVAL;
/*
* debugfs_create_dir() and debugfs_create_file() both
* return -ENODEV if debugfs is disabled in the kernel.
* We make a distinction between these two functions
* failing and debugfs being disabled in the kernel.
* In the first case, we abort process private struct
* creation, in the second we continue without any changes.
* So if debugfs is disabled in kernel, return as
* success.
*/
dentry = debugfs_create_file("mem", 0400, private->debug_root, private,
&process_mem_fops);
if (mem_dentry) {
mem_dentry->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid;
mem_dentry->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid;
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
if (ret == -ENODEV)
ret = 0;
}
return ret;
}
void kgsl_core_debugfs_init(void)

View file

@ -21,7 +21,7 @@ struct kgsl_process_private;
void kgsl_core_debugfs_init(void);
void kgsl_core_debugfs_close(void);
void kgsl_device_debugfs_init(struct kgsl_device *device);
int kgsl_device_debugfs_init(struct kgsl_device *device);
extern struct dentry *kgsl_debugfs_dir;
static inline struct dentry *kgsl_get_debugfs_dir(void)

View file

@ -170,17 +170,32 @@ kgsl_process_uninit_sysfs(struct kgsl_process_private *private)
kobject_put(&private->kobj);
}
void
kgsl_process_init_sysfs(struct kgsl_process_private *private)
/**
* kgsl_process_init_sysfs() - Initialize and create sysfs files for a process
*
* @device: Pointer to kgsl device struct
* @private: Pointer to the structure for the process
*
* @returns: 0 on success, error code otherwise
*
* kgsl_process_init_sysfs() is called at the time of creating the
* process struct when a process opens the kgsl device for the first time.
* This function creates the sysfs files for the process.
*/
int
kgsl_process_init_sysfs(struct kgsl_device *device,
struct kgsl_process_private *private)
{
unsigned char name[16];
int i, ret;
int i, ret = 0;
snprintf(name, sizeof(name), "%d", private->pid);
if (kobject_init_and_add(&private->kobj, &ktype_mem_entry,
kgsl_driver.prockobj, name))
return;
ret = kobject_init_and_add(&private->kobj, &ktype_mem_entry,
kgsl_driver.prockobj, name);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(mem_stats); i++) {
/* We need to check the value of sysfs_create_file, but we
@ -191,6 +206,7 @@ kgsl_process_init_sysfs(struct kgsl_process_private *private)
ret = sysfs_create_file(&private->kobj,
&mem_stats[i].max_attr.attr);
}
return ret;
}
static int kgsl_drv_memstat_show(struct device *dev,

View file

@ -65,7 +65,8 @@ int kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc,
void kgsl_cache_range_op(struct kgsl_memdesc *memdesc, int op);
void kgsl_process_init_sysfs(struct kgsl_process_private *private);
int kgsl_process_init_sysfs(struct kgsl_device *device,
struct kgsl_process_private *private);
void kgsl_process_uninit_sysfs(struct kgsl_process_private *private);
int kgsl_sharedmem_init_sysfs(void);