patch-2.1.121 linux/fs/umsdos/rdir.c

Next file: linux/fs/umsdos/specs
Previous file: linux/fs/umsdos/namei.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.120/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
@@ -18,9 +18,6 @@
 
 #include <asm/uaccess.h>
 
-#define PRINTK(x)
-#define Printk(x) printk x
-
 
 extern struct inode *pseudo_root;
 
@@ -39,16 +36,13 @@
 	int ret = 0;
 	struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf;
 
-	PRINTK ((KERN_DEBUG "rdir_filldir /mn/: entering\n"));
 	if (d->real_root) {
 		PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
 		/* real root of a pseudo_rooted partition */
 		if (name_len != UMSDOS_PSDROOT_LEN
 		    || memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) {
 			/* So it is not the /linux directory */
-			if (name_len == 2
-			    && name[0] == '.'
-			    && name[1] == '.') {
+			if (name_len == 2 && name[0] == '.' && name[1] == '.') {
 				/* Make sure the .. entry points back to the pseudo_root */
 				ino = pseudo_root->i_ino;
 			}
@@ -56,30 +50,22 @@
 		}
 	} else {
 		/* Any DOS directory */
-		PRINTK ((KERN_DEBUG "rdir_filldir /mn/: calling d->filldir (%p) for %.*s (%lu)\n", d->filldir, name_len, name, ino));
 		ret = d->filldir (d->dirbuf, name, name_len, offset, ino);
 	}
 	return ret;
 }
 
 
-static int UMSDOS_rreaddir (
-				   struct file *filp,
-				   void *dirbuf,
-				   filldir_t filldir)
+static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir)
 {
-	struct RDIR_FILLDIR bufk;
 	struct inode *dir = filp->f_dentry->d_inode;
-
-	PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: entering %p %p\n", filldir, dirbuf));
-
+	struct RDIR_FILLDIR bufk;
 
 	bufk.filldir = filldir;
 	bufk.dirbuf = dirbuf;
-	bufk.real_root = pseudo_root
-	    && dir == iget (dir->i_sb, UMSDOS_ROOT_INO)
-	    && dir == iget (pseudo_root->i_sb, UMSDOS_ROOT_INO);
-	PRINTK ((KERN_DEBUG "UMSDOS_rreaddir /mn/: calling fat_readdir with filldir=%p and exiting\n", filldir));
+	bufk.real_root = pseudo_root &&
+			 dir->i_ino == UMSDOS_ROOT_INO && 
+			 dir->i_sb == pseudo_root->i_sb;
 	return fat_readdir (filp, &bufk, rdir_filldir);
 }
 
@@ -89,157 +75,138 @@
  * If the result is a directory, make sure we find out if it is
  * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
  */
