summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/autofs/expire.c103
1 files changed, 32 insertions, 71 deletions
diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index cdff0567aacb..2866fabf497f 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -70,6 +70,27 @@ done:
70 return status; 70 return status;
71} 71}
72 72
73/* p->d_lock held */
74static struct dentry *positive_after(struct dentry *p, struct dentry *child)
75{
76 if (child)
77 child = list_next_entry(child, d_child);
78 else
79 child = list_first_entry(&p->d_subdirs, struct dentry, d_child);
80
81 list_for_each_entry_from(child, &p->d_subdirs, d_child) {
82 spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
83 if (simple_positive(child)) {
84 dget_dlock(child);
85 spin_unlock(&child->d_lock);
86 return child;
87 }
88 spin_unlock(&child->d_lock);
89 }
90
91 return NULL;
92}
93
73/* 94/*
74 * Calculate and dget next entry in the subdirs list under root. 95 * Calculate and dget next entry in the subdirs list under root.
75 */ 96 */
@@ -77,43 +98,14 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev,
77 struct dentry *root) 98 struct dentry *root)
78{ 99{
79 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb); 100 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
80 struct list_head *next;
81 struct dentry *q; 101 struct dentry *q;
82 102
83 spin_lock(&sbi->lookup_lock); 103 spin_lock(&sbi->lookup_lock);
84 spin_lock(&root->d_lock); 104 spin_lock(&root->d_lock);
85 105 q = positive_after(root, prev);
86 if (prev)
87 next = prev->d_child.next;
88 else {
89 prev = dget_dlock(root);
90 next = prev->d_subdirs.next;
91 }
92
93cont:
94 if (next == &root->d_subdirs) {
95 spin_unlock(&root->d_lock);
96 spin_unlock(&sbi->lookup_lock);
97 dput(prev);
98 return NULL;
99 }
100
101 q = list_entry(next, struct dentry, d_child);
102
103 spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
104 /* Already gone or negative dentry (under construction) - try next */
105 if (!d_count(q) || !simple_positive(q)) {
106 spin_unlock(&q->d_lock);
107 next = q->d_child.next;
108 goto cont;
109 }
110 dget_dlock(q);
111 spin_unlock(&q->d_lock);
112 spin_unlock(&root->d_lock); 106 spin_unlock(&root->d_lock);
113 spin_unlock(&sbi->lookup_lock); 107 spin_unlock(&sbi->lookup_lock);
114
115 dput(prev); 108 dput(prev);
116
117 return q; 109 return q;
118} 110}
119 111
@@ -124,59 +116,28 @@ static struct dentry *get_next_positive_dentry(struct dentry *prev,
124 struct dentry *root) 116 struct dentry *root)
125{ 117{
126 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb); 118 struct autofs_sb_info *sbi = autofs_sbi(root->d_sb);
127 struct list_head *next; 119 struct dentry *p = prev, *ret = NULL, *d = NULL;
128 struct dentry *p, *ret;
129 120
130 if (prev == NULL) 121 if (prev == NULL)
131 return dget(root); 122 return dget(root);
132 123
133 spin_lock(&sbi->lookup_lock); 124 spin_lock(&sbi->lookup_lock);
134relock:
135 p = prev;
136 spin_lock(&p->d_lock); 125 spin_lock(&p->d_lock);
137again: 126 while (1) {
138 next = p->d_subdirs.next; 127 struct dentry *parent;
139 if (next == &p->d_subdirs) {
140 while (1) {
141 struct dentry *parent;
142
143 if (p == root) {
144 spin_unlock(&p->d_lock);
145 spin_unlock(&sbi->lookup_lock);
146 dput(prev);
147 return NULL;
148 }
149 128
150 parent = p->d_parent; 129 ret = positive_after(p, d);
151 if (!spin_trylock(&parent->d_lock)) { 130 if (ret || p == root)
152 spin_unlock(&p->d_lock); 131 break;
153 cpu_relax(); 132 parent = p->d_parent;
154 goto relock;
155 }
156 spin_unlock(&p->d_lock);
157 next = p->d_child.next;
158 p = parent;
159 if (next != &parent->d_subdirs)
160 break;
161 }
162 }
163 ret = list_entry(next, struct dentry, d_child);
164
165 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
166 /* Negative dentry - try next */
167 if (!simple_positive(ret)) {
168 spin_unlock(&p->d_lock); 133 spin_unlock(&p->d_lock);
169 lock_set_subclass(&ret->d_lock.dep_map, 0, _RET_IP_); 134 spin_lock(&parent->d_lock);
170 p = ret; 135 d = p;
171 goto again; 136 p = parent;
172 } 137 }
173 dget_dlock(ret);
174 spin_unlock(&ret->d_lock);
175 spin_unlock(&p->d_lock); 138 spin_unlock(&p->d_lock);
176 spin_unlock(&sbi->lookup_lock); 139 spin_unlock(&sbi->lookup_lock);
177
178 dput(prev); 140 dput(prev);
179
180 return ret; 141 return ret;
181} 142}
182 143