1 /* -*- c -*- --------------------------------------------------------------- *
3 * linux/fs/autofs/expire.c
5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6 * Copyright 1999-2000 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 * ------------------------------------------------------------------------- */
15 #include <linux/mount.h>
18 * Determine if a subtree of the namespace is busy.
20 * mnt is the mount tree under the autofs mountpoint
22 static inline int is_vfsmnt_tree_busy(struct vfsmount
*mnt
)
24 struct vfsmount
*this_parent
= mnt
;
25 struct list_head
*next
;
28 count
= atomic_read(&mnt
->mnt_count
) - 1;
31 next
= this_parent
->mnt_mounts
.next
;
32 DPRINTK(("is_vfsmnt_tree_busy: mnt=%p, this_parent=%p, next=%p\n",
33 mnt
, this_parent
, next
));
35 for( ; next
!= &this_parent
->mnt_mounts
; next
= next
->next
) {
36 struct vfsmount
*p
= list_entry(next
, struct vfsmount
,
39 /* -1 for struct vfs_mount's normal count,
40 -1 to compensate for child's reference to parent */
41 count
+= atomic_read(&p
->mnt_count
) - 1 - 1;
43 DPRINTK(("is_vfsmnt_tree_busy: p=%p, count now %d\n",
46 if (!list_empty(&p
->mnt_mounts
)) {
50 /* root is busy if any leaf is busy */
51 if (atomic_read(&p
->mnt_count
) > 1)
55 /* All done at this level ... ascend and resume the search. */
56 if (this_parent
!= mnt
) {
57 next
= this_parent
->mnt_child
.next
;
58 this_parent
= this_parent
->mnt_parent
;
62 DPRINTK(("is_vfsmnt_tree_busy: count=%d\n", count
));
63 return count
!= 0; /* remaining users? */
66 /* Traverse a dentry's list of vfsmounts and return the number of
68 static int check_vfsmnt(struct vfsmount
*mnt
, struct dentry
*dentry
)
70 int ret
= dentry
->d_mounted
;
71 struct vfsmount
*vfs
= lookup_mnt(mnt
, dentry
);
75 if (is_vfsmnt_tree_busy(vfs
))
78 DPRINTK(("check_vfsmnt: ret=%d\n", ret
));
82 /* Check dentry tree for busyness. If a dentry appears to be busy
83 because it is a mountpoint, check to see if the mounted
84 filesystem is busy. */
85 static int is_tree_busy(struct vfsmount
*topmnt
, struct dentry
*top
)
87 struct dentry
*this_parent
;
88 struct list_head
*next
;
91 count
= atomic_read(&top
->d_count
);
93 DPRINTK(("is_tree_busy: top=%p initial count=%d\n",
97 if (is_autofs4_dentry(top
)) {
99 DPRINTK(("is_tree_busy: autofs; count=%d\n", count
));
102 if (d_mountpoint(top
))
103 count
-= check_vfsmnt(topmnt
, top
);
106 next
= this_parent
->d_subdirs
.next
;
108 while (next
!= &this_parent
->d_subdirs
) {
110 struct dentry
*dentry
= list_entry(next
, struct dentry
,
114 count
+= atomic_read(&dentry
->d_count
) - 1;
116 if (d_mountpoint(dentry
))
117 adj
+= check_vfsmnt(topmnt
, dentry
);
119 if (is_autofs4_dentry(dentry
)) {
121 DPRINTK(("is_tree_busy: autofs; adj=%d\n",
127 if (!list_empty(&dentry
->d_subdirs
)) {
128 this_parent
= dentry
;
132 if (atomic_read(&dentry
->d_count
) != adj
) {
133 DPRINTK(("is_tree_busy: busy leaf (d_count=%d adj=%d)\n",
134 atomic_read(&dentry
->d_count
), adj
));
139 /* All done at this level ... ascend and resume the search. */
140 if (this_parent
!= top
) {
141 next
= this_parent
->d_child
.next
;
142 this_parent
= this_parent
->d_parent
;
146 DPRINTK(("is_tree_busy: count=%d\n", count
));
147 return count
!= 0; /* remaining users? */
151 * Find an eligible tree to time-out
152 * A tree is eligible if :-
153 * - it is unused by any user process
154 * - it has been unused for exp_timeout time
156 static struct dentry
*autofs4_expire(struct super_block
*sb
,
157 struct vfsmount
*mnt
,
158 struct autofs_sb_info
*sbi
,
161 unsigned long now
= jiffies
;
162 unsigned long timeout
;
163 struct dentry
*root
= sb
->s_root
;
164 struct list_head
*tmp
;
166 if (!sbi
->exp_timeout
|| !root
)
169 timeout
= sbi
->exp_timeout
;
171 spin_lock(&dcache_lock
);
172 for(tmp
= root
->d_subdirs
.next
;
173 tmp
!= &root
->d_subdirs
;
175 struct autofs_info
*ino
;
176 struct dentry
*dentry
= list_entry(tmp
, struct dentry
, d_child
);
178 if (dentry
->d_inode
== NULL
)
181 ino
= autofs4_dentry_ino(dentry
);
184 /* dentry in the process of being deleted */
188 /* No point expiring a pending mount */
189 if (dentry
->d_flags
& DCACHE_AUTOFS_PENDING
)
193 /* Too young to die */
194 if (time_after(ino
->last_used
+ timeout
, now
))
197 /* update last_used here :-
198 - obviously makes sense if it is in use now
199 - less obviously, prevents rapid-fire expire
200 attempts if expire fails the first time */
201 ino
->last_used
= now
;
203 if (!is_tree_busy(mnt
, dentry
)) {
204 DPRINTK(("autofs_expire: returning %p %.*s\n",
205 dentry
, (int)dentry
->d_name
.len
, dentry
->d_name
.name
));
206 /* Start from here next time */
207 list_del(&root
->d_subdirs
);
208 list_add(&root
->d_subdirs
, &dentry
->d_child
);
210 spin_unlock(&dcache_lock
);
215 spin_unlock(&dcache_lock
);
220 /* Perform an expiry operation */
221 int autofs4_expire_run(struct super_block
*sb
,
222 struct vfsmount
*mnt
,
223 struct autofs_sb_info
*sbi
,
224 struct autofs_packet_expire
*pkt_p
)
226 struct autofs_packet_expire pkt
;
227 struct dentry
*dentry
;
229 memset(&pkt
,0,sizeof pkt
);
231 pkt
.hdr
.proto_version
= sbi
->version
;
232 pkt
.hdr
.type
= autofs_ptype_expire
;
234 if ((dentry
= autofs4_expire(sb
, mnt
, sbi
, 0)) == NULL
)
237 pkt
.len
= dentry
->d_name
.len
;
238 memcpy(pkt
.name
, dentry
->d_name
.name
, pkt
.len
);
239 pkt
.name
[pkt
.len
] = '\0';
242 if ( copy_to_user(pkt_p
, &pkt
, sizeof(struct autofs_packet_expire
)) )
248 /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
250 int autofs4_expire_multi(struct super_block
*sb
, struct vfsmount
*mnt
,
251 struct autofs_sb_info
*sbi
, int *arg
)
253 struct dentry
*dentry
;
257 if (arg
&& get_user(do_now
, arg
))
260 if ((dentry
= autofs4_expire(sb
, mnt
, sbi
, do_now
)) != NULL
) {
261 struct autofs_info
*de_info
= autofs4_dentry_ino(dentry
);
263 /* This is synchronous because it makes the daemon a
265 de_info
->flags
|= AUTOFS_INF_EXPIRING
;
266 ret
= autofs4_wait(sbi
, &dentry
->d_name
, NFY_EXPIRE
);
267 de_info
->flags
&= ~AUTOFS_INF_EXPIRING
;