Author: johalun
Date: Fri Sep  6 15:43:53 2019
New Revision: 351937
URL: https://svnweb.freebsd.org/changeset/base/351937

Log:
  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

Modified:
  head/sys/compat/linuxkpi/common/include/linux/device.h
  head/sys/compat/linuxkpi/common/include/linux/sysfs.h
  head/sys/sys/param.h

Modified: head/sys/compat/linuxkpi/common/include/linux/device.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/device.h      Fri Sep  6 
15:01:47 2019        (r351936)
+++ head/sys/compat/linuxkpi/common/include/linux/device.h      Fri Sep  6 
15:43:53 2019        (r351937)
@@ -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);
 }
 

Modified: head/sys/compat/linuxkpi/common/include/linux/sysfs.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/sysfs.h       Fri Sep  6 
15:01:47 2019        (r351936)
+++ head/sys/compat/linuxkpi/common/include/linux/sysfs.h       Fri Sep  6 
15:43:53 2019        (r351937)
@@ -175,6 +175,27 @@ sysfs_remove_files(struct kobject *kobj, const struct 
                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 
 }
 
 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
@@ -222,6 +263,22 @@ sysfs_remove_dir(struct kobject *kobj)
        if (kobj->oidp == NULL)
                return;
        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)

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h        Fri Sep  6 15:01:47 2019        (r351936)
+++ head/sys/sys/param.h        Fri Sep  6 15:43:53 2019        (r351937)
@@ -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,
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to