Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Module sysfs support
  4 *
  5 * Copyright (C) 2008 Rusty Russell
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/kernel.h>
 10#include <linux/fs.h>
 11#include <linux/sysfs.h>
 12#include <linux/slab.h>
 13#include <linux/kallsyms.h>
 14#include <linux/mutex.h>
 15#include "internal.h"
 16
 17/*
 18 * /sys/module/foo/sections stuff
 19 * J. Corbet <corbet@lwn.net>
 20 */
 21#ifdef CONFIG_KALLSYMS
 22struct module_sect_attr {
 23	struct bin_attribute battr;
 24	unsigned long address;
 25};
 26
 27struct module_sect_attrs {
 28	struct attribute_group grp;
 29	unsigned int nsections;
 30	struct module_sect_attr attrs[];
 31};
 32
 33#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
 34static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
 35				struct bin_attribute *battr,
 36				char *buf, loff_t pos, size_t count)
 37{
 38	struct module_sect_attr *sattr =
 39		container_of(battr, struct module_sect_attr, battr);
 40	char bounce[MODULE_SECT_READ_SIZE + 1];
 41	size_t wrote;
 42
 43	if (pos != 0)
 44		return -EINVAL;
 45
 46	/*
 47	 * Since we're a binary read handler, we must account for the
 48	 * trailing NUL byte that sprintf will write: if "buf" is
 49	 * too small to hold the NUL, or the NUL is exactly the last
 50	 * byte, the read will look like it got truncated by one byte.
 51	 * Since there is no way to ask sprintf nicely to not write
 52	 * the NUL, we have to use a bounce buffer.
 53	 */
 54	wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n",
 55			  kallsyms_show_value(file->f_cred)
 56				? (void *)sattr->address : NULL);
 57	count = min(count, wrote);
 58	memcpy(buf, bounce, count);
 59
 60	return count;
 61}
 62
 63static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 64{
 65	unsigned int section;
 66
 67	for (section = 0; section < sect_attrs->nsections; section++)
 68		kfree(sect_attrs->attrs[section].battr.attr.name);
 69	kfree(sect_attrs);
 70}
 71
 72static void add_sect_attrs(struct module *mod, const struct load_info *info)
 73{
 74	unsigned int nloaded = 0, i, size[2];
 75	struct module_sect_attrs *sect_attrs;
 76	struct module_sect_attr *sattr;
 77	struct bin_attribute **gattr;
 
 78
 79	/* Count loaded sections and allocate structures */
 80	for (i = 0; i < info->hdr->e_shnum; i++)
 81		if (!sect_empty(&info->sechdrs[i]))
 82			nloaded++;
 83	size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
 84			sizeof(sect_attrs->grp.bin_attrs[0]));
 85	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
 86	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
 87	if (!sect_attrs)
 88		return;
 89
 90	/* Setup section attributes. */
 91	sect_attrs->grp.name = "sections";
 92	sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
 93
 94	sect_attrs->nsections = 0;
 95	sattr = &sect_attrs->attrs[0];
 96	gattr = &sect_attrs->grp.bin_attrs[0];
 97	for (i = 0; i < info->hdr->e_shnum; i++) {
 98		Elf_Shdr *sec = &info->sechdrs[i];
 99
100		if (sect_empty(sec))
101			continue;
102		sysfs_bin_attr_init(&sattr->battr);
103		sattr->address = sec->sh_addr;
104		sattr->battr.attr.name =
105			kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
106		if (!sattr->battr.attr.name)
 
107			goto out;
 
108		sect_attrs->nsections++;
109		sattr->battr.read = module_sect_read;
110		sattr->battr.size = MODULE_SECT_READ_SIZE;
111		sattr->battr.attr.mode = 0400;
112		*(gattr++) = &(sattr++)->battr;
113	}
114	*gattr = NULL;
115
116	if (sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp))
 
117		goto out;
118
119	mod->sect_attrs = sect_attrs;
120	return;
121out:
122	free_sect_attrs(sect_attrs);
 
