Blame view

fs/autofs/inode.c 6.54 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /* -*- linux-c -*- --------------------------------------------------------- *
   *
   * linux/fs/autofs/inode.c
   *
   *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
   *
   * This file is part of the Linux kernel and is made available under
   * the terms of the GNU General Public License, version 2, or at your
   * option, any later version, incorporated herein by reference.
   *
   * ------------------------------------------------------------------------- */
  
  #include <linux/kernel.h>
  #include <linux/mm.h>
  #include <linux/slab.h>
  #include <linux/file.h>
  #include <linux/parser.h>
  #include <linux/bitops.h>
e18fa700c   Jeff Garzik   Move several *_SU...
19
  #include <linux/magic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include "autofs_i.h"
  #include <linux/module.h>
0e7d73824   David Howells   [PATCH] autofs3: ...
22
  void autofs_kill_sb(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  {
  	struct autofs_sb_info *sbi = autofs_sbi(sb);
  	unsigned int n;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
26
27
28
  	/*
  	 * In the event of a failure in get_sb_nodev the superblock
  	 * info is not present so nothing else has been setup, so
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
29
30
  	 * just call kill_anon_super when we are called from
  	 * deactivate_super.
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
31
32
  	 */
  	if (!sbi)
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
33
  		goto out_kill_sb;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
34

d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
35
  	if (!sbi->catatonic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  		autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
37
  	put_pid(sbi->oz_pgrp);
f76baf936   Alexander Krizhanovsky   [PATCH] autofs: f...
38
  	autofs_hash_nuke(sbi);
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
39
40
  	for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
  		if (test_bit(n, sbi->symlink_bitmap))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
  			kfree(sbi->symlink[n].data);
  	}
  
  	kfree(sb->s_fs_info);
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
45
  out_kill_sb:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
  	DPRINTK(("autofs: shutting down
  "));
0e7d73824   David Howells   [PATCH] autofs3: ...
48
  	kill_anon_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
  }
  
  static void autofs_read_inode(struct inode *inode);
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
52
  static const struct super_operations autofs_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  	.read_inode	= autofs_read_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  	.statfs		= simple_statfs,
  };
  
  enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
  
  static match_table_t autofs_tokens = {
  	{Opt_fd, "fd=%u"},
  	{Opt_uid, "uid=%u"},
  	{Opt_gid, "gid=%u"},
  	{Opt_pgrp, "pgrp=%u"},
  	{Opt_minproto, "minproto=%u"},
  	{Opt_maxproto, "maxproto=%u"},
  	{Opt_err, NULL}
  };
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
68
69
  static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
  		pid_t *pgrp, int *minproto, int *maxproto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
  
  	*uid = current->uid;
  	*gid = current->gid;
  	*pgrp = process_group(current);
  
  	*minproto = *maxproto = AUTOFS_PROTO_VERSION;
  
  	*pipefd = -1;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, autofs_tokens, args);
  		switch (token) {
  		case Opt_fd:
  			if (match_int(&args[0], &option))
  				return 1;
  			*pipefd = option;
  			break;
  		case Opt_uid:
  			if (match_int(&args[0], &option))
  				return 1;
  			*uid = option;
  			break;
  		case Opt_gid:
  			if (match_int(&args[0], &option))
  				return 1;
  			*gid = option;
  			break;
  		case Opt_pgrp:
  			if (match_int(&args[0], &option))
  				return 1;
  			*pgrp = option;
  			break;
  		case Opt_minproto:
  			if (match_int(&args[0], &option))
  				return 1;
  			*minproto = option;
  			break;
  		case Opt_maxproto:
  			if (match_int(&args[0], &option))
  				return 1;
  			*maxproto = option;
  			break;
  		default:
  			return 1;
  		}
  	}
  	return (*pipefd < 0);
  }
  
  int autofs_fill_super(struct super_block *s, void *data, int silent)
  {
  	struct inode * root_inode;
  	struct dentry * root;
  	struct file * pipe;
  	int pipefd;
  	struct autofs_sb_info *sbi;
  	int minproto, maxproto;
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
138
  	pid_t pgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
140
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
141
  	if (!sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  		goto fail_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
  	DPRINTK(("autofs: starting up, sbi = %p
  ",sbi));
  
  	s->s_fs_info = sbi;
  	sbi->magic = AUTOFS_SBI_MAGIC;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
148
149
  	sbi->pipe = NULL;
  	sbi->catatonic = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  	sbi->exp_timeout = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
157
158
159
  	autofs_initialize_hash(&sbi->dirhash);
  	sbi->queues = NULL;
  	memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
  	sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO;
  	s->s_blocksize = 1024;
  	s->s_blocksize_bits = 10;
  	s->s_magic = AUTOFS_SUPER_MAGIC;
  	s->s_op = &autofs_sops;
  	s->s_time_gran = 1;
f76baf936   Alexander Krizhanovsky   [PATCH] autofs: f...
160
  	sbi->sb = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
167
168
169
  
  	root_inode = iget(s, AUTOFS_ROOT_INO);
  	root = d_alloc_root(root_inode);
  	pipe = NULL;
  
  	if (!root)
  		goto fail_iput;
  
  	/* Can this call block?  - WTF cares? s is locked. */
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
170
  	if (parse_options(data, &pipefd, &root_inode->i_uid,
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
171
  				&root_inode->i_gid, &pgid, &minproto,
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
172
  				&maxproto)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
178
  		printk("autofs: called with bogus options
  ");
  		goto fail_dput;
  	}
  
  	/* Couldn't this be tested earlier? */
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
179
180
  	if (minproto > AUTOFS_PROTO_VERSION ||
  	     maxproto < AUTOFS_PROTO_VERSION) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
  		printk("autofs: kernel does not match daemon version
  ");
  		goto fail_dput;
  	}
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
185
186
187
188
189
190
191
192
193
  	DPRINTK(("autofs: pipe fd = %d, pgrp = %u
  ", pipefd, pgid));
  	sbi->oz_pgrp = find_get_pid(pgid);
  
  	if (!sbi->oz_pgrp) {
  		printk("autofs: could not find process group %d
  ", pgid);
  		goto fail_dput;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  	pipe = fget(pipefd);
  	
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
196
  	if (!pipe) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
  		printk("autofs: could not open pipe file descriptor
  ");
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
199
  		goto fail_put_pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	}
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
201

d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
202
  	if (!pipe->f_op || !pipe->f_op->write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  		goto fail_fput;
  	sbi->pipe = pipe;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
205
  	sbi->catatonic = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
210
211
212
213
214
215
216
  
  	/*
  	 * Success! Install the root dentry now to indicate completion.
  	 */
  	s->s_root = root;
  	return 0;
  
  fail_fput:
  	printk("autofs: pipe file descriptor does not contain proper ops
  ");
  	fput(pipe);
fa0334f19   Sukadev Bhattiprolu   Replace pid_t in ...
217
218
  fail_put_pid:
  	put_pid(sbi->oz_pgrp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
224
225
226
227
  fail_dput:
  	dput(root);
  	goto fail_free;
  fail_iput:
  	printk("autofs: get root dentry failed
  ");
  	iput(root_inode);
  fail_free:
  	kfree(sbi);
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
228
  	s->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  fail_unlock:
  	return -EINVAL;
  }
  
  static void autofs_read_inode(struct inode *inode)
  {
  	ino_t ino = inode->i_ino;
  	unsigned int n;
  	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
  
  	/* Initialize to the default case (stub directory) */
  
  	inode->i_op = &simple_dir_inode_operations;
  	inode->i_fop = &simple_dir_operations;
  	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
  	inode->i_nlink = 2;
  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  	inode->i_blocks = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
248
  	if (ino == AUTOFS_ROOT_INO) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
254
255
256
257
258
  		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
  		inode->i_op = &autofs_root_inode_operations;
  		inode->i_fop = &autofs_root_operations;
  		inode->i_uid = inode->i_gid = 0; /* Changed in read_super */
  		return;
  	} 
  	
  	inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
  	inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
  	
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
259
  	if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
  		/* Symlink inode - should be in symlink list */
  		struct autofs_symlink *sl;
  
  		n = ino - AUTOFS_FIRST_SYMLINK;
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
264
  		if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
  			printk("autofs: Looking for bad symlink inode %u
  ", (unsigned int) ino);
  			return;
  		}
  		
  		inode->i_op = &autofs_symlink_inode_operations;
  		sl = &sbi->symlink[n];
8e18e2941   Theodore Ts'o   [PATCH] inode_die...
272
  		inode->i_private = sl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
278
279
  		inode->i_mode = S_IFLNK | S_IRWXUGO;
  		inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
  		inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
  		inode->i_size = sl->len;
  		inode->i_nlink = 1;
  	}
  }