Blame view

fs/autofs4/expire.c 13.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /* -*- c -*- --------------------------------------------------------------- *
   *
   * linux/fs/autofs/expire.c
   *
   *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
   *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
7
   *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
   *
   * This file is part of the Linux kernel and is made available under
   * the terms of the GNU General Public License, version 2, or at your
   * option, any later version, incorporated herein by reference.
   *
   * ------------------------------------------------------------------------- */
  
  #include "autofs_i.h"
  
  static unsigned long now;
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
18
  /* Check if a dentry can be expired */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
26
  static inline int autofs4_can_expire(struct dentry *dentry,
  					unsigned long timeout, int do_now)
  {
  	struct autofs_info *ino = autofs4_dentry_ino(dentry);
  
  	/* dentry in the process of being deleted */
  	if (ino == NULL)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  	if (!do_now) {
  		/* Too young to die */
c0ba7e514   Ian Kent   [PATCH] autofs4: ...
29
  		if (!timeout || time_after(ino->last_used + timeout, now))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
  			return 0;
  
  		/* update last_used here :-
  		   - obviously makes sense if it is in use now
  		   - less obviously, prevents rapid-fire expire
  		     attempts if expire fails the first time */
  		ino->last_used = now;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
  	return 1;
  }
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
40
41
  /* Check a mount point for busyness */
  static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
43
  	struct dentry *top = dentry;
9393bd07c   Al Viro   switch follow_down()
44
  	struct path path = {.mnt = mnt, .dentry = dentry};
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
45
  	int status = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  
  	DPRINTK("dentry %p %.*s",
  		dentry, (int)dentry->d_name.len, dentry->d_name.name);
9393bd07c   Al Viro   switch follow_down()
49
  	path_get(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

cc53ce53c   David Howells   Add a dentry op t...
51
  	if (!follow_down_one(&path))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  		goto done;
9393bd07c   Al Viro   switch follow_down()
53
54
  	if (is_autofs4_dentry(path.dentry)) {
  		struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);
bc9c40683   Ian Kent   autofs4: correct ...
55
56
  
  		/* This is an autofs submount, we can't expire it */
a92daf6ba   Ian Kent   autofs4: make aut...
57
  		if (autofs_type_indirect(sbi->type))
bc9c40683   Ian Kent   autofs4: correct ...
58
59
60
61
62
63
  			goto done;
  
  		/*
  		 * Otherwise it's an offset mount and we need to check
  		 * if we can umount its mount, if there is one.
  		 */
9393bd07c   Al Viro   switch follow_down()
64
  		if (!d_mountpoint(path.dentry)) {
a8985f3ac   Ian Kent   autofs4: fix inco...
65
  			status = 0;
bc9c40683   Ian Kent   autofs4: correct ...
66
  			goto done;
a8985f3ac   Ian Kent   autofs4: fix inco...
67
  		}
bc9c40683   Ian Kent   autofs4: correct ...
68
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69

e0a7aae94   Ian Kent   [PATCH] autofs4: ...
70
  	/* Update the expiry counter if fs is busy */
37d0892c5   Ian Kent   autofs4 - fix mis...
71
  	if (!may_umount_tree(path.mnt)) {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
72
73
74
75
76
77
  		struct autofs_info *ino = autofs4_dentry_ino(top);
  		ino->last_used = jiffies;
  		goto done;
  	}
  
  	status = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  done:
  	DPRINTK("returning = %d", status);
9393bd07c   Al Viro   switch follow_down()
80
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  	return status;
  }
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
83
  /*
d4a85e35d   Ian Kent   autofs4 - fix aut...
84
85
86
87
88
   * Calculate and dget next entry in the subdirs list under root.
   */
  static struct dentry *get_next_positive_subdir(struct dentry *prev,
  						struct dentry *root)
  {
e7854723d   Ian Kent   autofs4 - remove ...
89
  	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
d4a85e35d   Ian Kent   autofs4 - fix aut...
90
91
  	struct list_head *next;
  	struct dentry *p, *q;
e7854723d   Ian Kent   autofs4 - remove ...
92
  	spin_lock(&sbi->lookup_lock);
d4a85e35d   Ian Kent   autofs4 - fix aut...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  
  	if (prev == NULL) {
  		spin_lock(&root->d_lock);
  		prev = dget_dlock(root);
  		next = prev->d_subdirs.next;
  		p = prev;
  		goto start;
  	}
  
  	p = prev;
  	spin_lock(&p->d_lock);
  again:
  	next = p->d_u.d_child.next;
  start:
  	if (next == &root->d_subdirs) {
  		spin_unlock(&p->d_lock);
e7854723d   Ian Kent   autofs4 - remove ...
109
  		spin_unlock(&sbi->lookup_lock);
d4a85e35d   Ian Kent   autofs4 - fix aut...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  		dput(prev);
  		return NULL;
  	}
  
  	q = list_entry(next, struct dentry, d_u.d_child);
  
  	spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
  	/* Negative dentry - try next */
  	if (!simple_positive(q)) {
  		spin_unlock(&p->d_lock);
  		p = q;
  		goto again;
  	}
  	dget_dlock(q);
  	spin_unlock(&q->d_lock);
  	spin_unlock(&p->d_lock);
e7854723d   Ian Kent   autofs4 - remove ...
126
  	spin_unlock(&sbi->lookup_lock);
d4a85e35d   Ian Kent   autofs4 - fix aut...
127
128
129
130
131
132
133
  
  	dput(prev);
  
  	return q;
  }
  
  /*
2fd6b7f50   Nick Piggin   fs: dcache scale ...
134
   * Calculate and dget next entry in top down tree traversal.
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
135
   */
2fd6b7f50   Nick Piggin   fs: dcache scale ...
136
137
  static struct dentry *get_next_positive_dentry(struct dentry *prev,
  						struct dentry *root)
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
138
  {
e7854723d   Ian Kent   autofs4 - remove ...
139
  	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
140
141
142
143
  	struct list_head *next;
  	struct dentry *p, *ret;
  
  	if (prev == NULL)
c14cc63a6   Ian Kent   autofs4 - fix get...
144
  		return dget(root);
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
145

e7854723d   Ian Kent   autofs4 - remove ...
146
  	spin_lock(&sbi->lookup_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
147
148
149
150
151
  relock:
  	p = prev;
  	spin_lock(&p->d_lock);
  again:
  	next = p->d_subdirs.next;
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
152
153
  	if (next == &p->d_subdirs) {
  		while (1) {
2fd6b7f50   Nick Piggin   fs: dcache scale ...
154
155
156
157
  			struct dentry *parent;
  
  			if (p == root) {
  				spin_unlock(&p->d_lock);
e7854723d   Ian Kent   autofs4 - remove ...
158
  				spin_unlock(&sbi->lookup_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
159
  				dput(prev);
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
160
  				return NULL;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
161
162
163
164
165
166
167
168
169
  			}
  
  			parent = p->d_parent;
  			if (!spin_trylock(&parent->d_lock)) {
  				spin_unlock(&p->d_lock);
  				cpu_relax();
  				goto relock;
  			}
  			spin_unlock(&p->d_lock);
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
170
  			next = p->d_u.d_child.next;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
171
172
  			p = parent;
  			if (next != &parent->d_subdirs)
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
173
  				break;
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
174
175
  		}
  	}
2fd6b7f50   Nick Piggin   fs: dcache scale ...
176
177
178
179
180
  	ret = list_entry(next, struct dentry, d_u.d_child);
  
  	spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
  	/* Negative dentry - try next */
  	if (!simple_positive(ret)) {
c14cc63a6   Ian Kent   autofs4 - fix get...
181
  		spin_unlock(&p->d_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
182
183
184
185
186
187
  		p = ret;
  		goto again;
  	}
  	dget_dlock(ret);
  	spin_unlock(&ret->d_lock);
  	spin_unlock(&p->d_lock);
e7854723d   Ian Kent   autofs4 - remove ...
188
  	spin_unlock(&sbi->lookup_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
189
190
191
192
  
  	dput(prev);
  
  	return ret;
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
193
  }
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
194
195
196
197
198
199
200
201
202
203
204
205
206
  /*
   * Check a direct mount point for busyness.
   * Direct mounts have similar expiry semantics to tree mounts.
   * The tree is not busy iff no mountpoints are busy and there are no
   * autofs submounts.
   */
  static int autofs4_direct_busy(struct vfsmount *mnt,
  				struct dentry *top,
  				unsigned long timeout,
  				int do_now)
  {
  	DPRINTK("top %p %.*s",
  		top, (int) top->d_name.len, top->d_name.name);
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  	/* If it's busy update the expiry counters */
  	if (!may_umount_tree(mnt)) {
  		struct autofs_info *ino = autofs4_dentry_ino(top);
  		if (ino)
  			ino->last_used = jiffies;
  		return 1;
  	}
  
  	/* Timeout of a direct mount is determined by its top dentry */
  	if (!autofs4_can_expire(top, timeout, do_now))
  		return 1;
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  /* Check a directory tree of mount points for busyness
   * The tree is not busy iff no mountpoints are busy
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
   */
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
224
225
226
227
  static int autofs4_tree_busy(struct vfsmount *mnt,
  	       		     struct dentry *top,
  			     unsigned long timeout,
  			     int do_now)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
229
  	struct autofs_info *top_ino = autofs4_dentry_ino(top);
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
230
  	struct dentry *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231

1f5f2c305   Ian Kent   [PATCH] autofs4: ...
232
  	DPRINTK("top %p %.*s",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
  		top, (int)top->d_name.len, top->d_name.name);
  
  	/* Negative dentry - give up */
  	if (!simple_positive(top))
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
237
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238

2fd6b7f50   Nick Piggin   fs: dcache scale ...
239
240
  	p = NULL;
  	while ((p = get_next_positive_dentry(p, top))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  		DPRINTK("dentry %p %.*s",
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
242
  			p, (int) p->d_name.len, p->d_name.name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
244
245
246
247
  		/*
  		 * Is someone visiting anywhere in the subtree ?
  		 * If there's no mount we need to check the usage
  		 * count for the autofs dentry.
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
248
  		 * If the fs is busy update the expiry counter.
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
249
  		 */
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
250
  		if (d_mountpoint(p)) {
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
251
  			if (autofs4_mount_busy(mnt, p)) {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
252
  				top_ino->last_used = jiffies;
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
253
  				dput(p);
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
254
  				return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  			}
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
256
  		} else {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
257
  			struct autofs_info *ino = autofs4_dentry_ino(p);
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
258
  			unsigned int ino_count = atomic_read(&ino->count);
f9022f663   Ian Kent   [PATCH] autofs4: ...
259
260
261
262
263
  			/*
  			 * Clean stale dentries below that have not been
  			 * invalidated after a mount fail during lookup
  			 */
  			d_invalidate(p);
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
264
265
266
267
268
  			/* allow for dget above and top is already dgot */
  			if (p == top)
  				ino_count += 2;
  			else
  				ino_count++;
b7ab39f63   Nick Piggin   fs: dcache scale ...
269
  			if (p->d_count > ino_count) {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
270
  				top_ino->last_used = jiffies;
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
271
272
273
  				dput(p);
  				return 1;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  	}
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
276
277
278
279
  
  	/* Timeout of a tree mount is ultimately determined by its top dentry */
  	if (!autofs4_can_expire(top, timeout, do_now))
  		return 1;
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
280
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
285
286
287
  }
  
  static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
  					   struct dentry *parent,
  					   unsigned long timeout,
  					   int do_now)
  {
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
288
  	struct dentry *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
  
  	DPRINTK("parent %p %.*s",
  		parent, (int)parent->d_name.len, parent->d_name.name);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
292
293
  	p = NULL;
  	while ((p = get_next_positive_dentry(p, parent))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
  		DPRINTK("dentry %p %.*s",
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
295
  			p, (int) p->d_name.len, p->d_name.name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296

1ce12bad8   Ian Kent   [PATCH] autofs4: ...
297
  		if (d_mountpoint(p)) {
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
298
299
  			/* Can we umount this guy */
  			if (autofs4_mount_busy(mnt, p))
2fd6b7f50   Nick Piggin   fs: dcache scale ...
300
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301

e0a7aae94   Ian Kent   [PATCH] autofs4: ...
302
303
  			/* Can we expire this guy */
  			if (autofs4_can_expire(p, timeout, do_now))
1ce12bad8   Ian Kent   [PATCH] autofs4: ...
304
  				return p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  	return NULL;
  }
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
309
  /* Check if we can expire a direct mount (possibly a tree) */
8d7b48e0b   Ian Kent   autofs4: add misc...
310
311
312
313
  struct dentry *autofs4_expire_direct(struct super_block *sb,
  				     struct vfsmount *mnt,
  				     struct autofs_sb_info *sbi,
  				     int how)
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
314
315
316
317
  {
  	unsigned long timeout;
  	struct dentry *root = dget(sb->s_root);
  	int do_now = how & AUTOFS_EXP_IMMEDIATE;
b5b801779   Ian Kent   autofs4: Add d_ma...
318
  	struct autofs_info *ino;
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
319

c0ba7e514   Ian Kent   [PATCH] autofs4: ...
320
  	if (!root)
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
321
322
323
324
  		return NULL;
  
  	now = jiffies;
  	timeout = sbi->exp_timeout;
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
325
  	spin_lock(&sbi->fs_lock);
b5b801779   Ian Kent   autofs4: Add d_ma...
326
327
  	ino = autofs4_dentry_ino(root);
  	/* No point expiring a pending mount */
f9398c233   Ian Kent   autofs4 - fix den...
328
329
  	if (ino->flags & AUTOFS_INF_PENDING)
  		goto out;
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
330
331
  	if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
  		struct autofs_info *ino = autofs4_dentry_ino(root);
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
332
  		ino->flags |= AUTOFS_INF_EXPIRING;
6e60a9ab5   Ian Kent   autofs4: fix dire...
333
  		init_completion(&ino->expire_complete);
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
334
335
336
  		spin_unlock(&sbi->fs_lock);
  		return root;
  	}
f9398c233   Ian Kent   autofs4 - fix den...
337
  out:
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
338
339
340
341
342
  	spin_unlock(&sbi->fs_lock);
  	dput(root);
  
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
  /*
   * Find an eligible tree to time-out
   * A tree is eligible if :-
   *  - it is unused by any user process
   *  - it has been unused for exp_timeout time
   */
8d7b48e0b   Ian Kent   autofs4: add misc...
349
350
351
352
  struct dentry *autofs4_expire_indirect(struct super_block *sb,
  				       struct vfsmount *mnt,
  				       struct autofs_sb_info *sbi,
  				       int how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
  {
  	unsigned long timeout;
  	struct dentry *root = sb->s_root;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
356
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	struct dentry *expired = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  	int do_now = how & AUTOFS_EXP_IMMEDIATE;
  	int exp_leaves = how & AUTOFS_EXP_LEAVES;
97e7449a7   Ian Kent   autofs4: fix indi...
360
361
  	struct autofs_info *ino;
  	unsigned int ino_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362

c0ba7e514   Ian Kent   [PATCH] autofs4: ...
363
  	if (!root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
367
  		return NULL;
  
  	now = jiffies;
  	timeout = sbi->exp_timeout;
2fd6b7f50   Nick Piggin   fs: dcache scale ...
368
  	dentry = NULL;
d4a85e35d   Ian Kent   autofs4 - fix aut...
369
  	while ((dentry = get_next_positive_subdir(dentry, root))) {
97e7449a7   Ian Kent   autofs4: fix indi...
370
371
  		spin_lock(&sbi->fs_lock);
  		ino = autofs4_dentry_ino(dentry);
b5b801779   Ian Kent   autofs4: Add d_ma...
372
373
  		/* No point expiring a pending mount */
  		if (ino->flags & AUTOFS_INF_PENDING)
3c3199852   Ian Kent   autofs4 - reinsta...
374
  			goto next;
97e7449a7   Ian Kent   autofs4: fix indi...
375

3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
376
377
378
379
380
381
  		/*
  		 * Case 1: (i) indirect mount or top level pseudo direct mount
  		 *	   (autofs-4.1).
  		 *	   (ii) indirect mount with offset mount, check the "/"
  		 *	   offset (autofs-5.0+).
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
  		if (d_mountpoint(dentry)) {
  			DPRINTK("checking mountpoint %p %.*s",
  				dentry, (int)dentry->d_name.len, dentry->d_name.name);
97e7449a7   Ian Kent   autofs4: fix indi...
385
386
  			/* Path walk currently on this dentry? */
  			ino_count = atomic_read(&ino->count) + 2;
b7ab39f63   Nick Piggin   fs: dcache scale ...
387
  			if (dentry->d_count > ino_count)
97e7449a7   Ian Kent   autofs4: fix indi...
388
  				goto next;
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
389
390
  			/* Can we umount this guy */
  			if (autofs4_mount_busy(mnt, dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  				goto next;
e0a7aae94   Ian Kent   [PATCH] autofs4: ...
392
393
  			/* Can we expire this guy */
  			if (autofs4_can_expire(dentry, timeout, do_now)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  				expired = dentry;
afec570c3   Ian Kent   autofs4: fix spar...
395
  				goto found;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
  			}
  			goto next;
  		}
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
399
  		if (simple_empty(dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
402
403
  			goto next;
  
  		/* Case 2: tree mount, expire iff entire tree is not busy */
  		if (!exp_leaves) {
97e7449a7   Ian Kent   autofs4: fix indi...
404
405
  			/* Path walk currently on this dentry? */
  			ino_count = atomic_read(&ino->count) + 1;
b7ab39f63   Nick Piggin   fs: dcache scale ...
406
  			if (dentry->d_count > ino_count)
97e7449a7   Ian Kent   autofs4: fix indi...
407
  				goto next;
3a9720ce7   Ian Kent   [PATCH] autofs4: ...
408

97e7449a7   Ian Kent   autofs4: fix indi...
409
  			if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
3a9720ce7   Ian Kent   [PATCH] autofs4: ...
410
  				expired = dentry;
afec570c3   Ian Kent   autofs4: fix spar...
411
  				goto found;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  			}
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
413
414
415
416
  		/*
  		 * Case 3: pseudo direct mount, expire individual leaves
  		 *	   (autofs-4.1).
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  		} else {
97e7449a7   Ian Kent   autofs4: fix indi...
418
419
  			/* Path walk currently on this dentry? */
  			ino_count = atomic_read(&ino->count) + 1;
b7ab39f63   Nick Piggin   fs: dcache scale ...
420
  			if (dentry->d_count > ino_count)
97e7449a7   Ian Kent   autofs4: fix indi...
421
  				goto next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
  			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
  			if (expired) {
  				dput(dentry);
afec570c3   Ian Kent   autofs4: fix spar...
425
  				goto found;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
  			}
  		}
  next:
97e7449a7   Ian Kent   autofs4: fix indi...
429
  		spin_unlock(&sbi->fs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	return NULL;
afec570c3   Ian Kent   autofs4: fix spar...
432
433
434
435
  
  found:
  	DPRINTK("returning %p %.*s",
  		expired, (int)expired->d_name.len, expired->d_name.name);
97e7449a7   Ian Kent   autofs4: fix indi...
436
437
  	ino = autofs4_dentry_ino(expired);
  	ino->flags |= AUTOFS_INF_EXPIRING;
6e60a9ab5   Ian Kent   autofs4: fix dire...
438
  	init_completion(&ino->expire_complete);
97e7449a7   Ian Kent   autofs4: fix indi...
439
  	spin_unlock(&sbi->fs_lock);
e7854723d   Ian Kent   autofs4 - remove ...
440
  	spin_lock(&sbi->lookup_lock);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
441
442
  	spin_lock(&expired->d_parent->d_lock);
  	spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
afec570c3   Ian Kent   autofs4: fix spar...
443
  	list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
2fd6b7f50   Nick Piggin   fs: dcache scale ...
444
445
  	spin_unlock(&expired->d_lock);
  	spin_unlock(&expired->d_parent->d_lock);
e7854723d   Ian Kent   autofs4 - remove ...
446
  	spin_unlock(&sbi->lookup_lock);
afec570c3   Ian Kent   autofs4: fix spar...
447
  	return expired;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  }
06a359855   Ian Kent   autofs4: reorgani...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  int autofs4_expire_wait(struct dentry *dentry)
  {
  	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
  	struct autofs_info *ino = autofs4_dentry_ino(dentry);
  	int status;
  
  	/* Block on any pending expire */
  	spin_lock(&sbi->fs_lock);
  	if (ino->flags & AUTOFS_INF_EXPIRING) {
  		spin_unlock(&sbi->fs_lock);
  
  		DPRINTK("waiting for expire %p name=%.*s",
  			 dentry, dentry->d_name.len, dentry->d_name.name);
  
  		status = autofs4_wait(sbi, dentry, NFY_NONE);
  		wait_for_completion(&ino->expire_complete);
  
  		DPRINTK("expire done status=%d", status);
4b1ae27a9   Al Viro   Revert "autofs4: ...
467
  		if (d_unhashed(dentry))
06a359855   Ian Kent   autofs4: reorgani...
468
469
470
471
472
473
474
475
  			return -EAGAIN;
  
  		return status;
  	}
  	spin_unlock(&sbi->fs_lock);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
479
480
481
482
  /* Perform an expiry operation */
  int autofs4_expire_run(struct super_block *sb,
  		      struct vfsmount *mnt,
  		      struct autofs_sb_info *sbi,
  		      struct autofs_packet_expire __user *pkt_p)
  {
  	struct autofs_packet_expire pkt;
97e7449a7   Ian Kent   autofs4: fix indi...
483
  	struct autofs_info *ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  	struct dentry *dentry;
97e7449a7   Ian Kent   autofs4: fix indi...
485
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
  
  	memset(&pkt,0,sizeof pkt);
  
  	pkt.hdr.proto_version = sbi->version;
  	pkt.hdr.type = autofs_ptype_expire;
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
491
  	if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
496
497
498
499
  		return -EAGAIN;
  
  	pkt.len = dentry->d_name.len;
  	memcpy(pkt.name, dentry->d_name.name, pkt.len);
  	pkt.name[pkt.len] = '\0';
  	dput(dentry);
  
  	if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
97e7449a7   Ian Kent   autofs4: fix indi...
500
  		ret = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501

97e7449a7   Ian Kent   autofs4: fix indi...
502
503
504
  	spin_lock(&sbi->fs_lock);
  	ino = autofs4_dentry_ino(dentry);
  	ino->flags &= ~AUTOFS_INF_EXPIRING;
6e60a9ab5   Ian Kent   autofs4: fix dire...
505
  	complete_all(&ino->expire_complete);
97e7449a7   Ian Kent   autofs4: fix indi...
506
507
508
  	spin_unlock(&sbi->fs_lock);
  
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  }
56fcef751   Ian Kent   autofs4: cleanup ...
510
511
  int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
  			    struct autofs_sb_info *sbi, int when)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
514
  {
  	struct dentry *dentry;
  	int ret = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515

a92daf6ba   Ian Kent   autofs4: make aut...
516
  	if (autofs_type_trigger(sbi->type))
56fcef751   Ian Kent   autofs4: cleanup ...
517
  		dentry = autofs4_expire_direct(sb, mnt, sbi, when);
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
518
  	else
56fcef751   Ian Kent   autofs4: cleanup ...
519
  		dentry = autofs4_expire_indirect(sb, mnt, sbi, when);
3a15e2ab5   Ian Kent   [PATCH] autofs4: ...
520
521
  
  	if (dentry) {
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
522
  		struct autofs_info *ino = autofs4_dentry_ino(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
  
  		/* This is synchronous because it makes the daemon a
                     little easier */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
6e60a9ab5   Ian Kent   autofs4: fix dire...
527

97e7449a7   Ian Kent   autofs4: fix indi...
528
  		spin_lock(&sbi->fs_lock);
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
529
  		ino->flags &= ~AUTOFS_INF_EXPIRING;
b5b801779   Ian Kent   autofs4: Add d_ma...
530
  		spin_lock(&dentry->d_lock);
3c3199852   Ian Kent   autofs4 - reinsta...
531
  		if (!ret) {
b5b801779   Ian Kent   autofs4: Add d_ma...
532
533
534
535
536
537
538
  			if ((IS_ROOT(dentry) ||
  			    (autofs_type_indirect(sbi->type) &&
  			     IS_ROOT(dentry->d_parent))) &&
  			    !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
  				__managed_dentry_set_automount(dentry);
  		}
  		spin_unlock(&dentry->d_lock);
6e60a9ab5   Ian Kent   autofs4: fix dire...
539
  		complete_all(&ino->expire_complete);
97e7449a7   Ian Kent   autofs4: fix indi...
540
  		spin_unlock(&sbi->fs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  		dput(dentry);
  	}
1f5f2c305   Ian Kent   [PATCH] autofs4: ...
543

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  	return ret;
  }
56fcef751   Ian Kent   autofs4: cleanup ...
546
547
548
549
550
551
552
553
554
555
556
557
  /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
     more to be done */
  int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
  			struct autofs_sb_info *sbi, int __user *arg)
  {
  	int do_now = 0;
  
  	if (arg && get_user(do_now, arg))
  		return -EFAULT;
  
  	return autofs4_do_expire_multi(sb, mnt, sbi, do_now);
  }