inode.c 8.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/* -*- c -*- --------------------------------------------------------------- *
 *
 * linux/fs/autofs/inode.c
 *
 *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6
 *  Copyright 2005-2006 Ian Kent <raven@themaw.net>
L
Linus Torvalds 已提交
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>
17
#include <linux/seq_file.h>
L
Linus Torvalds 已提交
18 19 20
#include <linux/pagemap.h>
#include <linux/parser.h>
#include <linux/bitops.h>
21
#include <linux/magic.h>
L
Linus Torvalds 已提交
22 23 24
#include "autofs_i.h"
#include <linux/module.h>

A
Al Viro 已提交
25
struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi)
L
Linus Torvalds 已提交
26
{
A
Al Viro 已提交
27 28
	struct autofs_info *ino = kzalloc(sizeof(*ino), GFP_KERNEL);
	if (ino) {
29 30
		INIT_LIST_HEAD(&ino->active);
		INIT_LIST_HEAD(&ino->expiring);
A
Al Viro 已提交
31 32
		ino->last_used = jiffies;
		ino->sbi = sbi;
33
	}
A
Al Viro 已提交
34 35
	return ino;
}
36

A
Al Viro 已提交
37 38
void autofs4_clean_ino(struct autofs_info *ino)
{
39 40
	ino->uid = 0;
	ino->gid = 0;
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48
	ino->last_used = jiffies;
}

void autofs4_free_ino(struct autofs_info *ino)
{
	kfree(ino);
}

49
void autofs4_kill_sb(struct super_block *sb)
L
Linus Torvalds 已提交
50 51 52
{
	struct autofs_sb_info *sbi = autofs4_sbi(sb);

I
Ian Kent 已提交
53 54 55
	/*
	 * In the event of a failure in get_sb_nodev the superblock
	 * info is not present so nothing else has been setup, so
56 57
	 * just call kill_anon_super when we are called from
	 * deactivate_super.
I
Ian Kent 已提交
58 59
	 */
	if (!sbi)
60
		goto out_kill_sb;
I
Ian Kent 已提交
61

I
Ian Kent 已提交
62 63
	/* Free wait queues, close pipe */
	autofs4_catatonic_mode(sbi);
L
Linus Torvalds 已提交
64

65
	sb->s_fs_info = NULL;
L
Linus Torvalds 已提交
66 67
	kfree(sbi);

68
out_kill_sb:
L
Linus Torvalds 已提交
69
	DPRINTK("shutting down");
70
	kill_litter_super(sb);
L
Linus Torvalds 已提交
71 72
}

73
static int autofs4_show_options(struct seq_file *m, struct dentry *root)
74
{
75 76
	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
	struct inode *root_inode = root->d_sb->s_root->d_inode;
77 78 79 80 81

	if (!sbi)
		return 0;

	seq_printf(m, ",fd=%d", sbi->pipefd);
M
Miklos Szeredi 已提交
82 83 84 85
	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);
86 87 88 89 90
	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);

91
	if (autofs_type_offset(sbi->type))
92
		seq_printf(m, ",offset");
93
	else if (autofs_type_direct(sbi->type))
94 95 96 97
		seq_printf(m, ",direct");
	else
		seq_printf(m, ",indirect");

98 99 100
	return 0;
}

101 102 103 104 105 106
static void autofs4_evict_inode(struct inode *inode)
{
	end_writeback(inode);
	kfree(inode->i_private);
}

107
static const struct super_operations autofs4_sops = {
L
Linus Torvalds 已提交
108
	.statfs		= simple_statfs,
109
	.show_options	= autofs4_show_options,
110
	.evict_inode	= autofs4_evict_inode,
L
Linus Torvalds 已提交
111 112
};

113 114
enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
	Opt_indirect, Opt_direct, Opt_offset};
L
Linus Torvalds 已提交
115

116
static const match_table_t tokens = {
L
Linus Torvalds 已提交
117 118 119 120 121 122
	{Opt_fd, "fd=%u"},
	{Opt_uid, "uid=%u"},
	{Opt_gid, "gid=%u"},
	{Opt_pgrp, "pgrp=%u"},
	{Opt_minproto, "minproto=%u"},
	{Opt_maxproto, "maxproto=%u"},
123 124 125
	{Opt_indirect, "indirect"},
	{Opt_direct, "direct"},
	{Opt_offset, "offset"},
L
Linus Torvalds 已提交
126 127 128 129
	{Opt_err, NULL}
};

static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
130
		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
L
Linus Torvalds 已提交
131 132 133 134 135
{
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;

136 137
	*uid = current_uid();
	*gid = current_gid();
P
Pavel Emelianov 已提交
138
	*pgrp = task_pgrp_nr(current);
L
Linus Torvalds 已提交
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 173 174 175 176 177 178 179 180 181 182 183

	*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;
184
		case Opt_indirect:
185
			set_autofs_type_indirect(type);
186 187
			break;
		case Opt_direct:
188
			set_autofs_type_direct(type);
189 190
			break;
		case Opt_offset:
191
			set_autofs_type_offset(type);
192
			break;
L
Linus Torvalds 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
		default:
			return 1;
		}
	}
	return (*pipefd < 0);
}

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;

209
	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
210
	if (!sbi)
L
Linus Torvalds 已提交
211 212 213 214 215
		goto fail_unlock;
	DPRINTK("starting up, sbi = %p",sbi);

	s->s_fs_info = sbi;
	sbi->magic = AUTOFS_SBI_MAGIC;
