diff options
Diffstat (limited to 'fs/autofs/inode.c')
-rw-r--r-- | fs/autofs/inode.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c new file mode 100644 index 000000000000..4888c1fabbf7 --- /dev/null +++ b/fs/autofs/inode.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* -*- linux-c -*- --------------------------------------------------------- * | ||
2 | * | ||
3 | * linux/fs/autofs/inode.c | ||
4 | * | ||
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | ||
6 | * | ||
7 | * 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 | * option, any later version, incorporated herein by reference. | ||
10 | * | ||
11 | * ------------------------------------------------------------------------- */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/file.h> | ||
17 | #include <linux/parser.h> | ||
18 | #include <linux/bitops.h> | ||
19 | #include "autofs_i.h" | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | static void autofs_put_super(struct super_block *sb) | ||
23 | { | ||
24 | struct autofs_sb_info *sbi = autofs_sbi(sb); | ||
25 | unsigned int n; | ||
26 | |||
27 | if ( !sbi->catatonic ) | ||
28 | autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ | ||
29 | |||
30 | autofs_hash_nuke(&sbi->dirhash); | ||
31 | for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { | ||
32 | if ( test_bit(n, sbi->symlink_bitmap) ) | ||
33 | kfree(sbi->symlink[n].data); | ||
34 | } | ||
35 | |||
36 | kfree(sb->s_fs_info); | ||
37 | |||
38 | DPRINTK(("autofs: shutting down\n")); | ||
39 | } | ||
40 | |||
41 | static void autofs_read_inode(struct inode *inode); | ||
42 | |||
43 | static struct super_operations autofs_sops = { | ||
44 | .read_inode = autofs_read_inode, | ||
45 | .put_super = autofs_put_super, | ||
46 | .statfs = simple_statfs, | ||
47 | }; | ||
48 | |||
49 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto}; | ||
50 | |||
51 | static match_table_t autofs_tokens = { | ||
52 | {Opt_fd, "fd=%u"}, | ||
53 | {Opt_uid, "uid=%u"}, | ||
54 | {Opt_gid, "gid=%u"}, | ||
55 | {Opt_pgrp, "pgrp=%u"}, | ||
56 | {Opt_minproto, "minproto=%u"}, | ||
57 | {Opt_maxproto, "maxproto=%u"}, | ||
58 | {Opt_err, NULL} | ||
59 | }; | ||
60 | |||
61 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto) | ||
62 | { | ||
63 | char *p; | ||
64 | substring_t args[MAX_OPT_ARGS]; | ||
65 | int option; | ||
66 | |||
67 | *uid = current->uid; | ||
68 | *gid = current->gid; | ||
69 | *pgrp = process_group(current); | ||
70 | |||
71 | *minproto = *maxproto = AUTOFS_PROTO_VERSION; | ||
72 | |||
73 | *pipefd = -1; | ||
74 | |||
75 | if (!options) | ||
76 | return 1; | ||
77 | |||
78 | while ((p = strsep(&options, ",")) != NULL) { | ||
79 | int token; | ||
80 | if (!*p) | ||
81 | continue; | ||
82 | |||
83 | token = match_token(p, autofs_tokens, args); | ||
84 | switch (token) { | ||
85 | case Opt_fd: | ||
86 | if (match_int(&args[0], &option)) | ||
87 | return 1; | ||
88 | *pipefd = option; | ||
89 | break; | ||
90 | case Opt_uid: | ||
91 | if (match_int(&args[0], &option)) | ||
92 | return 1; | ||
93 | *uid = option; | ||
94 | break; | ||
95 | case Opt_gid: | ||
96 | if (match_int(&args[0], &option)) | ||
97 | return 1; | ||
98 | *gid = option; | ||
99 | break; | ||
100 | case Opt_pgrp: | ||
101 | if (match_int(&args[0], &option)) | ||
102 | return 1; | ||
103 | *pgrp = option; | ||
104 | break; | ||
105 | case Opt_minproto: | ||
106 | if (match_int(&args[0], &option)) | ||
107 | return 1; | ||
108 | *minproto = option; | ||
109 | break; | ||
110 | case Opt_maxproto: | ||
111 | if (match_int(&args[0], &option)) | ||
112 | return 1; | ||
113 | *maxproto = option; | ||
114 | break; | ||
115 | default: | ||
116 | return 1; | ||
117 | } | ||
118 | } | ||
119 | return (*pipefd < 0); | ||
120 | } | ||
121 | |||
122 | int autofs_fill_super(struct super_block *s, void *data, int silent) | ||
123 | { | ||
124 | struct inode * root_inode; | ||
125 | struct dentry * root; | ||
126 | struct file * pipe; | ||
127 | int pipefd; | ||
128 | struct autofs_sb_info *sbi; | ||
129 | int minproto, maxproto; | ||
130 | |||
131 | sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); | ||
132 | if ( !sbi ) | ||
133 | goto fail_unlock; | ||
134 | memset(sbi, 0, sizeof(*sbi)); | ||
135 | DPRINTK(("autofs: starting up, sbi = %p\n",sbi)); | ||
136 | |||
137 | s->s_fs_info = sbi; | ||
138 | sbi->magic = AUTOFS_SBI_MAGIC; | ||
139 | sbi->catatonic = 0; | ||
140 | sbi->exp_timeout = 0; | ||
141 | sbi->oz_pgrp = process_group(current); | ||
142 | autofs_initialize_hash(&sbi->dirhash); | ||
143 | sbi->queues = NULL; | ||
144 | memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); | ||
145 | sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO; | ||
146 | s->s_blocksize = 1024; | ||
147 | s->s_blocksize_bits = 10; | ||
148 | s->s_magic = AUTOFS_SUPER_MAGIC; | ||
149 | s->s_op = &autofs_sops; | ||
150 | s->s_time_gran = 1; | ||
151 | |||
152 | root_inode = iget(s, AUTOFS_ROOT_INO); | ||
153 | root = d_alloc_root(root_inode); | ||
154 | pipe = NULL; | ||
155 | |||
156 | if (!root) | ||
157 | goto fail_iput; | ||
158 | |||
159 | /* Can this call block? - WTF cares? s is locked. */ | ||
160 | if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { | ||
161 | printk("autofs: called with bogus options\n"); | ||
162 | goto fail_dput; | ||
163 | } | ||
164 | |||
165 | /* Couldn't this be tested earlier? */ | ||
166 | if ( minproto > AUTOFS_PROTO_VERSION || | ||
167 | maxproto < AUTOFS_PROTO_VERSION ) { | ||
168 | printk("autofs: kernel does not match daemon version\n"); | ||
169 | goto fail_dput; | ||
170 | } | ||
171 | |||
172 | DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp)); | ||
173 | pipe = fget(pipefd); | ||
174 | |||
175 | if ( !pipe ) { | ||
176 | printk("autofs: could not open pipe file descriptor\n"); | ||
177 | goto fail_dput; | ||
178 | } | ||
179 | if ( !pipe->f_op || !pipe->f_op->write ) | ||
180 | goto fail_fput; | ||
181 | sbi->pipe = pipe; | ||
182 | |||
183 | /* | ||
184 | * Success! Install the root dentry now to indicate completion. | ||
185 | */ | ||
186 | s->s_root = root; | ||
187 | return 0; | ||
188 | |||
189 | fail_fput: | ||
190 | printk("autofs: pipe file descriptor does not contain proper ops\n"); | ||
191 | fput(pipe); | ||
192 | fail_dput: | ||
193 | dput(root); | ||
194 | goto fail_free; | ||
195 | fail_iput: | ||
196 | printk("autofs: get root dentry failed\n"); | ||
197 | iput(root_inode); | ||
198 | fail_free: | ||
199 | kfree(sbi); | ||
200 | fail_unlock: | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | |||
204 | static void autofs_read_inode(struct inode *inode) | ||
205 | { | ||
206 | ino_t ino = inode->i_ino; | ||
207 | unsigned int n; | ||
208 | struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); | ||
209 | |||
210 | /* Initialize to the default case (stub directory) */ | ||
211 | |||
212 | inode->i_op = &simple_dir_inode_operations; | ||
213 | inode->i_fop = &simple_dir_operations; | ||
214 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
215 | inode->i_nlink = 2; | ||
216 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
217 | inode->i_blocks = 0; | ||
218 | inode->i_blksize = 1024; | ||
219 | |||
220 | if ( ino == AUTOFS_ROOT_INO ) { | ||
221 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; | ||
222 | inode->i_op = &autofs_root_inode_operations; | ||
223 | inode->i_fop = &autofs_root_operations; | ||
224 | inode->i_uid = inode->i_gid = 0; /* Changed in read_super */ | ||
225 | return; | ||
226 | } | ||
227 | |||
228 | inode->i_uid = inode->i_sb->s_root->d_inode->i_uid; | ||
229 | inode->i_gid = inode->i_sb->s_root->d_inode->i_gid; | ||
230 | |||
231 | if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) { | ||
232 | /* Symlink inode - should be in symlink list */ | ||
233 | struct autofs_symlink *sl; | ||
234 | |||
235 | n = ino - AUTOFS_FIRST_SYMLINK; | ||
236 | if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) { | ||
237 | printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino); | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | inode->i_op = &autofs_symlink_inode_operations; | ||
242 | sl = &sbi->symlink[n]; | ||
243 | inode->u.generic_ip = sl; | ||
244 | inode->i_mode = S_IFLNK | S_IRWXUGO; | ||
245 | inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime; | ||
246 | inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; | ||
247 | inode->i_size = sl->len; | ||
248 | inode->i_nlink = 1; | ||
249 | } | ||
250 | } | ||