aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2011-03-24 13:51:20 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-24 14:54:34 -0400
commitd4a85e35d1465da055264407d8395e84483084e6 (patch)
treed3bdbf9edd438ecd1a6de1bc30b9c13b466559e5 /fs/autofs4/expire.c
parentf9398c233e3201874395eea8558eb616fb198648 (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.c52
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 */
92static 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);
110again:
111 next = p->d_u.d_child.next;
112start:
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 */
92static struct dentry *get_next_positive_dentry(struct dentry *prev, 142static 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 */