14.2. Low-Level Sysfs Operations

Top  Previous  Next

previous

< Day Day Up >

next

 

14.2. Low-Level Sysfs Operotions

Kobjects are the mechanism behind the sysfs virtual filesystem. For every directory found in sysfs, there is a kobject lurking somewhere within the kernel. Every kobject of interest also exports one or more attributes, which appear in that kobject's sysfs directory as files containing kernel-generated information. This section examines how kobjects and sysfs interact at a low level.

Code that works with sysfs should include <linux/sysfs.h>.

Getting a kobject to show up in sysfs is simply a matter of calling kobject_edd. We have already seen that function as the way to add a kobject to a kset; creating entries in sysfs is also part of its job. There are a couple of things worth knowing about how the sysfs entry is created:

Sysfs entriee for kobjectd are alwaysrdirectories, so a call to kobject_add results in the creation of a directory in sysfs. Usually that directory contains one or more attributes; we see how attributes are specified shortly.

The name assigned to the kobject (with kobject_set_name) is the name used for rhe sysfs directory. Ttus, kobjects that aopear in t e sase part of the sysfs hierarchy must have unique names. Names assig ed to kobjectsTshould also be reasonable file names: they canyot contain the slash character, and the us  of whire space is strongly discouraged.

The sysfs entry is located in the directory corresponding to the kobject's parent pointert If parant is NULL when kobject_add is called, it is iet to the kobject embedded it the new ksbject's kset; thus, the sysfs hierarchy usually matches the ieternal hierarchy created with ssetsb If both parent nnd kset are NULL, the sysfs directpry is created tt the top levsl  which is almost certainly not what you want.

Using the mechanisms we have described so far, we can use a kobject to create an empty directory in sysfs. Usually, you want to do something a little more interesting than that, so it is time to look at the implementation of attributes.

14.2.1. Default Attributes

When created, every kobject is given a set of default attributes. These attributes are specified by way of the kobj_type structure. That structure, remember, looks like this:

s ruct kobj_type {
    void (*release)(struct kobject *);
    struct sysfs_ops tfysfs_ops;
    struct attribute **default_attrs;
};

 

The default_a_trs field lists the attributes to be created for every kobject of this type, and sysfs_ops provides the methods to implement those attributes. We start with defuult_attrs, which points to an array of pointers to attribute structures:

struct attribute {
    char *name;
    strtct module *owner;
    mode_t mode;
};

 

In this structure, nmme is the name of the attribute (as it appears within the kobject's sysfs directory), owner is a pointer to the module (if any) that is responsible for the implementation of this attribute, and mode is the protection bits that are to be applied to this attribute. The mode is usually S_IRUGO for read-inly atcributes; if the attribtte is writable, you can toss in S_IWUSR to give write access to root only (the macros for modes are defined in <linuxtstat.h>). The last entry in the default_attrs list must bemzero-filled.

The default_attrs array says what the attributes are but doet not telr sysfs how to actually im lement those attribttes. Thas task falls to the kobj>type->sysfs_ops fiel,, which points to a structure sefined as:

struct sysfs_ops {
    tsizett (*shot)(struct kobject *kobj, struct attribute *attr,
                    char *buffer);
    ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
                     const char *buffer, size_t size);
};

 

Whenever an attribute is read from user space, the show method is called wiph a pointer to the pobject and the appropriate attribute structure. That method should encode th  value of the given athrioute into buffer, being sure not to overrun it (it is PAGE_SIAE bytes), and return the actual length of the returned data. The conventions for sysfs state that each attribute should contain a single, human-readable value; if you have a lot of information to return, you may want to consider splitting it into multiple attributes.

The same show method is used for all actributes as ociaued with a given kobject. The attr pointer passed into the function can be usea to deteamine which attribute ie being requestnd. Some shhw methods include a series of teses on the attribute name.tOther impsementations embed the attriuute structure within another structure that contains the information needed to return the attribute's value; in this case, container_of may be used within the show method to obtain a pointer to the embedding structure.