-int umsdos_rlookup_x (
-			     struct inode *dir,
-			     struct dentry *dentry,
-			     int nopseudo)
-{				/* Don't care about pseudo root mode */
+/* #Specification: pseudo root / DOS/..
+ * In the real root directory (c:\), the directory ..
+ * is the pseudo root (c:\linux).
+ */
+int umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo)
+{
 	/* so locating "linux" will work */
-	int len = dentry->d_name.len;
 	const char *name = dentry->d_name.name;
+	int len = dentry->d_name.len;
 	struct inode *inode;
 	int ret;
 
-	if (pseudo_root
-	    && len == 2
-	    && name[0] == '.'
-	    && name[1] == '.'
-	    && dir == iget (dir->i_sb, UMSDOS_ROOT_INO)
-	    && dir == iget (pseudo_root->i_sb, UMSDOS_ROOT_INO)) {
-		/*    *result = pseudo_root; */
-		Printk ((KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n"));
-		inc_count (pseudo_root);
+	if (pseudo_root && len == 2 && name[0] == '.' && name[1] == '.' &&
+	    dir->i_ino == UMSDOS_ROOT_INO && dir->i_sb == pseudo_root->i_sb) {
+printk (KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n");
+		pseudo_root->i_count++;
+		d_add(dentry, pseudo_root);
 		ret = 0;
-		/* #Specification: pseudo root / DOS/..
-		 * In the real root directory (c:\), the directory ..
-		 * is the pseudo root (c:\linux).
-		 */
-	} else {
-		inc_count (dir);
-		ret = umsdos_real_lookup (dir, dentry);
-		inode = dentry->d_inode;
-
-#if 0
-		Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup for %.*s in %lu returned %d\n", len, name, dir->i_ino, ret));
-		Printk ((KERN_DEBUG "umsdos_rlookup_x: umsdos_real_lookup: inode is %p resolving to ", inode));
-		if (inode) {	/* /mn/ FIXME: DEL_ME */
-			Printk ((KERN_DEBUG "i_ino=%lu\n", inode->i_ino));
-		} else {
-			Printk ((KERN_DEBUG "NONE!\n"));
-		}
-#endif
-
-		if ((ret == 0) && inode) {
+		goto out;
+	}
 
-			if (pseudo_root && inode == pseudo_root && !nopseudo) {
-				/* #Specification: pseudo root / DOS/linux
-				 * Even in the real root directory (c:\), the directory
-				 * /linux won't show
-				 */
-				Printk ((KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n"));
-				ret = -ENOENT;
-				iput (pseudo_root); /* FIXME? */
-
-			} else if (S_ISDIR (inode->i_mode)) {
-				/* We must place the proper function table */
-				/* depending on whether this is an MS-DOS or a UMSDOS directory */
-				Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", inode->i_ino));
-				umsdos_setup_dir_inode (inode);
-			}
+	ret = umsdos_real_lookup (dir, dentry);
+	inode = dentry->d_inode;
+	if ((ret == 0) && inode) {
+		if (inode == pseudo_root && !nopseudo) {
+			/* #Specification: pseudo root / DOS/linux
+			 * Even in the real root directory (c:\), the directory
+			 * /linux won't show
+			 */
+printk(KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n");
+			/* make the dentry negative */
+			d_delete(dentry);
+		}
+		else if (S_ISDIR (inode->i_mode)) {
+			/* We must place the proper function table
+			 * depending on whether this is an MS-DOS or 
+			 * a UMSDOS directory
+			 */
+Printk ((KERN_DEBUG "umsdos_rlookup_x: setting up setup_dir_inode %lu...\n",
+inode->i_ino));
+			umsdos_setup_dir(dentry);
 		}
-		iput (dir);
 	}
+out:
 	PRINTK ((KERN_DEBUG "umsdos_rlookup_x: returning %d\n", ret));
 	return ret;
 }
 
 
-int UMSDOS_rlookup (
-			   struct inode *dir,
-			   struct dentry *dentry
-)
+int UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry)
 {
-	PRINTK ((KERN_DEBUG "UMSDOS_rlookup /mn/: executing umsdos_rlookup_x for ino=%lu in %.*s\n", dir->i_ino, (int) dentry->d_name.len, dentry->d_name.name));
 	return umsdos_rlookup_x (dir, dentry, 0);
 }
 
 
-static int UMSDOS_rrmdir (
-				 struct inode *dir,
-				 struct dentry *dentry)
+/* #Specification: dual mode / rmdir in a DOS directory
+ * In a DOS (not EMD in it) directory, we use a reverse strategy
+ * compared with a UMSDOS directory. We assume that a subdirectory
+ * of a DOS directory is also a DOS directory. This is not always
+ * true (umssync may be used anywhere), but makes sense.
+ * 
+ * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
+ * then we check if it is a Umsdos directory. We check if it is
+ * really empty (only . .. and --linux-.--- in it). If it is true
+ * we remove the EMD and do a msdos_rmdir() again.
+ * 
+ * In a Umsdos directory, we assume all subdirectories are also
+ * Umsdos directories, so we check the EMD file first.
+ */
+/* #Specification: pseudo root / rmdir /DOS
+ * The pseudo sub-directory /DOS can't be removed!
+ * This is done even if the pseudo root is not a Umsdos
+ * directory anymore (very unlikely), but an accident (under
+ * MS-DOS) is always possible.
+ * 
+ * EPERM is returned.
+ */
+static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
 {
-	/* #Specification: dual mode / rmdir in a DOS directory
-	 * In a DOS (not EMD in it) directory, we use a reverse strategy
-	 * compared with a UMSDOS directory. We assume that a subdirectory
-	 * of a DOS directory is also a DOS directory. This is not always
-	 * true (umssync may be used anywhere), but make sense.
-	 * 
-	 * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
-	 * then we check if it is a Umsdos directory. We check if it is
-	 * really empty (only . .. and --linux-.--- in it). If it is true
-	 * we remove the EMD and do a msdos_rmdir() again.
-	 * 
-	 * In a Umsdos directory, we assume all subdirectory are also
-	 * Umsdos directory, so we check the EMD file first.
-	 */
-	int ret;
+	int ret, empty;
 
-	if (umsdos_is_pseudodos (dir, dentry)) {
-		/* #Specification: pseudo root / rmdir /DOS
-		 * The pseudo sub-directory /DOS can't be removed!
-		 * This is done even if the pseudo root is not a Umsdos
-		 * directory anymore (very unlikely), but an accident (under
-		 * MS-DOS) is always possible.
-		 * 
-		 * EPERM is returned.
-		 */
-		ret = -EPERM;
-	} else {
-		umsdos_lockcreate (dir);
-		inc_count (dir);
-		ret = msdos_rmdir (dir, dentry);
-		if (ret == -ENOTEMPTY) {
-			struct inode *sdir;
-
-			inc_count (dir);
-
-			ret = UMSDOS_rlookup (dir, dentry);
-			sdir = dentry->d_inode;
-			PRINTK (("rrmdir lookup %d ", ret));
-			if (ret == 0) {
-				int empty;
-
-				if ((empty = umsdos_isempty (sdir)) != 0) {
-					PRINTK (("isempty %d i_count %d ", empty,
-					  atomic_read (&sdir->i_count)));
-					if (empty == 2) {
-						/*
-						 * Not a Umsdos directory, so the previous msdos_rmdir
-						 * was not lying :-)
-						 */
-						ret = -ENOTEMPTY;
-					} else if (empty == 1) {
-						/* We have to remove the EMD file. */
-						struct dentry *temp;
-
-						Printk ((KERN_WARNING "UMSDOS_rmdir: hmmm... what about inode? FIXME\n"));
-						temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL);	/* FIXME: probably should fill inode part ? */
-						ret = msdos_unlink (sdir, temp);
-						sdir = NULL;
-						if (ret == 0) {
-							inc_count (dir);
-							ret = msdos_rmdir (dir, dentry);
-						}
-					}
-				} else {
-					ret = -ENOTEMPTY;
-				}
-				/* iput (sdir); FIXME */
-			}
+	ret = -EPERM;
+	if (umsdos_is_pseudodos (dir, dentry))
+		goto out;
+
+	umsdos_lockcreate (dir);
+	ret = -EBUSY;
+	if (dentry->d_count > 1) {
+		shrink_dcache_parent(dentry);
+		if (dentry->d_count > 1)
+			goto out_unlock;
+	}
+
+	ret = msdos_rmdir (dir, dentry);
+	if (ret != -ENOTEMPTY)
+		goto out_check;
+
+#if 0	/* why do this? we have the dentry ... */
+	ret = UMSDOS_rlookup (dir, dentry);
+	PRINTK (("rrmdir lookup %d ", ret));
+	if (ret)
+		goto out_unlock;
+	ret = -ENOTEMPTY;
+#endif
+
+	empty = umsdos_isempty (dentry);
+	if (empty == 1) {
+		struct dentry *temp;
+		/* We have to remove the EMD file. */
+		temp = umsdos_lookup_dentry(dentry, UMSDOS_EMD_FILE, 
+						UMSDOS_EMD_NAMELEN);
+		ret = PTR_ERR(temp);
+		if (!IS_ERR(temp)) {
+			ret = 0;
+			if (temp->d_inode)
+				ret = msdos_unlink (dentry->d_inode, temp);
+			dput(temp);
 		}
-		umsdos_unlockcreate (dir);
+		if (ret)
+			goto out_unlock;
 	}
-	/* iput (dir); FIXME */
+	/* now retry the original ... */
+	ret = msdos_rmdir (dir, dentry);
+
+out_check:
+	/* Check whether we succeeded ... */
+	if (!ret)
+		d_delete(dentry);
+
+out_unlock:
+	umsdos_unlockcreate (dir);
+out:
 	check_inode (dir);
 	return ret;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov