LinuxKPI: Improve sysfs support.

- Add functions for creating and merging sysfs groups.
- Add sysfs_streq function to compare strings ignoring newline from the
  sysctl userland call.
- Add a call to sysfs_create_groups in device_add.
- Remove duplicate header include.
- Bump __FreeBSD_version.

Reviewed by:	hselasky
Approved by:	imp (mentor), hselasky
MFC after:	4 days
Differential Revision:	D21542
This commit is contained in:
Johannes Lundberg 2019-09-06 15:43:53 +00:00
parent 2c24ffacd6
commit f6668e9f56
3 changed files with 71 additions and 11 deletions

View File

@ -40,7 +40,6 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/sysfs.h>
#include <linux/kdev_t.h>
#include <asm/atomic.h>
@ -316,6 +315,10 @@ device_add(struct device *dev)
dev->devt = makedev(0, device_get_unit(dev->bsddev));
}
kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev));
if (dev->groups)
return (sysfs_create_groups(&dev->kobj, dev->groups));
return (0);
}

View File

@ -175,6 +175,27 @@ sysfs_remove_files(struct kobject *kobj, const struct attribute * const *attrs)
sysfs_remove_file(kobj, attrs[i]);
}
static inline int
sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp)
{
struct attribute **attr;
struct sysctl_oid *oidp;
/* Don't create the group node if grp->name is undefined. */
if (grp->name)
oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(kobj->oidp),
OID_AUTO, grp->name, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, grp->name);
else
oidp = kobj->oidp;
for (attr = grp->attrs; *attr != NULL; attr++) {
SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(oidp), OID_AUTO,
(*attr)->name, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE,
kobj, (uintptr_t)*attr, sysctl_handle_attr, "A", "");
}
return (0);
}
static inline void
sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp)
{
@ -184,20 +205,40 @@ sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp)
}
static inline int
sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp)
sysfs_create_groups(struct kobject *kobj, const struct attribute_group **grps)
{
int error = 0;
int i;
for (i = 0; grps[i] && !error; i++)
error = sysfs_create_group(kobj, grps[i]);
while (error && --i >= 0)
sysfs_remove_group(kobj, grps[i]);
return (error);
}
static inline int
sysfs_merge_group(struct kobject *kobj, const struct attribute_group *grp)
{
/* Really expected behavior is to return failure if group exists. */
return (sysfs_create_group(kobj, grp));
}
static inline void
sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp)
{
struct attribute **attr;
struct sysctl_oid *oidp;
oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(kobj->oidp),
OID_AUTO, grp->name, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, grp->name);
for (attr = grp->attrs; *attr != NULL; attr++) {
SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(oidp), OID_AUTO,
(*attr)->name, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE,
kobj, (uintptr_t)*attr, sysctl_handle_attr, "A", "");
SLIST_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp), oid_link) {
if (strcmp(oidp->oid_name, grp->name) != 0)
continue;
for (attr = grp->attrs; *attr != NULL; attr++) {
sysctl_remove_name(oidp, (*attr)->name, 1, 1);
}
}
return (0);
}
static inline int
@ -224,6 +265,22 @@ sysfs_remove_dir(struct kobject *kobj)
sysctl_remove_oid(kobj->oidp, 1, 1);
}
static inline bool
sysfs_streq(const char *s1, const char *s2)
{
int l1, l2;
l1 = strlen(s1);
l2 = strlen(s2);
if (l1 != 0 && s1[l1-1] == '\n')
l1--;
if (l2 != 0 && s2[l2-1] == '\n')
l2--;
return (l1 == l2 && strncmp(s1, s2, l1) == 0);
}
#define sysfs_attr_init(attr) do {} while(0)
#endif /* _LINUX_SYSFS_H_ */

View File

@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1300045 /* Master, propagated to newvers */
#define __FreeBSD_version 1300046 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,