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.c102
1 files changed, 40 insertions, 62 deletions
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index bcc17f533699..165fe9e2d570 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -72,6 +72,27 @@ done:
72 return status; 72 return status;
73} 73}
74 74
75/*
76 * Calculate next entry in top down tree traversal.
77 * From next_mnt in namespace.c - elegant.
78 */
79static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
80{
81 struct list_head *next = p->d_subdirs.next;
82
83 if (next == &p->d_subdirs) {
84 while (1) {
85 if (p == root)
86 return NULL;
87 next = p->d_u.d_child.next;
88 if (next != &p->d_parent->d_subdirs)
89 break;
90 p = p->d_parent;
91 }
92 }
93 return list_entry(next, struct dentry, d_u.d_child);
94}
95
75/* Check a directory tree of mount points for busyness 96/* Check a directory tree of mount points for busyness
76 * The tree is not busy iff no mountpoints are busy 97 * The tree is not busy iff no mountpoints are busy
77 */ 98 */
@@ -80,8 +101,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
80 unsigned long timeout, 101 unsigned long timeout,
81 int do_now) 102 int do_now)
82{ 103{
83 struct dentry *this_parent = top; 104 struct dentry *p;
84 struct list_head *next;
85 105
86 DPRINTK("top %p %.*s", 106 DPRINTK("top %p %.*s",
87 top, (int)top->d_name.len, top->d_name.name); 107 top, (int)top->d_name.len, top->d_name.name);
@@ -99,49 +119,28 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
99 return 1; 119 return 1;
100 120
101 spin_lock(&dcache_lock); 121 spin_lock(&dcache_lock);
102repeat: 122 for (p = top; p; p = next_dentry(p, top)) {
103 next = this_parent->d_subdirs.next;
104resume:
105 while (next != &this_parent->d_subdirs) {
106 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
107
108 /* Negative dentry - give up */ 123 /* Negative dentry - give up */
109 if (!simple_positive(dentry)) { 124 if (!simple_positive(p))
110 next = next->next;
111 continue; 125 continue;
112 }
113 126
114 DPRINTK("dentry %p %.*s", 127 DPRINTK("dentry %p %.*s",
115 dentry, (int)dentry->d_name.len, dentry->d_name.name); 128 p, (int) p->d_name.len, p->d_name.name);
116
117 if (!simple_empty_nolock(dentry)) {
118 this_parent = dentry;
119 goto repeat;
120 }
121 129
122 dentry = dget(dentry); 130 p = dget(p);
123 spin_unlock(&dcache_lock); 131 spin_unlock(&dcache_lock);
124 132
125 if (d_mountpoint(dentry)) { 133 if (d_mountpoint(p)) {
126 /* First busy => tree busy */ 134 /* First busy => tree busy */
127 if (autofs4_mount_busy(mnt, dentry)) { 135 if (autofs4_mount_busy(mnt, p)) {
128 dput(dentry); 136 dput(p);
129 return 1; 137 return 1;
130 } 138 }
131 } 139 }
132 140 dput(p);
133 dput(dentry);
134 spin_lock(&dcache_lock); 141 spin_lock(&dcache_lock);
135 next = next->next;
136 }
137
138 if (this_parent != top) {
139 next = this_parent->d_u.d_child.next;
140 this_parent = this_parent->d_parent;
141 goto resume;
142 } 142 }
143 spin_unlock(&dcache_lock); 143 spin_unlock(&dcache_lock);
144
145 return 0; 144 return 0;
146} 145}
147 146
@@ -150,59 +149,38 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
150 unsigned long timeout, 149 unsigned long timeout,
151 int do_now) 150 int do_now)
152{ 151{
153 struct dentry *this_parent = parent; 152 struct dentry *p;
154 struct list_head *next;
155 153
156 DPRINTK("parent %p %.*s", 154 DPRINTK("parent %p %.*s",
157 parent, (int)parent->d_name.len, parent->d_name.name); 155 parent, (int)parent->d_name.len, parent->d_name.name);
158 156
159 spin_lock(&dcache_lock); 157 spin_lock(&dcache_lock);
160repeat: 158 for (p = parent; p; p = next_dentry(p, parent)) {
161 next = this_parent->d_subdirs.next;
162resume:
163 while (next != &this_parent->d_subdirs) {
164 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
165
166 /* Negative dentry - give up */ 159 /* Negative dentry - give up */
167 if (!simple_positive(dentry)) { 160 if (!simple_positive(p))
168 next = next->next;
169 continue; 161 continue;
170 }
171 162
172 DPRINTK("dentry %p %.*s", 163 DPRINTK("dentry %p %.*s",
173 dentry, (int)dentry->d_name.len, dentry->d_name.name); 164 p, (int) p->d_name.len, p->d_name.name);
174 165
175 if (!list_empty(&dentry->d_subdirs)) { 166 p = dget(p);
176 this_parent = dentry;
177 goto repeat;
178 }
179
180 dentry = dget(dentry);
181 spin_unlock(&dcache_lock); 167 spin_unlock(&dcache_lock);
182 168
183 if (d_mountpoint(dentry)) { 169 if (d_mountpoint(p)) {
184 /* Can we expire this guy */ 170 /* Can we expire this guy */
185 if (!autofs4_can_expire(dentry, timeout, do_now)) 171 if (!autofs4_can_expire(p, timeout, do_now))
186 goto cont; 172 goto cont;
187 173
188 /* Can we umount this guy */ 174 /* Can we umount this guy */
189 if (!autofs4_mount_busy(mnt, dentry)) 175 if (!autofs4_mount_busy(mnt, p))
190 return dentry; 176 return p;
191 177
192 } 178 }
193cont: 179cont:
194 dput(dentry); 180 dput(p);
195 spin_lock(&dcache_lock); 181 spin_lock(&dcache_lock);
196 next = next->next;
197 }
198
199 if (this_parent != parent) {
200 next = this_parent->d_u.d_child.next;
201 this_parent = this_parent->d_parent;
202 goto resume;
203 } 182 }
204 spin_unlock(&dcache_lock); 183 spin_unlock(&dcache_lock);
205
206 return NULL; 184 return NULL;
207} 185}
208 186