mount.c 5.8 KB
Newer Older
D
David Teigland 已提交
1 2
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3
 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
D
David Teigland 已提交
4 5 6
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
7
 * of the GNU General Public License version 2.
D
David Teigland 已提交
8 9 10 11 12 13
 */

#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
14
#include <linux/gfs2_ondisk.h>
15
#include <linux/lm_interface.h>
16
#include <linux/parser.h>
D
David Teigland 已提交
17 18

#include "gfs2.h"
19
#include "incore.h"
D
David Teigland 已提交
20 21
#include "mount.h"
#include "sys.h"
22
#include "util.h"
D
David Teigland 已提交
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
enum {
	Opt_lockproto,
	Opt_locktable,
	Opt_hostdata,
	Opt_spectator,
	Opt_ignore_local_fs,
	Opt_localflocks,
	Opt_localcaching,
	Opt_debug,
	Opt_nodebug,
	Opt_upgrade,
	Opt_num_glockd,
	Opt_acl,
	Opt_noacl,
	Opt_quota_off,
	Opt_quota_account,
	Opt_quota_on,
	Opt_suiddir,
	Opt_nosuiddir,
	Opt_data_writeback,
	Opt_data_ordered,
};

static match_table_t tokens = {
	{Opt_lockproto, "lockproto=%s"},
	{Opt_locktable, "locktable=%s"},
	{Opt_hostdata, "hostdata=%s"},
	{Opt_spectator, "spectator"},
	{Opt_ignore_local_fs, "ignore_local_fs"},
	{Opt_localflocks, "localflocks"},
	{Opt_localcaching, "localcaching"},
	{Opt_debug, "debug"},
	{Opt_nodebug, "nodebug"},
	{Opt_upgrade, "upgrade"},
	{Opt_num_glockd, "num_glockd=%d"},
	{Opt_acl, "acl"},
	{Opt_noacl, "noacl"},
	{Opt_quota_off, "quota=off"},
	{Opt_quota_account, "quota=account"},
	{Opt_quota_on, "quota=on"},
	{Opt_suiddir, "suiddir"},
	{Opt_nosuiddir, "nosuiddir"},
	{Opt_data_writeback, "data=writeback"},
	{Opt_data_ordered, "data=ordered"}
};

D
David Teigland 已提交
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
/**
 * gfs2_mount_args - Parse mount options
 * @sdp:
 * @data:
 *
 * Return: errno
 */

int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
{
	struct gfs2_args *args = &sdp->sd_args;
	char *data = data_arg;
	char *options, *o, *v;
	int error = 0;

	if (!remount) {
		/*  If someone preloaded options, use those instead  */
		spin_lock(&gfs2_sys_margs_lock);
		if (gfs2_sys_margs) {
			data = gfs2_sys_margs;
			gfs2_sys_margs = NULL;
		}
		spin_unlock(&gfs2_sys_margs_lock);

		/*  Set some defaults  */
		args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
		args->ar_quota = GFS2_QUOTA_DEFAULT;
		args->ar_data = GFS2_DATA_DEFAULT;
	}

	/* Split the options into tokens with the "," character and
	   process them */

	for (options = data; (o = strsep(&options, ",")); ) {
104 105 106
		int token, option;
		substring_t tmp[MAX_OPT_ARGS];

D
David Teigland 已提交
107 108 109
		if (!*o)
			continue;

110 111 112 113 114 115 116 117 118
		token = match_token(o, tokens, tmp);
		switch (token) {
		case Opt_lockproto:
			v = match_strdup(&tmp[0]);
			if (!v) {
				fs_info(sdp, "no memory for lockproto\n");
				error = -ENOMEM;
				goto out_error;
			}
D
David Teigland 已提交
119

120 121
			if (remount && strcmp(v, args->ar_lockproto)) {
				kfree(v);
D
David Teigland 已提交
122
				goto cant_remount;
123 124
			}
			
D
David Teigland 已提交
125 126
			strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN);
			args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0;
127 128 129 130 131 132 133 134 135
			kfree(v);
			break;
		case Opt_locktable:
			v = match_strdup(&tmp[0]);
			if (!v) {
				fs_info(sdp, "no memory for locktable\n");
				error = -ENOMEM;
				goto out_error;
			}
D
David Teigland 已提交
136

137 138
			if (remount && strcmp(v, args->ar_locktable)) {
				kfree(v);
D
David Teigland 已提交
139
				goto cant_remount;
140 141
			}

D
David Teigland 已提交
142
			strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN);
143 144 145 146 147 148 149 150 151 152
			args->ar_locktable[GFS2_LOCKNAME_LEN - 1]  = 0;
			kfree(v);
			break;
		case Opt_hostdata:
			v = match_strdup(&tmp[0]);
			if (!v) {
				fs_info(sdp, "no memory for hostdata\n");
				error = -ENOMEM;
				goto out_error;
			}
D
David Teigland 已提交
153

154 155
			if (remount && strcmp(v, args->ar_hostdata)) {
				kfree(v);
D
David Teigland 已提交
156
				goto cant_remount;
157 158
			}

D
David Teigland 已提交
159 160
			strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN);
			args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0;
