diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 7 | ||||
-rw-r--r-- | fs/autofs4/root.c | 243 |
2 files changed, 0 insertions, 250 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index f0c95e0460cf..1ee3b9afbe9e 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -175,13 +175,6 @@ static inline int autofs4_ispending(struct dentry *dentry) | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static inline void autofs4_copy_atime(struct file *src, struct file *dst) | ||
179 | { | ||
180 | dst->f_path.dentry->d_inode->i_atime = | ||
181 | src->f_path.dentry->d_inode->i_atime; | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *); | 178 | struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *); |
186 | void autofs4_free_ino(struct autofs_info *); | 179 | void autofs4_free_ino(struct autofs_info *); |
187 | 180 | ||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index f1076b91a0fa..b2498c8cb0a7 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -36,9 +36,6 @@ static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); | |||
36 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 36 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
38 | 38 | ||
39 | #define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) | ||
40 | #define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE) | ||
41 | |||
42 | const struct file_operations autofs4_root_operations = { | 39 | const struct file_operations autofs4_root_operations = { |
43 | .open = dcache_dir_open, | 40 | .open = dcache_dir_open, |
44 | .release = dcache_dir_close, | 41 | .release = dcache_dir_close, |
@@ -114,14 +111,6 @@ static void autofs4_del_active(struct dentry *dentry) | |||
114 | return; | 111 | return; |
115 | } | 112 | } |
116 | 113 | ||
117 | static unsigned int autofs4_need_mount(unsigned int flags) | ||
118 | { | ||
119 | unsigned int res = 0; | ||
120 | if (flags & (TRIGGER_FLAGS | TRIGGER_INTENTS)) | ||
121 | res = 1; | ||
122 | return res; | ||
123 | } | ||
124 | |||
125 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 114 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
126 | { | 115 | { |
127 | struct dentry *dentry = file->f_path.dentry; | 116 | struct dentry *dentry = file->f_path.dentry; |
@@ -156,238 +145,6 @@ out: | |||
156 | return dcache_dir_open(inode, file); | 145 | return dcache_dir_open(inode, file); |
157 | } | 146 | } |
158 | 147 | ||
159 | static int try_to_fill_dentry(struct dentry *dentry, int flags) | ||
160 | { | ||
161 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
162 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
163 | int status; | ||
164 | |||
165 | DPRINTK("dentry=%p %.*s ino=%p", | ||
166 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | ||
167 | |||
168 | /* | ||
169 | * Wait for a pending mount, triggering one if there | ||
170 | * isn't one already | ||
171 | */ | ||
172 | if (dentry->d_inode == NULL) { | ||
173 | DPRINTK("waiting for mount name=%.*s", | ||
174 | dentry->d_name.len, dentry->d_name.name); | ||
175 | |||
176 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | ||
177 | |||
178 | DPRINTK("mount done status=%d", status); | ||
179 | |||
180 | /* Turn this into a real negative dentry? */ | ||
181 | if (status == -ENOENT) { | ||
182 | spin_lock(&sbi->fs_lock); | ||
183 | ino->flags &= ~AUTOFS_INF_PENDING; | ||
184 | spin_unlock(&sbi->fs_lock); | ||
185 | return status; | ||
186 | } else if (status) { | ||
187 | /* Return a negative dentry, but leave it "pending" */ | ||
188 | return status; | ||
189 | } | ||
190 | /* Trigger mount for path component or follow link */ | ||
191 | } else if (ino->flags & AUTOFS_INF_PENDING || | ||
192 | autofs4_need_mount(flags)) { | ||
193 | DPRINTK("waiting for mount name=%.*s", | ||
194 | dentry->d_name.len, dentry->d_name.name); | ||
195 | |||
196 | spin_lock(&sbi->fs_lock); | ||
197 | ino->flags |= AUTOFS_INF_PENDING; | ||
198 | spin_unlock(&sbi->fs_lock); | ||
199 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | ||
200 | |||
201 | DPRINTK("mount done status=%d", status); | ||
202 | |||
203 | if (status) { | ||
204 | spin_lock(&sbi->fs_lock); | ||
205 | ino->flags &= ~AUTOFS_INF_PENDING; | ||
206 | spin_unlock(&sbi->fs_lock); | ||
207 | return status; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | /* Initialize expiry counter after successful mount */ | ||
212 | ino->last_used = jiffies; | ||
213 | |||
214 | spin_lock(&sbi->fs_lock); | ||
215 | ino->flags &= ~AUTOFS_INF_PENDING; | ||
216 | spin_unlock(&sbi->fs_lock); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | /* For autofs direct mounts the follow link triggers the mount */ | ||
222 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
223 | { | ||
224 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
225 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
226 | int oz_mode = autofs4_oz_mode(sbi); | ||
227 | unsigned int lookup_type; | ||
228 | int status; | ||
229 | |||
230 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", | ||
231 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, | ||
232 | nd->flags); | ||
233 | /* | ||
234 | * For an expire of a covered direct or offset mount we need | ||
235 | * to break out of follow_down_one() at the autofs mount trigger | ||
236 | * (d_mounted--), so we can see the expiring flag, and manage | ||
237 | * the blocking and following here until the expire is completed. | ||
238 | */ | ||
239 | if (oz_mode) { | ||
240 | spin_lock(&sbi->fs_lock); | ||
241 | if (ino->flags & AUTOFS_INF_EXPIRING) { | ||
242 | spin_unlock(&sbi->fs_lock); | ||
243 | /* Follow down to our covering mount. */ | ||
244 | if (!follow_down_one(&nd->path)) | ||
245 | goto done; | ||
246 | goto follow; | ||
247 | } | ||
248 | spin_unlock(&sbi->fs_lock); | ||
249 | goto done; | ||
250 | } | ||
251 | |||
252 | /* If an expire request is pending everyone must wait. */ | ||
253 | autofs4_expire_wait(dentry); | ||
254 | |||
255 | /* We trigger a mount for almost all flags */ | ||
256 | lookup_type = autofs4_need_mount(nd->flags); | ||
257 | spin_lock(&sbi->fs_lock); | ||
258 | spin_lock(&autofs4_lock); | ||
259 | spin_lock(&dentry->d_lock); | ||
260 | if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) { | ||
261 | spin_unlock(&dentry->d_lock); | ||
262 | spin_unlock(&autofs4_lock); | ||
263 | spin_unlock(&sbi->fs_lock); | ||
264 | goto follow; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * If the dentry contains directories then it is an autofs | ||
269 | * multi-mount with no root mount offset. So don't try to | ||
270 | * mount it again. | ||
271 | */ | ||
272 | if (ino->flags & AUTOFS_INF_PENDING || | ||
273 | (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) { | ||
274 | spin_unlock(&dentry->d_lock); | ||
275 | spin_unlock(&autofs4_lock); | ||
276 | spin_unlock(&sbi->fs_lock); | ||
277 | |||
278 | status = try_to_fill_dentry(dentry, nd->flags); | ||
279 | if (status) | ||
280 | goto out_error; | ||
281 | |||
282 | goto follow; | ||
283 | } | ||
284 | spin_unlock(&dentry->d_lock); | ||
285 | spin_unlock(&autofs4_lock); | ||
286 | spin_unlock(&sbi->fs_lock); | ||
287 | follow: | ||
288 | /* | ||
289 | * If there is no root mount it must be an autofs | ||
290 | * multi-mount with no root offset so we don't need | ||
291 | * to follow it. | ||
292 | */ | ||
293 | if (d_managed(dentry)) { | ||
294 | status = follow_down(&nd->path, false); | ||
295 | if (status < 0) | ||
296 | goto out_error; | ||
297 | } | ||
298 | |||
299 | done: | ||
300 | return NULL; | ||
301 | |||
302 | out_error: | ||
303 | path_put(&nd->path); | ||
304 | return ERR_PTR(status); | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Revalidate is called on every cache lookup. Some of those | ||
309 | * cache lookups may actually happen while the dentry is not | ||
310 | * yet completely filled in, and revalidate has to delay such | ||
311 | * lookups.. | ||
312 | */ | ||
313 | static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
314 | { | ||
315 | struct inode *dir; | ||
316 | struct autofs_sb_info *sbi; | ||
317 | int oz_mode; | ||
318 | int flags = nd ? nd->flags : 0; | ||
319 | int status = 1; | ||
320 | |||
321 | if (flags & LOOKUP_RCU) | ||
322 | return -ECHILD; | ||
323 | |||
324 | dir = dentry->d_parent->d_inode; | ||
325 | sbi = autofs4_sbi(dir->i_sb); | ||
326 | oz_mode = autofs4_oz_mode(sbi); | ||
327 | |||
328 | /* Pending dentry */ | ||
329 | spin_lock(&sbi->fs_lock); | ||
330 | if (autofs4_ispending(dentry)) { | ||
331 | /* The daemon never causes a mount to trigger */ | ||
332 | spin_unlock(&sbi->fs_lock); | ||
333 | |||
334 | if (oz_mode) | ||
335 | return 1; | ||
336 | |||
337 | /* | ||
338 | * If the directory has gone away due to an expire | ||
339 | * we have been called as ->d_revalidate() and so | ||
340 | * we need to return false and proceed to ->lookup(). | ||
341 | */ | ||
342 | if (autofs4_expire_wait(dentry) == -EAGAIN) | ||
343 | return 0; | ||
344 | |||
345 | /* | ||
346 | * A zero status is success otherwise we have a | ||
347 | * negative error code. | ||
348 | */ | ||
349 | status = try_to_fill_dentry(dentry, flags); | ||
350 | if (status == 0) | ||
351 | return 1; | ||
352 | |||
353 | return status; | ||
354 | } | ||
355 | spin_unlock(&sbi->fs_lock); | ||
356 | |||
357 | /* Negative dentry.. invalidate if "old" */ | ||
358 | if (dentry->d_inode == NULL) | ||
359 | return 0; | ||
360 | |||
361 | /* Check for a non-mountpoint directory with no contents */ | ||
362 | spin_lock(&autofs4_lock); | ||
363 | spin_lock(&dentry->d_lock); | ||
364 | if (S_ISDIR(dentry->d_inode->i_mode) && | ||
365 | !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { | ||
366 | DPRINTK("dentry=%p %.*s, emptydir", | ||
367 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
368 | spin_unlock(&dentry->d_lock); | ||
369 | spin_unlock(&autofs4_lock); | ||
370 | |||
371 | /* The daemon never causes a mount to trigger */ | ||
372 | if (oz_mode) | ||
373 | return 1; | ||
374 | |||
375 | /* | ||
376 | * A zero status is success otherwise we have a | ||
377 | * negative error code. | ||
378 | */ | ||
379 | status = try_to_fill_dentry(dentry, flags); | ||
380 | if (status == 0) | ||
381 | return 1; | ||
382 | |||
383 | return status; | ||
384 | } | ||
385 | spin_unlock(&dentry->d_lock); | ||
386 | spin_unlock(&autofs4_lock); | ||
387 | |||
388 | return 1; | ||
389 | } | ||
390 | |||
391 | void autofs4_dentry_release(struct dentry *de) | 148 | void autofs4_dentry_release(struct dentry *de) |
392 | { | 149 | { |
393 | struct autofs_info *inf; | 150 | struct autofs_info *inf; |