Blame view

fs/autofs4/inode.c 9.13 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /* -*- c -*- --------------------------------------------------------------- *
   *
   * linux/fs/autofs/inode.c
   *
   *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
34ca959cf   Ian Kent   [PATCH] autofs4: ...
6
   *  Copyright 2005-2006 Ian Kent <raven@themaw.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
   *
   * 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/slab.h>
  #include <linux/file.h>
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
17
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
  #include <linux/pagemap.h>
  #include <linux/parser.h>
  #include <linux/bitops.h>
e18fa700c   Jeff Garzik   Move several *_SU...
21
  #include <linux/magic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
  #include "autofs_i.h"
  #include <linux/module.h>
  
  static void ino_lnkfree(struct autofs_info *ino)
  {
257673787   Ian Kent   autofs4: use look...
27
28
29
30
  	if (ino->u.symlink) {
  		kfree(ino->u.symlink);
  		ino->u.symlink = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  }
  
  struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
  				     struct autofs_sb_info *sbi, mode_t mode)
  {
  	int reinit = 1;
  
  	if (ino == NULL) {
  		reinit = 0;
  		ino = kmalloc(sizeof(*ino), GFP_KERNEL);
  	}
  
  	if (ino == NULL)
  		return NULL;
257673787   Ian Kent   autofs4: use look...
45
46
47
48
49
50
  	if (!reinit) {
  		ino->flags = 0;
  		ino->inode = NULL;
  		ino->dentry = NULL;
  		ino->size = 0;
  		INIT_LIST_HEAD(&ino->active);
4f8427d19   Ian Kent   autofs4: use help...
51
  		ino->active_count = 0;
257673787   Ian Kent   autofs4: use look...
52
53
54
  		INIT_LIST_HEAD(&ino->expiring);
  		atomic_set(&ino->count, 0);
  	}
f50b6f869   Ian Kent   [PATCH] autofs4: ...
55

c0f54d3e5   Ian Kent   autofs4: track ui...
56
57
  	ino->uid = 0;
  	ino->gid = 0;
257673787   Ian Kent   autofs4: use look...
58
  	ino->mode = mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  	ino->last_used = jiffies;
  
  	ino->sbi = sbi;
  
  	if (reinit && ino->free)
  		(ino->free)(ino);
  
  	memset(&ino->u, 0, sizeof(ino->u));
  
  	ino->free = NULL;
  
  	if (S_ISLNK(mode))
  		ino->free = ino_lnkfree;
  
  	return ino;
  }
  
  void autofs4_free_ino(struct autofs_info *ino)
  {
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
78
  	struct autofs_info *p_ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  	if (ino->dentry) {
  		ino->dentry->d_fsdata = NULL;
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
81
82
83
84
85
86
87
  		if (ino->dentry->d_inode) {
  			struct dentry *parent = ino->dentry->d_parent;
  			if (atomic_dec_and_test(&ino->count)) {
  				p_ino = autofs4_dentry_ino(parent);
  				if (p_ino && parent != ino->dentry)
  					atomic_dec(&p_ino->count);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  			dput(ino->dentry);
1aff3c8b0   Ian Kent   [PATCH] autofs4: ...
89
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
  		ino->dentry = NULL;
  	}
  	if (ino->free)
  		(ino->free)(ino);
  	kfree(ino);
  }
6ce315234   David Howells   [PATCH] AUTOFS: M...
96
  void autofs4_kill_sb(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  {
  	struct autofs_sb_info *sbi = autofs4_sbi(sb);
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
99
100
101
  	/*
  	 * 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...
102
103
  	 * just call kill_anon_super when we are called from
  	 * deactivate_super.
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
104
105
  	 */
  	if (!sbi)
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
106
  		goto out_kill_sb;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
107

5a11d4d0e   Ian Kent   autofs4: fix wait...
108
109
  	/* Free wait queues, close pipe */
  	autofs4_catatonic_mode(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110

f50b6f869   Ian Kent   [PATCH] autofs4: ...
111
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  	kfree(sbi);
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
113
  out_kill_sb:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  	DPRINTK("shutting down");
5b7e934d8   Al Viro   Use kill_litter_s...
115
  	kill_litter_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  }
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
117
118
119
  static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
  {
  	struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb);
aef97cb90   Miklos Szeredi   mount options: fi...
120
  	struct inode *root_inode = mnt->mnt_sb->s_root->d_inode;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
121
122
123
124
125
  
  	if (!sbi)
  		return 0;
  
  	seq_printf(m, ",fd=%d", sbi->pipefd);
aef97cb90   Miklos Szeredi   mount options: fi...
126
127
128
129
  	if (root_inode->i_uid != 0)
  		seq_printf(m, ",uid=%u", root_inode->i_uid);
  	if (root_inode->i_gid != 0)
  		seq_printf(m, ",gid=%u", root_inode->i_gid);
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
130
131
132
133
  	seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
  	seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
  	seq_printf(m, ",minproto=%d", sbi->min_proto);
  	seq_printf(m, ",maxproto=%d", sbi->max_proto);
