how to check if root is rw mounted? GNU Linux, kernel >=v5 - Page 1
Forum section: electronics / general

author: DiTBho
author_rank: Super Contributor
timestamp: January 07, 2025, 12:38:32 pm
content: Code:#/bin/bashfunction linea_arg2_get(){#returnans="$2"}function do_fs_mode_get(){local name="$1"local testtest="`cat /proc/mounts | grep $name`"test="`echo $test | awk '{print $1 "\011" tolower(substr($4,0,2))}'`"linea_arg2_get $test# return ans}This bash script works fine but is slow.You won't notice its slowness on a superfast GHz CPU, but you will definitely feel it on a 400 MHz one.In my case, the rb532a is mips32r2@400Mhz.The problems are:the check is part of a procedure that must protect { disk-cache-flush, synchronize, microdrive-park } the read-only filesystem before shutting down the node in case of emergency, e.g. power loss, small battery systemthe check is repeated multiple times by other (bash) scriptsI will probably end up rewriting this check in pure C, just wondering: is there a better way to check if /dev/root is mounted in rw mode?Code:uc-rb532 ~ # cat /proc/mounts/dev/root / xfs rw,noatime,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0none /proc proc rw,relatime 0 0none /sys sysfs rw,relatime 0 0mpme /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0

author: DiTBho
author_rank: Super Contributor
timestamp: January 07, 2025, 12:39:56 pm
content: awk is a nice slug

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 10:18:01 am
content: Code:test="`echo $test | awk '{print $1 "\011" tolower(substr($4,0,2))}'`"just this line takesCode:real 0m1.073suser 0m0.085ssys 0m0.090s

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 10:23:08 am
content: I am also thinking about hacking the Linux kernel to export something in /proc to directly show the { root, others } mount status { ro, rw }.A file for each mounted things, so you don't need to process by { awk, grep, egrep, ... , sed, ... whatever } a file to extract the information you need.This simple check can't take 1 second on rb532ait must take no more than 1/4 of a second!

author: brucehoult
author_rank: Super Contributor
timestamp: January 08, 2025, 10:48:51 am
content: q&d test .. wfm. Tried on x86 and on RISC-V (VisionFive 2)Code:#include <stdio.h>#include <stdlib.h>#include <sys/statvfs.h>int is_mount_rw(const char *path) {struct statvfs stat;// Get filesystem statsif (statvfs(path, &stat) != 0) {perror("statvfs");return -1; // Error occurred}// Check if the filesystem is read-onlyif (stat.f_flag & ST_RDONLY) {return 0; // Mount is read-only}return 1; // Mount is read-write}int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "Usage: %s <mount-point>\n", argv);return EXIT_FAILURE;}const char *mount_point = argv;int rw_status = is_mount_rw(mount_point);if (rw_status == -1) {fprintf(stderr, "Failed to determine the status of %s\n", mount_point);return EXIT_FAILURE;}if (rw_status) {printf("The mount point %s is read-write.\n", mount_point);} else {printf("The mount point %s is read-only.\n", mount_point);}return EXIT_SUCCESS;}

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 12:58:03 pm
content: Quote from: brucehoult on January 08, 2025, 10:48:51 amI hadn't thought of that.This makes it even easier and faster!Thanks!Code refactored for myC, it works on { MIPS5++, MIPS32r2le }Code:uc-rb532 # time ./myfs-mode-direct-get /rwreal 0m0.039suser 0m0.017ssys 0m0.003s

author: Nominal Animal
author_rank: Super Contributor
timestamp: January 08, 2025, 01:44:03 pm
content: Runningawk '$2 == "/" { print (("," $4 ",") ~ /,rw,/) }' /proc/mountsprints 1 if root is mounted read-write, 0 if root is not mounted read-write, and nothing if it cannot determine whether root is mounted read-write or not.I've verified that this works well with GNU awk (gawk) andmawk; mawk being somewhat more light-weight (and often faster) if you are worried about runtime size and speed.

