Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Apr 2013 16:34:14 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Andriy Gapon <avg@freebsd.org>
Cc:        freebsd-fs@freebsd.org
Subject:   Re: kern/177985: [zfs] disk usage problem when copying from one zfs dataset to another on the same pool using mv command
Message-ID:  <20130421154040.A888@besplex.bde.org>
In-Reply-To: <201304202030.r3KKU1uu001300@freefall.freebsd.org>
References:  <201304202030.r3KKU1uu001300@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 20 Apr 2013, Andriy Gapon wrote:

> The following reply was made to PR kern/177985; it has been noted by GNATS.
>
> From: Andriy Gapon <avg@FreeBSD.org>
> To: Jon <sybersnake@gmail.com>
> Cc: "bug-followup@FreeBSD.org" <bug-followup@FreeBSD.org>
> Subject: Re: kern/177985: [zfs] disk usage problem when copying from one zfs
> dataset to another on the same pool using mv command
> Date: Sat, 20 Apr 2013 23:25:40 +0300
>
> on 20/04/2013 22:49 Jon said the following:
> ...
> > This all can be
> > accomplished by deleting copied files more often than it currently does or at
> > least adding a flag to turn on synchronized deletes.
>
> No, it can not be accomplished that way, because it would violate how mv(1)
> across filesystems works.  Perhaps it's indeed the time to read the man page?

The behaviour of not removing the source tree until after successful
copying of the whole tree is also specified by POSIX, although a little
unclearly.  I thought that POSIX specified the FreeBSD behaviour (of
using cp -pRP to move across file systems, and then rm -rf of the
source path only if the cp succeeded).  But it seems to have a subtle
different that makes FreeBSD's implementation invalid (apart from the
bugs in cp -pRP):
- for cp -R, it is optional whether cp continues with remaining files (in
   the hierarchy under the current "source file" after a write error.
   FreeBSD's copy does continue.
- for cp -R, the continuing after most other errors (e.g., for open()) is
   not permitted, but FreeBSD's cp continues.
- for mv across file systems, not continuing after write errors seems to
   be required, although a little unclearly.  From POSIX.1-2001-draft7:

@ 25182                       If the duplication of the file hierarchy fails for any reason, mv shall write a diagnostic
@ 25183                       message to standard error, do nothing more with the current source_file, and go on to any
@ 25184                       remaining source_files.

This is fuzzy about when the error for duplication of the file hierarchy
must be detected and acted on, but any reasonable implementation will
detect errors for individual files as they are copied (modulo not detecting
async write errors until much later if at all), and then it takes a
weaselish reading of the above to allow the FreeBSD behaviour of not
quitting as soon as the error is detected, but instead buffering this
error and only reporting it after trying to copy all the other files.

Quitting here is the only way for avoiding falling through to clause 6
which specifies removing the source hierarchy.

@ 25185                       If the duplication of the file characteristics fails for any reason, mv shall write a diagnostic
@ 25186                       message to standard error, but this failure shall not cause mv to modify its exit status.

Continuing in this case is correct.  Not modifying the exit status in this
case is a bug in the spec IMO.  However, FreeBSD's implementation doesn't
have this bug.  For cp -p, the error handling for failing to copy attributes
is underspecified in POSIX (some cases are specified to write a diagnostic on
error, but no cases that I could find are specified to set the exit status
for such errors).  FreeBSD's cp -p sets the exit status for all failures to
copy attributes.  FreeBSD's mv across file system inherits this behaviour.
Thus failure to duplicate a single attribute in a large hierarchy causes
the whole cp to report falure to mv, and mv then consequently modifies its
exit status and refuses to remove the source hierarchy, so it doesn't have
this bug.  In some cases, the attributes might be important and their
might be billions of failures to duplicate them.  Then you don't want the
only copy of them in the source hierarchy being removed.

@ 25187                   6. The file hierarchy rooted in source_file shall be removed. If this fails for any reason, mv shall
@ 25188                       write a diagnostic message to the standard error, do nothing more with the current
@ 25189                       source_file, and go on to any remaining source_files.

We get here for no error in the cp for FreeBSD, or for no error except for
duplicating attributes in POSIX.  Again the spec is fuzzy about when "fails
for any reason" is.  Now it seems best to continue after errors in
intermediate steps, and that is what FreeBSD's rm -rf does.  (We know that
this rm -rf is safer than most, since we have just made a copy successfully.)
POSIX rm -r seems to require continuing after most errors.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130421154040.A888>