diff --git a/scst/src/scst_mem.c b/scst/src/scst_mem.c index 17310d223..c5139cf74 100644 --- a/scst/src/scst_mem.c +++ b/scst/src/scst_mem.c @@ -74,6 +74,12 @@ static struct shrinker sgv_shrinker; */ static LIST_HEAD(sgv_pools_list); +#ifndef CONFIG_SCST_PROC +static struct kobject *scst_sgv_kobj; +static int scst_sgv_sysfs_create(struct sgv_pool *pool); +static void scst_sgv_sysfs_del(struct sgv_pool *pool); +#endif + static inline bool sgv_pool_clustered(const struct sgv_pool *pool) { return pool->clustering_type != sgv_no_clustering; @@ -1462,9 +1468,11 @@ static int sgv_pool_init(struct sgv_pool *pool, const char *name, list_add_tail(&pool->sgv_pools_list_entry, &sgv_pools_list); spin_unlock_bh(&sgv_pools_lock); +#ifndef CONFIG_SCST_PROC res = scst_sgv_sysfs_create(pool); if (res != 0) goto out_del; +#endif res = 0; @@ -1472,10 +1480,12 @@ out: TRACE_EXIT_RES(res); return res; +#ifndef CONFIG_SCST_PROC out_del: spin_lock_bh(&sgv_pools_lock); list_del(&pool->sgv_pools_list_entry); spin_unlock_bh(&sgv_pools_lock); +#endif out_free: for (i = 0; i < pool->max_caches; i++) { @@ -1555,7 +1565,9 @@ static void sgv_pool_destroy(struct sgv_pool *pool) spin_unlock_bh(&sgv_pools_lock); mutex_unlock(&sgv_pools_mutex); +#ifndef CONFIG_SCST_PROC scst_sgv_sysfs_del(pool); +#endif for (i = 0; i < pool->max_caches; i++) { if (pool->caches[i]) @@ -1880,7 +1892,7 @@ int sgv_procinfo_show(struct seq_file *seq, void *v) #else /* CONFIG_SCST_PROC */ -ssize_t sgv_sysfs_stat_show(struct kobject *kobj, +static ssize_t sgv_sysfs_stat_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct sgv_pool *pool; @@ -1936,7 +1948,7 @@ ssize_t sgv_sysfs_stat_show(struct kobject *kobj, return res; } -ssize_t sgv_sysfs_stat_reset(struct kobject *kobj, +static ssize_t sgv_sysfs_stat_reset(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { struct sgv_pool *pool; @@ -1965,7 +1977,7 @@ ssize_t sgv_sysfs_stat_reset(struct kobject *kobj, return count; } -ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj, +static ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct sgv_pool *pool; @@ -1994,7 +2006,7 @@ ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj, return res; } -ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj, +static ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { TRACE_ENTRY(); @@ -2009,4 +2021,130 @@ ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj, return count; } +static struct kobj_attribute sgv_stat_attr = + __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show, + sgv_sysfs_stat_reset); + +static struct attribute *sgv_attrs[] = { + &sgv_stat_attr.attr, + NULL, +}; + +static void sgv_kobj_release(struct kobject *kobj) +{ + struct sgv_pool *pool; + + TRACE_ENTRY(); + + pool = container_of(kobj, struct sgv_pool, sgv_kobj); + if (pool->sgv_kobj_release_cmpl != NULL) + complete_all(pool->sgv_kobj_release_cmpl); + + TRACE_EXIT(); + return; +} + +static struct kobj_type sgv_pool_ktype = { + .sysfs_ops = &scst_sysfs_ops, + .release = sgv_kobj_release, + .default_attrs = sgv_attrs, +}; + +static int scst_sgv_sysfs_create(struct sgv_pool *pool) +{ + int res; + + TRACE_ENTRY(); + + res = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype, + scst_sgv_kobj, pool->name); + if (res) { + PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name); + goto out; + } + +out: + TRACE_EXIT_RES(res); + return res; +} + +static void scst_sgv_sysfs_del(struct sgv_pool *pool) +{ + int rc; + DECLARE_COMPLETION_ONSTACK(c); + + TRACE_ENTRY(); + + pool->sgv_kobj_release_cmpl = &c; + + kobject_del(&pool->sgv_kobj); + kobject_put(&pool->sgv_kobj); + + rc = wait_for_completion_timeout(pool->sgv_kobj_release_cmpl, HZ); + if (rc == 0) { + PRINT_INFO("Waiting for releasing sysfs entry " + "for SGV pool %s (%d refs)...", pool->name, + atomic_read(&pool->sgv_kobj.kref.refcount)); + wait_for_completion(pool->sgv_kobj_release_cmpl); + PRINT_INFO("Done waiting for releasing sysfs " + "entry for SGV pool %s", pool->name); + } + + TRACE_EXIT(); +} + +static struct kobj_attribute sgv_global_stat_attr = + __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show, + sgv_sysfs_global_stat_reset); + +static struct attribute *sgv_default_attrs[] = { + &sgv_global_stat_attr.attr, + NULL, +}; + +static void scst_sysfs_release(struct kobject *kobj) +{ + kfree(kobj); +} + +static struct kobj_type sgv_ktype = { + .sysfs_ops = &scst_sysfs_ops, + .release = scst_sysfs_release, + .default_attrs = sgv_default_attrs, +}; + +/** + * scst_add_sgv_kobj() - Initialize and add the root SGV kernel object. + */ +int scst_add_sgv_kobj(struct kobject *parent, const char *name) +{ + int res; + + WARN_ON(scst_sgv_kobj); + res = -ENOMEM; + scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL); + if (!scst_sgv_kobj) + goto out; + res = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype, parent, name); + if (res) + goto out_free; +out: + return res; +out_free: + kobject_put(scst_sgv_kobj); + scst_sgv_kobj = NULL; + goto out; +} + +/** + * scst_del_put_sgv_kobj() - Remove the root SGV kernel object. + */ +void scst_del_put_sgv_kobj(void) +{ + WARN_ON(!scst_sgv_kobj); + kobject_del(scst_sgv_kobj); + kobject_put(scst_sgv_kobj); + scst_sgv_kobj = NULL; +} + #endif /* CONFIG_SCST_PROC */ diff --git a/scst/src/scst_mem.h b/scst/src/scst_mem.h index 322fc8024..c6feb3065 100644 --- a/scst/src/scst_mem.h +++ b/scst/src/scst_mem.h @@ -142,15 +142,6 @@ void scst_sgv_pools_deinit(void); #ifdef CONFIG_SCST_PROC int sgv_procinfo_show(struct seq_file *seq, void *v); -#else -ssize_t sgv_sysfs_stat_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf); -ssize_t sgv_sysfs_stat_reset(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count); -ssize_t sgv_sysfs_global_stat_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf); -ssize_t sgv_sysfs_global_stat_reset(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t count); #endif void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index b589c8d3f..e98f9ec0c 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -139,8 +139,6 @@ extern struct kmem_cache *scst_acgd_cachep; extern spinlock_t scst_main_lock; -extern struct scst_sgv_pools scst_sgv; - extern unsigned long scst_flags; extern atomic_t scst_cmd_count; extern struct list_head scst_template_list; @@ -455,14 +453,13 @@ static inline int scst_acn_sysfs_create(struct scst_acn *acn) } static inline void scst_acn_sysfs_del(struct scst_acn *acn) { } -static inline int scst_sgv_sysfs_create(struct sgv_pool *pool) -{ - return 0; -} -static inline void scst_sgv_sysfs_del(struct sgv_pool *pool) { } - #else /* CONFIG_SCST_PROC */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) +extern const struct sysfs_ops scst_sysfs_ops; +#else +extern struct sysfs_ops scst_sysfs_ops; +#endif int scst_sysfs_init(void); void scst_sysfs_cleanup(void); int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt); @@ -473,8 +470,8 @@ void scst_tgt_sysfs_del(struct scst_tgt *tgt); int scst_sess_sysfs_create(struct scst_session *sess); void scst_sess_sysfs_del(struct scst_session *sess); int scst_recreate_sess_luns_link(struct scst_session *sess); -int scst_sgv_sysfs_create(struct sgv_pool *pool); -void scst_sgv_sysfs_del(struct sgv_pool *pool); +int scst_add_sgv_kobj(struct kobject *parent, const char *name); +void scst_del_put_sgv_kobj(void); int scst_devt_sysfs_create(struct scst_dev_type *devt); void scst_devt_sysfs_del(struct scst_dev_type *devt); int scst_dev_sysfs_create(struct scst_device *dev); diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 84bee368c..cbf686ecd 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -31,14 +31,12 @@ #include "scst.h" #endif #include "scst_priv.h" -#include "scst_mem.h" #include "scst_pres.h" static DECLARE_COMPLETION(scst_sysfs_root_release_completion); static struct kobject *scst_targets_kobj; static struct kobject *scst_devices_kobj; -static struct kobject *scst_sgv_kobj; static struct kobject *scst_handlers_kobj; static const char *scst_dev_handler_types[] = { @@ -738,9 +736,9 @@ static ssize_t scst_store(struct kobject *kobj, struct attribute *attr, } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) -static const struct sysfs_ops scst_sysfs_ops = { +const struct sysfs_ops scst_sysfs_ops = { #else -static struct sysfs_ops scst_sysfs_ops = { +struct sysfs_ops scst_sysfs_ops = { #endif .show = scst_show, .store = scst_store, @@ -4258,103 +4256,6 @@ void scst_acn_sysfs_del(struct scst_acn *acn) } -/** - ** SGV directory implementation - **/ - -static struct kobj_attribute sgv_stat_attr = - __ATTR(stats, S_IRUGO | S_IWUSR, sgv_sysfs_stat_show, - sgv_sysfs_stat_reset); - -static struct attribute *sgv_attrs[] = { - &sgv_stat_attr.attr, - NULL, -}; - -static void sgv_kobj_release(struct kobject *kobj) -{ - struct sgv_pool *pool; - - TRACE_ENTRY(); - - pool = container_of(kobj, struct sgv_pool, sgv_kobj); - if (pool->sgv_kobj_release_cmpl != NULL) - complete_all(pool->sgv_kobj_release_cmpl); - - TRACE_EXIT(); - return; -} - -static struct kobj_type sgv_pool_ktype = { - .sysfs_ops = &scst_sysfs_ops, - .release = sgv_kobj_release, - .default_attrs = sgv_attrs, -}; - -int scst_sgv_sysfs_create(struct sgv_pool *pool) -{ - int res; - - TRACE_ENTRY(); - - res = kobject_init_and_add(&pool->sgv_kobj, &sgv_pool_ktype, - scst_sgv_kobj, pool->name); - if (res) { - PRINT_ERROR("Can't add sgv pool %s to sysfs", pool->name); - goto out; - } - -out: - TRACE_EXIT_RES(res); - return res; -} - -void scst_sgv_sysfs_del(struct sgv_pool *pool) -{ - int rc; - DECLARE_COMPLETION_ONSTACK(c); - - TRACE_ENTRY(); - - pool->sgv_kobj_release_cmpl = &c; - - kobject_del(&pool->sgv_kobj); - kobject_put(&pool->sgv_kobj); - - rc = wait_for_completion_timeout(pool->sgv_kobj_release_cmpl, HZ); - if (rc == 0) { - PRINT_INFO("Waiting for releasing sysfs entry " - "for SGV pool %s (%d refs)...", pool->name, - atomic_read(&pool->sgv_kobj.kref.refcount)); - wait_for_completion(pool->sgv_kobj_release_cmpl); - PRINT_INFO("Done waiting for releasing sysfs " - "entry for SGV pool %s", pool->name); - } - - TRACE_EXIT(); - return; -} - -static struct kobj_attribute sgv_global_stat_attr = - __ATTR(global_stats, S_IRUGO | S_IWUSR, sgv_sysfs_global_stat_show, - sgv_sysfs_global_stat_reset); - -static struct attribute *sgv_default_attrs[] = { - &sgv_global_stat_attr.attr, - NULL, -}; - -static void scst_sysfs_release(struct kobject *kobj) -{ - kfree(kobj); -} - -static struct kobj_type sgv_ktype = { - .sysfs_ops = &scst_sysfs_ops, - .release = scst_sysfs_release, - .default_attrs = sgv_default_attrs, -}; - /** ** Dev handlers **/ @@ -5360,14 +5261,9 @@ int __init scst_sysfs_init(void) if (scst_devices_kobj == NULL) goto devices_kobj_error; - scst_sgv_kobj = kzalloc(sizeof(*scst_sgv_kobj), GFP_KERNEL); - if (scst_sgv_kobj == NULL) - goto sgv_kobj_error; - - res = kobject_init_and_add(scst_sgv_kobj, &sgv_ktype, - &scst_sysfs_root_kobj, "%s", "sgv"); + res = scst_add_sgv_kobj(&scst_sysfs_root_kobj, "sgv"); if (res) - goto sgv_kobj_add_error; + goto sgv_kobj_error; scst_handlers_kobj = kobject_create_and_add("handlers", &scst_sysfs_root_kobj); @@ -5379,10 +5275,7 @@ out: return res; handlers_kobj_error: - kobject_del(scst_sgv_kobj); - -sgv_kobj_add_error: - kobject_put(scst_sgv_kobj); + scst_del_put_sgv_kobj(); sgv_kobj_error: kobject_del(scst_devices_kobj); @@ -5412,8 +5305,7 @@ void scst_sysfs_cleanup(void) PRINT_INFO("%s", "Exiting SCST sysfs hierarchy..."); - kobject_del(scst_sgv_kobj); - kobject_put(scst_sgv_kobj); + scst_del_put_sgv_kobj(); kobject_del(scst_devices_kobj); kobject_put(scst_devices_kobj);