patch-2.2.6 linux/fs/umsdos/namei.c
Next file: linux/fs/vfat/namei.c
Previous file: linux/fs/umsdos/inode.c
Back to the patch index
Back to the overall index
- Lines: 364
- Date:
Mon Apr 12 10:03:45 1999
- Orig file:
v2.2.5/linux/fs/umsdos/namei.c
- Orig date:
Tue Dec 22 14:16:57 1998
diff -u --recursive --new-file v2.2.5/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
@@ -6,6 +6,10 @@
*
* Maintain and access the --linux alternate directory file.
*/
+ /*
+ * You are in the maze of twisted functions - half of them shouldn't
+ * be here...
+ */
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -258,16 +262,11 @@
goto out;
/* do a real lookup to get the short name dentry */
- fake = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname,
- info.fake.len, 1);
+ fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
ret = PTR_ERR(fake);
if (IS_ERR(fake))
goto out_remove;
- /* keep the short name anonymous ... */
- if (dentry != fake)
- d_drop(fake);
-
/* should not exist yet ... */
ret = -EEXIST;
if (fake->d_inode)
@@ -278,14 +277,8 @@
goto out_remove_dput;
inode = fake->d_inode;
- /*
- * Note! The long and short name might be the same,
- * so check first before doing the instantiate ...
- */
- if (dentry != fake) {
- inode->i_count++;
- d_instantiate (dentry, inode);
- }
+ inode->i_count++;
+ d_instantiate (dentry, inode);
dput(fake);
if (inode->i_count > 1) {
printk(KERN_WARNING
@@ -363,7 +356,7 @@
{
struct inode *old_inode = old_dentry->d_inode;
struct dentry *old, *new, *old_emd;
- int err, ret, rehash = 0;
+ int err, ret;
struct umsdos_info old_info;
struct umsdos_info new_info;
@@ -386,34 +379,11 @@
umsdos_lockcreate2 (old_dir, new_dir);
ret = umsdos_findentry(old_emd->d_parent, &old_info, 0);
- if (ret) {
- printk(KERN_ERR
- "umsdos_rename_f: old entry %s/%s not in EMD, ret=%d\n",
- old_dentry->d_parent->d_name.name, old_info.entry.name,
- ret);
- goto out_unlock;
- }
-
- /* check sticky bit on old_dir */
- ret = -EPERM;
- if (is_sticky(old_dir, old_info.entry.uid)) {
-printk("umsdos_rename_f: %s/%s old sticky bit, fsuid=%d, uid=%d, dir=%d\n",
-old_dentry->d_parent->d_name.name, old_info.entry.name,
-current->fsuid, old_info.entry.uid, old_dir->i_uid);
+ if (ret)
goto out_unlock;
- }
- /*
- * Check whether the new_name already exists, and
- * if so whether we're allowed to replace it.
- */
err = umsdos_findentry(new_dentry->d_parent, &new_info, 0);
if (err == 0) {
- /* Are we allowed to replace it? */
- if (is_sticky(new_dir, new_info.entry.uid)) {
-Printk (("sticky set on new "));
- goto out_unlock;
- }
/* check whether it _really_ exists ... */
ret = -EEXIST;
if (new_dentry->d_inode)
@@ -427,108 +397,41 @@
S_ISDIR(new_info.entry.mode));
}
-Printk (("new newentry "));
- /* create the new entry ... */
umsdos_ren_init (&new_info, &old_info);
if (flags)
new_info.entry.flags = flags;
ret = umsdos_newentry (new_dentry->d_parent, &new_info);
- if (ret) {
- printk(KERN_WARNING
- "umsdos_rename_f: newentry %s/%s failed, ret=%d\n",
- new_dentry->d_parent->d_name.name, new_info.entry.name,
- ret);
+ if (ret)
goto out_unlock;
- }
/* If we're moving a hardlink, drop it first */
if (old_info.entry.flags & UMSDOS_HLINK) {
- rehash = !list_empty(&old_dentry->d_hash);
d_drop(old_dentry);
-printk("umsdos_rename_f: moving hardlink %s/%s, rehash=%d\n",
-old_dentry->d_parent->d_name.name, old_info.entry.name, rehash);
}
- /* Do a real lookup to get the old short name dentry */
- old = umsdos_lookup_dentry(old_dentry->d_parent, old_info.fake.fname,
- old_info.fake.len, 1);
+ old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname,
+ old_info.fake.len);
ret = PTR_ERR(old);
- if (IS_ERR(old)) {
- printk(KERN_WARNING
- "umsdos_rename_f: lookup old dentry %s/%s, ret=%d\n",
- old_dentry->d_parent->d_name.name, old_info.fake.fname,
- ret);
+ if (IS_ERR(old))
goto out_unlock;
- }
- /* short and long name dentries match? */
- if (old == old_dentry)
- dput(old);
- else {
- /* make sure it's the same inode! */
- ret = -ENOENT;
- if (old->d_inode != old_inode)
- goto out_dput;
- /*
- * A cross-directory move with different short and long
- * names has nasty complications: msdos-fs will need to
- * change inodes, so we must check whether the original
- * dentry is busy, and if the rename succeeds the short
- * dentry will come back with a different inode.
- *
- * To handle this, we drop the dentry and free the inode,
- * and then pick up the new inode after the rename.
- */
- if (old_dir != new_dir) {
- ret = -EBUSY;
- if (old_dentry->d_count > 1) {
-printk("umsdos_rename_f: old dentry %s/%s busy, d_count=%d\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name,old_dentry->d_count);
- goto out_dput;
- }
- d_drop(old_dentry);
- d_delete(old_dentry);
-printk("umsdos_rename_f: cross-dir move, %s/%s dropped\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name);
- }
- }
+ /* make sure it's the same inode! */
+ ret = -ENOENT;
+ if (old->d_inode != old_inode)
+ goto out_dput;
- new = umsdos_lookup_dentry(new_dentry->d_parent, new_info.fake.fname,
- new_info.fake.len, 1);
+ new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname,
+ new_info.fake.len);
ret = PTR_ERR(new);
- if (IS_ERR(new)) {
- printk(KERN_WARNING
- "umsdos_rename_f: lookup new dentry %s/%s, ret=%d\n",
- new_dentry->d_parent->d_name.name, new_info.fake.fname,
- ret);
+ if (IS_ERR(new))
goto out_dput;
- }
-#ifdef UMSDOS_PARANOIA
-if (new->d_inode != new_dentry->d_inode)
-printk("umsdos_rename_f: new %s/%s, inode %p!=%p??\n",
-new->d_parent->d_name.name, new->d_name.name, new->d_inode,new_dentry->d_inode);
-#endif
- /* short and long name dentries match? */
- if (new == new_dentry)
- dput(new);
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_rename_f: msdos_rename %s/%s(%ld) to %s/%s(%ld)\n",
-old->d_parent->d_name.name, old->d_name.name, old->d_inode->i_ino,
-new->d_parent->d_name.name, new->d_name.name,
-new->d_inode ? new->d_inode->i_ino : 0);
-#endif
/* Do the msdos-level rename */
ret = msdos_rename (old_dir, old, new_dir, new);
-Printk(("umsdos_rename_f: now %s/%s, ret=%d\n",
-old->d_parent->d_name.name, old->d_name.name, ret));
- if (new != new_dentry)
- dput(new);
+ dput(new);
/* If the rename failed, remove the new EMD entry */
if (ret != 0) {
-Printk(("umsdos_rename_f: rename failed, ret=%d, removing %s/%s\n",
-ret, new_dentry->d_parent->d_name.name, new_info.entry.name));
umsdos_delentry (new_dentry->d_parent, &new_info,
S_ISDIR (new_info.entry.mode));
goto out_dput;
@@ -550,33 +453,6 @@
}
/*
- * Check whether to update the dcache ... if both
- * old and new dentries match, it's already correct.
- * If the targets were aliases, the old short-name
- * dentry has the original target name.
- */
- if (old_dentry != old) {
- if (!old_dentry->d_inode) {
- struct inode *inode = old->d_inode;
- inode->i_count++;
- d_instantiate(old_dentry, inode);
-printk("umsdos_rename_f: %s/%s gets new ino=%ld\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name, inode->i_ino);
- }
- if (new_dentry == new)
- new_dentry = old;
- goto move_it;
- } else if (new_dentry != new) {
- move_it:
- /* this will rehash the dentry ... */
- d_move(old_dentry, new_dentry);
- }
- /* Check whether the old inode changed ... */
- if (old_dentry->d_inode != old_inode) {
- umsdos_lookup_patch_new(old_dentry, &new_info);
- }
-
- /*
* Update f_pos so notify_change will succeed
* if the file was already in use.
*/
@@ -584,8 +460,7 @@
/* dput() the dentry if we haven't already */
out_dput:
- if (old_dentry != old)
- dput(old);
+ dput(old);
out_unlock:
dput(old_emd);
@@ -614,6 +489,9 @@
extern struct inode_operations umsdos_symlink_inode_operations;
+/*
+ * AV. Should be called with dir->i_sem down.
+ */
static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry,
const char *symname, int mode, char flags)
{
@@ -745,8 +623,9 @@
goto cleanup;
}
/* rename the link to the hidden location ... */
- ret = umsdos_rename_f (olddir, olddentry, olddir, temp,
+ ret = umsdos_rename_f(olddir, olddentry, olddir, temp,
UMSDOS_HIDDEN);
+ d_move(olddentry, temp);
dput(temp);
if (ret) {
printk("umsdos_link: rename to %s/%s failed, ret=%d\n",
@@ -1096,7 +975,7 @@
{
struct dentry *temp, *link = NULL;
struct inode *inode;
- int ret, rehash = 0;
+ int ret;
struct umsdos_info info;
Printk(("UMSDOS_unlink: entering %s/%s\n",
@@ -1135,10 +1014,7 @@
* the original dentry.
*/
if (info.entry.flags & UMSDOS_HLINK) {
- rehash = !list_empty(&dentry->d_hash);
d_drop(dentry);
-Printk(("UMSDOS_unlink: hard link %s/%s, fake=%s, rehash=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname, rehash));
}
/* Do a real lookup to get the short name dentry */
@@ -1247,57 +1123,31 @@
return ret;
}
-
/*
* Rename (move) a file.
*/
int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- struct dentry *new_target;
int ret;
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_rename: enter, %s/%s(%ld) to %s/%s(%ld)\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
-old_dentry->d_inode->i_ino,
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0);
-#endif
ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);
if (ret)
- goto out;
+ return ret;
- /*
- * If the target already exists, delete it first.
- */
+ /*
+ * If the target already exists, delete it first.
+ */
if (new_dentry->d_inode) {
- if (S_ISDIR(new_dentry->d_inode->i_mode))
+ new_dentry->d_count++;
+ if (S_ISDIR(old_dentry->d_inode->i_mode))
ret = UMSDOS_rmdir (new_dir, new_dentry);
else
ret = UMSDOS_unlink (new_dir, new_dentry);
+ dput(new_dentry);
if (ret)
- goto out;
+ return ret;
}
-
- /*
- * If we didn't get a negative dentry, make a copy and hash it.
- */
- new_target = new_dentry;
- if (new_dentry->d_inode) {
-printk("umsdos_rename: %s/%s not negative, hash=%d\n",
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-!list_empty(&new_dentry->d_hash));
- ret = -ENOMEM;
- new_target = d_alloc(new_dentry->d_parent, &new_dentry->d_name);
- if (!new_target)
- goto out;
- d_add(new_target, NULL);
- }
- ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_target, 0);
- if (new_target != new_dentry)
- dput(new_target);
-
-out:
+ ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0);
return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)