aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4/expire.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4/expire.c')
-rw-r--r--fs/autofs4/expire.c212
1 files changed, 137 insertions, 75 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index a796c9417fb1..450f529a4eae 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -26,10 +26,6 @@ static inline int autofs4_can_expire(struct dentry *dentry,
26 if (ino == NULL) 26 if (ino == NULL)
27 return 0; 27 return 0;
28 28
29 /* No point expiring a pending mount */
30 if (ino->flags & AUTOFS_INF_PENDING)
31 return 0;
32
33 if (!do_now) { 29 if (!do_now) {
34 /* Too young to die */ 30 /* Too young to die */
35 if (!timeout || time_after(ino->last_used + timeout, now)) 31 if (!timeout || time_after(ino->last_used + timeout, now))
@@ -56,7 +52,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
56 52
57 path_get(&path); 53 path_get(&path);
58 54
59 if (!follow_down(&path)) 55 if (!follow_down_one(&path))
60 goto done; 56 goto done;
61 57
62 if (is_autofs4_dentry(path.dentry)) { 58 if (is_autofs4_dentry(path.dentry)) {
@@ -91,24 +87,116 @@ done:
91} 87}
92 88
93/* 89/*
94 * Calculate next entry in top down tree traversal. 90 * Calculate and dget next entry in the subdirs list under root.
95 * From next_mnt in namespace.c - elegant.
96 */ 91 */
97static struct dentry *next_dentry(struct dentry *p, struct dentry *root) 92static struct dentry *get_next_positive_subdir(struct dentry *prev,
93 struct dentry *root)
98{ 94{
99 struct list_head *next = p->d_subdirs.next; 95 struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
96 struct list_head *next;
97 struct dentry *p, *q;
98
99 spin_lock(&sbi->lookup_lock);
100 100
101 if (prev == NULL) {
102 spin_lock(&root->d_lock);
103 prev = dget_dlock(root);
104 next = prev->d_subdirs.next;
105 p = prev;
106 goto start;
107 }
108
109 p = prev;
110 spin_lock(&p->d_lock);
111again:
112 next = p->d_u.d_child.next;
113start:
114 if (next == &root->d_subdirs) {
115 spin_unlock(&p->d_lock);
116 spin_unlock(&sbi->lookup_lock);
117 dput(prev);
118 return NULL;
119 }
120
121 q = list_entry(next, struct dentry, d_u.d_child);
122
123 spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
124 /* Negative dentry - try next */
125 if (!simple_positive(q)) {
126 spin_unlock(&p->d_lock);
127 p = q;
128 goto again;
129 }
130 dget_dlock(q);
131 spin_unlock(&q->d_lock);
132 spin_unlock(&p->d_lock);
133 spin_unlock(&sbi->lookup_lock);
134
135 dput(prev);
136
137 return q;
138}
139
140/*
141 * Calculate and dget next entry in top down tree traversal.
142 */
143static struct dentry *get_next_positive_dentry(struct dentry *prev,
144 struct dentry *root)
145{
146 struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
147 struct list_head *next;
148 struct dentry *p, *ret;
149
150 if (prev == NULL)
151 return dget(root);
152
153 spin_lock(&sbi->lookup_lock);
154relock:
155 p = prev;
156 spin_lock(&p->d_lock);
157again:
158 next = p->d_subdirs.next;
101 if (next == &p->d_subdirs) { 159 if (next == &p->d_subdirs) {
102 while (1) { 160 while (1) {
103 if (p == root) 161 struct dentry *parent;
162
163 if (p == root) {
164 spin_unlock(&p->d_lock);
165 spin_unlock(&sbi->lookup_lock);
166 dput(prev);
104 return NULL; 167 return NULL;
168 }
169
170 parent = p->d_parent;
171 if (!spin_trylock(&parent->d_lock)) {
172 spin_unlock(&p->d_lock);
173 cpu_relax();
174 goto relock;
175 }
176 spin_unlock(&p->d_lock);
105 next = p->d_u.d_child.next; 177 next = p->d_u.d_child.next;
106 if (next != &p->d_parent->d_subdirs) 178 p = parent;
179 if (next != &parent->d_subdirs)
107 break; 180 break;
108 p = p->d_parent;
109 } 181 }
110 } 182 }
111 return list_entry(next, struct dentry, d_u.d_child); 183 ret = list_entry(next, struct dentry, d_u.d_child);
184
185 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
186 /* Negative dentry - try next */
187 if (!simple_positive(ret)) {
188 spin_unlock(&p->d_lock);
189 p = ret;
190 goto again;
191 }
192 dget_dlock(ret);
193 spin_unlock(&ret->d_lock);
194 spin_unlock(&p->d_lock);
195 spin_unlock(&sbi->lookup_lock);
196
197 dput(prev);
198
199 return ret;
112} 200}
113 201
114/* 202/*
@@ -158,18 +246,11 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
158 if (!simple_positive(top)) 246 if (!simple_positive(top))
159 return 1; 247 return 1;
160 248
161 spin_lock(&dcache_lock); 249 p = NULL;
162 for (p = top; p; p = next_dentry(p, top)) { 250 while ((p = get_next_positive_dentry(p, top))) {
163 /* Negative dentry - give up */
164 if (!simple_positive(p))
165 continue;
166
167 DPRINTK("dentry %p %.*s", 251 DPRINTK("dentry %p %.*s",
168 p, (int) p->d_name.len, p->d_name.name); 252 p, (int) p->d_name.len, p->d_name.name);
169 253
170 p = dget(p);
171 spin_unlock(&dcache_lock);
172
173 /* 254 /*
174 * Is someone visiting anywhere in the subtree ? 255 * Is someone visiting anywhere in the subtree ?
175 * If there's no mount we need to check the usage 256 * If there's no mount we need to check the usage
@@ -198,16 +279,13 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
198 else 279 else
199 ino_count++; 280 ino_count++;
200 281
201 if (atomic_read(&p->d_count) > ino_count) { 282 if (p->d_count > ino_count) {
202 top_ino->last_used = jiffies; 283 top_ino->last_used = jiffies;
203 dput(p); 284 dput(p);
204 return 1; 285 return 1;
205 } 286 }
206 } 287 }
207 dput(p);
208 spin_lock(&dcache_lock);
209 } 288 }
210 spin_unlock(&dcache_lock);
211 289
212 /* Timeout of a tree mount is ultimately determined by its top dentry */ 290 /* Timeout of a tree mount is ultimately determined by its top dentry */
213 if (!autofs4_can_expire(top, timeout, do_now)) 291 if (!autofs4_can_expire(top, timeout, do_now))
@@ -226,32 +304,21 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
226 DPRINTK("parent %p %.*s", 304 DPRINTK("parent %p %.*s",
227 parent, (int)parent->d_name.len, parent->d_name.name); 305 parent, (int)parent->d_name.len, parent->d_name.name);
228 306
229 spin_lock(&dcache_lock); 307 p = NULL;
230 for (p = parent; p; p = next_dentry(p, parent)) { 308 while ((p = get_next_positive_dentry(p, parent))) {
231 /* Negative dentry - give up */
232 if (!simple_positive(p))
233 continue;
234
235 DPRINTK("dentry %p %.*s", 309 DPRINTK("dentry %p %.*s",
236 p, (int) p->d_name.len, p->d_name.name); 310 p, (int) p->d_name.len, p->d_name.name);
237 311
238 p = dget(p);
239 spin_unlock(&dcache_lock);
240
241 if (d_mountpoint(p)) { 312 if (d_mountpoint(p)) {
242 /* Can we umount this guy */ 313 /* Can we umount this guy */
243 if (autofs4_mount_busy(mnt, p)) 314 if (autofs4_mount_busy(mnt, p))
244 goto cont; 315 continue;
245 316
246 /* Can we expire this guy */ 317 /* Can we expire this guy */
247 if (autofs4_can_expire(p, timeout, do_now)) 318 if (autofs4_can_expire(p, timeout, do_now))
248 return p; 319 return p;
249 } 320 }
250cont:
251 dput(p);
252 spin_lock(&dcache_lock);
253 } 321 }
254 spin_unlock(&dcache_lock);
255 return NULL; 322 return NULL;
256} 323}
257 324
@@ -264,6 +331,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
264 unsigned long timeout; 331 unsigned long timeout;
265 struct dentry *root = dget(sb->s_root); 332 struct dentry *root = dget(sb->s_root);
266 int do_now = how & AUTOFS_EXP_IMMEDIATE; 333 int do_now = how & AUTOFS_EXP_IMMEDIATE;
334 struct autofs_info *ino;
267 335
268 if (!root) 336 if (!root)
269 return NULL; 337 return NULL;
@@ -272,17 +340,18 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
272 timeout = sbi->exp_timeout; 340 timeout = sbi->exp_timeout;
273 341
274 spin_lock(&sbi->fs_lock); 342 spin_lock(&sbi->fs_lock);
343 ino = autofs4_dentry_ino(root);
344 /* No point expiring a pending mount */
345 if (ino->flags & AUTOFS_INF_PENDING)
346 goto out;
275 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { 347 if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
276 struct autofs_info *ino = autofs4_dentry_ino(root); 348 struct autofs_info *ino = autofs4_dentry_ino(root);
277 if (d_mountpoint(root)) {
278 ino->flags |= AUTOFS_INF_MOUNTPOINT;
279 root->d_mounted--;
280 }
281 ino->flags |= AUTOFS_INF_EXPIRING; 349 ino->flags |= AUTOFS_INF_EXPIRING;
282 init_completion(&ino->expire_complete); 350 init_completion(&ino->expire_complete);
283 spin_unlock(&sbi->fs_lock); 351 spin_unlock(&sbi->fs_lock);
284 return root; 352 return root;
285 } 353 }
354out:
286 spin_unlock(&sbi->fs_lock); 355 spin_unlock(&sbi->fs_lock);
287 dput(root); 356 dput(root);
288 357
@@ -302,8 +371,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
302{ 371{
303 unsigned long timeout; 372 unsigned long timeout;
304 struct dentry *root = sb->s_root; 373 struct dentry *root = sb->s_root;
374 struct dentry *dentry;
305 struct dentry *expired = NULL; 375 struct dentry *expired = NULL;
306 struct list_head *next;
307 int do_now = how & AUTOFS_EXP_IMMEDIATE; 376 int do_now = how & AUTOFS_EXP_IMMEDIATE;
308 int exp_leaves = how & AUTOFS_EXP_LEAVES; 377 int exp_leaves = how & AUTOFS_EXP_LEAVES;
309 struct autofs_info *ino; 378 struct autofs_info *ino;
@@ -315,25 +384,13 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
315 now = jiffies; 384 now = jiffies;
316 timeout = sbi->exp_timeout; 385 timeout = sbi->exp_timeout;
317 386
318 spin_lock(&dcache_lock); 387 dentry = NULL;
319 next = root->d_subdirs.next; 388 while ((dentry = get_next_positive_subdir(dentry, root))) {
320
321 /* On exit from the loop expire is set to a dgot dentry
322 * to expire or it's NULL */
323 while ( next != &root->d_subdirs ) {
324 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
325
326 /* Negative dentry - give up */
327 if (!simple_positive(dentry)) {
328 next = next->next;
329 continue;
330 }
331
332 dentry = dget(dentry);
333 spin_unlock(&dcache_lock);
334
335 spin_lock(&sbi->fs_lock); 389 spin_lock(&sbi->fs_lock);
336 ino = autofs4_dentry_ino(dentry); 390 ino = autofs4_dentry_ino(dentry);
391 /* No point expiring a pending mount */
392 if (ino->flags & AUTOFS_INF_PENDING)
393 goto next;
337 394
338 /* 395 /*
339 * Case 1: (i) indirect mount or top level pseudo direct mount 396 * Case 1: (i) indirect mount or top level pseudo direct mount
@@ -347,7 +404,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
347 404
348 /* Path walk currently on this dentry? */ 405 /* Path walk currently on this dentry? */
349 ino_count = atomic_read(&ino->count) + 2; 406 ino_count = atomic_read(&ino->count) + 2;
350 if (atomic_read(&dentry->d_count) > ino_count) 407 if (dentry->d_count > ino_count)
351 goto next; 408 goto next;
352 409
353 /* Can we umount this guy */ 410 /* Can we umount this guy */
@@ -369,7 +426,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
369 if (!exp_leaves) { 426 if (!exp_leaves) {
370 /* Path walk currently on this dentry? */ 427 /* Path walk currently on this dentry? */
371 ino_count = atomic_read(&ino->count) + 1; 428 ino_count = atomic_read(&ino->count) + 1;
372 if (atomic_read(&dentry->d_count) > ino_count) 429 if (dentry->d_count > ino_count)
373 goto next; 430 goto next;
374 431
375 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { 432 if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
@@ -383,7 +440,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
383 } else { 440 } else {
384 /* Path walk currently on this dentry? */ 441 /* Path walk currently on this dentry? */
385 ino_count = atomic_read(&ino->count) + 1; 442 ino_count = atomic_read(&ino->count) + 1;
386 if (atomic_read(&dentry->d_count) > ino_count) 443 if (dentry->d_count > ino_count)
387 goto next; 444 goto next;
388 445
389 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); 446 expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
@@ -394,11 +451,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
394 } 451 }
395next: 452next:
396 spin_unlock(&sbi->fs_lock); 453 spin_unlock(&sbi->fs_lock);
397 dput(dentry);
398 spin_lock(&dcache_lock);
399 next = next->next;
400 } 454 }
401 spin_unlock(&dcache_lock);
402 return NULL; 455 return NULL;
403 456
404found: 457found:
@@ -408,9 +461,13 @@ found:
408 ino->flags |= AUTOFS_INF_EXPIRING; 461 ino->flags |= AUTOFS_INF_EXPIRING;
409 init_completion(&ino->expire_complete); 462 init_completion(&ino->expire_complete);
410 spin_unlock(&sbi->fs_lock); 463 spin_unlock(&sbi->fs_lock);
411 spin_lock(&dcache_lock); 464 spin_lock(&sbi->lookup_lock);
465 spin_lock(&expired->d_parent->d_lock);
466 spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
412 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); 467 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
413 spin_unlock(&dcache_lock); 468 spin_unlock(&expired->d_lock);
469 spin_unlock(&expired->d_parent->d_lock);
470 spin_unlock(&sbi->lookup_lock);
414 return expired; 471 return expired;
415} 472}
416 473
@@ -498,11 +555,16 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
498 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); 555 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
499 556
500 spin_lock(&sbi->fs_lock); 557 spin_lock(&sbi->fs_lock);
501 if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
502 sb->s_root->d_mounted++;
503 ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
504 }
505 ino->flags &= ~AUTOFS_INF_EXPIRING; 558 ino->flags &= ~AUTOFS_INF_EXPIRING;
559 spin_lock(&dentry->d_lock);
560 if (!ret) {
561 if ((IS_ROOT(dentry) ||
562 (autofs_type_indirect(sbi->type) &&
563 IS_ROOT(dentry->d_parent))) &&
564 !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
565 __managed_dentry_set_automount(dentry);
566 }
567 spin_unlock(&dentry->d_lock);
506 complete_all(&ino->expire_complete); 568 complete_all(&ino->expire_complete);
507 spin_unlock(&sbi->fs_lock); 569 spin_unlock(&sbi->fs_lock);
508 dput(dentry); 570 dput(dentry);