4

I am under the belief that if you mv a file from an ext4 partition to itself, this is done instantly in constant time by updating directory entries and keeping the inode the same.

Instead, sometimes I am observing that the whole (30GB) file is being copied, then the original removed.

Why might this be happening?

1
  • 7
    Can you replicate the problem reliably and describe, so we can replicate it too? Is this under a single mountpoint? Are project IDs involved? Commented Mar 13, 2022 at 10:53

1 Answer 1

3

The mv command is calling rename() internally, and rename within a single filesystem mountpoint is only changing the name entry (either in the same directory or moving the name from one directory to another).

However, in some cases rename() will return EXDEV ("cross device link error") to the caller, and in this case mv will fall back to make a copy of the file (or entire directory tree) at the new location and delete the file/directory at the old location afterward.

The most common reason for rename() returning EXDEV is because the source and target directory of the rename() call are in different filesystems, of possibly different mountpoints of the same filesystem. If project quotas are in use (run "lsattr -p" on the source file/dir and target dir to check) and the source/target are using different project IDs, then EXDEV is also returned to userspace and it is up to mv to make a copy of the file/directory tree at the target and to change the projid to match the new parent.

The reason that different project IDs on the source and target directory trigger a copy instead of just updating the project ID directly in rename() is because this can become far too complex to handle atomically within the kernel, if there is a whole directory tree that needs the projid to be changed. There might be thousands or millions of files that need to be updated in this case. That said, the projid update could be done directly within rename() when renaming a single file, but this is not yet implemented in the ext4 code.

If you know project IDs are involved, you can avoid the "fallback copy" of a large file or directory tree by "pre-changing" the project ID of the source file(s)/directory tree to match the target projid. Run "chattr -R -p <target_projid> " before using "mv", so that the source and target projid are the same, then rename() should work without returning EXDEV and will not trigger the copy.

2
  • 1
    Also note that if you have the same filesystem mounted multiple places that will trigger a copy too even though technically they're on the same filesystem. Commented Mar 13, 2022 at 23:46
  • 1
    @CR. I think this is the explanation -- there is a bind mount in fstab, and moving to the bind-mounted location causes this behaviour. Commented Mar 14, 2022 at 14:57

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.