To: linux-m68k@lists.linux-m68k.org
Subject: L68K: Patches for minixfs
X-Yow: Is this TERMINAL fun?
From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Date: 21 Nov 1997 11:24:40 +0100
Sender: owner-linux-m68k@phil.uni-sb.de

Hi!

This patch for the minix filesystem adds proper filename alias handling
and fixes a check for busy directories in rmdir.

Andreas.

----------------------------------------------------------------------
--- linux/fs/minix/inode.c.~1~	Mon Jul 28 17:29:54 1997
+++ linux/fs/minix/inode.c	Sat Aug 23 16:33:09 1997
@@ -280,6 +280,7 @@
 		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
+	s->s_root->d_op = &minix_dentry_operations;
 
 	errmsg = minix_checkroot(s, root_inode);
 	if (errmsg) {
--- linux/fs/minix/namei.c.~1~	Thu Sep 18 17:51:26 1997
+++ linux/fs/minix/namei.c	Thu Nov 20 20:56:01 1997
@@ -23,34 +23,12 @@
 static inline int namecompare(int len, int maxlen,
 	const char * name, const char * buffer)
 {
-	if (len > maxlen)
-		return 0;
 	if (len < maxlen && buffer[len])
 		return 0;
 	return !memcmp(name, buffer, len);
 }
 
 /*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use minix_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure.
- */
-static int minix_match(int len, const char * name,
-	struct buffer_head * bh, unsigned long * offset,
-	struct minix_sb_info * info)
-{
-	struct minix_dir_entry * de;
-
-	de = (struct minix_dir_entry *) (bh->b_data + *offset);
-	*offset += info->s_dirsize;
-	if (!de->inode || len > info->s_namelen)
-		return 0;
-	return namecompare(len,info->s_namelen,name,de->name);
-}
-
-/*
  *	minix_find_entry()
  *
  * finds an entry in the specified directory with the wanted name. It
@@ -64,18 +42,16 @@
 	unsigned long block, offset;
 	struct buffer_head * bh;
 	struct minix_sb_info * info;
+	struct minix_dir_entry *de;
 
 	*res_dir = NULL;
 	if (!dir || !dir->i_sb)
 		return NULL;
 	info = &dir->i_sb->u.minix_sb;
-	if (namelen > info->s_namelen) {
 #ifdef NO_TRUNCATE
+	if (namelen > info->s_namelen)
 		return NULL;
-#else
-		namelen = info->s_namelen;
 #endif
-	}
 	bh = NULL;
 	block = offset = 0;
 	while (block*BLOCK_SIZE+offset < dir->i_size) {
@@ -86,9 +62,12 @@
 				continue;
 			}
 		}
-		*res_dir = (struct minix_dir_entry *) (bh->b_data + offset);
-		if (minix_match(namelen,name,bh,&offset,info))
+		de = (struct minix_dir_entry *) (bh->b_data + offset);
+		offset += info->s_dirsize;
+		if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) {
+			*res_dir = de;
 			return bh;
+		}
 		if (offset < bh->b_size)
 			continue;
 		brelse(bh);
@@ -97,16 +76,52 @@
 		block++;
 	}
 	brelse(bh);
-	*res_dir = NULL;
 	return NULL;
 }
 
+#ifndef NO_TRUNCATE
+
+static int minix_hash(struct dentry *dentry, struct qstr *qstr)
+{
+	unsigned long hash;
+	int i;
+	const char *name;
+
+	i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
+	if (i >= qstr->len)
+		return 0;
+	/* Truncate the name in place, avoids having to define a compare
+	   function. */
+	qstr->len = i;
+	name = qstr->name;
+	hash = init_name_hash();
+	while (i--)
+		hash = partial_name_hash(*name++, hash);
+	qstr->hash = end_name_hash(hash);
+	return 0;
+}
+
+#endif
+
+struct dentry_operations minix_dentry_operations = {
+	0,		/* revalidate */
+#ifndef NO_TRUNCATE
+	minix_hash,
+#else
+	0,
+#endif
+	0		/* compare */
+};
+
 int minix_lookup(struct inode * dir, struct dentry *dentry)
 {
 	struct inode * inode = NULL;
 	struct minix_dir_entry * de;
 	struct buffer_head * bh;
 
+#ifndef NO_TRUNCATE
+	dentry->d_op = &minix_dentry_operations;
+#endif
 	bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
 	if (bh) {
 		int ino = de->inode;
@@ -146,13 +161,10 @@
 	if (!dir || !dir->i_sb)
 		return -ENOENT;
 	info = &dir->i_sb->u.minix_sb;
-	if (namelen > info->s_namelen) {
 #ifdef NO_TRUNCATE
+	if (namelen > info->s_namelen)
 		return -ENAMETOOLONG;
-#else
-		namelen = info->s_namelen;
 #endif
-	}
 	if (!namelen)
 		return -ENOENT;
 	bh = NULL;
@@ -434,7 +446,9 @@
 		retval = -ENOENT;
 		goto end_rmdir;
 	}
-	if (inode->i_count > 1) {
+	if (dentry->d_count > 1)
+		shrink_dcache_parent(dentry);
+	if (dentry->d_count > 1) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
--- linux/include/linux/minix_fs.h.~1~	Mon Oct 13 18:16:16 1997
+++ linux/include/linux/minix_fs.h	Mon Sep 22 18:23:20 1997
@@ -126,6 +126,7 @@
 extern struct inode_operations minix_file_inode_operations;
 extern struct inode_operations minix_dir_inode_operations;
 extern struct inode_operations minix_symlink_inode_operations;
+extern struct dentry_operations minix_dentry_operations;
 
 #endif /* __KERNEL__ */
 
