* rename("a", "b") would not always remove "a" on success. ?!!
@ 2011-10-28 15:25 Denys Vlasenko
2011-10-28 15:32 ` Pádraig Brady
0 siblings, 1 reply; 6+ messages in thread
From: Denys Vlasenko @ 2011-10-28 15:25 UTC (permalink / raw)
To: linux-kernel, Al Viro; +Cc: Christian Engelmayer
Hi,
One of my users stumbled over a problem when power failure
hit his system at rename() and the filesystem he uses
(I don't know which) ended up having both old and new
file names in the directory. Basically, he ended up with
one file with two hardlinks pointing to it.
IOW: the scenario does not require unlucky power offs
to reproduce, just "ln a b" would do.
In his case these two particular hardlinks were pointing
to rotated log files.
When system restarted, it eventually tried to rotate files
again, via rename("a", "b").
rename succeeded, but since they are hardlinks, rename
did NOT remove "a".
Which made the logger process very confused.
The user dug into it and discovered that SUS actually
specifies this insane behavior:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
'If the old argument and the new argument resolve to either .... or different
directory entries for the same existing file, rename() shall return
successfully and perform no other action.'
It's incredible they had audacity to put such nonsense into standard.
The page says in "RATIONALE" section:
'The specification that if old and new refer to the same file is
intended to guarantee that:
rename("x", "x");
does not remove the file.'
Why didn't they just explicitly say that they actually want THIS
particular case to work correctly, not OTHER cases to be fucked up?!
Anyway. My question is, does it really need to be implemented in Linux?
It looks bogus to me, and it basically requires any program
to contain a work-around for this case. For example, mv from util-linux
apparently already has a workaround:
$ touch a; ln a b
$ strace mv a b
...
stat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat64("a", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
geteuid32() = 0
unlink("a") = 0
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
--
vda
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: rename("a", "b") would not always remove "a" on success. ?!!
2011-10-28 15:25 rename("a", "b") would not always remove "a" on success. ?!! Denys Vlasenko
@ 2011-10-28 15:32 ` Pádraig Brady
2011-10-28 15:42 ` Eric Blake
0 siblings, 1 reply; 6+ messages in thread
From: Pádraig Brady @ 2011-10-28 15:32 UTC (permalink / raw)
To: Denys Vlasenko; +Cc: linux-kernel, Al Viro, Christian Engelmayer, Coreutils
On 10/28/2011 04:25 PM, Denys Vlasenko wrote:
> Hi,
>
> One of my users stumbled over a problem when power failure
> hit his system at rename() and the filesystem he uses
> (I don't know which) ended up having both old and new
> file names in the directory. Basically, he ended up with
> one file with two hardlinks pointing to it.
>
> IOW: the scenario does not require unlucky power offs
> to reproduce, just "ln a b" would do.
>
> In his case these two particular hardlinks were pointing
> to rotated log files.
>
> When system restarted, it eventually tried to rotate files
> again, via rename("a", "b").
> rename succeeded, but since they are hardlinks, rename
> did NOT remove "a".
> Which made the logger process very confused.
>
>
> The user dug into it and discovered that SUS actually
> specifies this insane behavior:
>
> http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
>
> 'If the old argument and the new argument resolve to either .... or different
> directory entries for the same existing file, rename() shall return
> successfully and perform no other action.'
>
> It's incredible they had audacity to put such nonsense into standard.
>
> The page says in "RATIONALE" section:
>
> 'The specification that if old and new refer to the same file is
> intended to guarantee that:
>
> rename("x", "x");
>
> does not remove the file.'
>
> Why didn't they just explicitly say that they actually want THIS
> particular case to work correctly, not OTHER cases to be fucked up?!
>
>
> Anyway. My question is, does it really need to be implemented in Linux?
> It looks bogus to me, and it basically requires any program
> to contain a work-around for this case. For example, mv from util-linux
> apparently already has a workaround:
>
> $ touch a; ln a b
> $ strace mv a b
> ...
> stat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
> lstat64("a", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
> lstat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
> geteuid32() = 0
> unlink("a") = 0
> close(0) = 0
> close(1) = 0
> close(2) = 0
> exit_group(0) = ?
mv is from coreutils BTW.
Here is the related comment from the source:
"Set *UNLINK_SRC if we've determined that the caller wants to do
`rename (a, b)' where `a' and `b' are distinct hard links to the same
file. In that case, the caller should try to unlink `a' and then return
successfully. Ideally, we wouldn't have to do that, and we'd be
able to rely on rename to remove the source file. However, POSIX
mistakenly requires that such a rename call do *nothing* and return
successfully."
Perhaps it could be brought up as an issue with the standards guys?
cheers,
Pádraig.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: rename("a", "b") would not always remove "a" on success. ?!!
2011-10-28 15:32 ` Pádraig Brady
@ 2011-10-28 15:42 ` Eric Blake
2011-10-28 15:58 ` Eric Blake
2011-10-29 1:00 ` Denys Vlasenko
0 siblings, 2 replies; 6+ messages in thread
From: Eric Blake @ 2011-10-28 15:42 UTC (permalink / raw)
To: Pádraig Brady
Cc: Denys Vlasenko, Coreutils, linux-kernel, Christian Engelmayer, Al Viro
On 10/28/2011 09:32 AM, Pádraig Brady wrote:
>> http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
>>
>> 'If the old argument and the new argument resolve to either .... or different
>> directory entries for the same existing file, rename() shall return
>> successfully and perform no other action.'
>>
>> It's incredible they had audacity to put such nonsense into standard.
>>
>> The page says in "RATIONALE" section:
>>
>> 'The specification that if old and new refer to the same file is
>> intended to guarantee that:
>>
>> rename("x", "x");
>>
>> does not remove the file.'
>>
>> Why didn't they just explicitly say that they actually want THIS
>> particular case to work correctly, not OTHER cases to be fucked up?!
Because it is historical precedent, and changing it now would break
software that has come to expect this behavior on hard links.
>>
>>
>> Anyway. My question is, does it really need to be implemented in Linux?
>> It looks bogus to me, and it basically requires any program
>> to contain a work-around for this case. For example, mv from util-linux
>> apparently already has a workaround:
>>
>> $ touch a; ln a b
>> $ strace mv a b
>> ...
>> stat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
>> lstat64("a", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
>> lstat64("b", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
>> geteuid32() = 0
>> unlink("a") = 0
>> close(0) = 0
>> close(1) = 0
>> close(2) = 0
>> exit_group(0) = ?
>
> mv is from coreutils BTW.
> Here is the related comment from the source:
>
> "Set *UNLINK_SRC if we've determined that the caller wants to do
> `rename (a, b)' where `a' and `b' are distinct hard links to the same
> file. In that case, the caller should try to unlink `a' and then return
> successfully. Ideally, we wouldn't have to do that, and we'd be
> able to rely on rename to remove the source file. However, POSIX
> mistakenly requires that such a rename call do *nothing* and return
> successfully."
>
> Perhaps it could be brought up as an issue with the standards guys?
We already have. And POSIX 2008 already acted on that. While you
quoted rename(2) (which was intentionally not changed), you forgot to
also read the POSIX wording on mv(1):
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html
2. If the source_file operand and destination path name the same
existing file, then the destination path shall not be removed, and one
of the following shall occur:
a. No change is made to source_file, no error occurs, and no
diagnostic is issued.
b. No change is made to source_file, a diagnostic is issued to
standard error identifying the two names, and the exit status is affected.
c. If the source_file operand and destination path name distinct
directory entries, then the source_file operand is removed, no error
occurs, and no diagnostic is issued.
2a is the naive approach (using rename(2) semantics)
2b is the typical mv(1) approach (IIRC, both Solaris and BSD mv
independently implemented this mode)
2c is the GNU coreutils approach (make mv(1) do what you meant, even
though rename(2) is _required_ to do nothing)
Do NOT change the Linux kernel to "fix" rename(2); that will only cause
more heartache by deviating from the standard.
--
Eric Blake eblake@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: rename("a", "b") would not always remove "a" on success. ?!!
2011-10-28 15:42 ` Eric Blake
@ 2011-10-28 15:58 ` Eric Blake
2011-10-29 1:00 ` Denys Vlasenko
1 sibling, 0 replies; 6+ messages in thread
From: Eric Blake @ 2011-10-28 15:58 UTC (permalink / raw)
Cc: Pádraig Brady, Denys Vlasenko, Al Viro, Coreutils,
Christian Engelmayer, linux-kernel
On 10/28/2011 09:42 AM, Eric Blake wrote:
>> Perhaps it could be brought up as an issue with the standards guys?
>
> We already have. And POSIX 2008 already acted on that. While you quoted
> rename(2) (which was intentionally not changed), you forgot to also read
> the POSIX wording on mv(1):
>
> http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html
>
> 2. If the source_file operand and destination path name the same
> existing file, then the destination path shall not be removed, and one
> of the following shall occur:
>
> a. No change is made to source_file, no error occurs, and no diagnostic
> is issued.
> b. No change is made to source_file, a diagnostic is issued to standard
> error identifying the two names, and the exit status is affected.
> c. If the source_file operand and destination path name distinct
> directory entries, then the source_file operand is removed, no error
> occurs, and no diagnostic is issued.
Contrast this to the POSIX 2001 wording for mv:
http://pubs.opengroup.org/onlinepubs/009695399/utilities/mv.html
2. The mv utility shall perform actions equivalent to the rename()
function defined in the System Interfaces volume of IEEE Std 1003.1-2001,...
with no escape clause for identical files. That is, POSIX 2008
specifically inserted a new step 2 (renumbering the step 2 from POSIX
2001 to step 3 in POSIX 2008) at GNU Coreutils' insistence that the
requirements were wrong. See also
http://www.opengroup.org/austin/aardvark/latest/xcubug2.txt, and search
for AI-169, which was where the change in wording was made; including
this rationale:
Note that ERN 88 was rejected in spite of the fact that
http://www.opengroup.org/austin/mailarchives/austin-group-l/msg05155.html
claims the original intent was to have rename detect identical
directory entries rather than identical files. One of the arguments
presented for rejecting ERN 88 was that rename(2) has the property
of preserving link count, whereas having rename("a", "b") unlink
"a" when the two names are hard links would not.
Unfortunately, that link no longer works, so I can't point you to the
historical conversation at the time where it was argued that changing
rename(2) behavior would be detrimental. But it does give enough
context to provide an alternate interpretation of rename() semantics
that fit the standardized behavior: a successful rename("a","b")
guarantees that "b" now has the same link count as "a" had prior to the
rename call, even if that meant a hard-linked "a" had to be left
untouched to avoid changing the link count of hard-linked "b".
--
Eric Blake eblake@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: rename("a", "b") would not always remove "a" on success. ?!!
2011-10-28 15:42 ` Eric Blake
2011-10-28 15:58 ` Eric Blake
@ 2011-10-29 1:00 ` Denys Vlasenko
2011-10-29 1:19 ` richard -rw- weinberger
1 sibling, 1 reply; 6+ messages in thread
From: Denys Vlasenko @ 2011-10-29 1:00 UTC (permalink / raw)
To: Eric Blake
Cc: Pádraig Brady, Coreutils, linux-kernel,
Christian Engelmayer, Al Viro
On Friday 28 October 2011 17:42, Eric Blake wrote:
> On 10/28/2011 09:32 AM, Pádraig Brady wrote:
> >> http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
> >>
> >> 'If the old argument and the new argument resolve to either .... or different
> >> directory entries for the same existing file, rename() shall return
> >> successfully and perform no other action.'
> >>
> >> It's incredible they had audacity to put such nonsense into standard.
> >>
> >> The page says in "RATIONALE" section:
> >>
> >> 'The specification that if old and new refer to the same file is
> >> intended to guarantee that:
> >>
> >> rename("x", "x");
> >>
> >> does not remove the file.'
> >>
> >> Why didn't they just explicitly say that they actually want THIS
> >> particular case to work correctly, not OTHER cases to be fucked up?!
>
> Because it is historical precedent, and changing it now would break
> software that has come to expect this behavior on hard links.
There is centain level of absurdity, after which fixing a goof in standards
makes sense even if it theoretically can break some existing program.
In my opinion, the key word here is "theoritically".
Is there even one real-world program which depends on this?
I bet there is not.
--
vda
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: rename("a", "b") would not always remove "a" on success. ?!!
2011-10-29 1:00 ` Denys Vlasenko
@ 2011-10-29 1:19 ` richard -rw- weinberger
0 siblings, 0 replies; 6+ messages in thread
From: richard -rw- weinberger @ 2011-10-29 1:19 UTC (permalink / raw)
To: Denys Vlasenko
Cc: Eric Blake, Pádraig Brady, Coreutils, linux-kernel,
Christian Engelmayer, Al Viro
On Sat, Oct 29, 2011 at 3:00 AM, Denys Vlasenko
<vda.linux@googlemail.com> wrote:
> In my opinion, the key word here is "theoritically".
> Is there even one real-world program which depends on this?
> I bet there is not.
>
The best way to find such a program is breaking it by changing the
kernel's behavior. ;-)
--
Thanks,
//richard
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-10-29 1:19 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-28 15:25 rename("a", "b") would not always remove "a" on success. ?!! Denys Vlasenko
2011-10-28 15:32 ` Pádraig Brady
2011-10-28 15:42 ` Eric Blake
2011-10-28 15:58 ` Eric Blake
2011-10-29 1:00 ` Denys Vlasenko
2011-10-29 1:19 ` richard -rw- weinberger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.