/** * kobject_namespace() - Return @kobj's namespace tag. * @kobj: kobject in question * * Returns namespace tag of @kobj if its parent has namespace ops enabled * and thus @kobj should have a namespace tag associated with it. Returns * %NULL otherwise.
*/ constvoid *kobject_namespace(conststruct kobject *kobj)
{ conststruct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) return NULL;
return kobj->ktype->namespace(kobj);
}
/** * kobject_get_ownership() - Get sysfs ownership data for @kobj. * @kobj: kobject in question * @uid: kernel user ID for sysfs objects * @gid: kernel group ID for sysfs objects * * Returns initial uid/gid pair that should be used when creating sysfs * representation of given kobject. Normally used to adjust ownership of * objects in a container.
*/ void kobject_get_ownership(conststruct kobject *kobj, kuid_t *uid, kgid_t *gid)
{
*uid = GLOBAL_ROOT_UID;
*gid = GLOBAL_ROOT_GID;
if (kobj->ktype->get_ownership)
kobj->ktype->get_ownership(kobj, uid, gid);
}
error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj)); if (error) return error;
if (ktype) {
error = sysfs_create_groups(kobj, ktype->default_groups); if (error) {
sysfs_remove_dir(kobj); return error;
}
}
/* * @kobj->sd may be deleted by an ancestor going away. Hold an * extra reference so that it stays until @kobj is gone.
*/
sysfs_get(kobj->sd);
/* * If @kobj has ns_ops, its children need to be filtered based on * their namespace tags. Enable namespace support on @kobj->sd.
*/
ops = kobj_child_ns_ops(kobj); if (ops) {
BUG_ON(!kobj_ns_type_is_valid(ops->type));
BUG_ON(!kobj_ns_type_registered(ops->type));
/* walk up the ancestors until we hit the one pointing to the * root. * Add 1 to strlen for leading '/' of each level.
*/ do { if (kobject_name(parent) == NULL) return 0;
length += strlen(kobject_name(parent)) + 1;
parent = parent->parent;
} while (parent); return length;
}
--length; for (parent = kobj; parent; parent = parent->parent) { int cur = strlen(kobject_name(parent)); /* back up enough to print this name with '/' */
length -= cur; if (length <= 0) return -EINVAL;
memcpy(path + length, kobject_name(parent), cur);
*(path + --length) = '/';
}
/** * kobject_get_path() - Allocate memory and fill in the path for @kobj. * @kobj: kobject in question, with which to build the path * @gfp_mask: the allocation type used to allocate the path * * Return: The newly allocated memory, caller must free with kfree().
*/ char *kobject_get_path(conststruct kobject *kobj, gfp_t gfp_mask)
{ char *path; int len;
retry:
len = get_kobj_path_length(kobj); if (len == 0) return NULL;
path = kzalloc(len, gfp_mask); if (!path) return NULL; if (fill_kobj_path(kobj, path, len)) {
kfree(path); goto retry;
}
if (!kobj->name || !kobj->name[0]) {
WARN(1, "kobject: (%p): attempted to be registered with empty name!\n",
kobj); return -EINVAL;
}
parent = kobject_get(kobj->parent);
/* join kset if set, use it as parent if we do not already have one */ if (kobj->kset) { if (!parent)
parent = kobject_get(&kobj->kset->kobj);
kobj_kset_join(kobj);
kobj->parent = parent;
}
/* be noisy on error issues */ if (error == -EEXIST)
pr_err("%s failed for %s with -EEXIST, don't try to register things with the same name in the same directory.\n",
__func__, kobject_name(kobj)); else
pr_err("%s failed for %s (error: %d parent: %s)\n",
__func__, kobject_name(kobj), error,
parent ? kobject_name(parent) : "'none'");
} else
kobj->state_in_sysfs = 1;
return error;
}
/** * kobject_set_name_vargs() - Set the name of a kobject. * @kobj: struct kobject to set the name of * @fmt: format string used to build the name * @vargs: vargs to format the string.
*/ int kobject_set_name_vargs(struct kobject *kobj, constchar *fmt,
va_list vargs)
{ constchar *s;
if (kobj->name && !fmt) return 0;
s = kvasprintf_const(GFP_KERNEL, fmt, vargs); if (!s) return -ENOMEM;
/* * ewww... some of these buggers have '/' in the name ... If * that's the case, we need to make sure we have an actual * allocated copy to modify, since kvasprintf_const may have * returned something from .rodata.
*/ if (strchr(s, '/')) { char *t;
t = kstrdup(s, GFP_KERNEL);
kfree_const(s); if (!t) return -ENOMEM;
s = strreplace(t, '/', '!');
}
kfree_const(kobj->name);
kobj->name = s;
return 0;
}
/** * kobject_set_name() - Set the name of a kobject. * @kobj: struct kobject to set the name of * @fmt: format string used to build the name * * This sets the name of the kobject. If you have already added the * kobject to the system, you must call kobject_rename() in order to * change the name of the kobject.
*/ int kobject_set_name(struct kobject *kobj, constchar *fmt, ...)
{
va_list vargs; int retval;
/** * kobject_init() - Initialize a kobject structure. * @kobj: pointer to the kobject to initialize * @ktype: pointer to the ktype for this kobject. * * This function will properly initialize a kobject such that it can then * be passed to the kobject_add() call. * * After this function is called, the kobject MUST be cleaned up by a call * to kobject_put(), not by a call to kfree directly to ensure that all of * the memory is cleaned up properly.
*/ void kobject_init(struct kobject *kobj, conststruct kobj_type *ktype)
{ char *err_str;
if (!kobj) {
err_str = "invalid kobject pointer!"; goto error;
} if (!ktype) {
err_str = "must have a ktype to be initialized properly!\n"; goto error;
} if (kobj->state_initialized) { /* do not error out as sometimes we can recover */
pr_err("kobject (%p): tried to init an initialized object, something is seriously wrong.\n",
kobj);
dump_stack_lvl(KERN_ERR);
}
static __printf(3, 0) int kobject_add_varg(struct kobject *kobj, struct kobject *parent, constchar *fmt, va_list vargs)
{ int retval;
retval = kobject_set_name_vargs(kobj, fmt, vargs); if (retval) {
pr_err("can not set name properly!\n"); return retval;
}
kobj->parent = parent; return kobject_add_internal(kobj);
}
/** * kobject_add() - The main kobject add function. * @kobj: the kobject to add * @parent: pointer to the parent of the kobject. * @fmt: format to name the kobject with. * * The kobject name is set and added to the kobject hierarchy in this * function. * * If @parent is set, then the parent of the @kobj will be set to it. * If @parent is NULL, then the parent of the @kobj will be set to the * kobject associated with the kset assigned to this kobject. If no kset * is assigned to the kobject, then the kobject will be located in the * root of the sysfs tree. * * Note, no "add" uevent will be created with this call, the caller should set * up all of the necessary sysfs files for the object and then call * kobject_uevent() with the UEVENT_ADD parameter to ensure that * userspace is properly notified of this kobject's creation. * * Return: If this function returns an error, kobject_put() must be * called to properly clean up the memory associated with the * object. Under no instance should the kobject that is passed * to this function be directly freed with a call to kfree(), * that can leak memory. * * If this function returns success, kobject_put() must also be called * in order to properly clean up the memory associated with the object. * * In short, once this function is called, kobject_put() MUST be called * when the use of the object is finished in order to properly free * everything.
*/ int kobject_add(struct kobject *kobj, struct kobject *parent, constchar *fmt, ...)
{
va_list args; int retval;
if (!kobj) return -EINVAL;
if (!kobj->state_initialized) {
pr_err("kobject '%s' (%p): tried to add an uninitialized object, something is seriously wrong.\n",
kobject_name(kobj), kobj);
dump_stack_lvl(KERN_ERR); return -EINVAL;
}
va_start(args, fmt);
retval = kobject_add_varg(kobj, parent, fmt, args);
va_end(args);
return retval;
}
EXPORT_SYMBOL(kobject_add);
/** * kobject_init_and_add() - Initialize a kobject structure and add it to * the kobject hierarchy. * @kobj: pointer to the kobject to initialize * @ktype: pointer to the ktype for this kobject. * @parent: pointer to the parent of this kobject. * @fmt: the name of the kobject. * * This function combines the call to kobject_init() and kobject_add(). * * If this function returns an error, kobject_put() must be called to * properly clean up the memory associated with the object. This is the * same type of error handling after a call to kobject_add() and kobject * lifetime rules are the same here.
*/ int kobject_init_and_add(struct kobject *kobj, conststruct kobj_type *ktype, struct kobject *parent, constchar *fmt, ...)
{
va_list args; int retval;
/** * kobject_rename() - Change the name of an object. * @kobj: object in question. * @new_name: object's new name * * It is the responsibility of the caller to provide mutual * exclusion between two different calls of kobject_rename * on the same kobject and to ensure that new_name is valid and * won't conflict with other kobjects.
*/ int kobject_rename(struct kobject *kobj, constchar *new_name)
{ int error = 0; constchar *devpath = NULL; constchar *dup_name = NULL, *name; char *devpath_string = NULL; char *envp[2];
kobj = kobject_get(kobj); if (!kobj) return -EINVAL; if (!kobj->parent) {
kobject_put(kobj); return -EINVAL;
}
name = dup_name = kstrdup_const(new_name, GFP_KERNEL); if (!name) {
error = -ENOMEM; goto out;
}
error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj)); if (error) goto out;
/* Install the new kobject name */
dup_name = kobj->name;
kobj->name = name;
/* This function is mostly/only used for network interface. * Some hotplug package track interfaces by their name and
* therefore want to know when the name is changed by the user. */
kobject_uevent_env(kobj, KOBJ_MOVE, envp);
if (ktype)
sysfs_remove_groups(kobj, ktype->default_groups);
/* send "remove" if the caller did not do it but sent "add" */ if (kobj->state_add_uevent_sent && !kobj->state_remove_uevent_sent) {
pr_debug("'%s' (%p): auto cleanup 'remove' event\n",
kobject_name(kobj), kobj);
kobject_uevent(kobj, KOBJ_REMOVE);
}
/** * kobject_del() - Unlink kobject from hierarchy. * @kobj: object. * * This is the function that should be called to delete an object * successfully added via kobject_add().
*/ void kobject_del(struct kobject *kobj)
{ struct kobject *parent;
if (t && !t->release)
pr_debug("'%s' (%p): does not have a release() function, it is broken and must be fixed. See Documentation/core-api/kobject.rst.\n",
kobject_name(kobj), kobj);
/* remove from sysfs if the caller did not do it */ if (kobj->state_in_sysfs) {
pr_debug("'%s' (%p): auto cleanup kobject_del\n",
kobject_name(kobj), kobj);
__kobject_del(kobj);
} else { /* avoid dropping the parent reference unnecessarily */
parent = NULL;
}
/** * kobject_create() - Create a struct kobject dynamically. * * This function creates a kobject structure dynamically and sets it up * to be a "dynamic" kobject with a default release function set up. * * If the kobject was not able to be created, NULL will be returned. * The kobject structure returned from here must be cleaned up with a * call to kobject_put() and not kfree(), as kobject_init() has * already been called on this structure.
*/ staticstruct kobject *kobject_create(void)
{ struct kobject *kobj;
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); if (!kobj) return NULL;
/** * kobject_create_and_add() - Create a struct kobject dynamically and * register it with sysfs. * @name: the name for the kobject * @parent: the parent kobject of this kobject, if any. * * This function creates a kobject structure dynamically and registers it * with sysfs. When you are finished with this structure, call * kobject_put() and the structure will be dynamically freed when * it is no longer being used. * * If the kobject was not able to be created, NULL will be returned.
*/ struct kobject *kobject_create_and_add(constchar *name, struct kobject *parent)
{ struct kobject *kobj; int retval;
/** * kset_register() - Initialize and add a kset. * @k: kset. * * NOTE: On error, the kset.kobj.name allocated by() kobj_set_name() * is freed, it can not be used any more.
*/ int kset_register(struct kset *k)
{ int err;
if (!k) return -EINVAL;
if (!k->kobj.ktype) {
pr_err("must have a ktype to be initialized properly!\n"); return -EINVAL;
}
kset_init(k);
err = kobject_add_internal(&k->kobj); if (err) {
kfree_const(k->kobj.name); /* Set it to NULL to avoid accessing bad pointer in callers. */
k->kobj.name = NULL; return err;
}
kobject_uevent(&k->kobj, KOBJ_ADD); return 0;
}
EXPORT_SYMBOL(kset_register);
/** * kset_find_obj() - Search for object in kset. * @kset: kset we're looking in. * @name: object's name. * * Lock kset via @kset->subsys, and iterate over @kset->list, * looking for a matching kobject. If matching object is found * take a reference and return the object.
*/ struct kobject *kset_find_obj(struct kset *kset, constchar *name)
{ struct kobject *k; struct kobject *ret = NULL;
spin_lock(&kset->list_lock);
list_for_each_entry(k, &kset->list, entry) { if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
ret = kobject_get_unless_zero(k); break;
}
}
/** * kset_create() - Create a struct kset dynamically. * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @parent_kobj: the parent kobject of this kset, if any. * * This function creates a kset structure dynamically. This structure can * then be registered with the system and show up in sysfs with a call to * kset_register(). When you are finished with this structure, if * kset_register() has been called, call kset_unregister() and the * structure will be dynamically freed when it is no longer being used. * * If the kset was not able to be created, NULL will be returned.
*/ staticstruct kset *kset_create(constchar *name, conststruct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj)
{ struct kset *kset; int retval;
/* * The kobject of this kset will have a type of kset_ktype and belong to * no kset itself. That way we can properly free it when it is * finished being used.
*/
kset->kobj.ktype = &kset_ktype;
kset->kobj.kset = NULL;
return kset;
}
/** * kset_create_and_add() - Create a struct kset dynamically and add it to sysfs. * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @parent_kobj: the parent kobject of this kset, if any. * * This function creates a kset structure dynamically and registers it * with sysfs. When you are finished with this structure, call * kset_unregister() and the structure will be dynamically freed when it * is no longer being used. * * If the kset was not able to be created, NULL will be returned.
*/ struct kset *kset_create_and_add(constchar *name, conststruct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj)
{ struct kset *kset; int error;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.