bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Correct semantics in rm -rf ?


From: shailesh jain
Subject: Re: Correct semantics in rm -rf ?
Date: Wed, 26 Aug 2009 13:25:47 -0400

On Wed, Aug 26, 2009 at 2:36 AM, Jim Meyering <address@hidden> wrote:

> shailesh jain wrote:
> > rm -rf does following (highly simplified)
> > ----
> >
> > remove_cwd_entries() {
> >
> >    // Check if dirp is empty ...
> >   readdir();
> > }
> >
> > remove_dir() {
> > while(1) {
> >
> >      remove_cwd_entries();
> >
> >     // Get the fd of directory
> >     fd = open();
> >
> >     // Unlink empty_dir
> >     unlinkat();
> >
> >     dirp = fdopendir(fd);
> >
> > }
> > }
> > -----
> >
> > open() call on directory goes to the VFS layer that is when the directory
> > stream gets attached to it. Any subsequent modifications made to the
> > directory like unlinkat() may or may not be reflected in readdir() calls.
> > (Note: fdopendir() call does not goto underlying filesystem... ). So the
> > code in remove_cwd_entries() that checks if directory is empty may find
> the
> > deleted directory entry.... Isn't this code relying upon incorrect
> semantics
> > ?
>
> Thanks for the report.
>
> I guess you're worried that rm -rf would perform extra work
> in attempting to remove those already-removed entries again?
> If this is really a problem, I'd be concerned with a user-visible
> consequence, like rm -ri prompting twice about the same name.
>
> There may well be file system implementations for which rm
> misbehaves, but so far, no one has reported such a problem.
>
> > I see that local filesystems tend to work even with this behavior but
> > network file systems that would bring in entire directory contents on
> open()
> > will not work ?
>
> If you can demonstrate an actual failure, or even that rm is
> merely performing unnecessary unlinkat calls, please provide details.
>


Thanks for consideration. I will describe how 'rm -rf parent' fails:
---
mkdir parent
cd parent
mkdir Child
cd ..
cd ..
---

Now you have following directory structure:

                                                   parent/ .
                                                                ..
                                                                Child/ .
                                                                          ..


Now, unlinkat() will delete child directory on unlinkat() and then do dirp =
fdopendir(parent_fd). Then it will perform readdir() calls on parent just to
find out that  'Child' directory is still present and it will mark 'Child'
directory is unremovable... (and I think it subsequently tries to remove
'Child' and doesn't find 'Child' and terminates with ENOENT when I use rm
-riv)

I read from the posix semantics that fdopendir() should behave same as
opendir(), however given that the VFS layer and the underlying filesystem
cannot distinguish between open() and opendir(), I do not see any reasonable
way to do that. Thus relying on readdir() to reflect updates made by
unlinkat() is broken (although local file systems tend to reflect this very
well).

Do I sound paranoid ?


Shailesh Jain


reply via email to

[Prev in Thread] Current Thread [Next in Thread]