mv is implemented as a simple rename() whenever possible, falling back to copy-then-delete whenever renaming doesn't work. In practice (but not in theory), these two cases correspond to source and destination being on the same or on different filesystems, respectively.

My question: Does mv, as defined by the POSIX standard and implemented as part of the GNU coreutils, make any guarantee that in the latter case (i.e. rename not possible, fall back to copy-then-delete), filesystem caches are flushed (in the sense of sync) between the copy and delete operation so that disconnecting the destination filesystem at just the right moment won't lead to data loss?

What I've found so far: The POSIX spec for mv says that

termination at any point shall leave either source_file or the destination path complete

which would suggest "yes", but then I'm not sure whether disconnecting a filesystem would be classed as simple "termination" or not, whether such statements in general only apply to the "surface" filesystem state, and so on.

There is a Hacker News comment answering "no" but not citing any sources.

Maybe the question is actually ill-defined because POSIX sync() does not even guarantee completion of the flush, only triggering it, so there is no way to implement a "completely safe" copy-then-delete across filesystems anyway?

I tried to find out how it's actually implemented in GNU coreutils' mv's source code, but before I waste any more time on this and in the interest of anyone else with the same question, I thought I'd ask here, too.

  • I think you need to make a difference between "on storage medium" and "userland visible"; sync flushes in-kernel caches to disk. However, the moment some write operation is in that cache, a read operation would already yield the cached value. So the question really is whether the copy operation is userland-wise done before the unlink happens Aug 29, 2022 at 23:03
  • 1
    @MarcusMüller That's what I was trying to get at with "surface filesystem state", I just didn't know the correct terminology. If that sentence in the standard only applies to the userland-visible state, I guess the answer to my question would be "no". I'm not sure what you mean by your last sentence - userland-wise the copy is definitely completed before the unlink happens. The cache flush question is the only ambiguous part.
    – smheidrich
    Aug 29, 2022 at 23:23
  • mv doesn't flush anything when it's copying data. sync at least in Linux does indeed flush data, only there's no way of knowing when it completes - it only asks the kernel to do that. Aug 30, 2022 at 9:01
  • 1
    @ArtemS.Tashkinov How do you figure? Also, as an aside, both the sync() Linux system call and sync GNU coreutils program are guaranteed to flush everything that was in the cache at the time when they were called before returning (from man 2 sync: "Linux waits for I/O completions, and thus sync() or syncfs() provide the same guarantees as fsync() called on every file in the system or filesystem respectively."). The caveat about sync() merely scheduling the flush only applies to its formal POSIX specification.
    – smheidrich
    Aug 30, 2022 at 18:15
  • Thanks, didn't know that. Aug 31, 2022 at 10:52


You must log in to answer this question.

Browse other questions tagged .