123}
124
125static void remove_sect_attrs(struct module *mod)
126{
127	if (mod->sect_attrs) {
128		sysfs_remove_group(&mod->mkobj.kobj,
129				   &mod->sect_attrs->grp);
130		/*
131		 * We are positive that no one is using any sect attrs
132		 * at this point.  Deallocate immediately.
133		 */
134		free_sect_attrs(mod->sect_attrs);
135		mod->sect_attrs = NULL;
136	}
137}
138
139/*
140 * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections.
141 */
142
143struct module_notes_attrs {
144	struct kobject *dir;
145	unsigned int notes;
146	struct bin_attribute attrs[];
147};
148
149static ssize_t module_notes_read(struct file *filp, struct kobject *kobj,
150				 struct bin_attribute *bin_attr,
151				 char *buf, loff_t pos, size_t count)
152{
153	/*
154	 * The caller checked the pos and count against our size.
155	 */
156	memcpy(buf, bin_attr->private + pos, count);
157	return count;
158}
159
160static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
161			     unsigned int i)
162{
163	if (notes_attrs->dir) {
164		while (i-- > 0)
165			sysfs_remove_bin_file(notes_attrs->dir,
166					      &notes_attrs->attrs[i]);
167		kobject_put(notes_attrs->dir);
168	}
169	kfree(notes_attrs);
170}
171
172static void add_notes_attrs(struct module *mod, const struct load_info *info)
173{
174	unsigned int notes, loaded, i;
175	struct module_notes_attrs *notes_attrs;
176	struct bin_attribute *nattr;
177
178	/* failed to create section attributes, so can't create notes */
179	if (!mod->sect_attrs)
180		return;
181
182	/* Count notes sections and allocate structures.  */
183	notes = 0;
184	for (i = 0; i < info->hdr->e_shnum; i++)
185		if (!sect_empty(&info->sechdrs[i]) &&
186		    info->sechdrs[i].sh_type == SHT_NOTE)
187			++notes;
188
189	if (notes == 0)
190		return;
191
192	notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes),
193			      GFP_KERNEL);
194	if (!notes_attrs)
195		return;
196
197	notes_attrs->notes = notes;
198	nattr = &notes_attrs->attrs[0];
199	for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
200		if (sect_empty(&info->sechdrs[i]))
201			continue;
202		if (info->sechdrs[i].sh_type == SHT_NOTE) {
203			sysfs_bin_attr_init(nattr);
204			nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;
205			nattr->attr.mode = 0444;
206			nattr->size = info->sechdrs[i].sh_size;
207			nattr->private = (void *)info->sechdrs[i].sh_addr;
208			nattr->read = module_notes_read;
209			++nattr;
210		}
211		++loaded;
212	}
213
214	notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
215	if (!notes_attrs->dir)
 
216		goto out;
 
217
218	for (i = 0; i < notes; ++i)
219		if (sysfs_create_bin_file(notes_attrs->dir,
220					  &notes_attrs->attrs[i]))
221			goto out;
 
222
223	mod->notes_attrs = notes_attrs;
224	return;
225
226out:
227	free_notes_attrs(notes_attrs, i);
 
228}
229
230static void remove_notes_attrs(struct module *mod)
231{
232	if (mod->notes_attrs)
233		free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
234}
235
236#else /* !CONFIG_KALLSYMS */
237static inline void add_sect_attrs(struct module *mod, const struct load_info *info) { }
 
 
 
238static inline void remove_sect_attrs(struct module *mod) { }
239static inline void add_notes_attrs(struct module *mod, const struct load_info *info) { }
 
 
 
