diff options
author | Ian Kent <raven@themaw.net> | 2011-03-24 13:51:20 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-24 14:54:34 -0400 |
commit | d4a85e35d1465da055264407d8395e84483084e6 (patch) | |
tree | d3bdbf9edd438ecd1a6de1bc30b9c13b466559e5 /fs/autofs4/expire.c | |
parent | f9398c233e3201874395eea8558eb616fb198648 (diff) |
autofs4 - fix autofs4_expire_indirect() traversal
The vfs-scale changes changed the traversal used in
autofs4_expire_indirect() from a list to a depth first tree traversal
which isn't right.
Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r-- | fs/autofs4/expire.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index c403abcc725b..bc482e07b925 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -87,6 +87,56 @@ done: | |||
87 | } | 87 | } |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Calculate and dget next entry in the subdirs list under root. | ||
91 | */ | ||
92 | static struct dentry *get_next_positive_subdir(struct dentry *prev, | ||
93 | struct dentry *root) | ||
94 | { | ||
95 | struct list_head *next; | ||
96 | struct dentry *p, *q; | ||
97 | |||
98 | spin_lock(&autofs4_lock); | ||
99 | |||
100 | if (prev == NULL) { | ||
101 | spin_lock(&root->d_lock); | ||
102 | prev = dget_dlock(root); | ||
103 | next = prev->d_subdirs.next; | ||
104 | p = prev; | ||
105 | goto start; | ||
106 | } | ||
107 | |||
108 | p = prev; | ||
109 | spin_lock(&p->d_lock); | ||
110 | again: | ||
111 | next = p->d_u.d_child.next; | ||
112 | start: | ||
113 | if (next == &root->d_subdirs) { | ||
114 | spin_unlock(&p->d_lock); | ||
115 | spin_unlock(&autofs4_lock); | ||
116 | dput(prev); | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | q = list_entry(next, struct dentry, d_u.d_child); | ||
121 | |||
122 | spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); | ||
123 | /* Negative dentry - try next */ | ||
124 | if (!simple_positive(q)) { | ||
125 | spin_unlock(&p->d_lock); | ||
126 | p = q; | ||
127 | goto again; | ||
128 | } | ||
129 | dget_dlock(q); | ||
130 | spin_unlock(&q->d_lock); | ||
131 | spin_unlock(&p->d_lock); | ||
132 | spin_unlock(&autofs4_lock); | ||
133 | |||
134 | dput(prev); | ||
135 | |||
136 | return q; | ||
137 | } | ||
138 | |||
139 | /* | ||
90 | * Calculate and dget next entry in top down tree traversal. | 140 | * Calculate and dget next entry in top down tree traversal. |
91 | */ | 141 | */ |
92 | static struct dentry *get_next_positive_dentry(struct dentry *prev, | 142 | static struct dentry *get_next_positive_dentry(struct dentry *prev, |
@@ -333,7 +383,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
333 | timeout = sbi->exp_timeout; | 383 | timeout = sbi->exp_timeout; |
334 | 384 | ||
335 | dentry = NULL; | 385 | dentry = NULL; |
336 | while ((dentry = get_next_positive_dentry(dentry, root))) { | 386 | while ((dentry = get_next_positive_subdir(dentry, root))) { |
337 | spin_lock(&sbi->fs_lock); | 387 | spin_lock(&sbi->fs_lock); |
338 | ino = autofs4_dentry_ino(dentry); | 388 | ino = autofs4_dentry_ino(dentry); |
339 | /* No point expiring a pending mount */ | 389 | /* No point expiring a pending mount */ |