From dfeec65dc160264b4cd0925ecb8d354c596653c8 Mon Sep 17 00:00:00 2001 From: Carter Cooper Date: Wed, 10 Jul 2013 14:01:22 -0600 Subject: [PATCH] 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 Signed-off-by: Carter Cooper --- drivers/gpu/msm/kgsl.c | 22 ++++++++------- drivers/gpu/msm/kgsl_debugfs.c | 48 +++++++++++++++++++++++++------- drivers/gpu/msm/kgsl_debugfs.h | 2 +- drivers/gpu/msm/kgsl_sharedmem.c | 28 +++++++++++++++---- drivers/gpu/msm/kgsl_sharedmem.h | 3 +- 5 files changed, 75 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index d81af55c51fd..59398435e682 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -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) diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 60fe1fe17e2e..7f4aa2bafb5a 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -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) diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h index ae5601fb40ad..b2f137cd4b09 100644 --- a/drivers/gpu/msm/kgsl_debugfs.h +++ b/drivers/gpu/msm/kgsl_debugfs.h @@ -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) diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index cf07e128d185..f656b99708d7 100755 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -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, diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index b08c6d685da3..21237da2f677 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -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);