[OpenAFS-devel] Re: OpenAFS client crashes on RHEL 5.10 and RHEL 6.5

Andrew Deason adeason@sinenomine.net
Tue, 18 Mar 2014 14:16:12 -0500


On Tue, 18 Mar 2014 14:04:12 -0500
Andrew Deason <adeason@sinenomine.net> wrote:

> Due to the various bug reports filed about this issue, Red Hat has
> indicated that they are considering this issue a regression in Red Hat
> Enterprise Linux and will be providing a fix in at least RHEL 6.6 and an
> RHEL 6.5 update. Red Hat has not yet indicated that a fix will be
> available for RHEL 5, though they will probably be investigating a fix
> for that version.

The following is a fix from Red Hat that I was testing against. Red Hat
is okay with sharing this, but they want it to be clear that running
with this is _not_ supported, and the actual fix that makes it into 6.6
et al may be different.

Anyway, I wanted to share this so others can confirm my thoughts and to
see what's probably going to happen:

---------------------

diff --git a/fs/dcache.c b/fs/dcache.c
index 81aa7ba..59a0ae3 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1220,6 +1220,19 @@ struct dentry *d_obtain_alias(struct inode *inode)
 }
 EXPORT_SYMBOL(d_obtain_alias);

+static struct dentry *__find_moveable_alias(struct inode *inode,
+                                               struct dentry *parent)
+{
+       struct dentry *alias;
+
+       if (list_empty(&inode->i_dentry))
+               return NULL;
+       alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
+       if (alias->d_parent == parent || IS_ROOT(alias))
+               return __dget_locked(alias);
+       return NULL;
+}
+
 /**
  * d_splice_alias - splice a disconnected dentry into the tree if one exists
  * @inode:  the inode which may have a disconnected dentry
@@ -1242,20 +1255,14 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)

        if (inode && S_ISDIR(inode->i_mode)) {
                spin_lock(&dcache_lock);
-               new = __d_find_any_alias(inode);
+               new = __find_moveable_alias(inode, dentry->d_parent);
                if (new) {
-                       if (new->d_parent != dentry->d_parent &&
-                                       !IS_ROOT(new->d_parent)) {
-                               WARN_ON_ONCE(1);
-                               goto add_duplicate_alias;
-                       }
                        spin_unlock(&dcache_lock);
                        security_d_instantiate(new, inode);
                        d_rehash(dentry);
                        d_move(new, dentry);
                        iput(inode);
                } else {
-add_duplicate_alias:
                        /* already taking dcache_lock, so d_add() by hand */
                        __d_instantiate(dentry, inode);
                        spin_unlock(&dcache_lock);

------------------

That seems like it gets rid of any problems. Now 'new' will be NULL if
it finds a "non-moveable alias", so we still get to use our aliased
dentry. If the duplicate mount point is in the same parent dir, it may
be a little strange since we may ping-pong d_move'ing back and forth
between the entries, but I can't find any actual problems with that
happening.

-- 
Andrew Deason
adeason@sinenomine.net