Skip to content

Commit

Permalink
uvol: replace with re-write in ucode
Browse files Browse the repository at this point in the history
Replace previous Shell draft-quality implementation of uvol with a
rewrite in ucode[1].
While the new code is slightly larger, it performs much better (as
we no longer fork() for parsing strings like in Shell with grep, sed
and friends).

Before:
  time uvol list -j
  [ ... ]
  real	0m 0.82s
  user	0m 0.13s
  sys	0m 0.10s

After:
  time uvol list -j
  [ ... ]
  real	0m 0.47s
  user	0m 0.05s
  sys	0m 0.05s

[1]: https://github.com/jow-/ucode
Signed-off-by: Daniel Golle <[email protected]>
  • Loading branch information
dangowrt committed Mar 31, 2022
1 parent 73b304b commit 6350c7b
Show file tree
Hide file tree
Showing 9 changed files with 1,226 additions and 938 deletions.
22 changes: 13 additions & 9 deletions utils/uvol/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=uvol
PKG_VERSION:=0.6
PKG_VERSION:=0.7
PKG_RELEASE:=$(AUTORELEASE)

PKG_MAINTAINER:=Daniel Golle <[email protected]>
Expand All @@ -19,27 +19,30 @@ define Package/autopart
endef

define Package/autopart/description
Automatically allocate the GPT partition for LVM and initialize it
on first boot.
Automatically allocate and initialize a partition for LVM on first boot.
endef

define Package/uvol
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=Disc
TITLE:=OpenWrt UBI/LVM volume abstraction
DEPENDS:=+blockd
DEPENDS:=+blockd +ucode +ucode-mod-fs +ucode-mod-uci
PKGARCH=all
endef

define Package/uvol/description
'uvol' is tool to automate storage volume handling on embedded
devices in a generic way.
Depending on what is available, 'uvol' will use either UBI or LVM2
as storage backends and transparently offer identical operations on
top of them.

Also install the 'autopart' package to easily make use of 'uvol' on
block-storage based devices.

Examples:
uvol create example_volume_1 256MiB rw
uvol create example_volume_1 268435456 rw
uvol up example_volume_1
uvol device example_volume_1

Expand All @@ -64,11 +67,12 @@ define Package/autopart/install
endef

