I am working on a safe and race-condition-free alternative to umount -l with removable devices:

I'm planning on:

  1. umount --move under a 000 permissions directory so no more files can be opened by absolute path
  2. Interactively kill (or gracefully shutdown) processes with files open for writing
  3. Atomically remount read-only only if step (2) is complete
  4. Interactively kill / close read-only processes that may cause cause issues
  5. Finally have umount succeed

There is a race condition in step (3) where a file with relative path could be opened rw after the last interactive kill and before the mount -o remount,ro.

Is mount -o remount,ro guaranteed to fail if there is any file on the filesystem opened for writing?

The manual page is silent on this, and I'm a bit paranoid after finding out that devices are writable even after blockdev --setro.

  • I have to ask "why?". Why is a plain old umount not good enough for this job? umount is written to be deliberately cautious in order to prevent data loss through premature umounting, and you're throwing those safeguards away - is your reason for doing so good enough to justify that? or is this just satisfying some minor aesthetic itch? – cas Aug 14 '17 at 6:15
  • 1
    Plain umount will only succeed if all open files are closed. I'm generally ok in killing all ro processes, but I first want to investigate and gracefully close any rw processes so as to avoid in-file corruption. I want to avoid new rw processes being created while all that is going on. As it turns out, umount -f won't work on a non-NFS filesystem, so fuser -kM seems to be required for remaining ro processes. – Tom Hale Aug 14 '17 at 7:40
  • I agree with cas, this seems like a lot of effort for something you can do with umount. That does leave the race with new processes, but it’s not as if there’s a gremlin constantly starting processes writing to your removable drive, or at least there shouldn’t be... – Stephen Kitt Aug 14 '17 at 8:08
  • Perhaps I don't understand what you both intend by just using plain umount... Do you mean a fuser -kiM /mountpoint && umount /mountpoint? I am trying to get the advantages of umount --lazy without the non-determinism. – Tom Hale Aug 14 '17 at 8:21
  • 1
    “Using plain umount” in my mind just means “run umount, if it succeeds, good, if it doesn’t, figure out why and try again”. Your putative approach still involves the figuring out part, so I don’t see much point in making it any more complex. – Stephen Kitt Aug 14 '17 at 9:50

Yes. The relevant code is in sb_prepare_remount_readonly (as of Linux 4.0, the code may be organized differently on other versions). The logic is:

  • For each instance of the mount:
    • If that instance is not read-only:
      • Prevent any new writer from registering (MNT_WRITE_HOLD).
      • If there are registered writers, set the error flag (return EBUSY).
  • If there are any files that are removed (inode count = 0) but not yet deleted (still present because the file is open), set the error flag.
  • If the error flag is not set, mark the partition as read-only.
  • For each instance of the mount:
    • Stop preventing writers from registering.

Registered writers are files open for writing as well as ongoing operations that write metadata (mkdir, chmod, etc.). Check out calls to mnt_want_write which is where the count of registered writers is incremented.

The design of the system ensures that a read-only remount is a write registration barrier: if it succeeds then there is no registered writer, in particular there can't be any file open for writing at the time of the remount operation. After the remount, no file can be opened for writing, so there is still no file that's open for writing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.