author: MarkL
author_rank: Unknown
timestamp: January 08, 2025, 08:24:35 pm
content: If you're doing this from bash, here is two forms using only bash primitives (does not call out to other programs).Code:#!/bin/bash# Prints root mount status: rw, ro, or nothing if no match.mounts=$(< /proc/mounts)[[ $'\n'"$mounts" =~ $'\n'[^\ ]*' / '[^\ ]*' '(r), ]] && echo "${BASH_REMATCH}"Code:#!/bin/bash# Or here it is as a bash function (only tests for rw).test_root_rw() {## Return status 0 if root is rw, non-zero otherwise#mounts=$(< /proc/mounts)[[ $'\n'"$mounts" =~ $'\n'([^\ ]*)' / '[^\ ]*' rw,' ]] && return 0return 1}# Usage...#if test_root_rw; thenecho "root is rw"elseecho "root is not rw"fi

author: brucehoult
author_rank: Super Contributor
timestamp: January 08, 2025, 09:59:09 pm
content: Quote from: DiTBho on January 08, 2025, 12:58:03 pmConfession: I simply asked ChatGPT "How to check from C code if a Linux mount is rw?" and got exactly the above. Gave it a quick code review -- as I would if an intern tried to merge it into my project --- and it LGTM. So there you are.I would not suggest using code from an LLM without reviewing it first, but that definitely saved time.

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 10:12:54 pm
content: Quote from: brucehoult on January 08, 2025, 09:59:09 pmI don't have an account and, to be honest, I don't like any public ChatGPT.I will probably buy a GPU(1) with 24 GB of VRAM (> 2000 euros) in the near future at least to dedicate to LLM.This, to have my personal AI assistant at home.In the meantime, I just bought a UNIX programming book.Second hand, on Amazon. 25 euros.It will teach things I don't know, that I don't remember.(1)NVIDIA Jetson-something?AMD-GPU + RISC-V SBC?We will see ...

author: amyk
author_rank: Super Contributor
timestamp: January 08, 2025, 10:17:12 pm
content: Code:touch /tmp.txt

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 10:21:16 pm
content: Quote from: MarkL on January 08, 2025, 08:24:35 pmCode:time ./myfs-mode-direct-get---bash-only.shrwreal 0m0.119suser 0m0.037ssys 0m0.020sfaster than bash+awk, but slower than the C version

author: DiTBho
author_rank: Super Contributor
timestamp: January 08, 2025, 10:26:09 pm
content: Quote from: Nominal Animal on January 08, 2025, 01:44:03 pmI am using sys-apps/gawk v3.1.6, ~2009, mips32r2 stage4, compiled by gcc v4.1.2, glibcIronically all the last 2024/12 stage3-s have sys-apps/gawk >=v5.1.1, compiled by gcc v12.0, still glibc, but on the rb532 are 10% slower.Which .... is weird.I should try uclibc and MUSL versions ...

author: brucehoult
author_rank: Super Contributor
timestamp: January 08, 2025, 10:51:11 pm
content: Quote from: DiTBho on January 08, 2025, 10:18:01 amJust for fun, I tried this on a JavaScript RISC-V emulation running Fedora 33 in the Chrome web browser on my M1 Mac Mini.https://bellard.org/jslinux/vm.html?cpu=riscv64&url=fedora33-riscv.cfg&mem=2560.196s vs your 1.073sThe C code takes 0.029s vs your 0.039sThat MIPS is quite the slug!

author: MarkL
author_rank: Unknown
timestamp: January 08, 2025, 11:05:23 pm
content: Quote from: DiTBho on January 08, 2025, 10:21:16 pmWell, I doubt anything is going to beat the C version. I was just proffering something that would be a little more speedy by not exec'ing anything like awk etc, and not require the building of an executable. Regex is never going to be the zippiest solution but it does seem to meet your requirement of 1/4 second or less.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 08, 2025, 11:54:35 pm
content: It doesn't seem to have been mentioned, unless I missed it, so here is an alternative.If you have util-linux installed, you should have the 'findmnt' utility.The following options will give you the mount options of / (root).Code:$ findmnt -o OPTIONS -n /rw,relatimeCode:time findmnt -o OPTIONS -n /rw,relatimereal 0m0,002suser 0m0,002ssys 0m0,000s