define Package/uvol/install
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec/uvol $(1)/usr/sbin $(1)/lib/functions $(1)/etc/uci-defaults
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/uvol/backends $(1)/usr/sbin $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol
$(INSTALL_BIN) ./files/common.sh $(1)/lib/functions/uvol.sh
$(INSTALL_BIN) ./files/ubi.sh $(1)/usr/libexec/uvol/20-ubi.sh
$(INSTALL_BIN) ./files/lvm.sh $(1)/usr/libexec/uvol/50-lvm.sh
$(INSTALL_DATA) ./files/blockdev_common.uc $(1)/usr/lib/uvol/
$(INSTALL_DATA) ./files/uci.uc $(1)/usr/lib/uvol/
$(INSTALL_DATA) ./files/lvm.uc $(1)/usr/lib/uvol/backends/
$(INSTALL_DATA) ./files/ubi.uc $(1)/usr/lib/uvol/backends/
$(INSTALL_BIN) ./files/uvol $(1)/usr/sbin
$(INSTALL_BIN) ./files/uvol.defaults $(1)/etc/uci-defaults/90-uvol-init
endef
Expand Down
123 changes: 123 additions & 0 deletions utils/uvol/files/blockdev_common.uc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
{%
// SPDX-License-Identifier: GPL-2.0-or-later
// Helper functions used to identify the boot device
// adapted from /lib/functions.sh
let cmdline_get_var = function(var) {
let cmdline = fs.open("/proc/cmdline", "r");
let allargs = cmdline.read("all");
cmdline.close();
let ret = null;
for (let arg in split(allargs, /[ \t\n]/)) {
let el = split(arg, "=");
if (shift(el) == var)
return join("=", el);
}
return ret;
};

// adapted from /lib/upgrade/common.sh
let get_blockdevs = function() {
let devs = [];
for (let dev in fs.glob('/dev/*'))
if (fs.stat(dev).type == "block")
push(devs, split(dev, '/')[-1]);

return devs;
};

// adapted from /lib/upgrade/common.sh
let get_uevent_major_minor = function(file) {
let uevf = fs.open(file, "r");
if (!uevf)
return null;

let r = {};
let evl;
while ((evl = uevf.read("line"))) {
let ev = split(evl, '=');
if (ev[0] == "MAJOR")
r.major = +ev[1];
if (ev[0] == "MINOR")
r.minor = +ev[1];
}
uevf.close();
return r;
};

// adapted from /lib/upgrade/common.sh
let get_bootdev = function(void) {
let rootpart = cmdline_get_var("root");
let uevent = null;

if (wildcard(rootpart, "PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9]")) {
let uuidarg = split(substr(rootpart, 9), '-')[0];
for (let bd in get_blockdevs()) {
let bdf = fs.open(sprintf("/dev/%s", bd), "r");
bdf.seek(440);
let bduuid = bdf.read(4);
bdf.close();
if (uuidarg == sprintf("%x%x%x%x", ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0))) {
uevent = sprintf("/sys/class/block/%s/uevent", bd);
break;
}
}
} else if (wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????0?/PARTNROFF=*") ||
wildcard(rootpart, "PARTUUID=????????-????-????-????-??????????02")) {
let uuidarg = substr(split(substr(rootpart, 9), '/')[0], 0, -2) + "00";
for (let bd in get_blockdevs()) {
let bdf = fs.open(sprintf("/dev/%s", bd), "r");
bdf.seek(568);
let bduuid = bdf.read(16);
bdf.close();
if (!bduuid)
continue;

let uuid = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
ord(bduuid, 3), ord(bduuid, 2), ord(bduuid, 1), ord(bduuid, 0),
ord(bduuid, 5), ord(bduuid, 4),
ord(bduuid, 7), ord(bduuid, 6),
ord(bduuid, 8), ord(bduuid, 9),
ord(bduuid, 10), ord(bduuid, 11), ord(bduuid, 12), ord(bduuid, 13), ord(bduuid, 14), ord(bduuid, 15));
if (uuidarg == uuid) {
uevent = sprintf("/sys/class/block/%s/uevent", bd);
break;
}
}
} else if (wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9]") ||
wildcard(rootpart, "0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9]") ||
wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9]") ||
wildcard(rootpart, "[a-f0-9][a-f0-9][a-f0-9][a-f0-9]")) {
let devid = rootpart;
if (substr(devid, 0, 2) == "0x")
devid = substr(devid, 2);

devid = hex(devid);
for (let bd in get_blockdevs()) {
let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
if (r && (r.major == devid / 256) && (r.minor == devid % 256)) {
uevent = sprintf("/sys/class/block/%s/../uevent", bd);
break;
}
}
} else if (wildcard(rootpart, "/dev/*")) {
uevent = sprintf("/sys/class/block/%s/../uevent", split(rootpart, '/')[-1]);
}
return get_uevent_major_minor(uevent);
};

// adapted from /lib/upgrade/common.sh
let get_partition = function(dev, num) {
for (let bd in get_blockdevs()) {
let r = get_uevent_major_minor(sprintf("/sys/class/block/%s/uevent", bd));
if (r.major == dev.major && r.minor == dev.minor + num) {
return bd;
break;
}
}
return null;
};

blockdev_common = {};
blockdev_common.get_partition = get_partition;
blockdev_common.get_bootdev = get_bootdev;
%}
83 changes: 0 additions & 83 deletions utils/uvol/files/common.sh

This file was deleted.

Loading

0 comments on commit 6350c7b

Please sign in to comment.