a92daf6ba   Ian Kent   autofs4: make aut...
134
  	if (autofs_type_offset(sbi->type))
34ca959cf   Ian Kent   [PATCH] autofs4: ...
135
  		seq_printf(m, ",offset");
a92daf6ba   Ian Kent   autofs4: make aut...
136
  	else if (autofs_type_direct(sbi->type))
34ca959cf   Ian Kent   [PATCH] autofs4: ...
137
138
139
  		seq_printf(m, ",direct");
  	else
  		seq_printf(m, ",indirect");
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
140
141
  	return 0;
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
142
  static const struct super_operations autofs4_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	.statfs		= simple_statfs,
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
144
  	.show_options	= autofs4_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  };
34ca959cf   Ian Kent   [PATCH] autofs4: ...
146
147
  enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
  	Opt_indirect, Opt_direct, Opt_offset};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

a447c0932   Steven Whitehouse   vfs: Use const fo...
149
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
155
  	{Opt_fd, "fd=%u"},
  	{Opt_uid, "uid=%u"},
  	{Opt_gid, "gid=%u"},
  	{Opt_pgrp, "pgrp=%u"},
  	{Opt_minproto, "minproto=%u"},
  	{Opt_maxproto, "maxproto=%u"},
34ca959cf   Ian Kent   [PATCH] autofs4: ...
156
157
158
  	{Opt_indirect, "indirect"},
  	{Opt_direct, "direct"},
  	{Opt_offset, "offset"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
  	{Opt_err, NULL}
  };
  
  static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
163
  		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
0eb790e3a   David Howells   CRED: Wrap task c...
168
169
  	*uid = current_uid();
  	*gid = current_gid();
a47afb0f9   Pavel Emelianov   pid namespaces: r...
170
  	*pgrp = task_pgrp_nr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  
  	*minproto = AUTOFS_MIN_PROTO_VERSION;
  	*maxproto = AUTOFS_MAX_PROTO_VERSION;
  
  	*pipefd = -1;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_fd:
  			if (match_int(args, pipefd))
  				return 1;
  			break;
  		case Opt_uid:
  			if (match_int(args, &option))
  				return 1;
  			*uid = option;
  			break;
  		case Opt_gid:
  			if (match_int(args, &option))
  				return 1;
  			*gid = option;
  			break;
  		case Opt_pgrp:
  			if (match_int(args, &option))
  				return 1;
  			*pgrp = option;
  			break;
  		case Opt_minproto:
  			if (match_int(args, &option))
  				return 1;
  			*minproto = option;
  			break;
  		case Opt_maxproto:
  			if (match_int(args, &option))
  				return 1;
  			*maxproto = option;
  			break;
34ca959cf   Ian Kent   [PATCH] autofs4: ...
216
  		case Opt_indirect:
a92daf6ba   Ian Kent   autofs4: make aut...
217
  			set_autofs_type_indirect(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
218
219
  			break;
  		case Opt_direct:
a92daf6ba   Ian Kent   autofs4: make aut...
220
  			set_autofs_type_direct(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
221
222
  			break;
  		case Opt_offset:
a92daf6ba   Ian Kent   autofs4: make aut...
223
  			set_autofs_type_offset(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
224
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  		default:
  			return 1;
  		}
  	}
  	return (*pipefd < 0);
  }
  
  static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi)
  {
  	struct autofs_info *ino;
  
  	ino = autofs4_init_ino(NULL, sbi, S_IFDIR | 0755);
  	if (!ino)
  		return NULL;
  
  	return ino;
  }