author: brucehoult
author_rank: Super Contributor
timestamp: January 09, 2025, 12:05:05 am
content: Quote from: SiliconWizard on January 08, 2025, 11:54:35 pmYeah, but that's only theawk '$2 == "/" {print $4}' /proc/mountspart, which on that Javascript emulator is the same 0.12s as yourfindmntYou still need to parse out therwfrom the mount options, which if you're already in awk is faster to do there.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 09, 2025, 12:25:13 am
content: As the question was to find if it was rw mounted, just pipe it to 'grep rw', which is much faster. Then just test the exit status. 0 if it's mounted rw, 1 if not.Code:$time findmnt -o OPTIONS -n / | grep rwrw,relatimereal 0m0,002suser 0m0,003ssys 0m0,000sYou can test the exit code in bash with '$?'.Just many ways to skin a cat. The benefit of using findmnt with the above options is that it directly gives you the mount options of root. No need to further process the output except just with looking for "rw", which is very fast.

author: brucehoult
author_rank: Super Contributor
timestamp: January 09, 2025, 01:03:51 am
content: Quote from: SiliconWizard on January 09, 2025, 12:25:13 amStart a whole extra process? On the Javascript RISC-V emulator that takes the execution time from 0.12s to 0.16s. It will be more like 0.3s on OP's slow MIPS.Just adding asplitinto the awk makes no perceptible difference to the execution time.Code:time awk '$2 == "/" {split($4,a,","); print a}' /proc/mountsrwreal 0m0.118suser 0m0.020ssys 0m0.103sThe same goes for setting an exit codeexit a == "rw"instead of print .. in fact faster. And, finally, you can also for essentially zero cost read the "/" from something like ENVIRON["dir"] instead of hard coding it.Code:dir=/ awk '$2 == ENVIRON["dir"] {split($4,a,","); exit a == "rw"}' /proc/mountsQuoteIndeed many ways to skin a cat, and if it's taking 0.002s on your fast PC  then you probably don't care, but every extra process in the pipeline costs a lot of time on a machine as slow as DiTBho's where you're rapidly getting into whole seconds. as it does on my i9, but it's 0.014 on my VisionFive 2 and will be a lot more on a single core 400 MHz MIPS.

author: DiTBho
author_rank: Super Contributor
timestamp: January 09, 2025, 04:03:58 am
content: 400Mhz, 8kb D/I cacheIDT-79RC32H435, made in 20061 instruction per cycle, five stage pipelineNo FPU, softfloat kernel emulation

author: brucehoult
author_rank: Super Contributor
timestamp: January 09, 2025, 05:39:00 am
content: Quote from: DiTBho on January 09, 2025, 04:03:58 amOh wow. I took a look at the µarch.That's *maximum* one instruction per cycle, but there are going be a lot of times that isn't achieved.The TLB setup in particular is very minimal by modern standards, with a 16 entry "JTLB" that generates an exception on a miss, so OS software will then do a software walk of the page table and insert the translation into the JTLB before returning. There are also 3-entry ITLB and DTLB that go at full speed, and cause a 2 cycle delay if an address is accessed that misses in the ITLB or DTLB but is in the JTLB.That's the same kind of structure as modern CPUs, but tiny!For example the Arm A53 has 10 entries each for ITLB and DTLB, and 512 entries in the shared L2 TLB. And hardware refill of the L2 TLB on a miss. SiFive's U74 core (competitor to Arm A53 and A55) has 40 ITLB and 40 DTLB entries and 512 shared L2 TLB entries.AMD Zen2 has 64 L1 TLB entries and 2048 L2 TLB entries.What this means is that on the MIPS 79RC32H435, using 4k pages, the JTLB can cover any 64k of RAM without misses. If you're using more RAM that that then there will be very frequent software interrupts to refill the JTLB.Arm A53 and SiFive U74 on the other hand both cover 2 MB of RAM with their L2 TLBs. U74-MC in e.g. VisionFive 2 also has 2 MB of L2 cache, so that matches quite well. Arm A53 has a maximum of 2 MB of L2 cache, but for example the Pi 3 / Pi Zero 2 have 512k of L2 cache.The 79RC32H435 appears to not have L2 cache, just 8k each of icache and dcache.I don't see anything about branch prediction. I guess there is none, and it's just depending on the MIPS branch delay slot to cover fetching the instruction at the branch target.Sooo ... the 79RC32H435 should be able to run at 1 IPC a lot of the time with carefully written small code and data, but running things such as bash, awk, python etc is going to be spending a LOT of time waiting for TLB and cache misses.

