Search code examples
clinux-kernelsysfs

Confused on creation of binary sysfs entry


On kernel 4.0, when stepping through the kernel source for sysfs_create_bin_file, I notice it passes to sysfs_add_file(kobj->sd, &attr->attr, true); The &attr->attr being the struct attribute struct within the bin_attribute struct.

This makes sense until I visit sysfs_add_file_mode_ns, which is directly called from sysfs_add_file, and on line #277 sets temp variable stuct bin_attribute *battr = (void*)attr;

Isn't this pointing to a struct attribute at this point, how is it resolving this to the proper struct (due to the call to sysfs_add_file using &attr->attr on line #483)?

Code

int sysfs_create_bin_file(struct kobject *kobj,
              const struct bin_attribute *attr)
{
    BUG_ON(!kobj || !kobj->sd || !attr);

    return sysfs_add_file(kobj->sd, &attr->attr, true);
}

int sysfs_add_file(struct kernfs_node *parent, const struct attribute *attr,
           bool is_bin)
{
    return sysfs_add_file_mode_ns(parent, attr, is_bin, attr->mode, NULL);
}

int sysfs_add_file_mode_ns(struct kernfs_node *parent,
               const struct attribute *attr, bool is_bin,
               umode_t mode, const void *ns)
{
    struct lock_class_key *key = NULL;
    const struct kernfs_ops *ops;
    struct kernfs_node *kn;
    loff_t size;

    if (!is_bin) {
        ...
    } else {


        struct bin_attribute *battr = (void *)attr;
         ...
    }

Solution

  • Line

    stuct bin_attribute *battr = (void*)attr;
    

    correctly obtains pointer to the bin_attribute structure from the pointer to its first field attr of type struct attribute.


    Normally, Linux kernel developers tend to use container_of macro for obtaining pointer to the structure type knowing pointer to its field. More "canonical" way for the transformation above would be:

    stuct bin_attribute *battr = container_of(attr, struct bin_attribute, attr);
    

    (In this call the first attr argument refers to the pointer, and the third attr argument refers to the field's name).