161 162 163
			kfree(v);
			break;
		case Opt_spectator:
D
David Teigland 已提交
164 165 166 167
			if (remount && !args->ar_spectator)
				goto cant_remount;
			args->ar_spectator = 1;
			sdp->sd_vfs->s_flags |= MS_RDONLY;
168 169
			break;
		case Opt_ignore_local_fs:
D
David Teigland 已提交
170 171 172
			if (remount && !args->ar_ignore_local_fs)
				goto cant_remount;
			args->ar_ignore_local_fs = 1;
173 174
			break;
		case Opt_localflocks:
D
David Teigland 已提交
175 176 177
			if (remount && !args->ar_localflocks)
				goto cant_remount;
			args->ar_localflocks = 1;
178 179
			break;
		case Opt_localcaching:
D
David Teigland 已提交
180 181 182
			if (remount && !args->ar_localcaching)
				goto cant_remount;
			args->ar_localcaching = 1;
183 184
			break;
		case Opt_debug:
D
David Teigland 已提交
185
			args->ar_debug = 1;
186 187
			break;
		case Opt_nodebug:
D
David Teigland 已提交
188
			args->ar_debug = 0;
189 190
			break;
		case Opt_upgrade:
D
David Teigland 已提交
191 192 193
			if (remount && !args->ar_upgrade)
				goto cant_remount;
			args->ar_upgrade = 1;
194 195 196 197 198 199
			break;
		case Opt_num_glockd:
			if ((error = match_int(&tmp[0], &option))) {
				fs_info(sdp, "problem getting num_glockd\n");
				goto out_error;
			}
D
David Teigland 已提交
200

201
			if (remount && option != args->ar_num_glockd)
D
David Teigland 已提交
202
				goto cant_remount;
203
			if (!option || option > GFS2_GLOCKD_MAX) {
D
David Teigland 已提交
204
				fs_info(sdp, "0 < num_glockd <= %u  (not %u)\n",
205
				        GFS2_GLOCKD_MAX, option);
D
David Teigland 已提交
206
				error = -EINVAL;
207
				goto out_error;
D
David Teigland 已提交
208
			}
209 210 211
			args->ar_num_glockd = option;
			break;
		case Opt_acl:
D
David Teigland 已提交
212 213
			args->ar_posix_acl = 1;
			sdp->sd_vfs->s_flags |= MS_POSIXACL;
214 215
			break;
		case Opt_noacl:
D
David Teigland 已提交
216 217
			args->ar_posix_acl = 0;
			sdp->sd_vfs->s_flags &= ~MS_POSIXACL;
218 219 220 221 222 223 224 225 226 227 228
			break;
		case Opt_quota_off:
			args->ar_quota = GFS2_QUOTA_OFF;
			break;
		case Opt_quota_account:
			args->ar_quota = GFS2_QUOTA_ACCOUNT;
			break;
		case Opt_quota_on:
			args->ar_quota = GFS2_QUOTA_ON;
			break;
		case Opt_suiddir:
D
David Teigland 已提交
229
			args->ar_suiddir = 1;
230 231
			break;
		case Opt_nosuiddir:
D
David Teigland 已提交
232
			args->ar_suiddir = 0;
233 234 235 236 237 238 239 240
			break;
		case Opt_data_writeback:
			args->ar_data = GFS2_DATA_WRITEBACK;
			break;
		case Opt_data_ordered:
			args->ar_data = GFS2_DATA_ORDERED;
			break;
		default:
D
David Teigland 已提交
241 242
			fs_info(sdp, "unknown option: %s\n", o);
			error = -EINVAL;
243
			goto out_error;
D
David Teigland 已提交
244 245 246
		}
	}

247
out_error:
D
David Teigland 已提交
248 249 250 251 252 253 254 255
	if (error)
		fs_info(sdp, "invalid mount option(s)\n");

	if (data != data_arg)
		kfree(data);

	return error;

256
cant_remount:
D
David Teigland 已提交
257 258 259 260
	fs_info(sdp, "can't remount with option %s\n", o);
	return -EINVAL;
}