Blame view

fs/autofs4/inode.c 8.08 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
  #include "autofs_i.h"
  #include <linux/module.h>
26e6c9106   Al Viro   autofs4: split au...
24
  struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  {
26e6c9106   Al Viro   autofs4: split au...
26
27
  	struct autofs_info *ino = kzalloc(sizeof(*ino), GFP_KERNEL);
  	if (ino) {
257673787   Ian Kent   autofs4: use look...
28
29
  		INIT_LIST_HEAD(&ino->active);
  		INIT_LIST_HEAD(&ino->expiring);
26e6c9106   Al Viro   autofs4: split au...
30
31
  		ino->last_used = jiffies;
  		ino->sbi = sbi;
257673787   Ian Kent   autofs4: use look...
32
  	}
26e6c9106   Al Viro   autofs4: split au...
33
34
  	return ino;
  }
f50b6f869   Ian Kent   [PATCH] autofs4: ...
35

26e6c9106   Al Viro   autofs4: split au...
36
37
  void autofs4_clean_ino(struct autofs_info *ino)
  {
c0f54d3e5   Ian Kent   autofs4: track ui...
38
39
  	ino->uid = 0;
  	ino->gid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	ino->last_used = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
  }
  
  void autofs4_free_ino(struct autofs_info *ino)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
  	kfree(ino);
  }