08f11513f   Al Viro   constify dentry_o...
242
  static const struct dentry_operations autofs4_sb_dentry_operations = {
34ca959cf   Ian Kent   [PATCH] autofs4: ...
243
244
  	.d_release      = autofs4_dentry_release,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
  int autofs4_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;
  	struct autofs_info *ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

b63d50c43   Mariusz Kozlowski   fs/autofs4/inode....
254
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
255
  	if (!sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
  		goto fail_unlock;
  	DPRINTK("starting up, sbi = %p",sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
  	s->s_fs_info = sbi;
  	sbi->magic = AUTOFS_SBI_MAGIC;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
260
  	sbi->pipefd = -1;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
261
262
  	sbi->pipe = NULL;
  	sbi->catatonic = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	sbi->exp_timeout = 0;
a47afb0f9   Pavel Emelianov   pid namespaces: r...
264
  	sbi->oz_pgrp = task_pgrp_nr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  	sbi->sb = s;
  	sbi->version = 0;
  	sbi->sub_version = 0;
a92daf6ba   Ian Kent   autofs4: make aut...
268
  	set_autofs_type_indirect(&sbi->type);
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
269
270
  	sbi->min_proto = 0;
  	sbi->max_proto = 0;
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
271
  	mutex_init(&sbi->wq_mutex);
3a9720ce7   Ian Kent   [PATCH] autofs4: ...
272
  	spin_lock_init(&sbi->fs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  	sbi->queues = NULL;
5f6f4f28b   Ian Kent   autofs4: don't ma...
274
  	spin_lock_init(&sbi->lookup_lock);
257673787   Ian Kent   autofs4: use look...
275
  	INIT_LIST_HEAD(&sbi->active_list);
5f6f4f28b   Ian Kent   autofs4: don't ma...
276
  	INIT_LIST_HEAD(&sbi->expiring_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
284
285
286
287
288
289
  	s->s_blocksize = 1024;
  	s->s_blocksize_bits = 10;
  	s->s_magic = AUTOFS_SUPER_MAGIC;
  	s->s_op = &autofs4_sops;
  	s->s_time_gran = 1;
  
  	/*
  	 * Get the root inode and dentry, but defer checking for errors.
  	 */
  	ino = autofs4_mkroot(sbi);
  	if (!ino)
  		goto fail_free;
  	root_inode = autofs4_get_inode(s, ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  	if (!root_inode)
34ca959cf   Ian Kent   [PATCH] autofs4: ...
291
  		goto fail_ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  	root = d_alloc_root(root_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
  	if (!root)
  		goto fail_iput;
34ca959cf   Ian Kent   [PATCH] autofs4: ...
296
297
298
299
  	pipe = NULL;
  
  	root->d_op = &autofs4_sb_dentry_operations;
  	root->d_fsdata = ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
  
  	/* Can this call block? */
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
302
303
304
  	if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
  				&sbi->oz_pgrp, &sbi->type, &sbi->min_proto,
  				&sbi->max_proto)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
  		printk("autofs: called with bogus options
  ");
  		goto fail_dput;
  	}
34ca959cf   Ian Kent   [PATCH] autofs4: ...
309
  	root_inode->i_fop = &autofs4_root_operations;
a92daf6ba   Ian Kent   autofs4: make aut...
310
  	root_inode->i_op = autofs_type_trigger(sbi->type) ?
34ca959cf   Ian Kent   [PATCH] autofs4: ...
311
312
  			&autofs4_direct_root_inode_operations :
  			&autofs4_indirect_root_inode_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  	/* Couldn't this be tested earlier? */
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
314
315
  	if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
  	    sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
  		printk("autofs: kernel does not match daemon version "
  		       "daemon (%d, %d) kernel (%d, %d)
  ",
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
319
  			sbi->min_proto, sbi->max_proto,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
  			AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
  		goto fail_dput;
  	}
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
323
324
325
326
327
  	/* Establish highest kernel protocol version */
  	if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
  		sbi->version = AUTOFS_MAX_PROTO_VERSION;
  	else
  		sbi->version = sbi->max_proto;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
  	sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
  
  	DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
  	pipe = fget(pipefd);
  	
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
333
  	if (!pipe) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
  		printk("autofs: could not open pipe file descriptor
  ");
  		goto fail_dput;
  	}
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
338
  	if (!pipe->f_op || !pipe->f_op->write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
  		goto fail_fput;
  	sbi->pipe = pipe;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
341
  	sbi->pipefd = pipefd;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
342
  	sbi->catatonic = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  
  	/*
  	 * Success! Install the root dentry now to indicate completion.
  	 */
  	s->s_root = root;
  	return 0;
  	
  	/*
  	 * Failure ... clean up.
  	 */
  fail_fput:
  	printk("autofs: pipe file descriptor does not contain proper ops
  ");
  	fput(pipe);
  	/* fall through */
  fail_dput:
  	dput(root);
  	goto fail_free;
  fail_iput:
  	printk("autofs: get root dentry failed
  ");
  	iput(root_inode);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
365
366
  fail_ino:
  	kfree(ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
  fail_free:
  	kfree(sbi);
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
369
  	s->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  fail_unlock:
  	return -EINVAL;
  }
  
  struct inode *autofs4_get_inode(struct super_block *sb,
  				struct autofs_info *inf)
  {
  	struct inode *inode = new_inode(sb);
  
  	if (inode == NULL)
  		return NULL;
  
  	inf->inode = inode;
  	inode->i_mode = inf->mode;
  	if (sb->s_root) {
  		inode->i_uid = sb->s_root->d_inode->i_uid;
  		inode->i_gid = sb->s_root->d_inode->i_gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
391
392
393
394
395
396
397
398
399
400
  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  
  	if (S_ISDIR(inf->mode)) {
  		inode->i_nlink = 2;
  		inode->i_op = &autofs4_dir_inode_operations;
  		inode->i_fop = &autofs4_dir_operations;
  	} else if (S_ISLNK(inf->mode)) {
  		inode->i_size = inf->size;
  		inode->i_op = &autofs4_symlink_inode_operations;
  	}
  
  	return inode;
  }