240static inline void remove_notes_attrs(struct module *mod) { }
241#endif /* CONFIG_KALLSYMS */
242
243static void del_usage_links(struct module *mod)
244{
245#ifdef CONFIG_MODULE_UNLOAD
246	struct module_use *use;
247
248	mutex_lock(&module_mutex);
249	list_for_each_entry(use, &mod->target_list, target_list)
250		sysfs_remove_link(use->target->holders_dir, mod->name);
251	mutex_unlock(&module_mutex);
252#endif
253}
254
255static int add_usage_links(struct module *mod)
256{
257	int ret = 0;
258#ifdef CONFIG_MODULE_UNLOAD
259	struct module_use *use;
260
261	mutex_lock(&module_mutex);
262	list_for_each_entry(use, &mod->target_list, target_list) {
263		ret = sysfs_create_link(use->target->holders_dir,
264					&mod->mkobj.kobj, mod->name);
265		if (ret)
266			break;
267	}
268	mutex_unlock(&module_mutex);
269	if (ret)
270		del_usage_links(mod);
271#endif
272	return ret;
273}
274
275static void module_remove_modinfo_attrs(struct module *mod, int end)
276{
277	struct module_attribute *attr;
278	int i;
279
280	for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
281		if (end >= 0 && i > end)
282			break;
283		/* pick a field to test for end of list */
284		if (!attr->attr.name)
285			break;
286		sysfs_remove_file(&mod->mkobj.kobj, &attr->attr);
287		if (attr->free)
288			attr->free(mod);
289	}
290	kfree(mod->modinfo_attrs);
291}
292
293static int module_add_modinfo_attrs(struct module *mod)
294{
295	struct module_attribute *attr;
296	struct module_attribute *temp_attr;
297	int error = 0;
298	int i;
299
300	mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *
301					(modinfo_attrs_count + 1)),
302					GFP_KERNEL);
303	if (!mod->modinfo_attrs)
304		return -ENOMEM;
305
306	temp_attr = mod->modinfo_attrs;
307	for (i = 0; (attr = modinfo_attrs[i]); i++) {
308		if (!attr->test || attr->test(mod)) {
309			memcpy(temp_attr, attr, sizeof(*temp_attr));
310			sysfs_attr_init(&temp_attr->attr);
311			error = sysfs_create_file(&mod->mkobj.kobj,
312						  &temp_attr->attr);
313			if (error)
314				goto error_out;
315			++temp_attr;
316		}
317	}
318
319	return 0;
320
321error_out:
322	if (i > 0)
323		module_remove_modinfo_attrs(mod, --i);
324	else
325		kfree(mod->modinfo_attrs);
326	return error;
327}
328
329static void mod_kobject_put(struct module *mod)
330{
331	DECLARE_COMPLETION_ONSTACK(c);
332
333	mod->mkobj.kobj_completion = &c;
334	kobject_put(&mod->mkobj.kobj);
335	wait_for_completion(&c);
336}
337
338static int mod_sysfs_init(struct module *mod)
339{
340	int err;
341	struct kobject *kobj;
342
343	if (!module_kset) {
344		pr_err("%s: module sysfs not initialized\n", mod->name);
345		err = -EINVAL;
346		goto out;
347	}
348
349	kobj = kset_find_obj(module_kset, mod->name);
350	if (kobj) {
351		pr_err("%s: module is already loaded\n", mod->name);
352		kobject_put(kobj);
353		err = -EINVAL;
354		goto out;
355	}
356
357	mod->mkobj.mod = mod;
358
359	memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));
360	mod->mkobj.kobj.kset = module_kset;
361	err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
362				   "%s", mod->name);
363	if (err)
364		mod_kobject_put(mod);
365
366out:
367	return err;
368}
369
370int mod_sysfs_setup(struct module *mod,
371		    const struct load_info *info,
372			   struct kernel_param *kparam,
373			   unsigned int num_params)
374{
375	int err;
376
377	err = mod_sysfs_init(mod);
378	if (err)
379		goto out;
380
381	mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
382	if (!mod->holders_dir) {
383		err = -ENOMEM;
384		goto out_unreg;
385	}
386
387	err = module_param_sysfs_setup(mod, kparam, num_params);
388	if (err)
389		goto out_unreg_holders;
390
391	err = module_add_modinfo_attrs(mod);
392	if (err)
393		goto out_unreg_param;
394
395	err = add_usage_links(mod);
396	if (err)
397		goto out_unreg_modinfo_attrs;
398
399	add_sect_attrs(mod, info);
400	add_notes_attrs(mod, info);
 
 
 
 
 
401
402	return 0;
403
 
 
 
 
404out_unreg_modinfo_attrs:
405	module_remove_modinfo_attrs(mod, -1);
406out_unreg_param:
407	module_param_sysfs_remove(mod);
408out_unreg_holders:
409	kobject_put(mod->holders_dir);
410out_unreg:
411	mod_kobject_put(mod);
412out:
413	return err;
414}
415
416static void mod_sysfs_fini(struct module *mod)
417{
418	remove_notes_attrs(mod);
419	remove_sect_attrs(mod);
420	mod_kobject_put(mod);
421}
422
423void mod_sysfs_teardown(struct module *mod)
424{
425	del_usage_links(mod);
426	module_remove_modinfo_attrs(mod, -1);
427	module_param_sysfs_remove(mod);
428	kobject_put(mod->mkobj.drivers_dir);
429	kobject_put(mod->holders_dir);
430	mod_sysfs_fini(mod);
431}
432
433void init_param_lock(struct module *mod)
434{
435	mutex_init(&mod->param_lock);
436}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Module sysfs support
  4 *
  5 * Copyright (C) 2008 Rusty Russell
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/kernel.h>
 10#include <linux/fs.h>
 11#include <linux/sysfs.h>
 12#include <linux/slab.h>
 13#include <linux/kallsyms.h>
 14#include <linux/mutex.h>
 15#include "internal.h"
 16
 17/*
 18 * /sys/module/foo/sections stuff
 19 * J. Corbet <corbet@lwn.net>
 20 */
 21#ifdef CONFIG_KALLSYMS
 22struct module_sect_attr {
 23	struct bin_attribute battr;
 24	unsigned long address;
 25};
 26
 27struct module_sect_attrs {
 28	struct attribute_group grp;
 29	unsigned int nsections;
 30	struct module_sect_attr attrs[];
 31};
 32
 33#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
 34static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
 35				struct bin_attribute *battr,
 36				char *buf, loff_t pos, size_t count)
 37{
 38	struct module_sect_attr *sattr =
 39		container_of(battr, struct module_sect_attr, battr);
 40	char bounce[MODULE_SECT_READ_SIZE + 1];
 41	size_t wrote;
 42
 43	if (pos != 0)
 44		return -EINVAL;
 45
 46	/*
 47	 * Since we're a binary read handler, we must account for the
 48	 * trailing NUL byte that sprintf will write: if "buf" is
 49	 * too small to hold the NUL, or the NUL is exactly the last
 50	 * byte, the read will look like it got truncated by one byte.
 51	 * Since there is no way to ask sprintf nicely to not write
 52	 * the NUL, we have to use a bounce buffer.
 53	 */
 54	wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n",
 55			  kallsyms_show_value(file->f_cred)
 56				? (void *)sattr->address : NULL);
 57	count = min(count, wrote);
 58	memcpy(buf, bounce, count);
 59
 60	return count;
 61}
 62
 63static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 64{
 65	unsigned int section;
 66
 67	for (section = 0; section < sect_attrs->nsections; section++)
 68		kfree(sect_attrs->attrs[section].battr.attr.name);
 69	kfree(sect_attrs);
 70}
 71
 72static int add_sect_attrs(struct module *mod, const struct load_info *info)
 73{
 74	unsigned int nloaded = 0, i, size[2];
 75	struct module_sect_attrs *sect_attrs;
 76	struct module_sect_attr *sattr;
 77	struct bin_attribute **gattr;
 78	int ret;
 79
 80	/* Count loaded sections and allocate structures */
 81	for (i = 0; i < info->hdr->e_shnum; i++)
 82		if (!sect_empty(&info->sechdrs[i]))
 83			nloaded++;
 84	size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
 85			sizeof(sect_attrs->grp.bin_attrs[0]));
 86	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
 87	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
 88	if (!sect_attrs)
 89		return -ENOMEM;
 90
 91	/* Setup section attributes. */
 92	sect_attrs->grp.name = "sections";
 93	sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
 94
 95	sect_attrs->nsections = 0;
 96	sattr = &sect_attrs->attrs[0];
 97	gattr = &sect_attrs->grp.bin_attrs[0];
 98	for (i = 0; i < info->hdr->e_shnum; i++) {
 99		Elf_Shdr *sec = &info->sechdrs[i];
100
101		if (sect_empty(sec))
102			continue;
103		sysfs_bin_attr_init(&sattr->battr);
104		sattr->address = sec->sh_addr;
105		sattr->battr.attr.name =
106			kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
107		if (!sattr->battr.attr.name) {
108			ret = -ENOMEM;
109			goto out;
110		}
111		sect_attrs->nsections++;
112		sattr->battr.read = module_sect_read;
113		sattr->battr.size = MODULE_SECT_READ_SIZE;
114		sattr->battr.attr.mode = 0400;
115		*(gattr++) = &(sattr++)->battr;
116	}
117	*gattr = NULL;
118
119	ret = sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp);
120	if (ret)
121		goto out;
122
123	mod->sect_attrs = sect_attrs;
124	return 0;
125out:
126	free_sect_attrs(sect_attrs);
127	return ret;
128}
129
130static void remove_sect_attrs(struct module *mod)
131{
132	if (mod->sect_attrs) {
133		sysfs_remove_group(&mod->mkobj.kobj,
134				   &mod->sect_attrs->grp);
135		/*
136		 * We are positive that no one is using any sect attrs
137		 * at this point.  Deallocate immediately.
138		 */
139		free_sect_attrs(mod->sect_attrs);
140		mod->sect_attrs = NULL;
141	}
142}
143
144/*
145 * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections.
146 */
147
148struct module_notes_attrs {
149	struct kobject *dir;
150	unsigned int notes;
151	struct bin_attribute attrs[] __counted_by(notes);
152};
153
 
 
 
 
 
 
 
 
 
 
 
