• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/fs/autofs4/
1/* -*- c -*- --------------------------------------------------------------- *
2 *
3 * linux/fs/autofs/expire.c
4 *
5 *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6 *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
7 *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
8 *
9 * This file is part of the Linux kernel and is made available under
10 * the terms of the GNU General Public License, version 2, or at your
11 * option, any later version, incorporated herein by reference.
12 *
13 * ------------------------------------------------------------------------- */
14
15#include "autofs_i.h"
16
17static unsigned long now;
18
19/* Check if a dentry can be expired */
20static inline int autofs4_can_expire(struct dentry *dentry,
21					unsigned long timeout, int do_now)
22{
23	struct autofs_info *ino = autofs4_dentry_ino(dentry);
24
25	/* dentry in the process of being deleted */
26	if (ino == NULL)
27		return 0;
28
29	/* No point expiring a pending mount */
30	if (ino->flags & AUTOFS_INF_PENDING)
31		return 0;
32
33	if (!do_now) {
34		/* Too young to die */
35		if (!timeout || time_after(ino->last_used + timeout, now))
36			return 0;
37
38		/* update last_used here :-
39		   - obviously makes sense if it is in use now
40		   - less obviously, prevents rapid-fire expire
41		     attempts if expire fails the first time */
42		ino->last_used = now;
43	}
44	return 1;
45}
46
47/* Check a mount point for busyness */
48static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
49{
50	struct dentry *top = dentry;
51	struct path path = {.mnt = mnt, .dentry = dentry};
52	int status = 1;
53
54	DPRINTK("dentry %p %.*s",
55		dentry, (int)dentry->d_name.len, dentry->d_name.name);
56
57	path_get(&path);
58
59	if (!follow_down(&path))
60		goto done;
61
62	if (is_autofs4_dentry(path.dentry)) {
63		struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);
64
65		/* This is an autofs submount, we can't expire it */
66		if (autofs_type_indirect(sbi->type))
67			goto done;
68
69		/*
70		 * Otherwise it's an offset mount and we need to check
71		 * if we can umount its mount, if there is one.
72		 */
73		if (!d_mountpoint(path.dentry)) {
74			status = 0;
75			goto done;
76		}
77	}
78
79	/* Update the expiry counter if fs is busy */
80	if (!may_umount_tree(path.mnt)) {
81		struct autofs_info *ino = autofs4_dentry_ino(top);
82		ino->last_used = jiffies;
83		goto done;
84	}
85
86	status = 0;
87done:
88	DPRINTK("returning = %d", status);
89	path_put(&path);
90	return status;
91}
92
93/*
94 * Calculate next entry in top down tree traversal.
95 * From next_mnt in namespace.c - elegant.
96 */
97static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
98{
99	struct list_head *next = p->d_subdirs.next;
100
101	if (next == &p->d_subdirs) {
102		while (1) {
103			if (p == root)
104				return NULL;
105			next = p->d_u.d_child.next;
106			if (next != &p->d_parent->d_subdirs)
107				break;
108			p = p->d_parent;
109		}
110	}
111	return list_entry(next, struct dentry, d_u.d_child);
112}
113
114/*
115 * Check a direct mount point for busyness.
116 * Direct mounts have similar expiry semantics to tree mounts.
117 * The tree is not busy iff no mountpoints are busy and there are no
118 * autofs submounts.
119 */
120static int autofs4_direct_busy(struct vfsmount *mnt,
121				struct dentry *top,
122				unsigned long timeout,
123				int do_now)
124{
125	DPRINTK("top %p %.*s",
126		top, (int) top->d_name.len, top->d_name.name);
127
128	/* If it's busy update the expiry counters */
129	if (!may_umount_tree(mnt)) {
130		struct autofs_info *ino = autofs4_dentry_ino(top);
131		if (ino)
132			ino->last_used = jiffies;
133		return 1;
134	}
135
136	/* Timeout of a direct mount is determined by its top dentry */
137	if (!autofs4_can_expire(top, timeout, do_now))
138		return 1;
139
140	return 0;
141}
142
143/* Check a directory tree of mount points for busyness
144 * The tree is not busy iff no mountpoints are busy
145 */
146static int autofs4_tree_busy(struct vfsmount *mnt,
147	       		     struct dentry *top,
148			     unsigned long timeout,
149			     int do_now)
150{
151	struct autofs_info *top_ino = autofs4_dentry_ino(top);
152	struct dentry *p;
153
154	DPRINTK("top %p %.*s",
155		top, (int)top->d_name.len, top->d_name.name);
156
157	/* Negative dentry - give up */
158	if (!simple_positive(top))
159		return 1;
160
161	spin_lock(&dcache_lock);
162	for (p = top; p; p = next_dentry(p, top)) {
163		/* Negative dentry - give up */
164		if (!simple_positive(p))
165			continue;
166
167		DPRINTK("dentry %p %.*s",
168			p, (int) p->d_name.len, p->d_name.name);
169
170		p = dget(p);
171		spin_unlock(&dcache_lock);
172
173		/*
174		 * Is someone visiting anywhere in the subtree ?
175		 * If there's no mount we need to check the usage
176		 * count for the autofs dentry.
177		 * If the fs is busy update the expiry counter.
178		 */
179		if (d_mountpoint(p)) {
180			if (autofs4_mount_busy(mnt, p)) {
181				top_ino->last_used = jiffies;
182				dput(p);
183				return 1;
184			}
185		} else {
186			struct autofs_info *ino = autofs4_dentry_ino(p);
187			unsigned int ino_count = atomic_read(&ino->count);
188
189			/*
190			 * Clean stale dentries below that have not been
191			 * invalidated after a mount fail during lookup
192			 */
193			d_invalidate(p);
194
195			/* allow for dget above and top is already dgot */
196			if (p == top)
197				ino_count += 2;
198			else
199				ino_count++;
200
201			if (atomic_read(&p->d_count) > ino_count) {
202				top_ino->last_used = jiffies;
203				dput(p);
204				return 1;
205			}
206		}
207		dput(p);
208		spin_lock(&dcache_lock);
209	}
210	spin_unlock(&dcache_lock);
211
212	/* Timeout of a tree mount is ultimately determined by its top dentry */
213	if (!autofs4_can_expire(top, timeout, do_now))
214		return 1;
215
216	return 0;
217}
218
219static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
220					   struct dentry *parent,
221					   unsigned long timeout,
222					   int do_now)
223{
224	struct dentry *p;
225
226	DPRINTK("parent %p %.*s",
227		parent, (int)parent->d_name.len, parent->d_name.name);
228
229	spin_lock(&dcache_lock);
230	for (p = parent; p; p = next_dentry(p, parent)) {
231		/* Negative dentry - give up */
232		if (!simple_positive(p))
233			continue;
234
235		DPRINTK("dentry %p %.*s",
236			p, (int) p->d_name.len, p->d_name.name);
237
238		p = dget(p);
239		spin_unlock(&dcache_lock);
240
241		if (d_mountpoint(p)) {
242			/* Can we umount this guy */
243			if (autofs4_mount_busy(mnt, p))
244				goto cont;
245
246			/* Can we expire this guy */
247			if (autofs4_can_expire(p, timeout, do_now))
248				return p;
249		}
250cont:
251		dput(p);
252		spin_lock(&dcache_lock);
253	}
254	spin_unlock(&dcache_lock);
255	return NULL;
256}
257
258/* Check if we can expire a direct mount (possibly a tree) */
259struct dentry *autofs4_expire_direct(struct super_block *sb,
260				     struct vfsmount *mnt,
261				     struct autofs_sb_info *sbi,
262				     int how)
263{
264	unsigned long timeout;
265	struct dentry *root = dget(sb->s_root);
266	int do_now = how & AUTOFS_EXP_IMMEDIATE;
267
268	if (!root)
269		return NULL;
270
271	now = jiffies;
272	timeout = sbi->exp_timeout;
273
274	spin_lock(&sbi->fs_lock);
275	if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
276		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;
282		init_completion(&ino->expire_complete);
283		spin_unlock(&sbi->fs_lock);
284		return root;
285	}
286	spin_unlock(&sbi->fs_lock);
287	dput(root);
288
289	return NULL;
290}
291
292/*
293 * Find an eligible tree to time-out
294 * A tree is eligible if :-
295 *  - it is unused by any user process
296 *  - it has been unused for exp_timeout time
297 */
298struct dentry *autofs4_expire_indirect(struct super_block *sb,
299				       struct vfsmount *mnt,
300				       struct autofs_sb_info *sbi,
301				       int how)
302{
303	unsigned long timeout;
304	struct dentry *root = sb->s_root;
305	struct dentry *expired = NULL;
306	struct list_head *next;
307	int do_now = how & AUTOFS_EXP_IMMEDIATE;
308	int exp_leaves = how & AUTOFS_EXP_LEAVES;
309	struct autofs_info *ino;
310	unsigned int ino_count;
311
312	if (!root)
313		return NULL;
314
315	now = jiffies;
316	timeout = sbi->exp_timeout;
317
318	spin_lock(&dcache_lock);
319	next = root->d_subdirs.next;
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);
336		ino = autofs4_dentry_ino(dentry);
337
338		/*
339		 * Case 1: (i) indirect mount or top level pseudo direct mount
340		 *	   (autofs-4.1).
341		 *	   (ii) indirect mount with offset mount, check the "/"
342		 *	   offset (autofs-5.0+).
343		 */
344		if (d_mountpoint(dentry)) {
345			DPRINTK("checking mountpoint %p %.*s",
346				dentry, (int)dentry->d_name.len, dentry->d_name.name);
347
348			/* Path walk currently on this dentry? */
349			ino_count = atomic_read(&ino->count) + 2;
350			if (atomic_read(&dentry->d_count) > ino_count)
351				goto next;
352
353			/* Can we umount this guy */
354			if (autofs4_mount_busy(mnt, dentry))
355				goto next;
356
357			/* Can we expire this guy */
358			if (autofs4_can_expire(dentry, timeout, do_now)) {
359				expired = dentry;
360				goto found;
361			}
362			goto next;
363		}
364
365		if (simple_empty(dentry))
366			goto next;
367
368		/* Case 2: tree mount, expire iff entire tree is not busy */
369		if (!exp_leaves) {
370			/* Path walk currently on this dentry? */
371			ino_count = atomic_read(&ino->count) + 1;
372			if (atomic_read(&dentry->d_count) > ino_count)
373				goto next;
374
375			if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
376				expired = dentry;
377				goto found;
378			}
379		/*
380		 * Case 3: pseudo direct mount, expire individual leaves
381		 *	   (autofs-4.1).
382		 */
383		} else {
384			/* Path walk currently on this dentry? */
385			ino_count = atomic_read(&ino->count) + 1;
386			if (atomic_read(&dentry->d_count) > ino_count)
387				goto next;
388
389			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
390			if (expired) {
391				dput(dentry);
392				goto found;
393			}
394		}
395next:
396		spin_unlock(&sbi->fs_lock);
397		dput(dentry);
398		spin_lock(&dcache_lock);
399		next = next->next;
400	}
401	spin_unlock(&dcache_lock);
402	return NULL;
403
404found:
405	DPRINTK("returning %p %.*s",
406		expired, (int)expired->d_name.len, expired->d_name.name);
407	ino = autofs4_dentry_ino(expired);
408	ino->flags |= AUTOFS_INF_EXPIRING;
409	init_completion(&ino->expire_complete);
410	spin_unlock(&sbi->fs_lock);
411	spin_lock(&dcache_lock);
412	list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
413	spin_unlock(&dcache_lock);
414	return expired;
415}
416
417int autofs4_expire_wait(struct dentry *dentry)
418{
419	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
420	struct autofs_info *ino = autofs4_dentry_ino(dentry);
421	int status;
422
423	/* Block on any pending expire */
424	spin_lock(&sbi->fs_lock);
425	if (ino->flags & AUTOFS_INF_EXPIRING) {
426		spin_unlock(&sbi->fs_lock);
427
428		DPRINTK("waiting for expire %p name=%.*s",
429			 dentry, dentry->d_name.len, dentry->d_name.name);
430
431		status = autofs4_wait(sbi, dentry, NFY_NONE);
432		wait_for_completion(&ino->expire_complete);
433
434		DPRINTK("expire done status=%d", status);
435
436		if (d_unhashed(dentry))
437			return -EAGAIN;
438
439		return status;
440	}
441	spin_unlock(&sbi->fs_lock);
442
443	return 0;
444}
445
446/* Perform an expiry operation */
447int autofs4_expire_run(struct super_block *sb,
448		      struct vfsmount *mnt,
449		      struct autofs_sb_info *sbi,
450		      struct autofs_packet_expire __user *pkt_p)
451{
452	struct autofs_packet_expire pkt;
453	struct autofs_info *ino;
454	struct dentry *dentry;
455	int ret = 0;
456
457	memset(&pkt,0,sizeof pkt);
458
459	pkt.hdr.proto_version = sbi->version;
460	pkt.hdr.type = autofs_ptype_expire;
461
462	if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
463		return -EAGAIN;
464
465	pkt.len = dentry->d_name.len;
466	memcpy(pkt.name, dentry->d_name.name, pkt.len);
467	pkt.name[pkt.len] = '\0';
468	dput(dentry);
469
470	if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
471		ret = -EFAULT;
472
473	spin_lock(&sbi->fs_lock);
474	ino = autofs4_dentry_ino(dentry);
475	ino->flags &= ~AUTOFS_INF_EXPIRING;
476	complete_all(&ino->expire_complete);
477	spin_unlock(&sbi->fs_lock);
478
479	return ret;
480}
481
482int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
483			    struct autofs_sb_info *sbi, int when)
484{
485	struct dentry *dentry;
486	int ret = -EAGAIN;
487
488	if (autofs_type_trigger(sbi->type))
489		dentry = autofs4_expire_direct(sb, mnt, sbi, when);
490	else
491		dentry = autofs4_expire_indirect(sb, mnt, sbi, when);
492
493	if (dentry) {
494		struct autofs_info *ino = autofs4_dentry_ino(dentry);
495
496		/* This is synchronous because it makes the daemon a
497                   little easier */
498		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
499
500		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;
506		complete_all(&ino->expire_complete);
507		spin_unlock(&sbi->fs_lock);
508		dput(dentry);
509	}
510
511	return ret;
512}
513
514/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
515   more to be done */
516int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
517			struct autofs_sb_info *sbi, int __user *arg)
518{
519	int do_now = 0;
520
521	if (arg && get_user(do_now, arg))
522		return -EFAULT;
523
524	return autofs4_do_expire_multi(sb, mnt, sbi, do_now);
525}
526