mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Support for dx directories in ext3_get_parent (NFSD)
@ 2005-05-09  8:57 Henrik Grubbström
  2005-05-09  9:24 ` Andreas Dilger
  0 siblings, 1 reply; 8+ messages in thread
From: Henrik Grubbström @ 2005-05-09  8:57 UTC (permalink / raw)
  To: sct, akpm, adilger, neilb; +Cc: linux-kernel

The 2.6.10 ext3_get_parent attempts to use ext3_find_entry to look up the
entry "..", which fails for dx directories since ".." is not present in
the directory hash table. The patch below solves this by looking up the
dotdot entry in the dx_root block.

Typical symptoms of the above bug are intermittent claims by nfsd that
files or directories are missing on exported ext3 filesystems.

cf https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=150759
and https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=144556

Signed-off-by: Henrik Grubbström <grubba@grubba.org>

--- linux/fs/ext3/namei.c.orig	2005-05-06 17:08:31.000000000 +0200
+++ linux/fs/ext3/namei.c	2005-05-07 17:57:24.000000000 +0200
@@ -999,24 +999,90 @@ static struct dentry *ext3_lookup(struct
 
 struct dentry *ext3_get_parent(struct dentry *child)
 {
-	unsigned long ino;
+	unsigned long ino = 0;
 	struct dentry *parent;
 	struct inode *inode;
-	struct dentry dotdot;
-	struct ext3_dir_entry_2 * de;
 	struct buffer_head *bh;
+	int err;
+	struct inode *dir = child->d_inode;
+	struct super_block *sb = dir->i_sb;
 
-	dotdot.d_name.name = "..";
-	dotdot.d_name.len = 2;
-	dotdot.d_parent = child; /* confusing, isn't it! */
+	/* In all cases the ".." entry is in block #0, so read it. */
+	bh = ext3_bread(NULL, dir, 0, 0, &err);
+	if (!bh) return ERR_PTR(err);
+
+#ifdef CONFIG_EXT3_INDEX
+	if (is_dx(dir)) {
+		/* Block #0 is a dx_root. */
+		struct dx_root *root = (struct dx_root *)bh->b_data;
+		if (root->info.hash_version == DX_HASH_TEA ||
+		    root->info.hash_version == DX_HASH_HALF_MD4 ||
+		    root->info.hash_version == DX_HASH_LEGACY) {
+			/* Is this paranoia actually needed? */
+			ino = le32_to_cpu(root->dotdot.inode);
+		} else {
+			ext3_error(sb, __FUNCTION__,
+				"unsupported dx hash_version (%d) for #%lu\n",
+				root->info.hash_version, dir->i_ino);
+		}
+	}
+	if (!ino)
+#endif
+	{
+		/* Block #0 is a sequence of ext3_dir_entry_2.
+		 * ".." is the second entry.
+		 */
+		struct ext3_dir_entry_2 *de =
+			(struct ext3_dir_entry_2 *)bh->b_data;
+		int len = le16_to_cpu(de->rec_len);
+		if (len > 0) {
+			/* The first entry should be ".". */
+			de = (struct ext3_dir_entry_2 *)((char *)de + len);
+			if ((de->name_len == 2) &&
+			    (de->name[0] == '.') &&
+			    (de->name[1] == '.')) {
+				/* The second entry should be "..". */
+				ino = le32_to_cpu(de->inode);
+			} else {
+				ext3_warning(sb, __FUNCTION__,
+					"second entry of #%lu not parent",
+					dir->i_ino);
+			}
+		} else {
+			ext3_error(sb, __FUNCTION__,
+				"first entry of #%lu has bad rec_len: %d",
+				dir->i_ino, len);
+		}
+#if 0
+		/* Fallback code to enable if the ".." entry ever can
+		 * be somewhere else than in the second entry of the
+		 * first block.
+		 */
+		if (!ino) {
+			struct dentry dotdot;
+
+			ext3_warning(sb, __FUNCTION__,
+				"falling back to ext3_find_entry for #%lu\n",
+				dir->i_ino);
+			brelse(bh);
+			dotdot.d_name.name = "..";
+			dotdot.d_name.len = 2;
+			dotdot.d_parent = child; /* confusing, isn't it! */
+
+			bh = ext3_find_entry(&dotdot, &de);
+			if (!bh)
+				return ERR_PTR(-ENOENT);
+			ino = le32_to_cpu(de->inode);
+		}
+#endif /* 0 */
+	}
 
-	bh = ext3_find_entry(&dotdot, &de);
-	inode = NULL;
-	if (!bh)
-		return ERR_PTR(-ENOENT);
-	ino = le32_to_cpu(de->inode);
 	brelse(bh);
-	inode = iget(child->d_inode->i_sb, ino);
+
+	if (!ino)
+		return ERR_PTR(-ENOENT);
+
+	inode = iget(sb, ino);
 
 	if (!inode)
 		return ERR_PTR(-EACCES);

--
Henrik Grubbström					grubba@grubba.org
Roxen Internet Software AB				grubba@roxen.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2005-05-09 16:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <42chI-3Rf-49@gated-at.bofh.it>
     [not found] ` <42cKy-4jT-9@gated-at.bofh.it>
2005-05-09 14:24   ` [PATCH] Support for dx directories in ext3_get_parent (NFSD) Bodo Eggert <harvested.in.lkml@posting.7eggert.dyndns.org>
2005-05-09 15:45     ` Stephen C. Tweedie
2005-05-09 16:55       ` Bodo Eggert
2005-05-09  8:57 Henrik Grubbström
2005-05-09  9:24 ` Andreas Dilger
2005-05-09  9:46   ` Henrik Grubbström
2005-05-09 14:05     ` Stephen C. Tweedie
2005-05-09 14:59       ` Henrik Grubbström

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®