216
	sbi->pipefd = -1;
I
Ian Kent 已提交
217 218
	sbi->pipe = NULL;
	sbi->catatonic = 1;
L
Linus Torvalds 已提交
219
	sbi->exp_timeout = 0;
P
Pavel Emelianov 已提交
220
	sbi->oz_pgrp = task_pgrp_nr(current);
L
Linus Torvalds 已提交
221 222 223
	sbi->sb = s;
	sbi->version = 0;
	sbi->sub_version = 0;
224
	set_autofs_type_indirect(&sbi->type);
225 226
	sbi->min_proto = 0;
	sbi->max_proto = 0;
I
Ingo Molnar 已提交
227
	mutex_init(&sbi->wq_mutex);
I
Ian Kent 已提交
228
	spin_lock_init(&sbi->fs_lock);
L
Linus Torvalds 已提交
229
	sbi->queues = NULL;
230
	spin_lock_init(&sbi->lookup_lock);
231
	INIT_LIST_HEAD(&sbi->active_list);
232
	INIT_LIST_HEAD(&sbi->expiring_list);
L
Linus Torvalds 已提交
233 234 235 236
	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = AUTOFS_SUPER_MAGIC;
	s->s_op = &autofs4_sops;
237
	s->s_d_op = &autofs4_dentry_operations;
L
Linus Torvalds 已提交
238 239 240 241 242
	s->s_time_gran = 1;

	/*
	 * Get the root inode and dentry, but defer checking for errors.
	 */
A
Al Viro 已提交
243
	ino = autofs4_new_ino(sbi);
L
Linus Torvalds 已提交
244 245
	if (!ino)
		goto fail_free;
246
	root_inode = autofs4_get_inode(s, S_IFDIR | 0755);
L
Linus Torvalds 已提交
247
	if (!root_inode)
248
		goto fail_ino;
L
Linus Torvalds 已提交
249 250 251 252

	root = d_alloc_root(root_inode);
	if (!root)
		goto fail_iput;
253 254 255
	pipe = NULL;

	root->d_fsdata = ino;
L
Linus Torvalds 已提交
256 257

	/* Can this call block? */
258 259 260
	if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
				&sbi->oz_pgrp, &sbi->type, &sbi->min_proto,
				&sbi->max_proto)) {
L
Linus Torvalds 已提交
261 262 263 264
		printk("autofs: called with bogus options\n");
		goto fail_dput;
	}

265
	if (autofs_type_trigger(sbi->type))
266
		__managed_dentry_set_managed(root);
267

268
	root_inode->i_fop = &autofs4_root_operations;
I
Ian Kent 已提交
269
	root_inode->i_op = &autofs4_dir_inode_operations;
270

L
Linus Torvalds 已提交
271
	/* Couldn't this be tested earlier? */
272 273
	if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
	    sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
L
Linus Torvalds 已提交
274 275
		printk("autofs: kernel does not match daemon version "
		       "daemon (%d, %d) kernel (%d, %d)\n",
276
			sbi->min_proto, sbi->max_proto,
L
Linus Torvalds 已提交
277 278 279 280
			AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
		goto fail_dput;
	}

281 282 283 284 285
	/* 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;
L
Linus Torvalds 已提交
286 287 288 289 290
	sbi->sub_version = AUTOFS_PROTO_SUBVERSION;

	DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
	pipe = fget(pipefd);
	
291
	if (!pipe) {
L
Linus Torvalds 已提交
292 293 294
		printk("autofs: could not open pipe file descriptor\n");
		goto fail_dput;
	}
295
	if (!pipe->f_op || !pipe->f_op->write)
L
Linus Torvalds 已提交
296 297
		goto fail_fput;
	sbi->pipe = pipe;
298
	sbi->pipefd = pipefd;
I
Ian Kent 已提交
299
	sbi->catatonic = 0;
L
Linus Torvalds 已提交
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

	/*
	 * 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\n");
	fput(pipe);
	/* fall through */
fail_dput:
	dput(root);
	goto fail_free;
fail_iput:
	printk("autofs: get root dentry failed\n");
	iput(root_inode);
320 321
fail_ino:
	kfree(ino);
L
Linus Torvalds 已提交
322 323
fail_free:
	kfree(sbi);
I
Ian Kent 已提交
324
	s->s_fs_info = NULL;
L
Linus Torvalds 已提交
325 326 327 328
fail_unlock:
	return -EINVAL;
}

A
Al Viro 已提交
329
struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode)
L
Linus Torvalds 已提交
330 331 332 333 334 335
{
	struct inode *inode = new_inode(sb);

	if (inode == NULL)
		return NULL;

336
	inode->i_mode = mode;
L
Linus Torvalds 已提交
337 338 339 340 341
	if (sb->s_root) {
		inode->i_uid = sb->s_root->d_inode->i_uid;
		inode->i_gid = sb->s_root->d_inode->i_gid;
	}
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
342
	inode->i_ino = get_next_ino();
L
Linus Torvalds 已提交
343

344
	if (S_ISDIR(mode)) {
M
Miklos Szeredi 已提交
345
		set_nlink(inode, 2);
L
Linus Torvalds 已提交
346 347
		inode->i_op = &autofs4_dir_inode_operations;
		inode->i_fop = &autofs4_dir_operations;
348
	} else if (S_ISLNK(mode)) {
L
Linus Torvalds 已提交
349 350 351 352 353
		inode->i_op = &autofs4_symlink_inode_operations;
	}

	return inode;
}