From 5fa406177428ff6249f905d700e98856e81d7565 Mon Sep 17 00:00:00 2001 From: shadow Date: Mon, 8 Sep 2008 09:04:09 +0000 Subject: [PATCH] add workaround for race in dcache with patchless client. Branch HEAD b=15975 i=johann i=adilger --- lustre/ChangeLog | 5 +++++ lustre/llite/dcache.c | 9 +++++++++ lustre/llite/file.c | 2 ++ lustre/llite/llite_internal.h | 5 +++++ lustre/llite/namei.c | 6 ++++++ 5 files changed, 27 insertions(+) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 797184c..f82850f 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -12,6 +12,11 @@ tbd Sun Microsystems, Inc. * RHEL 4 and RHEL 5/SLES 10 clients behaves differently on 'cd' to a removed cwd "./" (refer to Bugzilla 14399). +Severity : normal +Bugzilla : 15975 +Frequency : only patchless client +Description: add workaround for race between add/remove dentry from hash + Severity : enhancement Bugzilla : 16845 Description: Allow OST glimpses to return PW locks diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 117dde7..afb1a85 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -51,6 +51,8 @@ #include "llite_internal.h" +spinlock_t ll_lookup_lock = SPIN_LOCK_UNLOCKED; + /* should NOT be called with the dcache lock, see fs/dcache.c */ void ll_release(struct dentry *de) { @@ -209,7 +211,9 @@ int ll_drop_dentry(struct dentry *dentry) __d_drop(dentry); unlock_dentry(dentry); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); dput(dentry); + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); return 1; } @@ -257,6 +261,7 @@ void ll_unhash_aliases(struct inode *inode) inode->i_ino, inode->i_generation, inode); head = &inode->i_dentry; + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); restart: tmp = head; @@ -290,6 +295,8 @@ restart: goto restart; } spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); + EXIT; } @@ -506,12 +513,14 @@ revalidate_finish: /* unfortunately ll_intent_lock may cause a callback and revoke our * dentry */ + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); lock_dentry(de); __d_drop(de); unlock_dentry(de); d_rehash_cond(de, 0); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); out: /* We do not free request as it may be reused during following lookup diff --git a/lustre/llite/file.c b/lustre/llite/file.c index ce1169f..c46aa0b 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -3044,9 +3044,11 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) here to preserve get_cwd functionality on 2.6. Bug 10503 */ if (!dentry->d_inode->i_nlink) { + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); ll_drop_dentry(dentry); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); } ll_lookup_finish_locks(&oit, dentry); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index b5d9257..8631e1e 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -813,6 +813,11 @@ int ll_extent_lock_cancel_cb(struct ldlm_lock *lock, struct ldlm_lock_desc *new, void *data, int flag); /* llite/dcache.c */ +/* llite/namei.c */ +/** + * protect race ll_find_aliases vs ll_revalidate_it vs ll_unhash_aliases + */ +extern spinlock_t ll_lookup_lock; extern struct dentry_operations ll_init_d_ops; extern struct dentry_operations ll_d_ops; extern struct dentry_operations ll_fini_d_ops; diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index fac47a3..1bd7c2c 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -141,6 +141,7 @@ static void ll_drop_negative_dentry(struct inode *dir) { struct dentry *dentry, *tmp_alias, *tmp_subdir; + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); restart: list_for_each_entry_safe(dentry, tmp_alias, @@ -161,6 +162,7 @@ restart: } } spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); } @@ -335,6 +337,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) struct dentry *dentry; struct dentry *last_discon = NULL; + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); list_for_each(tmp, &inode->i_dentry) { dentry = list_entry(tmp, struct dentry, d_alias); @@ -373,6 +376,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) unlock_dentry(dentry); d_rehash_cond(dentry, 0); /* avoid taking dcache_lock inside */ spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); iput(inode); CDEBUG(D_DENTRY, "alias dentry %.*s (%p) parent %p inode %p " "refc %d\n", de->d_name.len, de->d_name.name, de, @@ -386,6 +390,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) atomic_read(&last_discon->d_count)); dget_locked(last_discon); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); d_rehash(de); d_move(last_discon, de); iput(inode); @@ -395,6 +400,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) ll_d_add(de, inode); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); return de; } -- 1.8.3.1