Hi Ludo, >It’s the ‘net-base’ package—see ‘operating-system-etc-service’.
Thanks! >> Thanks. I found it--and it syncs *before* unmounting. Why? >In case umount(2) fails. That makes sense. I've read through the relevant parts of the Linux kernel and it seems like this: the buffer cache (which is what "sync" syncs) is being used by the block device layer: whoever opened /dev/sda1 or /dev/mapper/xxx or whatever block device, whether that's user space or a file system, will have blocks cached into RAM instead of written to disk immediately ("writeback"). I think this means that if umount never puts its stuff into the block device, then no matter how many syncs you do, it won't help: the buffer cache is already empty, because the filesystem never put stuff (its own pending stuff etc) in there. I wasn't previously aware how terrible not being able to remount ro / is... O_O But the implementation of umount in the Linux kernel also calls the equivalent of "sync", somewhere around function "deactivate_super" (that means very, very, late)--see below. (But even if would call it earlier, that wouldn't have helped) int sync_filesystem(struct super_block *sb) { /* ... checks ... */ [...] /* * No point in starting writeback when the filesystem is read-only. */ if (sb_rdonly(sb)) return 0; trace_writeback_sync_filesystem(sb); <--- aha !! /* Write back inodes */ writeback_inodes_sb(sb, WB_REASON_SYNC); // <--- Write back dirty inodes/metadata /* Write back pages */ sync_mapping_buffers(sb->s_bdev->bd_inode->i_mapping); // <--- Sync block device buffers sync_mapping_buffers(sb->s_inode->i_mapping); // <--- Sync superblock inode buffers (if any) /* Wait for writeback */ return __sync_filesystem(sb, true); // <--- Wait for I/O completion } What our earlier "sync" call also causes is when write to the raw block device without a filesystem (for example grub-install does that sometimes), that is synced as well. >Not random: see ‘herd status log-rotation’ and this: > > https://www.gnu.org/software/shepherd/manual/html_node/Log-Rotation-Service.html Thanks. That's neat :D Also, I'd like to add some debugging stuff for next time. What do you think about something like the following? Right now, it probably doesn't work because stdin and stdout and stderr are closed already. We'd have to open /dev/tty (mode "rw") manually and have the child process put stuff there. If /dev is still there, hmm. I guess we could do (mknod) ourselves. Note: with-io-file is made-up, what's the correct incantation? call-with-input-file and a nested call-with-output-file ? diff --git i/gnu/services/base.scm w/gnu/services/base.scm index 8c6563c99d..77e397139e 100644 --- i/gnu/services/base.scm +++ w/gnu/services/base.scm @@ -369,6 +369,23 @@ (define %root-file-system-shepherd-service #:update-mtab? #f) #t) (const #f)) + (when (zero? n) + (catch 'system-error + (mknod "/tty" 'char-special #o600 (+ (* 5 256) 0)) + (const #f)) + (with-io-file "/tty" + (system* "/run/booted-system/profile/bin/fuser" "-vikm" "/")) + (unless (catch 'system-error + (lambda () + (mount #f "/" #f + (logior MS_REMOUNT MS_RDONLY) + #:update-mtab? #f) + #t) + (const #f)) + (with-io-file "/tty" + (display "umount / still not good\n") + (force-output))) + ((@ (fibers) sleep) 10)) (unless (zero? n) ;; Yield to the other fibers. That gives logging fibers ;; an opportunity to close log files so the 'mount' call