author: DiTBho
author_rank: Super Contributor
timestamp: January 09, 2025, 06:19:55 pm
content: Quote from: brucehoult on January 09, 2025, 05:39:00 amThat's why I ended up wroting an overlay to completely override the default portageI chose the EABI-1 profile, the oldest and simplest possible, cloned 2009-portage and I am replacing all ebuilds with my own "digest" versions, using the minimum USE flags possible and full of patches that remove everything that is not needed, or replacing libraries, tools (today I am working on "lsof_tiny") and programs entirely with things written specifically to be as light as possible with the glibc profile that I can't change.As a further improvement I installed a Crypto processor for the SSH and VPN parts, and a miniPCI network card that "offloads" the checksum functionalities related to the ethernet low level stack, in addition to the fact that it has hw code and manages the network buffers autonomously.20% more performance by recompiling the kernel and the entire openSSH stack, which not only has become smaller since I rely entirely on the hw crypto processor, but consumes much fewer CPU cycles.I think I'm squeezing every possible resource out of that little rb532a router

author: DiTBho
author_rank: Super Contributor
timestamp: January 09, 2025, 06:21:17 pm
content: Quote from: brucehoult on January 09, 2025, 05:39:00 amCorrect, no L2 cache, and no branch prediction.Quote from: brucehoult on January 09, 2025, 05:39:00 amYup, when it was brand-new, back to 2007, it was equipped with a custom OS, based on VxWorks, and Linux v2.4.Both lighter than modern ones by at least two orders of magnitude.e.g. the kernel v2.4 was less than 900Kbyte, while the new kernel v6.02 is 7.4Mbyte!!!The userland was also lighter, whole based on uclibc, which was stable enough in the early 2000s for MIPS.Talking about Gentoo, nowadays the uclibc-MIPS profile is abandoned in a perpetual "extremely experimental", which means completely broken and unusable, so with Catalyst (runs in a Qemu/MIPS VM) I can only resurrect a glibc-one, which is good and very stable on modern routers like the new RBM33G with modern MIPS32r2 dual core stuff, but on the little MIPS of the rb532a it adds 20 times the cache pressure of uclibc-one!Even worse, modern glibc-MIPS-stages are packed with extra features, for example { wget, curl, sync, ... } are pre-configured with "SSL support" to access those damn HTTPs web servers, not to mention the new trend of having Python support in every damn thing. It would be nice to have them if they didn't need to add more code and extra CPU clocks in every program.

author: DiTBho
author_rank: Super Contributor
timestamp: January 09, 2025, 06:22:14 pm
content: Quote from: brucehoult on January 09, 2025, 05:39:00 amYup, that why uclibc-stages run fasterBoth libraries and programs are smaller by a factor of 10 than glibc-ones.So, they can fit into the small cache, or at least generate fewer cache misses.

