... but will take a while to set up. i want to write a short tutorial on kobjects, sysfs and attributes so i want to make absolutely sure i understand them (which is something i should understand anyway. :-) from sysfs.h and kobject.h, we have the definition of the generic kernel-wide "attribute" and "kobj_attribute" structures: struct attribute { const char *name; umode_t mode; #ifdef CONFIG_DEBUG_LOCK_ALLOC bool ignore_lockdep:1; struct lock_class_key *key; struct lock_class_key skey; #endif }; and struct kobj_attribute { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf); ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); }; so what the above shows is that a "kobj_attribute" contains an "attribute" and has, as its internal callback routines, functions that deal only with completely generic kobject and kobj_attribute pointers. so if i'm creating a number of attributes for some kobject i've created, and i'm associating show and store routines with each one, those show and store routines must have that prototype. for example, look at mm/ksm.c and how the attributes and callback routines are defined -- here's one: //////// static ssize_t full_scans_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%lu\n", ksm_scan.seqnr); } KSM_ATTR_RO(full_scans); static struct attribute *ksm_attrs[] = { &sleep_millisecs_attr.attr, &pages_to_scan_attr.attr, &run_attr.attr, &pages_shared_attr.attr, &pages_sharing_attr.attr, &pages_unshared_attr.attr, &pages_volatile_attr.attr, &full_scans_attr.attr, #ifdef CONFIG_NUMA &merge_across_nodes_attr.attr, #endif NULL, }; static struct attribute_group ksm_attr_group = { .attrs = ksm_attrs, .name = "ksm", }; //////// so the way i've always interpreted the above is that, when i finally register the attributes with the kernel, i am registering really just the underlying generic "attribute" structure and, when i try to access that attribute file, it automatically dereferences to the enclosing kobj_attribute structure to pick up the corresponding show() and store() routines associated with that attribute. so the first question is, is my understanding correct? if, in the above case, whenever i try to access one of the ksm attributes in /sys/kernel/mm/ksm, does the kernel take the reference to that *generic* attribute and automatically dereference/container_of() on it to get the enclosing kobj_attribute structure to pick up the corresponding show() and store() routines? asked a shorter way, is it assumed that a kobject attribute is *always* contained inside a kobj_attribute structure? and that the code in mm/ksm.c is an example of how to add individual show() and store() routines to such attributes? now here's part 2, and it's just a followup from the above. the second variation for attributes is what you see in cpufreq.c. rather than each attribute having its own callback routines, that code defines a prototype for cpufreq-*specific* show and store routines and a cpufreq-specific "freq_attr": struct freq_attr { struct attribute attr; ssize_t (*show)(struct cpufreq_policy *, char *); ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); }; *however* (and here's the thing i want to make sure i understand), when you register all of the cpufreq attribute files, each one still has to be interpreted as if it's part of a generic kobj_attribute structure with generic show() and store() routines, so what cpufreq does is define two generic show() and store() routines, and a couple helper macros that allow those two routines to then dereference to the appropriate cpufreq_policy and freq_attr pointers, then call the attribute-specific show() and store() routines: ////////// #define to_policy(k) container_of(k, struct cpufreq_policy, kobj) #define to_attr(a) container_of(a, struct freq_attr, attr) static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ... snip ... } static ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ... snip ... } ////////// and at the end of that file, the attributes are all registered with: static const struct sysfs_ops sysfs_ops = { .show = show, .store = store, }; static struct kobj_type ktype_cpufreq = { .sysfs_ops = &sysfs_ops, .default_attrs = default_attrs, .release = cpufreq_sysfs_release, }; which i interpret as saying that all of those attributes should be registered with the same single show() and store() routines (as opposed to ksm, which used different show() and store() routines for each attribute. in closing(?), as i understand it, when i access a kobject attribute file, it is assumed that that attribute is enclosed in a kobj_attribute structure, which contains the generic show() and store() routines, and i've seen two patterns for that: 1) in mm/ksm.c, each attribute is *directly* registered with callback routines with that prototype specific to that attribute, or 2) in cpufreq.c, all attributes are, in one operation, all registered with the *same* pair of generic callback functions, and those functions are then required to dereference the generic pointers to be able to call the appropriate callbacks for the given attribute. do i have this about right? rday -- ======================================================================== Robert P. J. Day Ottawa, Ontario, CANADA http://crashcourse.ca Twitter: http://twitter.com/rpjday LinkedIn: http://ca.linkedin.com/in/rpjday ======================================================================== _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies