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 <daniel@makrotopia.org> (cherry picked from commit22d202e3a5
)
This commit is contained in:
parent
27b395871d
commit
3ef5254f4a
6 changed files with 932 additions and 943 deletions
|
@ -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/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
{%
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// LVM2 backend for uvol
|
||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||
|
@ -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;
|
||||
|
|
|
@ -1,378 +1,376 @@
|
|||
{%
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// UBI backend for uvol
|
||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||
//
|
||||
// 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;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
{%
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// UCI tools for uvol
|
||||
// (c) 2022 Daniel Golle <daniel@makrotopia.org>
|
||||
|
@ -136,4 +135,3 @@ uvol_uci = {
|
|||
return 0;
|
||||
}
|
||||
};
|
||||
%}
|
||||
|
|
|
@ -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 <daniel@makrotopia.org>
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue