diff options
author | Ian Kent <raven@themaw.net> | 2006-03-27 04:14:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:40 -0500 |
commit | 34ca959cfc15cf09ad4da4f31ab034691e51af78 (patch) | |
tree | 83bbe0a2b94ca58f39c65b1e605f44d421b9564b /fs/autofs4/root.c | |
parent | 051d381259eb57d6074d02a6ba6e90e744f1a29f (diff) |
[PATCH] autofs4: add v5 follow_link mount trigger method
This patch adds a follow_link inode method for the root of an autofs direct
mount trigger. It also adds the corresponding mount options and updates the
show_mount method.
Signed-off-by: Ian Kent <raven@themaw.net>
Cc: Al Viro <viro@ftp.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r-- | fs/autofs4/root.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 26eb1f024866..3f0048582248 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> | 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
7 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 7 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
8 | * | 8 | * |
9 | * This file is part of the Linux kernel and is made available under | 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 | 10 | * the terms of the GNU General Public License, version 2, or at your |
@@ -30,6 +30,7 @@ static int autofs4_dir_close(struct inode *inode, struct file *file); | |||
30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); | 30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); |
31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); | 31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); |
32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
33 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); | ||
33 | 34 | ||
34 | struct file_operations autofs4_root_operations = { | 35 | struct file_operations autofs4_root_operations = { |
35 | .open = dcache_dir_open, | 36 | .open = dcache_dir_open, |
@@ -46,7 +47,7 @@ struct file_operations autofs4_dir_operations = { | |||
46 | .readdir = autofs4_dir_readdir, | 47 | .readdir = autofs4_dir_readdir, |
47 | }; | 48 | }; |
48 | 49 | ||
49 | struct inode_operations autofs4_root_inode_operations = { | 50 | struct inode_operations autofs4_indirect_root_inode_operations = { |
50 | .lookup = autofs4_lookup, | 51 | .lookup = autofs4_lookup, |
51 | .unlink = autofs4_dir_unlink, | 52 | .unlink = autofs4_dir_unlink, |
52 | .symlink = autofs4_dir_symlink, | 53 | .symlink = autofs4_dir_symlink, |
@@ -54,6 +55,11 @@ struct inode_operations autofs4_root_inode_operations = { | |||
54 | .rmdir = autofs4_dir_rmdir, | 55 | .rmdir = autofs4_dir_rmdir, |
55 | }; | 56 | }; |
56 | 57 | ||
58 | struct inode_operations autofs4_direct_root_inode_operations = { | ||
59 | .lookup = autofs4_lookup, | ||
60 | .follow_link = autofs4_follow_link, | ||
61 | }; | ||
62 | |||
57 | struct inode_operations autofs4_dir_inode_operations = { | 63 | struct inode_operations autofs4_dir_inode_operations = { |
58 | .lookup = autofs4_lookup, | 64 | .lookup = autofs4_lookup, |
59 | .unlink = autofs4_dir_unlink, | 65 | .unlink = autofs4_dir_unlink, |
@@ -252,7 +258,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
252 | */ | 258 | */ |
253 | status = d_invalidate(dentry); | 259 | status = d_invalidate(dentry); |
254 | if (status != -EBUSY) | 260 | if (status != -EBUSY) |
255 | return 0; | 261 | return -ENOENT; |
256 | } | 262 | } |
257 | 263 | ||
258 | DPRINTK("dentry=%p %.*s ino=%p", | 264 | DPRINTK("dentry=%p %.*s ino=%p", |
@@ -271,17 +277,17 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
271 | DPRINTK("mount done status=%d", status); | 277 | DPRINTK("mount done status=%d", status); |
272 | 278 | ||
273 | if (status && dentry->d_inode) | 279 | if (status && dentry->d_inode) |
274 | return 0; /* Try to get the kernel to invalidate this dentry */ | 280 | return status; /* Try to get the kernel to invalidate this dentry */ |
275 | 281 | ||
276 | /* Turn this into a real negative dentry? */ | 282 | /* Turn this into a real negative dentry? */ |
277 | if (status == -ENOENT) { | 283 | if (status == -ENOENT) { |
278 | spin_lock(&dentry->d_lock); | 284 | spin_lock(&dentry->d_lock); |
279 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 285 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
280 | spin_unlock(&dentry->d_lock); | 286 | spin_unlock(&dentry->d_lock); |
281 | return 0; | 287 | return status; |
282 | } else if (status) { | 288 | } else if (status) { |
283 | /* Return a negative dentry, but leave it "pending" */ | 289 | /* Return a negative dentry, but leave it "pending" */ |
284 | return 0; | 290 | return status; |
285 | } | 291 | } |
286 | /* Trigger mount for path component or follow link */ | 292 | /* Trigger mount for path component or follow link */ |
287 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || | 293 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || |
@@ -300,7 +306,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
300 | spin_lock(&dentry->d_lock); | 306 | spin_lock(&dentry->d_lock); |
301 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 307 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
302 | spin_unlock(&dentry->d_lock); | 308 | spin_unlock(&dentry->d_lock); |
303 | return 0; | 309 | return status; |
304 | } | 310 | } |
305 | } | 311 | } |
306 | 312 | ||
@@ -311,7 +317,41 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
311 | spin_lock(&dentry->d_lock); | 317 | spin_lock(&dentry->d_lock); |
312 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 318 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
313 | spin_unlock(&dentry->d_lock); | 319 | spin_unlock(&dentry->d_lock); |
314 | return 1; | 320 | return status; |
321 | } | ||
322 | |||
323 | /* For autofs direct mounts the follow link triggers the mount */ | ||
324 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
325 | { | ||
326 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
327 | int oz_mode = autofs4_oz_mode(sbi); | ||
328 | unsigned int lookup_type; | ||
329 | int status; | ||
330 | |||
331 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", | ||
332 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, | ||
333 | nd->flags); | ||
334 | |||
335 | /* If it's our master or we shouldn't trigger a mount we're done */ | ||
336 | lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY); | ||
337 | if (oz_mode || !lookup_type) | ||
338 | goto done; | ||
339 | |||
340 | status = try_to_fill_dentry(dentry, 0); | ||
341 | if (status) | ||
342 | goto out_error; | ||
343 | |||
344 | if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) { | ||
345 | status = -ENOENT; | ||
346 | goto out_error; | ||
347 | } | ||
348 | |||
349 | done: | ||
350 | return NULL; | ||
351 | |||
352 | out_error: | ||
353 | path_release(nd); | ||
354 | return ERR_PTR(status); | ||
315 | } | 355 | } |
316 | 356 | ||
317 | /* | 357 | /* |
@@ -326,13 +366,13 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
326 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 366 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
327 | int oz_mode = autofs4_oz_mode(sbi); | 367 | int oz_mode = autofs4_oz_mode(sbi); |
328 | int flags = nd ? nd->flags : 0; | 368 | int flags = nd ? nd->flags : 0; |
329 | int status = 1; | 369 | int status = 0; |
330 | 370 | ||
331 | /* Pending dentry */ | 371 | /* Pending dentry */ |
332 | if (autofs4_ispending(dentry)) { | 372 | if (autofs4_ispending(dentry)) { |
333 | if (!oz_mode) | 373 | if (!oz_mode) |
334 | status = try_to_fill_dentry(dentry, flags); | 374 | status = try_to_fill_dentry(dentry, flags); |
335 | return status; | 375 | return !status; |
336 | } | 376 | } |
337 | 377 | ||
338 | /* Negative dentry.. invalidate if "old" */ | 378 | /* Negative dentry.. invalidate if "old" */ |
@@ -349,14 +389,14 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
349 | spin_unlock(&dcache_lock); | 389 | spin_unlock(&dcache_lock); |
350 | if (!oz_mode) | 390 | if (!oz_mode) |
351 | status = try_to_fill_dentry(dentry, flags); | 391 | status = try_to_fill_dentry(dentry, flags); |
352 | return status; | 392 | return !status; |
353 | } | 393 | } |
354 | spin_unlock(&dcache_lock); | 394 | spin_unlock(&dcache_lock); |
355 | 395 | ||
356 | return 1; | 396 | return 1; |
357 | } | 397 | } |
358 | 398 | ||
359 | static void autofs4_dentry_release(struct dentry *de) | 399 | void autofs4_dentry_release(struct dentry *de) |
360 | { | 400 | { |
361 | struct autofs_info *inf; | 401 | struct autofs_info *inf; |
362 | 402 | ||