mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 05:27:44 +00:00
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. Change-Id: I6d7bd190013a0250ca896af8d5182df55a3376b0 Signed-off-by: Anders Kaseorg <andersk@mit.edu> Reviewed-on: http://gerrit.openafs.org/9857 Reviewed-by: Alex Chernyakhovsky <achernya@mit.edu> Tested-by: Alex Chernyakhovsky <achernya@mit.edu> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Marc Dionne <marc.c.dionne@gmail.com> Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
This commit is contained in:
parent
13a3ba7ba2
commit
ad6e31d5fe
@ -19,10 +19,8 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep) {
|
|||||||
|
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct inode *inode = AFSTOV(avc);
|
struct inode *inode = AFSTOV(avc);
|
||||||
#if defined(D_ALIAS_IS_HLIST)
|
#if defined(D_ALIAS_IS_HLIST) && !defined(HLIST_ITERATOR_NO_NODE)
|
||||||
struct hlist_node *cur, *head, *list_end;
|
struct hlist_node *p;
|
||||||
#else
|
|
||||||
struct list_head *cur, *head, *list_end;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* First, see if we can evict the inode from the dcache */
|
/* 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)
|
#if defined(HAVE_DCACHE_LOCK)
|
||||||
spin_lock(&dcache_lock);
|
spin_lock(&dcache_lock);
|
||||||
head = &inode->i_dentry;
|
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
cur = head;
|
list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
|
||||||
while ((cur = cur->next) != head) {
|
|
||||||
dentry = list_entry(cur, struct dentry, d_alias);
|
|
||||||
|
|
||||||
if (d_unhashed(dentry))
|
if (d_unhashed(dentry))
|
||||||
continue;
|
continue;
|
||||||
dget_locked(dentry);
|
dget_locked(dentry);
|
||||||
@ -57,23 +51,17 @@ restart:
|
|||||||
spin_unlock(&dcache_lock);
|
spin_unlock(&dcache_lock);
|
||||||
#else /* HAVE_DCACHE_LOCK */
|
#else /* HAVE_DCACHE_LOCK */
|
||||||
spin_lock(&inode->i_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:
|
restart:
|
||||||
cur = head;
|
|
||||||
while ((cur = cur->next) != list_end) {
|
|
||||||
#if defined(D_ALIAS_IS_HLIST)
|
#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
|
# else
|
||||||
dentry = list_entry(cur, struct dentry, d_alias);
|
hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
spin_lock(&dentry->d_lock);
|
||||||
if (d_unhashed(dentry)) {
|
if (d_unhashed(dentry)) {
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user