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/inode.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/inode.c')
-rw-r--r-- | fs/autofs4/inode.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index d9a71dab40fc..3801bed94e45 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * linux/fs/autofs/inode.c | 3 | * linux/fs/autofs/inode.c |
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> | ||
6 | * | 7 | * |
7 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
8 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
@@ -177,6 +178,13 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
177 | seq_printf(m, ",minproto=%d", sbi->min_proto); | 178 | seq_printf(m, ",minproto=%d", sbi->min_proto); |
178 | seq_printf(m, ",maxproto=%d", sbi->max_proto); | 179 | seq_printf(m, ",maxproto=%d", sbi->max_proto); |
179 | 180 | ||
181 | if (sbi->type & AUTOFS_TYP_OFFSET) | ||
182 | seq_printf(m, ",offset"); | ||
183 | else if (sbi->type & AUTOFS_TYP_DIRECT) | ||
184 | seq_printf(m, ",direct"); | ||
185 | else | ||
186 | seq_printf(m, ",indirect"); | ||
187 | |||
180 | return 0; | 188 | return 0; |
181 | } | 189 | } |
182 | 190 | ||
@@ -186,7 +194,8 @@ static struct super_operations autofs4_sops = { | |||
186 | .show_options = autofs4_show_options, | 194 | .show_options = autofs4_show_options, |
187 | }; | 195 | }; |
188 | 196 | ||
189 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto}; | 197 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, |
198 | Opt_indirect, Opt_direct, Opt_offset}; | ||
190 | 199 | ||
191 | static match_table_t tokens = { | 200 | static match_table_t tokens = { |
192 | {Opt_fd, "fd=%u"}, | 201 | {Opt_fd, "fd=%u"}, |
@@ -195,11 +204,15 @@ static match_table_t tokens = { | |||
195 | {Opt_pgrp, "pgrp=%u"}, | 204 | {Opt_pgrp, "pgrp=%u"}, |
196 | {Opt_minproto, "minproto=%u"}, | 205 | {Opt_minproto, "minproto=%u"}, |
197 | {Opt_maxproto, "maxproto=%u"}, | 206 | {Opt_maxproto, "maxproto=%u"}, |
207 | {Opt_indirect, "indirect"}, | ||
208 | {Opt_direct, "direct"}, | ||
209 | {Opt_offset, "offset"}, | ||
198 | {Opt_err, NULL} | 210 | {Opt_err, NULL} |
199 | }; | 211 | }; |
200 | 212 | ||
201 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | 213 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, |
202 | pid_t *pgrp, int *minproto, int *maxproto) | 214 | pid_t *pgrp, unsigned int *type, |
215 | int *minproto, int *maxproto) | ||
203 | { | 216 | { |
204 | char *p; | 217 | char *p; |
205 | substring_t args[MAX_OPT_ARGS]; | 218 | substring_t args[MAX_OPT_ARGS]; |
@@ -253,6 +266,15 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | |||
253 | return 1; | 266 | return 1; |
254 | *maxproto = option; | 267 | *maxproto = option; |
255 | break; | 268 | break; |
269 | case Opt_indirect: | ||
270 | *type = AUTOFS_TYP_INDIRECT; | ||
271 | break; | ||
272 | case Opt_direct: | ||
273 | *type = AUTOFS_TYP_DIRECT; | ||
274 | break; | ||
275 | case Opt_offset: | ||
276 | *type = AUTOFS_TYP_DIRECT | AUTOFS_TYP_OFFSET; | ||
277 | break; | ||
256 | default: | 278 | default: |
257 | return 1; | 279 | return 1; |
258 | } | 280 | } |
@@ -271,6 +293,11 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) | |||
271 | return ino; | 293 | return ino; |
272 | } | 294 | } |
273 | 295 | ||
296 | void autofs4_dentry_release(struct dentry *); | ||
297 | static struct dentry_operations autofs4_sb_dentry_operations = { | ||
298 | .d_release = autofs4_dentry_release, | ||
299 | }; | ||
300 | |||
274 | int autofs4_fill_super(struct super_block *s, void *data, int silent) | 301 | int autofs4_fill_super(struct super_block *s, void *data, int silent) |
275 | { | 302 | { |
276 | struct inode * root_inode; | 303 | struct inode * root_inode; |
@@ -297,6 +324,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
297 | sbi->sb = s; | 324 | sbi->sb = s; |
298 | sbi->version = 0; | 325 | sbi->version = 0; |
299 | sbi->sub_version = 0; | 326 | sbi->sub_version = 0; |
327 | sbi->type = 0; | ||
300 | sbi->min_proto = 0; | 328 | sbi->min_proto = 0; |
301 | sbi->max_proto = 0; | 329 | sbi->max_proto = 0; |
302 | mutex_init(&sbi->wq_mutex); | 330 | mutex_init(&sbi->wq_mutex); |
@@ -315,27 +343,31 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
315 | if (!ino) | 343 | if (!ino) |
316 | goto fail_free; | 344 | goto fail_free; |
317 | root_inode = autofs4_get_inode(s, ino); | 345 | root_inode = autofs4_get_inode(s, ino); |
318 | kfree(ino); | ||
319 | if (!root_inode) | 346 | if (!root_inode) |
320 | goto fail_free; | 347 | goto fail_ino; |
321 | 348 | ||
322 | root_inode->i_op = &autofs4_root_inode_operations; | ||
323 | root_inode->i_fop = &autofs4_root_operations; | ||
324 | root = d_alloc_root(root_inode); | 349 | root = d_alloc_root(root_inode); |
325 | pipe = NULL; | ||
326 | |||
327 | if (!root) | 350 | if (!root) |
328 | goto fail_iput; | 351 | goto fail_iput; |
352 | pipe = NULL; | ||
353 | |||
354 | root->d_op = &autofs4_sb_dentry_operations; | ||
355 | root->d_fsdata = ino; | ||
329 | 356 | ||
330 | /* Can this call block? */ | 357 | /* Can this call block? */ |
331 | if (parse_options(data, &pipefd, | 358 | if (parse_options(data, &pipefd, |
332 | &root_inode->i_uid, &root_inode->i_gid, | 359 | &root_inode->i_uid, &root_inode->i_gid, |
333 | &sbi->oz_pgrp, | 360 | &sbi->oz_pgrp, &sbi->type, |
334 | &sbi->min_proto, &sbi->max_proto)) { | 361 | &sbi->min_proto, &sbi->max_proto)) { |
335 | printk("autofs: called with bogus options\n"); | 362 | printk("autofs: called with bogus options\n"); |
336 | goto fail_dput; | 363 | goto fail_dput; |
337 | } | 364 | } |
338 | 365 | ||
366 | root_inode->i_fop = &autofs4_root_operations; | ||
367 | root_inode->i_op = sbi->type & AUTOFS_TYP_DIRECT ? | ||
368 | &autofs4_direct_root_inode_operations : | ||
369 | &autofs4_indirect_root_inode_operations; | ||
370 | |||
339 | /* Couldn't this be tested earlier? */ | 371 | /* Couldn't this be tested earlier? */ |
340 | if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION || | 372 | if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION || |
341 | sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) { | 373 | sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) { |
@@ -391,6 +423,8 @@ fail_dput: | |||
391 | fail_iput: | 423 | fail_iput: |
392 | printk("autofs: get root dentry failed\n"); | 424 | printk("autofs: get root dentry failed\n"); |
393 | iput(root_inode); | 425 | iput(root_inode); |
426 | fail_ino: | ||
427 | kfree(ino); | ||
394 | fail_free: | 428 | fail_free: |
395 | kfree(sbi); | 429 | kfree(sbi); |
396 | fail_unlock: | 430 | fail_unlock: |