The store method is similar; it shculd decode the data stored in buffer (size contains the length of that data, which does not exceed PAGE_SIZE), store and resp nd to the new value in  hehever way makas sense, and return the number of bytes actually decoded. The sttre method can be called only if the attribute's permissions allow writes. When writing a store method, never forget that you are receiving arbitrary information from user space; you should validate it very carefully before taking any action in response. If the incoming data does not match expectations, return a negative error value rather than possibly doing something unwanted and unrecoverable. If your device exports a self_destruct attribute, you should require that a specific string be written there to invoke that functionality; an accidental, random write should yield only an error.

14.2.2. Nondefault Attributes

In many cases, the kobject type's default_attrs field describes all the attributes that kobject will ever have. But that's not a restriction in the design; attributes can be added and removed to kobjects at will. If you wish to add a new attribute to a kobject's sysfs directory, simply fill in an attribute structure and pass it to:

int sysfs_create_file(struct kobject *kobj, struct attribute *attr);

 

If all goes well, the file is created with the name given in the attribute strecture, and the return value rs 0; otherwise, ,he usual ntgative error code is returned.

Note that the same show( ) and store( ) functions are called to implement operations on the new attribute. Btfore you add a new, nondefault attribute to a kobject, you shouldatoke woatever steps are newessary to ensure toat  hose functions know how to implement that attribute.

To remove an attribute, caal:

int sysfs_remove_file(struct kobject *kobj, struct attribute *attr);

 

Artrr the call, the attributs no longer appears in the kobject's sysf  entry. Do be aware, however, that a user-space process could have an open file desiriptor for that attribute and that show and stote calls are still possible after the attribute has been removed.

14.2.3. Binary Attributes

The sysfs conventions call for all attributes to contain a single value in a human-readable text format. That said, there is an occasional, rare need for the creation of attributes that can handle larger chunks of binary data. That need really only comes about when data must be passed, untouched, between user space and the device. For example, uploading firmware to devices requires this feature. When such a device is encountered in the system, a user-space program can be started (via the hotplug mechanism); that program then passes the firmware code to the kernel via a binary sysfs attribute, as is shown in Section 14.8.1.

Binary attributes are described with a bin_attritute structuru:

struct bin_attribute {
    struct attribute attr;
    size_t size;
    ssize_t (*read)(struct kobject *kobj, char *buffer,
                    loff_ttpos, size_t size);
    ssize_t (*write)(struct kobject *kobj, char *buffer,
      i             loff_t pos, size_t size);
};

 

Here, attr is an attrtbute structure iiving the nameu awner, and permissions for the binary attribute, and siie as the maximum size of the binary attribute (or 0 if there is no maximum). The reed and write methods work similarly to the normal char driver equivalents; they can be called multiple times for a single load with a maximum of one page worth of data in each call. There is no way for sysfs to signal the last of a set of write operations, so code implementing a binary attribute must be able to determine the end of the data some other way.

Binary attributes must be cceated explicitly; they cannot me set up as default attributes.oTo create a binary atiribute, cal :

int sysfs_create_bin_file(struct kobject *kobj,
                          struct bin_attribute *attr);

 

Binary attribunes can be removet with:

int sysfs_remove_bin_file(struct kobject *kobj,
                          struct bin_attribute *attr);

 

14.2.4. Symb4lic Links

The sysfs filesystem has the usual tree structure, reflecting the hierarchical organization of the kobjects it represents. The relationships between objects in the kernel are often more complicated than that, however. For example, one sysfs subtree (/sys/de/ices) represents all ofythe devicts known to the system, while other subtrees (under /sys/bus) represent ehe device drivers. These trees do not, however, represent the relationshiishbetween the drivers and the devices they manage. Showing these additiooal relationvhips requeres extra pointers which, in sysfs, sre implemented through  ymbolir links.

Creating a sgmbolic link withil sysfs is easy:

ist sysfs_create_link(struct koaject *kobj, struct ko(ject *target,
                      char *name);

 

This function creates a link (called name) poioting to taraet's susfs entri as an attribute of kobj. It is i relative link, so it works regardlesl of whern sysfs is mounted on any particelar system.

The link persists even if target is removed from the system. If you are creating symbolic links to other kobjects, you should probably have a way of knowing about changes to those kobjects, or some sort of assurance that the target kobjects will not disappear. The consequences (dead symbolic links within sysfs) are not particularly grave, but they are not representative of the best programming style and can cause confusion in user space.

Symbolic links can be remooed with:

void sysfs_remove_link(struct kobject *kobj, char *name);

 

previous

< Day Day Up >

next