
\section{The sysfs filesystem}


sysfs is an in-memory filesystem with a kernel programming interface
for exporting object and their attributes. The purpose of sysfs is to
export kernel objects and their attributes. Sysfs is directly related
to the kobject infrastructure; every kobject that is added to the
system has a directory created for it in sysfs. Every directory that
is created in sysfs must have a kobject associated with it.\\

Sysfs uses the kobject hierarchy information to determine where to
create an object's directory. This enables sysfs to expose object
hierarchies, like the device hierarchy, with no additional
overhead. This also prevents a chaotic directory structure, which is
characteristic of the procfs filesystem. The following output is from
the tree(1) command, and expresses the device hierarchy, as
represented in sysfs.

\begin{alltt}
\begin{footnotesize}
\textbf{# tree -d /sys/devices/}
/sys/devices/
|-- ide0
|   |-- 0.0
|   `-- 0.1
|-- ide1
|   |-- 1.0
|   `-- 1.1
|-- legacy
|-- pci0
|   |-- 00:00.0
|   |-- 00:01.0
|   |   `-- 01:05.0
|   |-- 00:07.0
|   |-- 00:07.1
|   |-- 00:07.3
|   |-- 00:07.4
|   |-- 00:09.0
|   |-- 00:09.1
|   |-- 00:09.2
|   |-- 00:0b.0
|   `-- 00:0c.0
`-- sys
    |-- cpu0
    |-- cpu1
    |-- pic0
    `-- rtc0
\end{footnotesize}
\end{alltt}

Sysfs provides an extensible interface for exporting attributes of
objects. Attributes are represented by regular files in a kobject's
directory, with a preference for the files to be  in ASCII text format
with one value per file. These preferences are not encoded
programmatically, but objects exporting attributes are strongly
encouraged to follow this model. The following is output. The
following shows the contents of a PCI device's directory, which
contains four attribute files: 

\begin{alltt}
\begin{footnotesize}
\textbf{# tree /sys/devices/pci0/00:07.0/}
/sys/devices/pci0/00:07.0/
|-- irq
|-- name
|-- power
`-- resource

0 directories, 4 files
\end{footnotesize}
\end{alltt}

sysfs has been a standard part of the Linux kernel as of version
2.5.45. It has existed under a different name (driverfs or ddfs) since
kernel version 2.5.2. The de-facto standard mount point for sysfs is a
new directory named '/sys'. It may be mounted from user pace by doing:


\begin{alltt}
\begin{footnotesize}
\textbf{# mount -t sysfs sysfs /sys}
\end{footnotesize}
\end{alltt}


\subsection*{Basic Operation}

The sysfs header file is include/linux/sysfs.h. It contains the
definition of struct attribute and the prototypes for managing object
directories and attributes. Sysfs directories are created for kobjects
when the kobjects are added to the kobject hierarchy. The directories
are removed when the kobjects are deleted from the hierarchy.\\ 

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

sysfs\_create\_dir(
  struct kobject *
)
& int
& Create sysfs directory for kobject.
\\\hline

sysfs\_remove\_dir(
  struct kobject *
)
& void
& Remove sysfs directory of kobject.
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{sysfs Programming Interface.}}
\end{table}



\subsection*{Attributes}

In their simplest form, sysfs attributes consist of only a name and
the permissions for accessing the attribute. They provide no details
about the type of data presented by the attribute, or the object
exporting the attribute. The means for reading and writing attributes
are subsystem-dependent, and are discussed next. \\

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Type} & \textit{Description} \\ \hline \hline

name	& char *	& Name of attribute. \\\hline

mode	& mode\_t	& Filesystem permissions for attribute file. \\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct attribute Data Fields.}}
\end{table}


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

sysfs\_create\_file(
  struct kobject *,
  struct attribute *
)
& int
& Create attribute file for kobject.
\\\hline

sysfs\_remove\_file(
  struct kobject *,
  struct attribute *
)
& void
& Remove attribute file of kobject.
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct attribute Programming Interface.}}
\end{table}

An attribute may be added to the kobject's directory by calling
sysfs\_create\_file(). The function references the attribute
structure, and creates a file named 'name' with a mode of 'mode' in
the kobject's directory. The attribute can be removed by calling
sysfs\_remove\_file(), passing pointers to the kobject and the
attribute descriptor.  \\

It is important to note that attributes do not have to be specific to
one instance of an object. A single attribute descriptor may be reused
for any number of object instances. For instance, a single attribute
descriptor exports a device's name. An attribute file is created for
each device that is registered with the system, though the same
attribute descriptor is passed to sysfs\_create\_file() for each
one. \\



\subsection*{Reading and Writing Attributes}

Reading and writing kobject attributes involves passing data between
the user space process that is accessing an attribute file and the
entity that has exported the attribute. The base definition of
attributes does not provide this type of functionality. The definition
is ignorant of the type of the attribute and the specific data it
represents. In order to get this data, sysfs must call one of the
methods defined by the subsystem the kobject belongs to in its struct
sysfs\_ops object. \\


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

show(
  struct kobject *,
  struct attribute *,
  char *,
  size\_t,
  loff\_t
)
& ssize\_t
& Called by sysfs when a user space process is reading an attribute
	file. Data may be returned in the PAGE\_SIZE buffer. \\\hline

store(
  struct kobject *,
  struct attribute *,
  const char *, 
  size\_t, loff\_t
)
& ssize\_t
& Called by sysfs when a user space process writes to an attribute
	file. Data is stored in the PAGE\_SIZE buffer passed in. \\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct attribute I/O methods.}}
\end{table}

Sysfs calls a subsystem's show method when a user mode process
performs a read(2) operation on an attribute. It calls a subsystem's
show method when a write(2) is performed on the file. In both cases,
the size of the buffer passed to the methods is the size of one
page. \\

The current model places all responsibility of handling the data on
the downstream functions. They must format the data, handle partial
reads, and correctly handle seeks or consecutive reads. In this case,
sysfs is much like the default procfs operation, without using the
seq\_file interface. Though sysfs allows file creation and the
downstream functions to be much simpler, the interface is still
considered prohibitively complex. A new interface is being developed
that will ease the burden of the downstream formatting and parsing
functions.\\



\subsection*{Extending Attributes}

Attributes may be added for an object at any time, by any type of
kernel entity, whether they are a core part of the subsystem, a
dynamically loaded driver for the kobject, or even some proprietary
module. There is only one set of sysfs\_ops for a subsystem, though,
so struct attribute may be extended to describe the secondary methods
necessary to read or write an attribute. \\

Extending an attribute can be done for a type of object by defining a
new type of attribute, that contain an embedded struct attribute and
methods to read and write the data of the attribute. For example, the
following definitions exist in include/linux/device.h.

\begin{footnotesize}
\begin{verbatim}

struct device_attribute {
        struct attribute        attr;
        ssize_t (*show)(struct device *, char *, size_t, loff_t);
        ssize_t (*store)(struct device *, const char *, size_t, loff_t);
};

int device_create_file(struct device *, struct device_attribute *);
void device_remove_file(struct device *, struct device_attribute *);

\end{verbatim}
\end{footnotesize}

Kernel components must define an object of this type to export an
attribute of a device. The device\_attribute object is known by the
device subsystem. When it receives a call from sysfs to read or write
an attribute, it converts the attribute to a device\_attribute object,
as well as converting the kobject  to a struct device.\\

Components that export attributes for devices may define 'show' and
'store' methods to read and write that attribute. An explicit device
object is passed to these methods, so the definer of the method does
not have to manually convert the object. The methods are also not
passed a pointer to the attribute, as it should be implicit in the
method being called. \\



\subsection*{Reference Counting} 

Composite in-kernel filesystems suffer from potential race conditions
when user space is accessing objects exported by them. The object
could be removed, either by removing a physical device or by unloading
a module, while a user space process is still expecting a valid
object. Sysfs attempts to avoid this by integrating the kobject
semantics into the core of the filesystem. Note that this is only an
attempt. No current race conditions exist, though their existence is
not precluded entirely.\\

When a directory is created for a kobject, a pointer to the kobject is
stored in the d\_fsdata field of the dentry of the directory. When an
attribute file is created, a pointer to the attribute is stored in the
d\_fsdata field of the file. When an attribute file is opened, the
reference count on the kobject is incremented. When the file is
closed, the reference count of the kobject is decremented. This
prevents the kobject, and the structure its embedded in, from being
removed while the file is open. \\

Note that this does not prevent a device from being physically
removed, or a module being unloaded. Downstream calls should always
verify that the object a kobject refers to is still valid, and not
rely on the presence of the structure to determine that. \\



\subsection*{Expressing Object Relationships}

Objects throughout the kernel are referenced by multiple
subsystems. In many cases, each subsystem has a different object to
describe an entity, relevant to its own local context. Displaying only
the objects in relation to the subsystem is an incredibly handy
feature of sysfs. But, being able to symbolically and graphically
represent the relationship between objects of two different subsystems
can be invaluable. Sysfs provides a very simple means to do so, via
symbolic links in the filesystem.\\


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

sysfs\_create\_link(
struct kobject * kobj,
struct kobject * target,
char * name
)
& int
& Create symbolic link in kobj's sysfs directory that points to
	target's directory, with a name of 'name'. \\\hline

sysfs\_remove\_link(
struct kobject *, 
char * name
)
& void
& Remove symbolic link from kobject's directory with specified name.  \\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{sysfs Symbolic Link Interface.}}
\end{table}


An example use of symbolic links is in the block subsystem . When a
block device is registered, a symbolic link is created to the device's
directory in the physical hierarchy. A symbolic link is also created
in the device's directory that points to the corresponding directory
under the block directory. 
 
\begin{alltt}
\begin{footnotesize}
\textbf{# tree -d /sys/block/hda/}
/sys/block/hda/
|-- device -> ../../devices/ide0/0.0
|-- hda1
|-- hda2
|-- hda3
|-- hda4
|-- hda5
`-- hda6

7 directories
\textbf{# tree -d /sys/devices/ide0/0.0/}
/sys/devices/ide0/0.0/
`-- block -> ../../../block/hda

1 directory

\end{footnotesize}
\end{alltt}
