Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 3145
b: refs/heads/master
c: c988d2b
h: refs/heads/master
i:
  3143: 89c2381
v: v3
  • Loading branch information
Matt Domsch authored and Linus Torvalds committed Jun 24, 2005
1 parent 7697f07 commit ee8225a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f5bec39639d386e1893dc440dd536761136ab36b
refs/heads/master: c988d2b2845495373f666a381d354a7f80981d62
5 changes: 5 additions & 0 deletions trunk/include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ struct module_attribute {
ssize_t (*show)(struct module_attribute *, struct module *, char *);
ssize_t (*store)(struct module_attribute *, struct module *,
const char *, size_t count);
void (*setup)(struct module *, const char *);
int (*test)(struct module *);
void (*free)(struct module *);
};

struct module_kobject
Expand Down Expand Up @@ -239,6 +242,8 @@ struct module
/* Sysfs stuff. */
struct module_kobject mkobj;
struct module_param_attrs *param_attrs;
const char *version;
const char *srcversion;

/* Exported symbols */
const struct kernel_symbol *syms;
Expand Down
95 changes: 95 additions & 0 deletions trunk/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/notifier.h>
#include <linux/stop_machine.h>
#include <linux/device.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
Expand Down Expand Up @@ -370,6 +371,43 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,
#endif /* CONFIG_SMP */

#ifdef CONFIG_MODULE_UNLOAD
#define MODINFO_ATTR(field) \
static void setup_modinfo_##field(struct module *mod, const char *s) \
{ \
mod->field = kstrdup(s, GFP_KERNEL); \
} \
static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
struct module *mod, char *buffer) \
{ \
return sprintf(buffer, "%s\n", mod->field); \
} \
static int modinfo_##field##_exists(struct module *mod) \
{ \
return mod->field != NULL; \
} \
static void free_modinfo_##field(struct module *mod) \
{ \
kfree(mod->field); \
mod->field = NULL; \
} \
static struct module_attribute modinfo_##field = { \
.attr = { .name = __stringify(field), .mode = 0444, \
.owner = THIS_MODULE }, \
.show = show_modinfo_##field, \
.setup = setup_modinfo_##field, \
.test = modinfo_##field##_exists, \
.free = free_modinfo_##field, \
};

MODINFO_ATTR(version);
MODINFO_ATTR(srcversion);

static struct module_attribute *modinfo_attrs[] = {
&modinfo_version,
&modinfo_srcversion,
NULL,
};

/* Init the unload section of the module. */
static void module_unload_init(struct module *mod)
{
Expand Down Expand Up @@ -1031,6 +1069,32 @@ static void module_remove_refcnt_attr(struct module *mod)
}
#endif

#ifdef CONFIG_MODULE_UNLOAD
static int module_add_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
int error = 0;
int i;

for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
if (!attr->test ||
(attr->test && attr->test(mod)))
error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
}
return error;
}

static void module_remove_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
int i;

for (i = 0; (attr = modinfo_attrs[i]); i++) {
sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
attr->free(mod);
}
}
#endif

static int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
Expand All @@ -1056,6 +1120,12 @@ static int mod_sysfs_setup(struct module *mod,
if (err)
goto out_unreg;

#ifdef CONFIG_MODULE_UNLOAD
err = module_add_modinfo_attrs(mod);
if (err)
goto out_unreg;
#endif

return 0;

out_unreg:
Expand All @@ -1066,6 +1136,9 @@ static int mod_sysfs_setup(struct module *mod,

static void mod_kobject_remove(struct module *mod)
{
#ifdef CONFIG_MODULE_UNLOAD
module_remove_modinfo_attrs(mod);
#endif
module_remove_refcnt_attr(mod);
module_param_sysfs_remove(mod);

Expand Down Expand Up @@ -1311,6 +1384,23 @@ static char *get_modinfo(Elf_Shdr *sechdrs,
return NULL;
}

#ifdef CONFIG_MODULE_UNLOAD
static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
unsigned int infoindex)
{
struct module_attribute *attr;
int i;

for (i = 0; (attr = modinfo_attrs[i]); i++) {
if (attr->setup)
attr->setup(mod,
get_modinfo(sechdrs,
infoindex,
attr->attr.name));
}
}
#endif

#ifdef CONFIG_KALLSYMS
int is_exported(const char *name, const struct module *mod)
{
Expand Down Expand Up @@ -1615,6 +1705,11 @@ static struct module *load_module(void __user *umod,
/* Set up license info based on the info section */
set_license(mod, get_modinfo(sechdrs, infoindex, "license"));

#ifdef CONFIG_MODULE_UNLOAD
/* Set up MODINFO_ATTR fields */
setup_modinfo(mod, sechdrs, infoindex);
#endif

/* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
mod);
Expand Down

0 comments on commit ee8225a

Please sign in to comment.