From 22d202e3a56d6756543713ec2a2af3c65da31572 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Thu, 31 Mar 2022 21:41:17 +0100 Subject: [PATCH] uvol: unbreak build and adapt to updated ucode * Fix build which was broken by a wrong path in the Makefile. Adapt to ucode commit 4618807 ("main: rework CLI frontend"): * ucode now no longer needs the {% %} around each code file, remove that and safe one level of indentation. * ARGV now no longer includes ucode executable and script itself Fixes: 6350c7bc6 ("uvol: replace with re-write in ucode") Signed-off-by: Daniel Golle --- utils/uvol/Makefile | 2 +- utils/uvol/files/blockdev_common.uc | 194 +++---- utils/uvol/files/lvm.uc | 850 ++++++++++++++-------------- utils/uvol/files/ubi.uc | 660 +++++++++++---------- utils/uvol/files/uci.uc | 2 - utils/uvol/files/uvol | 167 +++--- 6 files changed, 932 insertions(+), 943 deletions(-) diff --git a/utils/uvol/Makefile b/utils/uvol/Makefile index 21d46fcff1..410788df33 100644 --- a/utils/uvol/Makefile +++ b/utils/uvol/Makefile @@ -67,7 +67,7 @@ define Package/autopart/install endef define Package/uvol/install - $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/uvol/backends $(1)/usr/sbin $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/lib/uvol/backends $(1)/usr/sbin $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol $(INSTALL_DATA) ./files/blockdev_common.uc $(1)/usr/lib/uvol/ $(INSTALL_DATA) ./files/uci.uc $(1)/usr/lib/uvol/ diff --git a/utils/uvol/files/blockdev_common.uc b/utils/uvol/files/blockdev_common.uc index f45e573d26..8edf65bfe3 100644 --- a/utils/uvol/files/blockdev_common.uc +++ b/utils/uvol/files/blockdev_common.uc @@ -1,64 +1,64 @@ -{% // 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]); +// 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; +}; - return devs; - }; +// 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]); - // adapted from /lib/upgrade/common.sh - let get_uevent_major_minor = function(file) { - let uevf = fs.open(file, "r"); - if (!uevf) - return null; + return devs; +}; - 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_uevent_major_minor = function(file) { + let uevf = fs.open(file, "r"); + if (!uevf) + return null; - // adapted from /lib/upgrade/common.sh - let get_bootdev = function(void) { - let rootpart = cmdline_get_var("root"); - let uevent = 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; +}; - 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; +// 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=*") || @@ -72,52 +72,52 @@ 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); + 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)); - 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; + if (uuidarg == uuid) { + uevent = sprintf("/sys/class/block/%s/uevent", bd); break; } } - return null; - }; + } 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); - blockdev_common = {}; - blockdev_common.get_partition = get_partition; - blockdev_common.get_bootdev = get_bootdev; -%} + 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; diff --git a/utils/uvol/files/lvm.uc b/utils/uvol/files/lvm.uc index 5be27e5c2c..d05701dc4a 100644 --- a/utils/uvol/files/lvm.uc +++ b/utils/uvol/files/lvm.uc @@ -1,4 +1,3 @@ -{% // SPDX-License-Identifier: GPL-2.0-or-later // LVM2 backend for uvol // (c) 2022 Daniel Golle @@ -10,458 +9,457 @@ // By setting the UCI option 'vg_name' in the 'uvol' section in /etc/config/fstab // you may set an arbitrary LVM2 volume group to back uvol instad. - let lvm_exec = "/sbin/lvm"; +let lvm_exec = "/sbin/lvm"; - function lvm(cmd, ...args) { - let lvm_json_cmds = [ "lvs", "pvs", "vgs" ]; - try { - let json_param = ""; - if (cmd in lvm_json_cmds) - json_param = "--reportformat json --units b "; - let stdout = fs.popen(sprintf("LVM_SUPPRESS_FD_WARNINGS=1 %s %s %s%s", lvm_exec, cmd, json_param, join(" ", args))); - let tmp; - if (stdout) { - tmp = stdout.read("all"); - let ret = {}; - ret.retval = stdout.close(); - if (json_param) { - let data = json(tmp); - if (data.report) - ret.report = data.report[0]; - } else { - ret.stdout = trim(tmp); - } - return ret; +function lvm(cmd, ...args) { + let lvm_json_cmds = [ "lvs", "pvs", "vgs" ]; + try { + let json_param = ""; + if (cmd in lvm_json_cmds) + json_param = "--reportformat json --units b "; + let stdout = fs.popen(sprintf("LVM_SUPPRESS_FD_WARNINGS=1 %s %s %s%s", lvm_exec, cmd, json_param, join(" ", args))); + let tmp; + if (stdout) { + tmp = stdout.read("all"); + let ret = {}; + ret.retval = stdout.close(); + if (json_param) { + let data = json(tmp); + if (data.report) + ret.report = data.report[0]; } else { - printf("lvm cli command failed: %s\n", fs.error()); + ret.stdout = trim(tmp); } - } catch(e) { - printf("Failed to parse lvm cli output: %s\n%s\n", e, e.stacktrace[0].context); - } - return null; - } - - function pvs() { - let fstab = cursor.get_all('fstab'); - for (let k, section in fstab) { - if (section['.type'] != 'uvol' || !section.vg_name) - continue; - - return section.vg_name; - } - include("/usr/lib/uvol/blockdev_common.uc"); - let rootdev = blockdev_common.get_partition(blockdev_common.get_bootdev(), 0); - let tmp = lvm("pvs", "-o", "vg_name", "-S", sprintf("\"pv_name=~^/dev/%s.*\$\"", rootdev)); - if (tmp.report.pv) - return tmp.report.pv[0].vg_name; - else - return null; - } - - function vgs(vg_name) { - let tmp = lvm("vgs", "-o", "vg_extent_size,vg_extent_count,vg_free_count", "-S", sprintf("\"vg_name=%s\"", vg_name)); - let ret = null; - if (tmp && tmp.report.vg) { - ret = tmp.report.vg; - for (let r in ret) { - r.vg_extent_size = +(rtrim(r.vg_extent_size, "B")); - r.vg_extent_count = +r.vg_extent_count; - r.vg_free_count = +r.vg_free_count; - } - } - if (ret) - return ret[0]; - else - return null; - } - - function lvs(vg_name, vol_name, extra_exp) { - let ret = []; - if (!vol_name) - vol_name = ".*"; - - let lvexpr = sprintf("\"lvname=~^[rw][owp]_%s\$ && vg_name=%s%s%s\"", - vol_name, vg_name, extra_exp?" && ":"", extra_exp?extra_exp:""); - let tmp = lvm("lvs", "-o", "lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path", "-S", lvexpr); - if (tmp && tmp.report.lv) { - ret = tmp.report.lv; - for (let r in ret) { - r.lv_size = +(rtrim(r.lv_size, "B")); - r.lv_active = (r.lv_active == "active"); - } - } - return ret; - } - - function getdev(lv) { - if (!lv) - return null; - - for (let dms in fs.glob("/sys/devices/virtual/block/dm-*")) { - let f = fs.open(sprintf("%s/dm/name", dms), "r"); - if (!f) - continue; - - let dm_name = trim(f.read("all")); - f.close(); - if ( split(lv.lv_dm_path, '/')[-1] == dm_name ) - return split(dms, '/')[-1] - } - return null; - } - - function lvm_init(ctx) { - cursor = ctx.cursor; - fs = ctx.fs; - if (!fs.access(lvm_exec, "x")) - return false; - - vg_name = pvs(); - if (!vg_name) - return false; - - vg = vgs(vg_name); - uvol_uci_add = ctx.uci_add; - uvol_uci_commit = ctx.uci_commit; - uvol_uci_remove = ctx.uci_remove; - uvol_uci_init = ctx.uci_init; - return true; - } - - function lvm_free() { - if (!vg || !vg.vg_free_count || !vg.vg_extent_size) - return 2; - - return sprintf("%d", vg.vg_free_count * vg.vg_extent_size); - } - - function lvm_total() { - if (!vg || !vg.vg_extent_count || !vg.vg_extent_size) - return 2; - - return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size); - } - - function lvm_align() { - if (!vg || !vg.vg_extent_size) - return 2; - - return sprintf("%d", vg.vg_extent_size); - } - - function lvm_list(vol_name) { - let vols = []; - - if (!vg_name) - return vols; - - let res = lvs(vg_name, vol_name); - for (let lv in res) { - let vol = {}; - if (substr(lv.lv_name, 3, 1) == ".") - continue; - - vol.name = substr(lv.lv_name, 3); - vol.mode = substr(lv.lv_name, 0, 2); - if (!lv.lv_active) { - if (vol.mode == "ro") - vol.mode = "rd"; - if (vol.mode == "rw") - vol.mode = "wd"; - } - vol.size = lv.lv_size; - push(vols, vol); - } - - return vols; - } - - function lvm_size(vol_name) { - if (!vol_name || !vg_name) - return 2; - - let res = lvs(vg_name, vol_name); - if (!res[0]) - return 2; - - return sprintf("%d", res[0].lv_size); - } - - function lvm_status(vol_name) { - if (!vol_name || !vg_name) - return 22; - - let res = lvs(vg_name, vol_name); - if (!res[0]) - return 2; - - let mode = substr(res[0].lv_name, 0, 2); - if ((mode != "ro" && mode != "rw") || !res[0].lv_active) - return 1; - - return 0; - } - - function lvm_device(vol_name) { - if (!vol_name || !vg_name) - return 22; - - let res = lvs(vg_name, vol_name); - if (!res[0]) - return 2; - - let mode = substr(res[0].lv_name, 0, 2); - if ((mode != "ro" && mode != "rw") || !res[0].lv_active) - return 22; - - return getdev(res[0]); - } - - function lvm_updown(vol_name, up) { - if (!vol_name || !vg_name) - return 22; - - let res = lvs(vg_name, vol_name); - if (!res[0]) - return 2; - - let lv = res[0]; - if (!lv.lv_path) - return 2; - - if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") || - wildcard(lv.lv_path, "/dev/*/wp_*"))) - return 22; - - if (up) - uvol_uci_commit(vol_name); - - if (lv.lv_active == up) - return 0; - - if (!up) { - let devname = getdev(lv); - if (devname) - system(sprintf("umount /dev/%s", devname)); - } - - let lvchange_r = lvm("lvchange", up?"-k":"-a", "n", lv.lv_full_name); - if (up && lvchange_r.retval != 0) - return lvchange_r.retval; - - lvchange_r = lvm("lvchange", up?"-a":"-k", "y", lv.lv_full_name); - if (lvchange_r.retval != 0) - return lvchange_r.retval; - - return 0 - } - - function lvm_up(vol_name) { - return lvm_updown(vol_name, true); - } - - function lvm_down(vol_name) { - return lvm_updown(vol_name, false); - } - - function lvm_create(vol_name, vol_size, vol_mode) { - if (!vol_name || !vg_name) - return 22; - - vol_size = +vol_size; - if (vol_size <= 0) - return 22; - - let res = lvs(vg_name, vol_name); - if (res[0]) - return 17; - - let size_ext = vol_size / vg.vg_extent_size; - if (vol_size % vg.vg_extent_size) - ++size_ext; - let lvmode, mode; - if (vol_mode == "ro" || vol_mode == "wo") { - lvmode = "r"; - mode = "wo"; - } else if (vol_mode == "rw") { - lvmode = "rw"; - mode = "wp"; + return ret; } else { - return 22; + printf("lvm cli command failed: %s\n", fs.error()); } + } catch(e) { + printf("Failed to parse lvm cli output: %s\n%s\n", e, e.stacktrace[0].context); + } + return null; +} - let ret = lvm("lvcreate", "-p", lvmode, "-a", "n", "-y", "-W", "n", "-Z", "n", "-n", sprintf("%s_%s", mode, vol_name), "-l", size_ext, vg_name); - if (ret.retval != 0 || lvmode == "r") +function pvs() { + let fstab = cursor.get_all('fstab'); + for (let k, section in fstab) { + if (section['.type'] != 'uvol' || !section.vg_name) + continue; + + return section.vg_name; + } + include("/usr/lib/uvol/blockdev_common.uc"); + let rootdev = blockdev_common.get_partition(blockdev_common.get_bootdev(), 0); + let tmp = lvm("pvs", "-o", "vg_name", "-S", sprintf("\"pv_name=~^/dev/%s.*\$\"", rootdev)); + if (tmp.report.pv) + return tmp.report.pv[0].vg_name; + else + return null; +} + +function vgs(vg_name) { + let tmp = lvm("vgs", "-o", "vg_extent_size,vg_extent_count,vg_free_count", "-S", sprintf("\"vg_name=%s\"", vg_name)); + let ret = null; + if (tmp && tmp.report.vg) { + ret = tmp.report.vg; + for (let r in ret) { + r.vg_extent_size = +(rtrim(r.vg_extent_size, "B")); + r.vg_extent_count = +r.vg_extent_count; + r.vg_free_count = +r.vg_free_count; + } + } + if (ret) + return ret[0]; + else + return null; +} + +function lvs(vg_name, vol_name, extra_exp) { + let ret = []; + if (!vol_name) + vol_name = ".*"; + + let lvexpr = sprintf("\"lvname=~^[rw][owp]_%s\$ && vg_name=%s%s%s\"", + vol_name, vg_name, extra_exp?" && ":"", extra_exp?extra_exp:""); + let tmp = lvm("lvs", "-o", "lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path", "-S", lvexpr); + if (tmp && tmp.report.lv) { + ret = tmp.report.lv; + for (let r in ret) { + r.lv_size = +(rtrim(r.lv_size, "B")); + r.lv_active = (r.lv_active == "active"); + } + } + return ret; +} + +function getdev(lv) { + if (!lv) + return null; + + for (let dms in fs.glob("/sys/devices/virtual/block/dm-*")) { + let f = fs.open(sprintf("%s/dm/name", dms), "r"); + if (!f) + continue; + + let dm_name = trim(f.read("all")); + f.close(); + if ( split(lv.lv_dm_path, '/')[-1] == dm_name ) + return split(dms, '/')[-1] + } + return null; +} + +function lvm_init(ctx) { + cursor = ctx.cursor; + fs = ctx.fs; + if (!fs.access(lvm_exec, "x")) + return false; + + vg_name = pvs(); + if (!vg_name) + return false; + + vg = vgs(vg_name); + uvol_uci_add = ctx.uci_add; + uvol_uci_commit = ctx.uci_commit; + uvol_uci_remove = ctx.uci_remove; + uvol_uci_init = ctx.uci_init; + return true; +} + +function lvm_free() { + if (!vg || !vg.vg_free_count || !vg.vg_extent_size) + return 2; + + return sprintf("%d", vg.vg_free_count * vg.vg_extent_size); +} + +function lvm_total() { + if (!vg || !vg.vg_extent_count || !vg.vg_extent_size) + return 2; + + return sprintf("%d", vg.vg_extent_count * vg.vg_extent_size); +} + +function lvm_align() { + if (!vg || !vg.vg_extent_size) + return 2; + + return sprintf("%d", vg.vg_extent_size); +} + +function lvm_list(vol_name) { + let vols = []; + + if (!vg_name) + return vols; + + let res = lvs(vg_name, vol_name); + for (let lv in res) { + let vol = {}; + if (substr(lv.lv_name, 3, 1) == ".") + continue; + + vol.name = substr(lv.lv_name, 3); + vol.mode = substr(lv.lv_name, 0, 2); + if (!lv.lv_active) { + if (vol.mode == "ro") + vol.mode = "rd"; + if (vol.mode == "rw") + vol.mode = "wd"; + } + vol.size = lv.lv_size; + push(vols, vol); + } + + return vols; +} + +function lvm_size(vol_name) { + if (!vol_name || !vg_name) + return 2; + + let res = lvs(vg_name, vol_name); + if (!res[0]) + return 2; + + return sprintf("%d", res[0].lv_size); +} + +function lvm_status(vol_name) { + if (!vol_name || !vg_name) + return 22; + + let res = lvs(vg_name, vol_name); + if (!res[0]) + return 2; + + let mode = substr(res[0].lv_name, 0, 2); + if ((mode != "ro" && mode != "rw") || !res[0].lv_active) + return 1; + + return 0; +} + +function lvm_device(vol_name) { + if (!vol_name || !vg_name) + return 22; + + let res = lvs(vg_name, vol_name); + if (!res[0]) + return 2; + + let mode = substr(res[0].lv_name, 0, 2); + if ((mode != "ro" && mode != "rw") || !res[0].lv_active) + return 22; + + return getdev(res[0]); +} + +function lvm_updown(vol_name, up) { + if (!vol_name || !vg_name) + return 22; + + let res = lvs(vg_name, vol_name); + if (!res[0]) + return 2; + + let lv = res[0]; + if (!lv.lv_path) + return 2; + + if (up && (wildcard(lv.lv_path, "/dev/*/wo_*") || + wildcard(lv.lv_path, "/dev/*/wp_*"))) + return 22; + + if (up) + uvol_uci_commit(vol_name); + + if (lv.lv_active == up) + return 0; + + if (!up) { + let devname = getdev(lv); + if (devname) + system(sprintf("umount /dev/%s", devname)); + } + + let lvchange_r = lvm("lvchange", up?"-k":"-a", "n", lv.lv_full_name); + if (up && lvchange_r.retval != 0) + return lvchange_r.retval; + + lvchange_r = lvm("lvchange", up?"-a":"-k", "y", lv.lv_full_name); + if (lvchange_r.retval != 0) + return lvchange_r.retval; + + return 0 +} + +function lvm_up(vol_name) { + return lvm_updown(vol_name, true); +} + +function lvm_down(vol_name) { + return lvm_updown(vol_name, false); +} + +function lvm_create(vol_name, vol_size, vol_mode) { + if (!vol_name || !vg_name) + return 22; + + vol_size = +vol_size; + if (vol_size <= 0) + return 22; + + let res = lvs(vg_name, vol_name); + if (res[0]) + return 17; + + let size_ext = vol_size / vg.vg_extent_size; + if (vol_size % vg.vg_extent_size) + ++size_ext; + let lvmode, mode; + if (vol_mode == "ro" || vol_mode == "wo") { + lvmode = "r"; + mode = "wo"; + } else if (vol_mode == "rw") { + lvmode = "rw"; + mode = "wp"; + } else { + return 22; + } + + let ret = lvm("lvcreate", "-p", lvmode, "-a", "n", "-y", "-W", "n", "-Z", "n", "-n", sprintf("%s_%s", mode, vol_name), "-l", size_ext, vg_name); + if (ret.retval != 0 || lvmode == "r") + return ret.retval; + + let lv = lvs(vg_name, vol_name); + if (!lv[0] || !lv[0].lv_full_name) + return 22; + + lv = lv[0]; + let ret = lvm("lvchange", "-a", "y", lv.lv_full_name); + if (ret.retval != 0) + return ret.retval; + + let use_f2fs = (lv.lv_size > (100 * 1024 * 1024)); + if (use_f2fs) { + let mkfs_ret = system(sprintf("/usr/sbin/mkfs.f2fs -f -l \"%s\" \"%s\"", vol_name, lv.lv_path)); + if (mkfs_ret != 0 && mkfs_ret != 134) { + lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name); + if (lvchange_r.retval != 0) + return lvchange_r.retval; + return mkfs_ret; + } + } else { + let mkfs_ret = system(sprintf("/usr/sbin/mke2fs -F -L \"%s\" \"%s\"", vol_name, lv.lv_path)); + if (mkfs_ret != 0) { + lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name); + if (lvchange_r.retval != 0) + return lvchange_r.retval; + return mkfs_ret; + } + } + uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "rw"); + + ret = lvm("lvchange", "-a", "n", lv.lv_full_name); + if (ret.retval != 0) + return ret.retval; + + ret = lvm("lvrename", vg_name, sprintf("wp_%s", vol_name), sprintf("rw_%s", vol_name)); + if (ret.retval != 0) + return ret.retval; + + return 0; +} + +function lvm_remove(vol_name) { + if (!vol_name || !vg_name) + return 22; + + let res = lvs(vg_name, vol_name); + if (!res[0]) + return 2; + + if (res[0].lv_active) + return 16; + + let ret = lvm("lvremove", "-y", res[0].lv_full_name); + if (ret.retval != 0) + return ret.retval; + + uvol_uci_remove(vol_name); + uvol_uci_commit(vol_name); + return 0; +} + +function lvm_dd(in_fd, out_fd, vol_size) { + let rem = vol_size; + let buf; + while ((buf = in_fd.read(vg.vg_extent_size)) && (rem > 0)) { + rem -= length(buf); + if (rem < 0) { + buf = substr(buf, 0, rem); + } + out_fd.write(buf); + } + return rem; +} + +function lvm_write(vol_name, vol_size) { + if (!vol_name || !vg_name) + return 22; + + let lv = lvs(vg_name, vol_name); + if (!lv[0] || !lv[0].lv_full_name) + return 2; + + lv = lv[0]; + vol_size = +vol_size; + if (vol_size > lv.lv_size) + return 27; + + if (wildcard(lv.lv_path, "/dev/*/wo_*")) { + let ret = lvm("lvchange", "-p", "rw", lv.lv_full_name); + if (ret.retval != 0) return ret.retval; - let lv = lvs(vg_name, vol_name); - if (!lv[0] || !lv[0].lv_full_name) - return 22; - - lv = lv[0]; let ret = lvm("lvchange", "-a", "y", lv.lv_full_name); if (ret.retval != 0) return ret.retval; - let use_f2fs = (lv.lv_size > (100 * 1024 * 1024)); - if (use_f2fs) { - let mkfs_ret = system(sprintf("/usr/sbin/mkfs.f2fs -f -l \"%s\" \"%s\"", vol_name, lv.lv_path)); - if (mkfs_ret != 0 && mkfs_ret != 134) { - lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name); - if (lvchange_r.retval != 0) - return lvchange_r.retval; - return mkfs_ret; - } - } else { - let mkfs_ret = system(sprintf("/usr/sbin/mke2fs -F -L \"%s\" \"%s\"", vol_name, lv.lv_path)); - if (mkfs_ret != 0) { - lvchange_r = lvm("lvchange", "-a", "n", lv.lv_full_name); - if (lvchange_r.retval != 0) - return lvchange_r.retval; - return mkfs_ret; - } + let volfile = fs.open(lv.lv_path, "w"); + let ret = lvm_dd(fs.stdin, volfile, vol_size); + volfile.close(); + if (ret < 0) { + printf("more %d bytes data than given size!\n", -ret); } - uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "rw"); - ret = lvm("lvchange", "-a", "n", lv.lv_full_name); + if (ret > 0) { + printf("reading finished %d bytes before given size!\n", ret); + } + + uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "ro"); + + let ret = lvm("lvchange", "-a", "n", lv.lv_full_name); if (ret.retval != 0) return ret.retval; - ret = lvm("lvrename", vg_name, sprintf("wp_%s", vol_name), sprintf("rw_%s", vol_name)); + let ret = lvm("lvchange", "-p", "r", lv.lv_full_name); if (ret.retval != 0) return ret.retval; - return 0; - } - - function lvm_remove(vol_name) { - if (!vol_name || !vg_name) - return 22; - - let res = lvs(vg_name, vol_name); - if (!res[0]) - return 2; - - if (res[0].lv_active) - return 16; - - let ret = lvm("lvremove", "-y", res[0].lv_full_name); + let ret = lvm("lvrename", vg_name, sprintf("wo_%s", vol_name), sprintf("ro_%s", vol_name)); if (ret.retval != 0) return ret.retval; - uvol_uci_remove(vol_name); - uvol_uci_commit(vol_name); - return 0; + } else { + return 22; } + return 0; +} - function lvm_dd(in_fd, out_fd, vol_size) { - let rem = vol_size; - let buf; - while ((buf = in_fd.read(vg.vg_extent_size)) && (rem > 0)) { - rem -= length(buf); - if (rem < 0) { - buf = substr(buf, 0, rem); - } - out_fd.write(buf); - } - return rem; +function lvm_detect() { + let temp_up = []; + let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0"); + for (let lv in inactive_lv) { + lvm("lvchange", "-k", "n", lv.lv_full_name); + lvm("lvchange", "-a", "y", lv.lv_full_name); + push(temp_up, lv.lv_full_name); } - - function lvm_write(vol_name, vol_size) { - if (!vol_name || !vg_name) - return 22; - - let lv = lvs(vg_name, vol_name); - if (!lv[0] || !lv[0].lv_full_name) - return 2; - - lv = lv[0]; - vol_size = +vol_size; - if (vol_size > lv.lv_size) - return 27; - - if (wildcard(lv.lv_path, "/dev/*/wo_*")) { - let ret = lvm("lvchange", "-p", "rw", lv.lv_full_name); - if (ret.retval != 0) - return ret.retval; - - let ret = lvm("lvchange", "-a", "y", lv.lv_full_name); - if (ret.retval != 0) - return ret.retval; - - let volfile = fs.open(lv.lv_path, "w"); - let ret = lvm_dd(fs.stdin, volfile, vol_size); - volfile.close(); - if (ret < 0) { - printf("more %d bytes data than given size!\n", -ret); - } - - if (ret > 0) { - printf("reading finished %d bytes before given size!\n", ret); - } - - uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), "ro"); - - let ret = lvm("lvchange", "-a", "n", lv.lv_full_name); - if (ret.retval != 0) - return ret.retval; - - let ret = lvm("lvchange", "-p", "r", lv.lv_full_name); - if (ret.retval != 0) - return ret.retval; - - let ret = lvm("lvrename", vg_name, sprintf("wo_%s", vol_name), sprintf("ro_%s", vol_name)); - if (ret.retval != 0) - return ret.retval; - - } else { - return 22; - } - return 0; + sleep(1000); + uvol_uci_init(); + for (let lv in lvs(vg_name)) { + let vol_name = substr(lv.lv_name, 3); + let vol_mode = substr(lv.lv_name, 0, 2); + uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), vol_mode); } - - function lvm_detect() { - let temp_up = []; - let inactive_lv = lvs(vg_name, null, "lv_skip_activation!=0"); - for (let lv in inactive_lv) { - lvm("lvchange", "-k", "n", lv.lv_full_name); - lvm("lvchange", "-a", "y", lv.lv_full_name); - push(temp_up, lv.lv_full_name); - } - sleep(1000); - uvol_uci_init(); - for (let lv in lvs(vg_name)) { - let vol_name = substr(lv.lv_name, 3); - let vol_mode = substr(lv.lv_name, 0, 2); - uvol_uci_add(vol_name, sprintf("/dev/%s", getdev(lv)), vol_mode); - } - uvol_uci_commit(); - for (let lv_full_name in temp_up) { - lvm("lvchange", "-a", "n", lv_full_name); - lvm("lvchange", "-k", "y", lv_full_name); - } - return 0; + uvol_uci_commit(); + for (let lv_full_name in temp_up) { + lvm("lvchange", "-a", "n", lv_full_name); + lvm("lvchange", "-k", "y", lv_full_name); } + return 0; +} - function lvm_boot() { - return 0; - } +function lvm_boot() { + return 0; +} - backend.backend = "LVM"; - backend.priority = 50; - backend.init = lvm_init; - backend.boot = lvm_boot; - backend.detect = lvm_detect; - backend.free = lvm_free; - backend.align = lvm_align; - backend.total = lvm_total; - backend.list = lvm_list; - backend.size = lvm_size; - backend.status = lvm_status; - backend.device = lvm_device; - backend.up = lvm_up; - backend.down = lvm_down; - backend.create = lvm_create; - backend.remove = lvm_remove; - backend.write = lvm_write; -%} +backend.backend = "LVM"; +backend.priority = 50; +backend.init = lvm_init; +backend.boot = lvm_boot; +backend.detect = lvm_detect; +backend.free = lvm_free; +backend.align = lvm_align; +backend.total = lvm_total; +backend.list = lvm_list; +backend.size = lvm_size; +backend.status = lvm_status; +backend.device = lvm_device; +backend.up = lvm_up; +backend.down = lvm_down; +backend.create = lvm_create; +backend.remove = lvm_remove; +backend.write = lvm_write; diff --git a/utils/uvol/files/ubi.uc b/utils/uvol/files/ubi.uc index 6f1cfbcd75..7d0872b169 100644 --- a/utils/uvol/files/ubi.uc +++ b/utils/uvol/files/ubi.uc @@ -1,378 +1,376 @@ -{% // SPDX-License-Identifier: GPL-2.0-or-later // UBI backend for uvol // (c) 2022 Daniel Golle // // This plugin uses UBI on NAND flash as a storage backend for uvol. - function read_file(file) { - let fp = fs.open(file); - if (!fp) - return null; - - let var = rtrim(fp.read("all")); - fp.close(); - return var; - } - - function mkdtemp() { - math = require("math"); - let r1 = math.rand(); - let r2 = math.rand(); - let randbytes = chr((r1 >> 24) & 0xff, (r1 >> 16) & 0xff, (r1 >> 8) & 0xff, r1 & 0xff, - (r2 >> 24) & 0xff, (r2 >> 16) & 0xff, (r2 >> 8) & 0xff, r2 & 0xff); - - let randstr = replace(b64enc(randbytes), /[\/-_.=]/g, ""); - let dirname = sprintf("/tmp/uvol-%s", randstr); - fs.mkdir(dirname, 0700); - return dirname; - } - - function ubi_get_dev(vol_name) { - let wcstring = sprintf("uvol-[rw][owpd]-%s", vol_name); - for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { - let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - if (wildcard(vol_ubiname, wcstring)) - return fs.basename(vol_dir); - } +function read_file(file) { + let fp = fs.open(file); + if (!fp) return null; - } - function vol_get_mode(vol_dev, mode) { - let vol_name = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/name", ubidev, vol_dev)); - return substr(vol_name, 5, 2); - } + let var = rtrim(fp.read("all")); + fp.close(); + return var; +} - function mkubifs(vol_dev) { - let temp_mp = mkdtemp(); - system(sprintf("mount -t ubifs /dev/%s %s", vol_dev, temp_mp)); - system(sprintf("umount %s", temp_mp)); - fs.rmdir(temp_mp); +function mkdtemp() { + math = require("math"); + let r1 = math.rand(); + let r2 = math.rand(); + let randbytes = chr((r1 >> 24) & 0xff, (r1 >> 16) & 0xff, (r1 >> 8) & 0xff, r1 & 0xff, + (r2 >> 24) & 0xff, (r2 >> 16) & 0xff, (r2 >> 8) & 0xff, r2 & 0xff); + + let randstr = replace(b64enc(randbytes), /[\/-_.=]/g, ""); + let dirname = sprintf("/tmp/uvol-%s", randstr); + fs.mkdir(dirname, 0700); + return dirname; +} + +function ubi_get_dev(vol_name) { + let wcstring = sprintf("uvol-[rw][owpd]-%s", vol_name); + for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { + let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); + if (wildcard(vol_ubiname, wcstring)) + return fs.basename(vol_dir); + } + return null; +} + +function vol_get_mode(vol_dev, mode) { + let vol_name = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/name", ubidev, vol_dev)); + return substr(vol_name, 5, 2); +} + +function mkubifs(vol_dev) { + let temp_mp = mkdtemp(); + system(sprintf("mount -t ubifs /dev/%s %s", vol_dev, temp_mp)); + system(sprintf("umount %s", temp_mp)); + fs.rmdir(temp_mp); + return 0; +} + +function block_hotplug(action, devname) { + return system(sprintf("ACTION=%s DEVNAME=%s /sbin/block hotplug", action, devname)); +} + +function ubi_init(ctx) { + cursor = ctx.cursor; + fs = ctx.fs; + + let ubiver = read_file("/sys/class/ubi/version"); + if (ubiver != 1) + return false; + + let ubidevpath = null; + for (ubidevpath in fs.glob("/sys/devices/virtual/ubi/*")) + break; + + if (!ubidevpath) + return false; + + ubidev = fs.basename(ubidevpath); + ebsize = read_file(sprintf("%s/eraseblock_size", ubidevpath)); + + uvol_uci_add = ctx.uci_add; + uvol_uci_commit = ctx.uci_commit; + uvol_uci_remove = ctx.uci_remove; + uvol_uci_init = ctx.uci_init; + + return true; +} + +function ubi_free() { + let availeb = read_file(sprintf("/sys/devices/virtual/ubi/%s/avail_eraseblocks", ubidev)); + return sprintf("%d", availeb * ebsize); +} + +function ubi_align() { + return sprintf("%d", ebsize); +} + +function ubi_total() { + let totaleb = read_file(sprintf("/sys/devices/virtual/ubi/%s/total_eraseblocks", ubidev)); + return sprintf("%d", totaleb * ebsize); +} + +function ubi_status(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode == "wo") return 22; + if (vol_mode == "wp") return 16; + if (vol_mode == "wd") return 1; + if (vol_mode == "ro" && + !fs.access(sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "r")) return 1; + + return 0; +} + +function ubi_size(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + + let vol_size = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/data_bytes", ubidev, vol_dev)); + return sprintf("%d", vol_size); +} + +function ubi_device(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode == "ro") + return sprintf("/dev/ubiblock%s", substr(vol_dev, 3)); + else if (vol_mode == "rw") + return sprintf("/dev/%s", vol_dev); + + return null; +} + +function ubi_create(vol_name, vol_size, vol_mode) { + let vol_dev = ubi_get_dev(vol_name); + if (vol_dev) + return 17; + + let mode; + if (vol_mode == "ro" || vol_mode == "wo") + mode = "wo"; + else if (vol_mode == "rw") + mode = "wp"; + else + return 22; + + let vol_size = +vol_size; + if (vol_size <= 0) + return 22; + let ret = system(sprintf("ubimkvol /dev/%s -N \"uvol-%s-%s\" -s %d", ubidev, mode, vol_name, vol_size)); + if (ret != 0) + return ret; + + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + + let ret = system(sprintf("ubiupdatevol -t /dev/%s", vol_dev)); + if (ret != 0) + return ret; + + if (mode != "wp") return 0; - } - function block_hotplug(action, devname) { - return system(sprintf("ACTION=%s DEVNAME=%s /sbin/block hotplug", action, devname)); - } + let ret = mkubifs(vol_dev); + if (ret != 0) + return ret; - function ubi_init(ctx) { - cursor = ctx.cursor; - fs = ctx.fs; + uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw"); - let ubiver = read_file("/sys/class/ubi/version"); - if (ubiver != 1) - return false; + let ret = system(sprintf("ubirename /dev/%s \"uvol-wp-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name)); + if (ret != 0) + return ret; - let ubidevpath = null; - for (ubidevpath in fs.glob("/sys/devices/virtual/ubi/*")) - break; + return 0; +} - if (!ubidevpath) - return false; +function ubi_remove(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; - ubidev = fs.basename(ubidevpath); - ebsize = read_file(sprintf("%s/eraseblock_size", ubidevpath)); + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode == "rw" || vol_mode == "ro") + return 16; - uvol_uci_add = ctx.uci_add; - uvol_uci_commit = ctx.uci_commit; - uvol_uci_remove = ctx.uci_remove; - uvol_uci_init = ctx.uci_init; + let volnum = split(vol_dev, "_")[1]; - return true; - } + let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum)); + if (ret != 0) + return ret; - function ubi_free() { - let availeb = read_file(sprintf("/sys/devices/virtual/ubi/%s/avail_eraseblocks", ubidev)); - return sprintf("%d", availeb * ebsize); - } + uvol_uci_remove(vol_name); + uvol_uci_commit(vol_name); - function ubi_align() { - return sprintf("%d", ebsize); - } + return 0; +} - function ubi_total() { - let totaleb = read_file(sprintf("/sys/devices/virtual/ubi/%s/total_eraseblocks", ubidev)); - return sprintf("%d", totaleb * ebsize); - } - - function ubi_status(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode == "wo") return 22; - if (vol_mode == "wp") return 16; - if (vol_mode == "wd") return 1; - if (vol_mode == "ro" && - !fs.access(sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "r")) return 1; +function ubi_up(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode == "rw" || vol_mode == "ro") return 0; - } + else if (vol_mode == "wo") + return 22; + else if (vol_mode == "wp") + return 16; - function ubi_size(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - let vol_size = read_file(sprintf("/sys/devices/virtual/ubi/%s/%s/data_bytes", ubidev, vol_dev)); - return sprintf("%d", vol_size); - } - - function ubi_device(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode == "ro") - return sprintf("/dev/ubiblock%s", substr(vol_dev, 3)); - else if (vol_mode == "rw") - return sprintf("/dev/%s", vol_dev); - - return null; - } - - function ubi_create(vol_name, vol_size, vol_mode) { - let vol_dev = ubi_get_dev(vol_name); - if (vol_dev) - return 17; - - let mode; - if (vol_mode == "ro" || vol_mode == "wo") - mode = "wo"; - else if (vol_mode == "rw") - mode = "wp"; - else - return 22; - - let vol_size = +vol_size; - if (vol_size <= 0) - return 22; - let ret = system(sprintf("ubimkvol /dev/%s -N \"uvol-%s-%s\" -s %d", ubidev, mode, vol_name, vol_size)); + uvol_uci_commit(vol_name); + if (vol_mode == "rd") { + let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name)); if (ret != 0) return ret; - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - let ret = system(sprintf("ubiupdatevol -t /dev/%s", vol_dev)); + return system(sprintf("ubiblock --create /dev/%s", vol_dev)); + } else if (vol_mode == "wd") { + let ret = system(sprintf("ubirename /dev/%s \"uvol-wd-%s\" \"uvol-rw-%s\"", ubidev, vol_name, vol_name)); if (ret != 0) return ret; - if (mode != "wp") - return 0; + return block_hotplug("add", vol_dev); + } + return 0; +} - let ret = mkubifs(vol_dev); - if (ret != 0) - return ret; - - uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw"); - - let ret = system(sprintf("ubirename /dev/%s \"uvol-wp-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name)); - if (ret != 0) - return ret; +function ubi_down(vol_name) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode == "rd" || vol_mode == "wd") return 0; + else if (vol_mode == "wo") + return 22; + else if (vol_mode == "wp") + return 16; + else if (vol_mode == "ro") { + system(sprintf("umount /dev/ubiblock%s 2>&1 >/dev/null", substr(vol_dev, 3))); + system(sprintf("ubiblock --remove /dev/%s", vol_dev)); + let ret = system(sprintf("ubirename /dev/%s \"uvol-ro-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name)); + return ret; + } else if (vol_mode == "rw") { + system(sprintf("umount /dev/%s 2>&1 >/dev/null", vol_dev)); + let ret = system(sprintf("ubirename /dev/%s \"uvol-rw-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name)); + block_hotplug("remove", vol_dev); + return ret; } + return 0; +} - function ubi_remove(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; +function ubi_list(search_name) { + let volumes = []; + for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { + let vol = {}; + let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); + if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*")) + continue; - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode == "rw" || vol_mode == "ro") - return 16; + let vol_mode = substr(vol_ubiname, 5, 2); + let vol_name = substr(vol_ubiname, 8); + let vol_size = read_file(sprintf("%s/data_bytes", vol_dir)); + if (substr(vol_name, 0, 1) == ".") + continue; - let volnum = split(vol_dev, "_")[1]; - - let ret = system(sprintf("ubirmvol /dev/%s -n %d", ubidev, volnum)); - if (ret != 0) - return ret; - - uvol_uci_remove(vol_name); - uvol_uci_commit(vol_name); - - return 0; + vol.name = vol_name; + vol.mode = vol_mode; + vol.size = vol_size; + push(volumes, vol); } + return volumes; +} - function ubi_up(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; +function ubi_detect() { + let tmpdev = []; + for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { + let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode == "rw" || vol_mode == "ro") - return 0; - else if (vol_mode == "wo") - return 22; - else if (vol_mode == "wp") - return 16; + if (!wildcard(vol_ubiname, "uvol-r[od]-*")) + continue; - uvol_uci_commit(vol_name); - if (vol_mode == "rd") { - let ret = system(sprintf("ubirename /dev/%s \"uvol-rd-%s\" \"uvol-ro-%s\"", ubidev, vol_name, vol_name)); - if (ret != 0) - return ret; + let vol_name = substr(vol_ubiname, 8); + let vol_mode = substr(vol_ubiname, 5, 2); + let vol_dev = fs.basename(vol_dir); - return system(sprintf("ubiblock --create /dev/%s", vol_dev)); - } else if (vol_mode == "wd") { - let ret = system(sprintf("ubirename /dev/%s \"uvol-wd-%s\" \"uvol-rw-%s\"", ubidev, vol_name, vol_name)); - if (ret != 0) - return ret; - - return block_hotplug("add", vol_dev); - } - return 0; - } - - function ubi_down(vol_name) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode == "rd" || vol_mode == "wd") - return 0; - else if (vol_mode == "wo") - return 22; - else if (vol_mode == "wp") - return 16; - else if (vol_mode == "ro") { - system(sprintf("umount /dev/ubiblock%s 2>&1 >/dev/null", substr(vol_dev, 3))); - system(sprintf("ubiblock --remove /dev/%s", vol_dev)); - let ret = system(sprintf("ubirename /dev/%s \"uvol-ro-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name)); - return ret; - } else if (vol_mode == "rw") { - system(sprintf("umount /dev/%s 2>&1 >/dev/null", vol_dev)); - let ret = system(sprintf("ubirename /dev/%s \"uvol-rw-%s\" \"uvol-wd-%s\"", ubidev, vol_name, vol_name)); - block_hotplug("remove", vol_dev); - return ret; - } - return 0; - } - - function ubi_list(search_name) { - let volumes = []; - for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { - let vol = {}; - let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*")) - continue; - - let vol_mode = substr(vol_ubiname, 5, 2); - let vol_name = substr(vol_ubiname, 8); - let vol_size = read_file(sprintf("%s/data_bytes", vol_dir)); - if (substr(vol_name, 0, 1) == ".") - continue; - - vol.name = vol_name; - vol.mode = vol_mode; - vol.size = vol_size; - push(volumes, vol); - } - return volumes; - } - - function ubi_detect() { - let tmpdev = []; - for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { - let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - - if (!wildcard(vol_ubiname, "uvol-r[od]-*")) - continue; - - let vol_name = substr(vol_ubiname, 8); - let vol_mode = substr(vol_ubiname, 5, 2); - let vol_dev = fs.basename(vol_dir); - - ret = system(sprintf("ubiblock --create /dev/%s", vol_dev)); - if (ret) - continue; - - if (vol_mode == "rd") - push(tmpdev, vol_dev); - } - - uvol_uci_init(); - - for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { - let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*")) - continue; - - let vol_dev = fs.basename(vol_dir); - let vol_name = substr(vol_ubiname, 8); - let vol_mode = substr(vol_ubiname, 5, 2); - - if (vol_mode == "ro" || vol_mode == "rd") - uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro"); - else if (vol_mode == "rw" || vol_mode == "wd") - uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw"); - } - - uvol_uci_commit(); - - for (vol_dev in tmpdev) - system(sprintf("ubiblock --remove /dev/%s", vol_dev)); - - return 0; - } - - function ubi_boot() { - for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { - let vol_dev = fs.basename(vol_dir); - let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); - - if (!wildcard(vol_ubiname, "uvol-ro-*")) - continue; - - system(sprintf("ubiblock --create /dev/%s", vol_dev)); - } - } - - function ubi_write(vol_name, write_size) { - let vol_dev = ubi_get_dev(vol_name); - if (!vol_dev) - return 2; - - write_size = +write_size; - if (write_size <= 0) - return 22; - - let vol_mode = vol_get_mode(vol_dev); - if (vol_mode != "wo") - return 22; - - let ret = system(sprintf("ubiupdatevol -s %s /dev/%s -", write_size, vol_dev)); + ret = system(sprintf("ubiblock --create /dev/%s", vol_dev)); if (ret) - return ret; + continue; + + if (vol_mode == "rd") + push(tmpdev, vol_dev); + } + + uvol_uci_init(); + + for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { + let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); + if (!wildcard(vol_ubiname, "uvol-[rw][wod]-*")) + continue; + + let vol_dev = fs.basename(vol_dir); + let vol_name = substr(vol_ubiname, 8); + let vol_mode = substr(vol_ubiname, 5, 2); + + if (vol_mode == "ro" || vol_mode == "rd") + uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro"); + else if (vol_mode == "rw" || vol_mode == "wd") + uvol_uci_add(vol_name, sprintf("/dev/%s", vol_dev), "rw"); + } + + uvol_uci_commit(); + + for (vol_dev in tmpdev) + system(sprintf("ubiblock --remove /dev/%s", vol_dev)); + + return 0; +} + +function ubi_boot() { + for (vol_dir in fs.glob(sprintf("/sys/devices/virtual/ubi/%s/%s_*", ubidev, ubidev))) { + let vol_dev = fs.basename(vol_dir); + let vol_ubiname = read_file(sprintf("%s/name", vol_dir)); + + if (!wildcard(vol_ubiname, "uvol-ro-*")) + continue; system(sprintf("ubiblock --create /dev/%s", vol_dev)); - uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro"); - system(sprintf("ubiblock --remove /dev/%s", vol_dev)); - system(sprintf("ubirename /dev/%s \"uvol-wo-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name)); - - return 0; } +} - backend.backend = "UBI"; - backend.priority = 20; - backend.init = ubi_init; - backend.boot = ubi_boot; - backend.detect = ubi_detect; - backend.free = ubi_free; - backend.align = ubi_align; - backend.total = ubi_total; - backend.list = ubi_list; - backend.size = ubi_size; - backend.status = ubi_status; - backend.device = ubi_device; - backend.up = ubi_up; - backend.down = ubi_down; - backend.create = ubi_create; - backend.remove = ubi_remove; - backend.write = ubi_write; -%} +function ubi_write(vol_name, write_size) { + let vol_dev = ubi_get_dev(vol_name); + if (!vol_dev) + return 2; + + write_size = +write_size; + if (write_size <= 0) + return 22; + + let vol_mode = vol_get_mode(vol_dev); + if (vol_mode != "wo") + return 22; + + let ret = system(sprintf("ubiupdatevol -s %s /dev/%s -", write_size, vol_dev)); + if (ret) + return ret; + + system(sprintf("ubiblock --create /dev/%s", vol_dev)); + uvol_uci_add(vol_name, sprintf("/dev/ubiblock%s", substr(vol_dev, 3)), "ro"); + system(sprintf("ubiblock --remove /dev/%s", vol_dev)); + system(sprintf("ubirename /dev/%s \"uvol-wo-%s\" \"uvol-rd-%s\"", ubidev, vol_name, vol_name)); + + return 0; +} + +backend.backend = "UBI"; +backend.priority = 20; +backend.init = ubi_init; +backend.boot = ubi_boot; +backend.detect = ubi_detect; +backend.free = ubi_free; +backend.align = ubi_align; +backend.total = ubi_total; +backend.list = ubi_list; +backend.size = ubi_size; +backend.status = ubi_status; +backend.device = ubi_device; +backend.up = ubi_up; +backend.down = ubi_down; +backend.create = ubi_create; +backend.remove = ubi_remove; +backend.write = ubi_write; diff --git a/utils/uvol/files/uci.uc b/utils/uvol/files/uci.uc index 24589ca4cb..be3bae1363 100644 --- a/utils/uvol/files/uci.uc +++ b/utils/uvol/files/uci.uc @@ -1,4 +1,3 @@ -{% // SPDX-License-Identifier: GPL-2.0-or-later // UCI tools for uvol // (c) 2022 Daniel Golle @@ -136,4 +135,3 @@ uvol_uci = { return 0; } }; -%} diff --git a/utils/uvol/files/uvol b/utils/uvol/files/uvol index f89b96687e..692606895f 100644 --- a/utils/uvol/files/uvol +++ b/utils/uvol/files/uvol @@ -1,13 +1,9 @@ #!/usr/bin/ucode -{% // SPDX-License-Identifier: GPL-2.0-or-later // uvol - storage volume manager for OpenWrt // (c) 2022 Daniel Golle - function help() { - %} -uvol storage volume manager - +let help_output = "uvol storage volume manager syntax: uvol command ... commands: @@ -29,102 +25,101 @@ commands: 1 - volume is not ready for use 2 - volume doesn'y exist write volname size write to volume from stdin, size in bytes -{% +" + +function help() { + printf("%s", help_output); +); + +let fs = require("fs"); +let uci = require("uci"); +let cursor = uci ? uci.cursor() : null; + +let ctx = {}; +ctx.cursor = cursor; +ctx.fs = fs; +include("/usr/lib/uvol/uci.uc"); +ctx.uci_add = uvol_uci.uvol_uci_add; +ctx.uci_remove = uvol_uci.uvol_uci_remove; +ctx.uci_commit = uvol_uci.uvol_uci_commit; +ctx.uci_init = uvol_uci.uvol_uci_init; + +let backend = null; +let tried_backends = []; +for (plugin in fs.glob("/usr/lib/uvol/backends/*.uc")) { + let current_backend = {}; + include(plugin, { backend: current_backend }); + push(tried_backends, current_backend.backend); + if (type(backend) == "object" && + type(backend.priority) == "int" && + type(current_backend.priority) == "int" && + backend.priority > current_backend.priority) + continue; + if (type(current_backend.init) == "function" && + current_backend.init(ctx)) { + backend = current_backend; + break; } +} - let fs = require("fs"); - let uci = require("uci"); - let cursor = uci ? uci.cursor() : null; +if (!backend) { + printf("No backend available. (tried: %s)\n", join(" ", tried_backends)); + printf("To setup devices with block storage install 'autopart'.\n"); + exit(2); +} - let ctx = {}; - ctx.cursor = cursor; - ctx.fs = fs; - include("/usr/lib/uvol/uci.uc"); - ctx.uci_add = uvol_uci.uvol_uci_add; - ctx.uci_remove = uvol_uci.uvol_uci_remove; - ctx.uci_commit = uvol_uci.uvol_uci_commit; - ctx.uci_init = uvol_uci.uvol_uci_init; +let cmd = shift(ARGV); - let backend = null; - let tried_backends = []; - for (plugin in fs.glob("/usr/lib/uvol/backends/*.uc")) { - let current_backend = {}; - include(plugin, { backend: current_backend }); - push(tried_backends, current_backend.backend); - if (type(backend) == "object" && - type(backend.priority) == "int" && - type(current_backend.priority) == "int" && - backend.priority > current_backend.priority) - continue; +if (!cmd || cmd == "-h" || cmd == "help") { + help(); + return cmd?0:22; +} - if (type(current_backend.init) == "function" && - current_backend.init(ctx)) { - backend = current_backend; - break; - } - } - - if (!backend) { - printf("No backend available. (tried: %s)\n", join(" ", tried_backends)); - printf("To setup devices with block storage install 'autopart'.\n"); - exit(2); - } +if (!(cmd in keys(backend))) { + printf("command %s not found\n", cmd); + return 22; +} +let json_output = false; +if (ARGV[0] == "-j") { + json_output = true; shift(ARGV); - shift(ARGV); - let cmd = shift(ARGV); +} - if (!cmd || cmd == "-h" || cmd == "help") { - help(); - return cmd?0:22; - } - - if (!(cmd in keys(backend))) { - printf("command %s not found\n", cmd); - return 22; - } - - let json_output = false; - if (ARGV[0] == "-j") { - json_output = true; - shift(ARGV); - } - - let legacy_output = function(var) { - let out = ""; - if (type(var) == "array") { - for (let line in var) { - out += join(" ", values(line)); - out += "\n"; - } - } else if (type(var) == "object") { +let legacy_output = function(var) { + let out = ""; + if (type(var) == "array") { + for (let line in var) { out += join(" ", values(line)); out += "\n"; } - return out; - }; + } else if (type(var) == "object") { + out += join(" ", values(line)); + out += "\n"; + } + return out; +}; - if (type(backend[cmd]) == "string") { - printf("%s\n", backend[cmd]); - } else if (type(backend[cmd]) == "function") { - let ret = backend[cmd](...ARGV); - if (type(ret) == "int") - exit(ret); +if (type(backend[cmd]) == "string") { + printf("%s\n", backend[cmd]); +} else if (type(backend[cmd]) == "function") { + let ret = backend[cmd](...ARGV); + if (type(ret) == "int") + exit(ret); - if (type(ret) == "string") { - printf("%s\n", ret); - } else { - if (json_output) - printf("%.J\n", ret); - else - printf("%s", legacy_output(ret)); - } + if (type(ret) == "string") { + printf("%s\n", ret); } else { if (json_output) - printf("%.J\n", backend[cmd]); + printf("%.J\n", ret); else - printf("%s\n", legacy_output(backend[cmd])); + printf("%s", legacy_output(ret)); } +} else { + if (json_output) + printf("%.J\n", backend[cmd]); + else + printf("%s\n", legacy_output(backend[cmd])); +} - return 0; -%} +exit(0);