Import 2.3.99pre7-1
[davej-history.git] / fs / autofs4 / expire.c
blob8a8767faa4a1d3cb1d0aaa782aa1dc6460f025ca
1 /* -*- c -*- --------------------------------------------------------------- *
3 * linux/fs/autofs/expire.c
5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6 * Copyright 1999 Jeremy Fitzhardinge <jeremy@goop.org>
8 * This file is part of the Linux kernel and is made available under
9 * the terms of the GNU General Public License, version 2, or at your
10 * option, any later version, incorporated herein by reference.
12 * ------------------------------------------------------------------------- */
14 #include "autofs_i.h"
17 * Determine if a dentry tree is in use. This is much the
18 * same as the standard is_root_busy() function, except
19 * that :-
20 * - the extra dentry reference in autofs dentries is not
21 * considered to be busy
22 * - mountpoints within the tree are not busy
23 * - it traverses across mountpoints
24 * XXX doesn't consider children of covered dentries at mountpoints
26 static int is_tree_busy(struct dentry *root)
28 struct dentry *this_parent;
29 struct list_head *next;
30 int count;
32 root = root->d_mounts;
34 count = root->d_count;
35 this_parent = root;
37 DPRINTK(("is_tree_busy: starting at %.*s/%.*s, d_count=%d\n",
38 root->d_covers->d_parent->d_name.len,
39 root->d_covers->d_parent->d_name.name,
40 root->d_name.len, root->d_name.name,
41 root->d_count));
43 /* Ignore autofs's extra reference */
44 if (is_autofs4_dentry(root)) {
45 DPRINTK(("is_tree_busy: autofs\n"));
46 count--;
49 /* Mountpoints don't count (either mountee or mounter) */
50 if (d_mountpoint(root) ||
51 root != root->d_covers) {
52 DPRINTK(("is_tree_busy: mountpoint\n"));
53 count--;
56 repeat:
57 next = this_parent->d_mounts->d_subdirs.next;
58 resume:
59 while (next != &this_parent->d_mounts->d_subdirs) {
60 int adj = 0;
61 struct list_head *tmp = next;
62 struct dentry *dentry = list_entry(tmp, struct dentry,
63 d_child);
65 next = tmp->next;
67 dentry = dentry->d_mounts;
69 DPRINTK(("is_tree_busy: considering %.*s/%.*s, d_count=%d, count=%d\n",
70 this_parent->d_name.len,
71 this_parent->d_name.name,
72 dentry->d_covers->d_name.len,
73 dentry->d_covers->d_name.name,
74 dentry->d_count, count));
76 /* Decrement count for unused children */
77 count += (dentry->d_count - 1);
79 /* Mountpoints don't count */
80 if (d_mountpoint(dentry)) {
81 DPRINTK(("is_tree_busy: mountpoint dentry=%p covers=%p mounts=%p\n",
82 dentry, dentry->d_covers, dentry->d_mounts));
83 adj++;
86 /* ... and roots - twice as much... */
87 if (dentry != dentry->d_covers) {
88 DPRINTK(("is_tree_busy: mountpoint dentry=%p covers=%p mounts=%p\n",
89 dentry, dentry->d_covers, dentry->d_mounts));
90 adj+=2;
93 /* Ignore autofs's extra reference */
94 if (is_autofs4_dentry(dentry)) {
95 DPRINTK(("is_tree_busy: autofs\n"));
96 adj++;
99 count -= adj;
101 if (!list_empty(&dentry->d_mounts->d_subdirs)) {
102 this_parent = dentry->d_mounts;
103 goto repeat;
106 /* root is busy if any leaf is busy */
107 if (dentry->d_count != adj) {
108 DPRINTK(("is_tree_busy: busy leaf (d_count=%d adj=%d)\n",
109 dentry->d_count, adj));
110 return 1;
114 * All done at this level ... ascend and resume the search.
116 if (this_parent != root) {
117 next = this_parent->d_covers->d_child.next;
118 this_parent = this_parent->d_covers->d_parent;
119 goto resume;
122 DPRINTK(("is_tree_busy: count=%d\n", count));
123 return count != 0; /* remaining users? */
127 * Find an eligible tree to time-out
128 * A tree is eligible if :-
129 * - it is unused by any user process
130 * - it has been unused for exp_timeout time
132 static struct dentry *autofs4_expire(struct super_block *sb,
133 struct autofs_sb_info *sbi,
134 int do_now)
136 unsigned long now = jiffies; /* snapshot of now */
137 unsigned long timeout;
138 struct dentry *root = sb->s_root;
139 struct list_head *tmp;
141 if (!sbi->exp_timeout || !root)
142 return NULL;
144 timeout = sbi->exp_timeout;
146 for(tmp = root->d_subdirs.next;
147 tmp != &root->d_subdirs;
148 tmp = tmp->next) {
149 struct autofs_info *ino;
150 struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
152 if (dentry->d_inode == NULL)
153 continue;
155 ino = autofs4_dentry_ino(dentry);
157 if (ino == NULL) {
158 /* dentry in the process of being deleted */
159 continue;
162 /* No point expiring a pending mount */
163 if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
164 continue;
166 if (!do_now) {
167 /* Too young to die */
168 if (time_after(ino->last_used+timeout, now))
169 continue;
171 /* update last_used here :-
172 - obviously makes sense if it is in use now
173 - less obviously, prevents rapid-fire expire
174 attempts if expire fails the first time */
175 ino->last_used = now;
178 if (!is_tree_busy(dentry)) {
179 DPRINTK(("autofs_expire: returning %p %.*s\n",
180 dentry, dentry->d_name.len, dentry->d_name.name));
181 /* Start from here next time */
182 list_del(&root->d_subdirs);
183 list_add(&root->d_subdirs, &dentry->d_child);
184 return dentry;
188 return NULL;
191 /* Perform an expiry operation */
192 int autofs4_expire_run(struct super_block *sb,
193 struct autofs_sb_info *sbi,
194 struct autofs_packet_expire *pkt_p)
196 struct autofs_packet_expire pkt;
197 struct dentry *dentry;
199 memset(&pkt,0,sizeof pkt);
201 pkt.hdr.proto_version = sbi->version;
202 pkt.hdr.type = autofs_ptype_expire;
204 if ((dentry = autofs4_expire(sb, sbi, 0)) == NULL)
205 return -EAGAIN;
207 pkt.len = dentry->d_name.len;
208 memcpy(pkt.name, dentry->d_name.name, pkt.len);
209 pkt.name[pkt.len] = '\0';
211 if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
212 return -EFAULT;
214 return 0;
217 /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
218 more to be done */
219 int autofs4_expire_multi(struct super_block *sb,
220 struct autofs_sb_info *sbi, int *arg)
222 struct dentry *dentry;
223 int ret = -EAGAIN;
224 int do_now = 0;
226 if (arg && get_user(do_now, arg))
227 return -EFAULT;
229 if ((dentry = autofs4_expire(sb, sbi, do_now)) != NULL) {
230 struct autofs_info *de_info = autofs4_dentry_ino(dentry);
232 /* This is synchronous because it makes the daemon a
233 little easier */
234 de_info->flags |= AUTOFS_INF_EXPIRING;
235 ret = autofs4_wait(sbi, &dentry->d_name, NFY_EXPIRE);
236 de_info->flags &= ~AUTOFS_INF_EXPIRING;
239 return ret;