6ce315234   David Howells   [PATCH] AUTOFS: M...
47
  void autofs4_kill_sb(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  {
  	struct autofs_sb_info *sbi = autofs4_sbi(sb);
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
50
51
52
  	/*
  	 * 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...
53
54
  	 * just call kill_anon_super when we are called from
  	 * deactivate_super.
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
55
56
  	 */
  	if (!sbi)
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
57
  		goto out_kill_sb;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
58

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

f50b6f869   Ian Kent   [PATCH] autofs4: ...
62
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  	kfree(sbi);
c949d4eb4   Jiri Kosina   [PATCH] autofs: f...
64
  out_kill_sb:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	DPRINTK("shutting down");
5b7e934d8   Al Viro   Use kill_litter_s...
66
  	kill_litter_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
68
  static int autofs4_show_options(struct seq_file *m, struct dentry *root)
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
69
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
70
71
  	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
  	struct inode *root_inode = root->d_sb->s_root->d_inode;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
72
73
74
75
76
  
  	if (!sbi)
  		return 0;
  
  	seq_printf(m, ",fd=%d", sbi->pipefd);
aef97cb90   Miklos Szeredi   mount options: fi...
77
78
79
80
  	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: ...
81
82
83
84
  	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...
85
  	if (autofs_type_offset(sbi->type))
34ca959cf   Ian Kent   [PATCH] autofs4: ...
86
  		seq_printf(m, ",offset");
a92daf6ba   Ian Kent   autofs4: make aut...
87
  	else if (autofs_type_direct(sbi->type))
34ca959cf   Ian Kent   [PATCH] autofs4: ...
88
89
90
  		seq_printf(m, ",direct");
  	else
  		seq_printf(m, ",indirect");
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
91
92
  	return 0;
  }
292c5ee80   Al Viro   autofs4: keep sym...
93
94
95
96
97
  static void autofs4_evict_inode(struct inode *inode)
  {
  	end_writeback(inode);
  	kfree(inode->i_private);
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
98
  static const struct super_operations autofs4_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	.statfs		= simple_statfs,
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
100
  	.show_options	= autofs4_show_options,
292c5ee80   Al Viro   autofs4: keep sym...
101
  	.evict_inode	= autofs4_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  };
34ca959cf   Ian Kent   [PATCH] autofs4: ...
103
104
  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
105

a447c0932   Steven Whitehouse   vfs: Use const fo...
106
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
  	{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: ...
113
114
115
  	{Opt_indirect, "indirect"},
  	{Opt_direct, "direct"},
  	{Opt_offset, "offset"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
  	{Opt_err, NULL}
  };
  
  static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
120
  		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
0eb790e3a   David Howells   CRED: Wrap task c...
125
126
  	*uid = current_uid();
  	*gid = current_gid();
a47afb0f9   Pavel Emelianov   pid namespaces: r...
127
  	*pgrp = task_pgrp_nr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  
  	*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: ...
173
  		case Opt_indirect:
a92daf6ba   Ian Kent   autofs4: make aut...
174
  			set_autofs_type_indirect(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
175
176
  			break;
  		case Opt_direct:
a92daf6ba   Ian Kent   autofs4: make aut...
177
  			set_autofs_type_direct(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
178
179
  			break;
  		case Opt_offset:
a92daf6ba   Ian Kent   autofs4: make aut...
180
  			set_autofs_type_offset(type);
34ca959cf   Ian Kent   [PATCH] autofs4: ...
181
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
186
187
  		default:
  			return 1;
  		}
  	}
  	return (*pipefd < 0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
191
192
193
194
195
  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
196

b63d50c43   Mariusz Kozlowski   fs/autofs4/inode....
197
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
198
  	if (!sbi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  		goto fail_unlock;
  	DPRINTK("starting up, sbi = %p",sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  	s->s_fs_info = sbi;
  	sbi->magic = AUTOFS_SBI_MAGIC;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
203
  	sbi->pipefd = -1;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
204
205
  	sbi->pipe = NULL;
  	sbi->catatonic = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  	sbi->exp_timeout = 0;
a47afb0f9   Pavel Emelianov   pid namespaces: r...
207
  	sbi->oz_pgrp = task_pgrp_nr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  	sbi->sb = s;
  	sbi->version = 0;
  	sbi->sub_version = 0;
a92daf6ba   Ian Kent   autofs4: make aut...
211
  	set_autofs_type_indirect(&sbi->type);
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
212
213
  	sbi->min_proto = 0;
  	sbi->max_proto = 0;
1d5599e39   Ingo Molnar   [PATCH] sem2mutex...
214
  	mutex_init(&sbi->wq_mutex);
d668dc566   Al Viro   autofs4: deal wit...
215
  	mutex_init(&sbi->pipe_mutex);
3a9720ce7   Ian Kent   [PATCH] autofs4: ...
216
  	spin_lock_init(&sbi->fs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  	sbi->queues = NULL;
5f6f4f28b   Ian Kent   autofs4: don't ma...
218
  	spin_lock_init(&sbi->lookup_lock);
257673787   Ian Kent   autofs4: use look...
219
  	INIT_LIST_HEAD(&sbi->active_list);
5f6f4f28b   Ian Kent   autofs4: don't ma...
220
  	INIT_LIST_HEAD(&sbi->expiring_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
  	s->s_blocksize = 1024;
  	s->s_blocksize_bits = 10;
  	s->s_magic = AUTOFS_SUPER_MAGIC;
  	s->s_op = &autofs4_sops;
b650c858c   David Howells   autofs4: Merge th...
225
  	s->s_d_op = &autofs4_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
229
230
  	s->s_time_gran = 1;
  
  	/*
  	 * Get the root inode and dentry, but defer checking for errors.
  	 */
26e6c9106   Al Viro   autofs4: split au...
231
  	ino = autofs4_new_ino(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  	if (!ino)
  		goto fail_free;
726a5e068   Al Viro   autofs4: autofs4_...
234
  	root_inode = autofs4_get_inode(s, S_IFDIR | 0755);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  	if (!root_inode)
34ca959cf   Ian Kent   [PATCH] autofs4: ...
236
  		goto fail_ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	root = d_alloc_root(root_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  	if (!root)
  		goto fail_iput;
34ca959cf   Ian Kent   [PATCH] autofs4: ...
241
  	pipe = NULL;
34ca959cf   Ian Kent   [PATCH] autofs4: ...
242
  	root->d_fsdata = ino;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
  
  	/* Can this call block? */
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
245
246
247
  	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
248
249
250
251
  		printk("autofs: called with bogus options
  ");
  		goto fail_dput;
  	}
b650c858c   David Howells   autofs4: Merge th...
252
  	if (autofs_type_trigger(sbi->type))
b5b801779   Ian Kent   autofs4: Add d_ma...
253
  		__managed_dentry_set_managed(root);
10584211e   Ian Kent   autofs4: Add d_au...
254

34ca959cf   Ian Kent   [PATCH] autofs4: ...
255
  	root_inode->i_fop = &autofs4_root_operations;
e61da20a5   Ian Kent   autofs4: Clean up...
256
  	root_inode->i_op = &autofs4_dir_inode_operations;
34ca959cf   Ian Kent   [PATCH] autofs4: ...
257

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	/* Couldn't this be tested earlier? */
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
259
260
  	if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
  	    sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
  		printk("autofs: kernel does not match daemon version "
  		       "daemon (%d, %d) kernel (%d, %d)
  ",
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
264
  			sbi->min_proto, sbi->max_proto,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  			AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
  		goto fail_dput;
  	}
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
268
269
270
271
272
  	/* 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
273
274
275
276
277
  	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...
278
  	if (!pipe) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
  		printk("autofs: could not open pipe file descriptor
  ");
  		goto fail_dput;
  	}
d78e53c89   Sukadev Bhattiprolu   Fix some coding-s...
283
  	if (!pipe->f_op || !pipe->f_op->write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
  		goto fail_fput;
  	sbi->pipe = pipe;
d7c4a5f10   Ian Kent   [PATCH] autofs4: ...
286
  	sbi->pipefd = pipefd;
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
287
  	sbi->catatonic = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  
  	/*
  	 * 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: ...
310
311
  fail_ino:
  	kfree(ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
  fail_free:
  	kfree(sbi);
ba8df43c0   Ian Kent   [PATCH] autofs4: ...
314
  	s->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
  fail_unlock:
  	return -EINVAL;
  }
030a8ba48   Al Viro   autofs4: propagat...
318
  struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
  {
  	struct inode *inode = new_inode(sb);
  
  	if (inode == NULL)
  		return NULL;
09f12c03f   Al Viro   autofs4: pass mod...
324
  	inode->i_mode = mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
  	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
328
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
85fe4025c   Christoph Hellwig   fs: do not assign...
330
  	inode->i_ino = get_next_ino();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331

09f12c03f   Al Viro   autofs4: pass mod...
332
  	if (S_ISDIR(mode)) {
bfe868486   Miklos Szeredi   filesystems: add ...
333
  		set_nlink(inode, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
  		inode->i_op = &autofs4_dir_inode_operations;
  		inode->i_fop = &autofs4_dir_operations;
09f12c03f   Al Viro   autofs4: pass mod...
336
  	} else if (S_ISLNK(mode)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
341
  		inode->i_op = &autofs4_symlink_inode_operations;
  	}
  
  	return inode;
  }