author: abeyer
author_rank: Frequent Contributor
timestamp: January 09, 2025, 09:49:02 pm
content: Quote from: DiTBho on January 08, 2025, 10:12:54 pmYou might try cpu only on a current cpu with a good amount of ram first, and see how far you get with that. The quality of some of the newer models that are tuned for cpu inference has improved a lot recently, and seems likely to continue that direction. And once you have your software stack set up to run on cpu it's easy enough to add on gpu later.If you are going the gpu route, I'd strongly suggest sticking w/ nvidia for this use case... CUDA is still very much the gold standard for software interfacing, and although AMD hardware is nice, it's just not caught up there yet. Depending on your timeline, it might also make sense to wait for either a 32gb 5090 or the Project DIGITS GB10 machine.

author: DiTBho
author_rank: Super Contributor
timestamp: January 10, 2025, 04:30:27 pm
content: Code:BYTEmark* Native Mode Benchmark ver. 2 (10/95)Index-split by Andrew D. Balsa (11/97)Linux/Unix* port by Uwe F. Mayer (12/96,11/97)TEST : Iterations/sec. : Old Index : New Index: : Pentium 90* : AMD K6/233*--------------------:------------------:-------------:------------NUMERIC SORT : 86.325 : 2.21 : 0.73STRING SORT : 7.2868 : 3.26 : 0.50BITFIELD : 3.2679e+07 : 5.61 : 1.17FP EMULATION : 7.1885 : 3.45 : 0.80FOURIER : 4.5823 : 0.01 : 0.00ASSIGNMENT : 1.4519 : 5.52 : 1.43IDEA : 342.73 : 5.24 : 1.56HUFFMAN : 13.21 : 0.37 : 0.12NEURAL NET : 0.0052957 : 0.01 : 0.00LU DECOMPOSITION : 0.12788 : 0.01 : 0.00==========================ORIGINAL BYTEMARK RESULTS==========================INTEGER INDEX : 2.837FLOATING-POINT INDEX: 0.007Baseline (MSDOS*) : Pentium* 90, 256 KB L2-cache, Watcom* compiler 10.0==============================LINUX DATA BELOW===============================CPU :L2 Cache :OS : Linux 6.2.0-rc2-rb532C compiler : mipsel-unknown-linux-gnu-gcclibc :MEMORY INDEX : 0.946INTEGER INDEX : 0.570FLOATING-POINT INDEX: 0.004Baseline (LINUX) : AMD K6/233*, 512 KB L2-cache, gcc 2.7.2.3, libc-5.4.38* Trademarks are property of their respective holder.It doesn't have much validity as a benchmark.But it gives you an idea more or less of what type of hardware you're working with.

author: brucehoult
author_rank: Super Contributor
timestamp: January 10, 2025, 10:16:37 pm
content: BYTEmark was well known, even in the 80s, as having several benchmarks that were not very suitable because a good compiler would either do a lot of the work at compile-time (e.g. in the case of BITFIELD merging loops to do things word at a time instead of bit at a time IIRC) or noticing that results were not used at all and simply deleting them.

author: DiTBho
author_rank: Super Contributor
timestamp: January 11, 2025, 04:05:36 pm
content: Quote from: brucehoult on January 10, 2025, 10:16:37 pmI think it only makes sense comparing machines with the same toolchains, GNU/Linux { gcc, binutils }.

author: macboy
author_rank: Super Contributor
timestamp: January 14, 2025, 06:34:41 pm
content: If you want it to run even faster, don't make it a script, but a function within your shell. Then when you call it, you are not spawning a new process to execute a new shell to run the script. Your interactive shell just does the work itself. This will be faster.You can put a function, or many of them, into a file (e.g. "myFunctions.sh") and source the file, which essentially executes all commands in the file. In bash, you source a file with the command "."e.g.:. myFunctions.shI do like MarkL's take on the problem, but if you are not a regex expert (a regexpert?) then it can be hard to follow. Here is what I had come up with:Code:function do_fs_mode_get(){while read a b c d e fdoif [ "$a" = "$1" ]thenecho "FS: $a mode: ${d%%,*}"return 0fidone < /proc/mountsreturn 1}