154static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
155			     unsigned int i)
156{
157	if (notes_attrs->dir) {
158		while (i-- > 0)
159			sysfs_remove_bin_file(notes_attrs->dir,
160					      &notes_attrs->attrs[i]);
161		kobject_put(notes_attrs->dir);
162	}
163	kfree(notes_attrs);
164}
165
166static int add_notes_attrs(struct module *mod, const struct load_info *info)
167{
168	unsigned int notes, loaded, i;
169	struct module_notes_attrs *notes_attrs;
170	struct bin_attribute *nattr;
171	int ret;
 
 
 
172
173	/* Count notes sections and allocate structures.  */
174	notes = 0;
175	for (i = 0; i < info->hdr->e_shnum; i++)
176		if (!sect_empty(&info->sechdrs[i]) &&
177		    info->sechdrs[i].sh_type == SHT_NOTE)
178			++notes;
179
180	if (notes == 0)
181		return 0;
182
183	notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes),
184			      GFP_KERNEL);
185	if (!notes_attrs)
186		return -ENOMEM;
187
188	notes_attrs->notes = notes;
189	nattr = &notes_attrs->attrs[0];
190	for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
191		if (sect_empty(&info->sechdrs[i]))
192			continue;
193		if (info->sechdrs[i].sh_type == SHT_NOTE) {
194			sysfs_bin_attr_init(nattr);
195			nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;
196			nattr->attr.mode = 0444;
197			nattr->size = info->sechdrs[i].sh_size;
198			nattr->private = (void *)info->sechdrs[i].sh_addr;
199			nattr->read = sysfs_bin_attr_simple_read;
200			++nattr;
201		}
202		++loaded;
203	}
204
205	notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
206	if (!notes_attrs->dir) {
207		ret = -ENOMEM;
208		goto out;
209	}
210
211	for (i = 0; i < notes; ++i) {
212		ret = sysfs_create_bin_file(notes_attrs->dir, &notes_attrs->attrs[i]);
213		if (ret)
214			goto out;
215	}
216
217	mod->notes_attrs = notes_attrs;
218	return 0;
219
220out:
221	free_notes_attrs(notes_attrs, i);
222	return ret;
223}
224
225static void remove_notes_attrs(struct module *mod)
226{
227	if (mod->notes_attrs)
228		free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
229}
230
231#else /* !CONFIG_KALLSYMS */
232static inline int add_sect_attrs(struct module *mod, const struct load_info *info)
233{
234	return 0;
235}
236static inline void remove_sect_attrs(struct module *mod) { }
237static inline int add_notes_attrs(struct module *mod, const struct load_info *info)
238{
239	return 0;
240}
241static inline void remove_notes_attrs(struct module *mod) { }
242#endif /* CONFIG_KALLSYMS */
243
244static void del_usage_links(struct module *mod)
245{
246#ifdef CONFIG_MODULE_UNLOAD
247	struct module_use *use;
248
249	mutex_lock(&module_mutex);
250	list_for_each_entry(use, &mod->target_list, target_list)
251		sysfs_remove_link(use->target->holders_dir, mod->name);
252	mutex_unlock(&module_mutex);
253#endif
254}
255
256static int add_usage_links(struct module *mod)
257{
258	int ret = 0;
259#ifdef CONFIG_MODULE_UNLOAD
260	struct module_use *use;
261
262	mutex_lock(&module_mutex);
263	list_for_each_entry(use, &mod->target_list, target_list) {
264		ret = sysfs_create_link(use->target->holders_dir,
265					&mod->mkobj.kobj, mod->name);
266		if (ret)
267			break;
268	}
269	mutex_unlock(&module_mutex);
270	if (ret)
271		del_usage_links(mod);
272#endif
273	return ret;
274}
275
276static void module_remove_modinfo_attrs(struct module *mod, int end)
277{
278	struct module_attribute *attr;
279	int i;
280
281	for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
282		if (end >= 0 && i > end)
283			break;
284		/* pick a field to test for end of list */
285		if (!attr->attr.name)
286			break;
287		sysfs_remove_file(&mod->mkobj.kobj, &attr->attr);
288		if (attr->free)
289			attr->free(mod);
290	}
291	kfree(mod->modinfo_attrs);
292}
293
294static int module_add_modinfo_attrs(struct module *mod)
295{
296	struct module_attribute *attr;
297	struct module_attribute *temp_attr;
298	int error = 0;
299	int i;
300
301	mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *
302					(modinfo_attrs_count + 1)),
303					GFP_KERNEL);
304	if (!mod->modinfo_attrs)
305		return -ENOMEM;
306
307	temp_attr = mod->modinfo_attrs;
308	for (i = 0; (attr = modinfo_attrs[i]); i++) {
309		if (!attr->test || attr->test(mod)) {
310			memcpy(temp_attr, attr, sizeof(*temp_attr));
311			sysfs_attr_init(&temp_attr->attr);
312			error = sysfs_create_file(&mod->mkobj.kobj,
313						  &temp_attr->attr);
314			if (error)
315				goto error_out;
316			++temp_attr;
317		}
318	}
319
320	return 0;
321
322error_out:
323	if (i > 0)
324		module_remove_modinfo_attrs(mod, --i);
325	else
326		kfree(mod->modinfo_attrs);
327	return error;
328}
329
330static void mod_kobject_put(struct module *mod)
331{
332	DECLARE_COMPLETION_ONSTACK(c);
333
334	mod->mkobj.kobj_completion = &c;
335	kobject_put(&mod->mkobj.kobj);
336	wait_for_completion(&c);
337}
338
339static int mod_sysfs_init(struct module *mod)
340{
341	int err;
342	struct kobject *kobj;
343
344	if (!module_kset) {
345		pr_err("%s: module sysfs not initialized\n", mod->name);
346		err = -EINVAL;
347		goto out;
348	}
349
350	kobj = kset_find_obj(module_kset, mod->name);
351	if (kobj) {
352		pr_err("%s: module is already loaded\n", mod->name);
353		kobject_put(kobj);
354		err = -EINVAL;
355		goto out;
356	}
357
358	mod->mkobj.mod = mod;
359
360	memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));
361	mod->mkobj.kobj.kset = module_kset;
362	err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,
363				   "%s", mod->name);
364	if (err)
365		mod_kobject_put(mod);
366
367out:
368	return err;
369}
370
371int mod_sysfs_setup(struct module *mod,
372		    const struct load_info *info,
373			   struct kernel_param *kparam,
374			   unsigned int num_params)
375{
376	int err;
377
378	err = mod_sysfs_init(mod);
379	if (err)
380		goto out;
381
382	mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
383	if (!mod->holders_dir) {
384		err = -ENOMEM;
385		goto out_unreg;
386	}
387
388	err = module_param_sysfs_setup(mod, kparam, num_params);
389	if (err)
390		goto out_unreg_holders;
391
392	err = module_add_modinfo_attrs(mod);
393	if (err)
394		goto out_unreg_param;
395
396	err = add_usage_links(mod);
397	if (err)
398		goto out_unreg_modinfo_attrs;
399
400	err = add_sect_attrs(mod, info);
401	if (err)
402		goto out_del_usage_links;
403
404	err = add_notes_attrs(mod, info);
405	if (err)
406		goto out_unreg_sect_attrs;
407
408	return 0;
409
410out_unreg_sect_attrs:
411	remove_sect_attrs(mod);
412out_del_usage_links:
413	del_usage_links(mod);
414out_unreg_modinfo_attrs:
415	module_remove_modinfo_attrs(mod, -1);
416out_unreg_param:
417	module_param_sysfs_remove(mod);
418out_unreg_holders:
419	kobject_put(mod->holders_dir);
420out_unreg:
421	mod_kobject_put(mod);
422out:
423	return err;
424}
425
426static void mod_sysfs_fini(struct module *mod)
427{
428	remove_notes_attrs(mod);
429	remove_sect_attrs(mod);
430	mod_kobject_put(mod);
431}
432
433void mod_sysfs_teardown(struct module *mod)
434{
435	del_usage_links(mod);
436	module_remove_modinfo_attrs(mod, -1);
437	module_param_sysfs_remove(mod);
438	kobject_put(mod->mkobj.drivers_dir);
439	kobject_put(mod->holders_dir);
440	mod_sysfs_fini(mod);
441}
442
443void init_param_lock(struct module *mod)
444{
445	mutex_init(&mod->param_lock);
446}