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

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)