summaryrefslogtreecommitdiff
path: root/share/docs/kernel/ctlfs.md
blob: 3087f60e89ebb023306b735c4cf6f59810ac2eb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# The Hyra control filesystem (ctlfs)

Written by Ian M. Moffett

## Rationale

Historically, Operating Systems of the Unix family typically relied
on syscalls like ``ioctl()`` or similar to perform operations (e.g., making calls through a driver)
via some file descriptor. Let's say for example, one wanted to acquire the framebuffer
dimensions of a given framebuffer device. To start, they'd acquire a file descriptor
by calling ``open()`` or similar on it. Then they'd make their ``ioctl()`` call.

```c
int fd = ...;

ioctl(fd, IOCTL_FBINFO, &fb_info);
...
```

While this works fine and is relatively simple to use from the user's
perspective, it is very clunky when you pop the hood and peer into the
inner-workings of it within the kernel. The number of possible requests
that can be passed through a file descriptor can grow quite rapidly which
can require really large switch statements within the drivers that implement
an ``ioctl()`` interface.

## Replacing ``ioctl()``

Hyra provides ctlfs, an abstract in-memory filesystem designed for
setting/getting various kernel / driver parameters and state via
the filesystem API. The control filesystem consists of several
instances of two fundamentals: "control nodes" and "control entries".

### Control nodes

Control nodes are simply directories within the ``/ctl`` root. For example,
console specific control files are in the ``/ctl/console`` node.

### Control entries

Control entries are simply files within specific control nodes. For example
console features may be find in the ``consfeat`` entry of the ``console`` node
(i.e., ``/ctl/console/consfeat``).

See ``sys/include/sys/console.h`` and ``sys/fs/ctlfs.h`` for more
information.

## The ctlfs API

The Hyra kernel provides an API for subsystems and drivers
to create their own ctlfs entries and nodes. This may be found
in sys/include/fs/ctlfs.h

### Control operations

Each control entry must define their own set of
"control operations" described by the ``ctlops`` structure:

```c
struct ctlops {
    int(*read)(struct ctlfs_dev *cdp, struct sio_txn *sio);
    int(*write)(struct ctlfs_dev *cdp, struct sio_txn *sio);
    ...
};
```

NOTE: Callbacks defined as ``NULL`` will be
ignored and unused.

## "Meow World": Creating a ctlfs entry

```c
#include <sys/types.h>
#include <sys/sio.h>
#include <fs/ctlfs.h>

static const struct ctlops meow_ctl;

/*
 * Ctlfs read callback - this will be called
 * when "/ctl/meow/hii" is read.
 */
static int
ctl_meow_read(struct ctlfs_dev *cdp, struct sio_txn *sio)
{
    char data[] = "Meow World!""

    /* Clamp the input length */
    if (sio->len > sizeof(data)) {
        sio->len = sizeof(data)
    }

    /* End of the data? */
    if ((sio->offset + sio->len) > sizeof(data)) {
        return 0;
    }

    /* Copy the data and return the length */
    memcpy(sio->buf, &data[sio->offset], sio->len);
    return sio->len;
}

static int
foo_init(void)
{
    char ctlname[] = "meow";
    struct ctlfs_dev ctl;

    /*
     * Here we create the "/ctl/meow" node.
     */
    ctl.mode = 0444;
    ctl.devname = devname;
    ctlfs_create_node(devname, &ctl);

    ctl.ops = &fb_size_ctl;
    ctlfs_create_entry("attr", &ctl);
    return 0;
}

static const struct ctlops meow_ctl = {
    .read = ctl_meow_read,
    .write = NULL,
};
```