GNU bug report logs - #34713
Files vanishing when moving to different FS

Previous Next

Package: coreutils;

Reported by: Christoph Michelbach <michelbach94 <at> gmail.com>

Date: Sat, 2 Mar 2019 22:12:02 UTC

Severity: normal

Tags: notabug

Done: Bob Proulx <bob <at> proulx.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 34713 in the body.
You can then email your comments to 34713 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#34713; Package coreutils. (Sat, 02 Mar 2019 22:12:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Christoph Michelbach <michelbach94 <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Sat, 02 Mar 2019 22:12:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Christoph Michelbach <michelbach94 <at> gmail.com>
To: bug-coreutils <at> gnu.org
Subject: Files vanishing when moving to different FS
Date: Sat, 02 Mar 2019 23:10:51 +0100
To reproduce this bug, you need two different file systems. Adapt the
paths to fit your system.

Set the experimental file structure up like this:

mkdir exp
cd exp
mkdir a
cd a
touch a{1..100000}
cd ..
mkdir b
cd b
touch b{1..10000}
mkdir /t/ae # /t has to be on a different file system

Then have two terminals open in the exp directory created above. In
one, execute this command:

mv a /t/ae

In the other, execute this one while the one in the first terminal
still is running (hence the large number of files so you have time to
do this):

mv b/* a

You will end up with 100 000 files in /t/ae. The 10 000 files beginning
with the letter b will be gone.

-- 
Christoph Michelbach <michelbach94 <at> gmail.com>





Information forwarded to bug-coreutils <at> gnu.org:
bug#34713; Package coreutils. (Mon, 04 Mar 2019 18:34:02 GMT) Full text and rfc822 format available.

Message #8 received at 34713 <at> debbugs.gnu.org (full text, mbox):

From: Bob Proulx <bob <at> proulx.com>
To: Christoph Michelbach <michelbach94 <at> gmail.com>
Cc: 34713 <at> debbugs.gnu.org
Subject: Re: bug#34713: Files vanishing when moving to different FS
Date: Mon, 4 Mar 2019 11:33:13 -0700
tags 34713 notabug
close 34713
thanks

Hello Christoph,

Christoph Michelbach wrote:
> To reproduce this bug, you need two different file systems. Adapt the
> paths to fit your system.

Thank you for making this bug report.  However what you are
experiencing is due to the race condition created by the non-atomic
nature of copying files from one file system to another, removing
files, and renaming files.  This is not a bug in mv but is an
intrinsic behavior.

> Set the experimental file structure up like this:
> 
> mkdir exp
> cd exp
> mkdir a
> cd a
> touch a{1..100000}
> cd ..
> mkdir b
> cd b
> touch b{1..10000}
> mkdir /t/ae # /t has to be on a different file system

Thank you for the very nice test case.

> Then have two terminals open in the exp directory created above.

This is a clue to the nature of the problem being a race condition.
It describes simultaneous parallel processes.

> In one, execute this command:
> 
> mv a /t/ae

Because /t is on a different file system mv cannot simply rename the
files but must perform the action in two steps.  It copies the file
from source to destination.  It removes source file.  This is
documented in the mv with:

    'mv' can move any type of file from one file system to another.
    Prior to version '4.0' of the fileutils, 'mv' could move only
    regular files between file systems.  For example, now 'mv' can
    move an entire directory hierarchy including special device files
    from one partition to another.  It first uses some of the same
    code that's used by 'cp -a' to copy the requested directories and
    files, then (assuming the copy succeeded) it removes the
    originals.  If the copy fails, then the part that was copied to
    the destination partition is removed.  If you were to copy three
    directories from one partition to another and the copy of the
    first directory succeeded, but the second didn't, the first would
    be left on the destination partition and the second and third
    would be left on the original partition.

The mv a /t/ae action is similar to cp -a a t/ae && rm -r a when the
action is successful.  Similar because there are two steps happening.
A first step with the copy and a second step with the removal and
there is a time skew between those actions.

> In the other, execute this one while the one in the first terminal
> still is running (hence the large number of files so you have time to
> do this):
> 
> mv b/* a

This is the second part of the race condition.  It it moving files
into the a directory at the same time that files are being copied out
of the directory and the directory itself being removed.

> You will end up with 100 000 files in /t/ae. The 10 000 files beginning
> with the letter b will be gone.

Look at the two actions explicitly:

Process 1:
  cp -a a /t/ae
  rm -rf a

Process 2:
  mv b/* a

Now it is more obvious that as soon as the first process copy finishes
that it will remove the source location, that is having files moved
into it by the second process, that the directory will be deleted by
the first process.

Does that make it easier to understand what is happening?

The copy and remove two actions do not occur when both the source and
destination are on the same file system.  In that case the file can be
renamed atomically without doing a copy.  But when the action is
across two file systems this is not possible and it is simulated (or
perhaps emulated) by the copy and remove two step action.

Whenever tasks are moving files into and out of the same directory at
the same time this is always something to be aware of regardless
because they may be an overlap of actions in that directory.

In this particular example the problem can be avoided by renaming "a"
first and then transfering the files to the other file system.
Because it was removed then the second process can create it without
collision.  Something like this pseudo-code.  However to safely use
temporary file names will require more code than this.  This is simply
for illustration purposes.

Process 1:
  mv a tmpdirname
  cp -a tmpdirname /t/ae
  rm -rf tmpdirname

Process 2:
  mkdir a
  mv b/* a

I hope this helps.

Since this is not a bug in mv I am going to close the ticket in our
bug database.  But please we would like to hear back from you in this
ticket for any further discussion.

Bob




Added tag(s) notabug. Request was from Bob Proulx <bob <at> proulx.com> to control <at> debbugs.gnu.org. (Mon, 04 Mar 2019 18:34:02 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 34713 <at> debbugs.gnu.org and Christoph Michelbach <michelbach94 <at> gmail.com> Request was from Bob Proulx <bob <at> proulx.com> to control <at> debbugs.gnu.org. (Mon, 04 Mar 2019 18:34:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-coreutils <at> gnu.org:
bug#34713; Package coreutils. (Mon, 04 Mar 2019 19:58:01 GMT) Full text and rfc822 format available.

Message #15 received at 34713 <at> debbugs.gnu.org (full text, mbox):

From: Christoph Michelbach <michelbach94 <at> gmail.com>
To: Bob Proulx <bob <at> proulx.com>
Cc: 34713 <at> debbugs.gnu.org
Subject: Re: bug#34713: Files vanishing when moving to different FS
Date: Mon, 4 Mar 2019 20:57:45 +0100
Hello, Bob

Thank you for your explanation. I understand what's going on and even 
looked at the part of the source code that causes the problem prior to 
filing the bug report.


Even if you don't consider it a bug, it's still unexpected behavior that 
could be avoided. I think that mv's behavior would be more logical if it 
only removed files that it copied prior to removal (simple solution to 
the problem without destroying user data) or also move files that 
appeared in the destination location during the copying process 
(emulating moving a directory within a file system better and not 
destroying user data).


In the first case, it should still try to remove directories after 
removing all files in them but adhere to the rule that non-empty 
directories cannot be deleted instead of simply emptying them of their 
content prior to deletion.


In the second case, it should attempt to delete the directory and if 
this fails because it is non-empty, copy the newly appeared files over 
to the destination.


I think that the second solution is better for the users as it emulates 
the behavior of a move operation within a file system. However, I see 
that the first solution is easier to implement. The current behavior of 
mv destroys user data which I think is highly unexpected behavior.


Christoph





bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 02 Apr 2019 11:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 5 years and 38 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.