From: Anders Kaseorg Date: Tue, 7 May 2013 04:27:33 +0000 (-0400) Subject: Linux: osi_TryEvictVCache: Don’t skip the first dentry if D_ALIAS_IS_HLIST X-Git-Tag: upstream/1.6.3^2~7 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=a71cc5511c115c1b6cb4a6a2997a846bab6e19e2;p=packages%2Fo%2Fopenafs.git Linux: osi_TryEvictVCache: Don’t skip the first dentry if D_ALIAS_IS_HLIST An hlist doesn’t begin with a sentinel like a list does, so the old code would skip the first dentry or crash with a NULL dereference if there wasn’t one. Use the kernel’s list_for_each_entry or hlist_for_each_entry macros instead of trying to do it manually. Should fix a crash observed by Alex Chernyakhovsky on kernel 3.6 and newer. Signed-off-by: Anders Kaseorg Reviewed-on: http://gerrit.openafs.org/9857 Reviewed-by: Alex Chernyakhovsky Tested-by: Alex Chernyakhovsky Tested-by: BuildBot Reviewed-by: Marc Dionne Reviewed-by: Jeffrey Altman (cherry picked from commit ad6e31d5fea221bf5eefcd35a416667bc7c1f9be) Change-Id: Id8b31246067b5a718af91c8c206d5abd5210c558 Reviewed-on: http://gerrit.openafs.org/9898 Tested-by: BuildBot Reviewed-by: Marc Dionne Reviewed-by: Stephan Wiesand --- diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index dc3685b63..99aab919d 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -19,10 +19,8 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { struct dentry *dentry; struct inode *inode = AFSTOV(avc); -#if defined(D_ALIAS_IS_HLIST) - struct hlist_node *cur, *head, *list_end; -#else - struct list_head *cur, *head, *list_end; +#if defined(D_ALIAS_IS_HLIST) && !defined(HLIST_ITERATOR_NO_NODE) + struct hlist_node *p; #endif /* First, see if we can evict the inode from the dcache */ @@ -33,13 +31,9 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) { #if defined(HAVE_DCACHE_LOCK) spin_lock(&dcache_lock); - head = &inode->i_dentry; restart: - cur = head; - while ((cur = cur->next) != head) { - dentry = list_entry(cur, struct dentry, d_alias); - + list_for_each_entry(dentry, &inode->i_dentry, d_alias) { if (d_unhashed(dentry)) continue; dget_locked(dentry); @@ -57,23 +51,17 @@ restart: spin_unlock(&dcache_lock); #else /* HAVE_DCACHE_LOCK */ spin_lock(&inode->i_lock); -#if defined(D_ALIAS_IS_HLIST) - head = inode->i_dentry.first; - list_end = NULL; -#else - head = &inode->i_dentry; - list_end = head; -#endif restart: - cur = head; - while ((cur = cur->next) != list_end) { #if defined(D_ALIAS_IS_HLIST) - dentry = hlist_entry(cur, struct dentry, d_alias); +# if defined(HLIST_ITERATOR_NO_NODE) + hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { +# else + hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { +# endif #else - dentry = list_entry(cur, struct dentry, d_alias); + list_for_each_entry(dentry, &inode->i_dentry, d_alias) { #endif - spin_lock(&dentry->d_lock); if (d_unhashed(dentry)) { spin_unlock(&dentry->d_lock);