From: Alexander Viro <viro@math.psu.edu>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] Df command in Plan9?
Date: Thu, 26 Oct 2000 00:54:58 -0400 [thread overview]
Message-ID: <Pine.GSO.4.21.0010250702190.12098-100000@weyl.math.psu.edu> (raw)
In-Reply-To: <39F65AD7.8195874E@arl.army.mil>
On Wed, 25 Oct 2000, Douglas A. Gwyn wrote:
> Boyd Roberts wrote:
> > ... it's working out whether
> > you're ripping out the tree from under yourself is the
> > nasty problem.
>
> But that's a move, not a rename.
rename(2) in 4.2BSD and other Unices that picked/inherited it _is_ move.
Yes, it's overcomplicated, it sucks badly wrt required locking, it has
extremely nasty potential for races with rmdir() and itself, yodda, yodda.
I have no idea why Kirk went for that horror. He did. Once it works right
it's a convenient thing to have around, but getting it work right...
<shudder> Apologies for self-quoting, but...
/*
* The worst of all namespace operations - renaming directory. "Perverted"
* doesn't even start to describe it. Somebody in UCB had a heck of a trip...
* Problems:
* a) we can get into loop creation. Check is done in is_subdir().
* b) race potential - two innocent renames can create a loop together.
* That's where 4.4 screws up. Current fix: serialization on
* sb->s_vfs_rename_sem. We might be more accurate, but that's another
* story.
* c) we have to lock _three_ objects - parents and victim (if it exists).
* And that - after we got ->i_sem on parents (until then we don't know
* whether the target exists at all, let alone whether it is a directory
* or not). Solution: ->i_zombie. Taken only after ->i_sem. Always taken
* on link creation/removal of any kind. And taken (without ->i_sem) on
* directory that will be removed (both in rmdir() and here).
* d) some filesystems don't support opened-but-unlinked directories,
* either because of layout or because they are not ready to deal with
* all cases correctly. The latter will be fixed (taking this sort of
* stuff into VFS), but the former is not going away. Solution: the same
* trick as in rmdir().
* [ the latter had been fixed, the former == NFS and SMBFS these days ]
* e) conversion from fhandle to dentry may come in the wrong moment - when
* we are removing the target. Solution: we will have to grab ->i_zombie
* in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
* ->i_sem on parents, which works but leads to some truely excessive
* locking].
*/
int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
int error;
struct inode *target;
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
error = may_delete(old_dir, old_dentry, 1);
if (error)
return error;
if (new_dir->i_dev != old_dir->i_dev)
return -EXDEV;
if (!new_dentry->d_inode)
error = may_create(new_dir, new_dentry);
else
error = may_delete(new_dir, new_dentry, 1);
if (error)
return error;
if (!old_dir->i_op || !old_dir->i_op->rename)
return -EPERM;
/*
* If we are going to change the parent - check write permissions,
* we'll need to flip '..'.
*/
if (new_dir != old_dir)
error = permission(old_dentry->d_inode, MAY_WRITE);
if (error)
return error;
DQUOT_INIT(old_dir);
DQUOT_INIT(new_dir);
down(&old_dir->i_sb->s_vfs_rename_sem);
error = -EINVAL;
if (is_subdir(new_dentry, old_dentry))
goto out_unlock;
target = new_dentry->d_inode;
if (target) { /* Hastur! Hastur! Hastur! */
triple_down(&old_dir->i_zombie,
&new_dir->i_zombie,
&target->i_zombie);
d_unhash(new_dentry);
} else
double_down(&old_dir->i_zombie,
&new_dir->i_zombie);
if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
error = -ENOENT;
else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry,
new_dir, new_dentry);
if (target) {
if (!error)
target->i_flags |= S_DEAD;
triple_up(&old_dir->i_zombie,
&new_dir->i_zombie,
&target->i_zombie);
if (d_unhashed(new_dentry))
d_rehash(new_dentry);
dput(new_dentry);
} else
double_up(&old_dir->i_zombie,
&new_dir->i_zombie);
if (!error)
d_move(old_dentry,new_dentry);
out_unlock:
up(&old_dir->i_sb->s_vfs_rename_sem);
return error;
}
... and that's just the directory-specific part of VFS side of the thing,
after we got i_sem on parents and got dentries of source and target.
->i_op->rename() does fs-dependent part of work.
Full-blown rename() is painful, just as full-blown truncate() and correct
handling of symlinks. Nice to have on the userland side of things, but
kernel side is something. truncate()/mmap()/write() alone makes for a
serious S&M shop.
next prev parent reply other threads:[~2000-10-26 4:54 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2000-10-20 20:31 Russ Cox
2000-10-20 21:44 ` Alexander Viro
2000-10-20 21:51 ` Boyd Roberts
2000-10-21 0:37 ` Rick Hohensee
2000-10-21 10:13 ` Alexander Viro
2000-10-22 0:13 ` Rick Hohensee
2000-10-22 0:25 ` Boyd Roberts
2000-10-22 15:41 ` Rick Hohensee
2000-10-23 9:02 ` Douglas A. Gwyn
2000-10-23 10:30 ` Alexander Viro
2000-10-24 11:37 ` Boyd Roberts
2000-10-25 8:30 ` Douglas A. Gwyn
2000-10-26 4:54 ` Alexander Viro [this message]
2000-10-26 5:44 ` Boyd Roberts
2000-10-22 11:34 ` Alexander Viro
2000-10-22 15:59 ` Rick Hohensee
2000-10-22 16:43 ` Alexander Viro
2000-10-23 5:06 ` Boyd Roberts
-- strict thread matches above, loose matches on Subject: below --
2000-10-22 17:06 forsyth
2000-10-23 2:23 ` Rick Hohensee
2000-10-22 11:04 forsyth
2000-10-22 12:49 ` Boyd Roberts
2000-10-22 13:16 ` Alexander Viro
2000-10-22 16:07 ` Rick Hohensee
2000-10-22 16:31 ` Alexander Viro
2000-10-23 2:07 ` Rick Hohensee
2000-10-22 16:05 ` Rick Hohensee
2000-10-20 21:51 presotto
2000-10-20 20:22 Mark C. Otto
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.GSO.4.21.0010250702190.12098-100000@weyl.math.psu.edu \
--to=viro@math.psu.edu \
--cc=9fans@cse.psu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).