Skip to content

Commit bfb4e7b

Browse files
committed
Add systemd integration via a template unit
Provide systemd support for mounting the gpiod-sysfs-proxy compatibility filesystem. The package now installs a single template unit, gpiod-sysfs-proxy@.service, with an instance name of the systemd-escaped mountpoint (e.g. gpiod-sysfs-proxy@run-gpio.service). No instance is enabled by default so the admin opts into the mountpoint they want: systemctl enable --now gpiod-sysfs-proxy@run-gpio.service systemctl enable --now gpiod-sysfs-proxy@sys-class-gpio.service Exposing /sys/class/gpio on a kernel where the sysfs GPIO interface is disabled needs the missing 'gpio' directory overlaid onto /sys/class first. The run-gpio-sys.mount and sys-class.mount units handle that and an instance-specific drop-in pulls them in only for the sys-class-gpio instance. PartOf= ties their lifetime to that instance for clean teardown and ConditionPathExists=!/sys/class/gpio makes them no-ops when the directory already exists. Other instances never touch the overlay. Fixes: #6 Signed-off-by: Christopher Obbard <christopher.obbard@linaro.org>
1 parent 03f5d62 commit bfb4e7b

6 files changed

Lines changed: 136 additions & 0 deletions

File tree

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,47 @@ For a complete list of available command-line options, please run:
3131
gpiod-sysfs-proxy --help
3232
```
3333

34+
## Integration
35+
36+
### systemd
37+
38+
The package installs a systemd template unit:
39+
40+
```
41+
gpiod-sysfs-proxy@.service
42+
```
43+
44+
No instance is enabled by default. The instance name is the
45+
systemd-escaped mountpoint. To expose the compatibility filesystem at
46+
`/run/gpio`:
47+
48+
```
49+
systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
50+
```
51+
52+
or, to mount over `/sys/class/gpio` (only works when that directory already
53+
exists, i.e. the kernel sysfs GPIO interface is enabled):
54+
55+
```
56+
systemctl enable --now gpiod-sysfs-proxy@sys-class-gpio.service
57+
```
58+
59+
You can generate the escaped instance name for any path with:
60+
61+
```
62+
systemd-escape --path /run/gpio
63+
systemd-escape --path /sys/class/gpio
64+
```
65+
66+
The `sys-class-gpio` instance also works on a kernel where sysfs GPIO support
67+
is disabled (so `/sys/class/gpio` does not exist): an instance-specific drop-in
68+
pulls in the bundled `run-gpio-sys.mount` and `sys-class.mount` units, which
69+
overlay the missing `gpio` directory onto `/sys/class` before the proxy starts
70+
and tear it back down when the instance is stopped. Nothing else enables those
71+
mounts, and they are skipped when `/sys/class/gpio` already exists. See the
72+
[Non-existent `/sys/class/gpio`](#non-existent-sysclassgpio) caveat below for
73+
the underlying mechanism.
74+
3475
## Caveats
3576

3677
Due to how FUSE works, there are certain limitations to the level of

pyproject.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@ authors = [
2222
Homepage = "https://github.com/brgl/gpiod-sysfs-proxy"
2323
Issues = "https://github.com/brgl/gpiod-sysfs-proxy/issues"
2424

25+
[tool.setuptools.data-files]
26+
# Install the systemd template unit but do not enable any instance by default.
27+
# The admin enables the mountpoint they want, e.g.:
28+
# systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
29+
#
30+
# The .mount units provide the /sys/class overlay needed to expose
31+
# /sys/class/gpio on kernels where the sysfs GPIO interface is disabled. They
32+
# are inert until pulled in: only the sys-class-gpio instance requires them
33+
# (via the drop-in below) and they carry ConditionPathExists=!/sys/class/gpio.
34+
"lib/systemd/system" = [
35+
"share/gpiod-sysfs-proxy@.service",
36+
"share/run-gpio-sys.mount",
37+
"share/sys-class.mount",
38+
]
39+
"lib/systemd/system/gpiod-sysfs-proxy@sys-class-gpio.service.d" = [
40+
"share/gpiod-sysfs-proxy@sys-class-gpio.service.d/overlay.conf",
41+
]
42+
2543
[build-system]
2644
requires = ["setuptools", "wheel"]
2745
build-backend = "setuptools.build_meta"

share/gpiod-sysfs-proxy@.service

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# SPDX-License-Identifier: CC0-1.0
2+
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
3+
4+
# Template unit: the instance name is the systemd-escaped mountpoint, e.g.
5+
#
6+
# systemctl enable --now gpiod-sysfs-proxy@run-gpio.service
7+
# systemctl enable --now gpiod-sysfs-proxy@sys-class-gpio.service
8+
#
9+
# Generate the instance name from a path with:
10+
#
11+
# systemd-escape --path /run/gpio
12+
# systemd-escape --path /sys/class/gpio
13+
#
14+
# Inside the unit %I expands back to the unescaped mountpoint path.
15+
#
16+
# Mounting over /sys/class/gpio only works when that directory already exists
17+
# (i.e. the kernel sysfs GPIO interface is enabled). To expose it on a kernel
18+
# where sysfs GPIO is disabled, see the overlay .mount example units shipped
19+
# alongside this file.
20+
21+
[Unit]
22+
Description=User-space, libgpiod-based GPIO sysfs compatibility layer at %I
23+
24+
[Service]
25+
RuntimeDirectory=gpio
26+
Type=simple
27+
ExecStart=/usr/bin/gpiod-sysfs-proxy %I -f -o allow_other -o default_permissions
28+
ExecStop=/bin/umount %I
29+
Restart=always
30+
31+
[Install]
32+
WantedBy=multi-user.target
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-License-Identifier: CC0-1.0
2+
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
3+
4+
# Instance-specific drop-in: only the sys-class-gpio instance needs the
5+
# /sys/class overlay. Pulling the mounts in here (rather than in the template)
6+
# keeps other instances, e.g. gpiod-sysfs-proxy@run-gpio.service, free of it.
7+
#
8+
# The mount units carry ConditionPathExists=!/sys/class/gpio, so on a kernel
9+
# where the sysfs GPIO interface is enabled they become no-ops and the proxy
10+
# simply mounts over the existing directory.
11+
12+
[Unit]
13+
Requires=run-gpio-sys.mount sys-class.mount
14+
After=run-gpio-sys.mount sys-class.mount

share/run-gpio-sys.mount

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-License-Identifier: CC0-1.0
2+
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
3+
4+
[Unit]
5+
Description=Remount of sysfs for gpiod-sysfs-proxy
6+
PartOf=gpiod-sysfs-proxy@sys-class-gpio.service
7+
ConditionPathExists=!/sys/class/gpio
8+
9+
[Mount]
10+
DirectoryMode=0700
11+
What=sysfs
12+
Where=/run/gpio/sys
13+
Type=sysfs
14+
Options=nosuid,nodev,noexec

share/sys-class.mount

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: CC0-1.0
2+
# SPDX-FileCopyrightText: 2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
3+
4+
[Unit]
5+
Description=Overlay on top of /sys/class adding the gpio class directory
6+
Before=gpiod-sysfs-proxy@sys-class-gpio.service
7+
After=run-gpio-sys.mount
8+
PartOf=gpiod-sysfs-proxy@sys-class-gpio.service
9+
ConditionPathExists=!/sys/class/gpio
10+
11+
[Mount]
12+
RuntimeDirectory=gpio/class/gpio
13+
DirectoryMode=0755
14+
What=overlay
15+
Where=/sys/class
16+
Type=overlay
17+
Options=upperdir=/run/gpio/class,lowerdir=/run/gpio/sys/class,workdir=/run/gpio/work,ro,nosuid,nodev,noexec,relatime

0 commit comments

Comments
 (0)