diff options
Diffstat (limited to 'fs/gfs2/mount.c')
-rw-r--r-- | fs/gfs2/mount.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c new file mode 100644 index 000000000000..ef3092e29607 --- /dev/null +++ b/fs/gfs2/mount.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * This copyrighted material is made available to anyone wishing to use, | ||
6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/completion.h> | ||
14 | #include <linux/buffer_head.h> | ||
15 | #include <linux/gfs2_ondisk.h> | ||
16 | #include <linux/lm_interface.h> | ||
17 | |||
18 | #include "gfs2.h" | ||
19 | #include "incore.h" | ||
20 | #include "mount.h" | ||
21 | #include "sys.h" | ||
22 | #include "util.h" | ||
23 | |||
24 | /** | ||
25 | * gfs2_mount_args - Parse mount options | ||
26 | * @sdp: | ||
27 | * @data: | ||
28 | * | ||
29 | * Return: errno | ||
30 | */ | ||
31 | |||
32 | int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | ||
33 | { | ||
34 | struct gfs2_args *args = &sdp->sd_args; | ||
35 | char *data = data_arg; | ||
36 | char *options, *o, *v; | ||
37 | int error = 0; | ||
38 | |||
39 | if (!remount) { | ||
40 | /* If someone preloaded options, use those instead */ | ||
41 | spin_lock(&gfs2_sys_margs_lock); | ||
42 | if (gfs2_sys_margs) { | ||
43 | data = gfs2_sys_margs; | ||
44 | gfs2_sys_margs = NULL; | ||
45 | } | ||
46 | spin_unlock(&gfs2_sys_margs_lock); | ||
47 | |||
48 | /* Set some defaults */ | ||
49 | args->ar_num_glockd = GFS2_GLOCKD_DEFAULT; | ||
50 | args->ar_quota = GFS2_QUOTA_DEFAULT; | ||
51 | args->ar_data = GFS2_DATA_DEFAULT; | ||
52 | } | ||
53 | |||
54 | /* Split the options into tokens with the "," character and | ||
55 | process them */ | ||
56 | |||
57 | for (options = data; (o = strsep(&options, ",")); ) { | ||
58 | if (!*o) | ||
59 | continue; | ||
60 | |||
61 | v = strchr(o, '='); | ||
62 | if (v) | ||
63 | *v++ = 0; | ||
64 | |||
65 | if (!strcmp(o, "lockproto")) { | ||
66 | if (!v) | ||
67 | goto need_value; | ||
68 | if (remount && strcmp(v, args->ar_lockproto)) | ||
69 | goto cant_remount; | ||
70 | strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); | ||
71 | args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; | ||
72 | } | ||
73 | |||
74 | else if (!strcmp(o, "locktable")) { | ||
75 | if (!v) | ||
76 | goto need_value; | ||
77 | if (remount && strcmp(v, args->ar_locktable)) | ||
78 | goto cant_remount; | ||
79 | strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); | ||
80 | args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; | ||
81 | } | ||
82 | |||
83 | else if (!strcmp(o, "hostdata")) { | ||
84 | if (!v) | ||
85 | goto need_value; | ||
86 | if (remount && strcmp(v, args->ar_hostdata)) | ||
87 | goto cant_remount; | ||
88 | strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); | ||
89 | args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; | ||
90 | } | ||
91 | |||
92 | else if (!strcmp(o, "spectator")) { | ||
93 | if (remount && !args->ar_spectator) | ||
94 | goto cant_remount; | ||
95 | args->ar_spectator = 1; | ||
96 | sdp->sd_vfs->s_flags |= MS_RDONLY; | ||
97 | } | ||
98 | |||
99 | else if (!strcmp(o, "ignore_local_fs")) { | ||
100 | if (remount && !args->ar_ignore_local_fs) | ||
101 | goto cant_remount; | ||
102 | args->ar_ignore_local_fs = 1; | ||
103 | } | ||
104 | |||
105 | else if (!strcmp(o, "localflocks")) { | ||
106 | if (remount && !args->ar_localflocks) | ||
107 | goto cant_remount; | ||
108 | args->ar_localflocks = 1; | ||
109 | } | ||
110 | |||
111 | else if (!strcmp(o, "localcaching")) { | ||
112 | if (remount && !args->ar_localcaching) | ||
113 | goto cant_remount; | ||
114 | args->ar_localcaching = 1; | ||
115 | } | ||
116 | |||
117 | else if (!strcmp(o, "debug")) | ||
118 | args->ar_debug = 1; | ||
119 | |||
120 | else if (!strcmp(o, "nodebug")) | ||
121 | args->ar_debug = 0; | ||
122 | |||
123 | else if (!strcmp(o, "upgrade")) { | ||
124 | if (remount && !args->ar_upgrade) | ||
125 | goto cant_remount; | ||
126 | args->ar_upgrade = 1; | ||
127 | } | ||
128 | |||
129 | else if (!strcmp(o, "num_glockd")) { | ||
130 | unsigned int x; | ||
131 | if (!v) | ||
132 | goto need_value; | ||
133 | sscanf(v, "%u", &x); | ||
134 | if (remount && x != args->ar_num_glockd) | ||
135 | goto cant_remount; | ||
136 | if (!x || x > GFS2_GLOCKD_MAX) { | ||
137 | fs_info(sdp, "0 < num_glockd <= %u (not %u)\n", | ||
138 | GFS2_GLOCKD_MAX, x); | ||
139 | error = -EINVAL; | ||
140 | break; | ||
141 | } | ||
142 | args->ar_num_glockd = x; | ||
143 | } | ||
144 | |||
145 | else if (!strcmp(o, "acl")) { | ||
146 | args->ar_posix_acl = 1; | ||
147 | sdp->sd_vfs->s_flags |= MS_POSIXACL; | ||
148 | } | ||
149 | |||
150 | else if (!strcmp(o, "noacl")) { | ||
151 | args->ar_posix_acl = 0; | ||
152 | sdp->sd_vfs->s_flags &= ~MS_POSIXACL; | ||
153 | } | ||
154 | |||
155 | else if (!strcmp(o, "quota")) { | ||
156 | if (!v) | ||
157 | goto need_value; | ||
158 | if (!strcmp(v, "off")) | ||
159 | args->ar_quota = GFS2_QUOTA_OFF; | ||
160 | else if (!strcmp(v, "account")) | ||
161 | args->ar_quota = GFS2_QUOTA_ACCOUNT; | ||
162 | else if (!strcmp(v, "on")) | ||
163 | args->ar_quota = GFS2_QUOTA_ON; | ||
164 | else { | ||
165 | fs_info(sdp, "invalid value for quota\n"); | ||
166 | error = -EINVAL; | ||
167 | break; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | else if (!strcmp(o, "suiddir")) | ||
172 | args->ar_suiddir = 1; | ||
173 | |||
174 | else if (!strcmp(o, "nosuiddir")) | ||
175 | args->ar_suiddir = 0; | ||
176 | |||
177 | else if (!strcmp(o, "data")) { | ||
178 | if (!v) | ||
179 | goto need_value; | ||
180 | if (!strcmp(v, "writeback")) | ||
181 | args->ar_data = GFS2_DATA_WRITEBACK; | ||
182 | else if (!strcmp(v, "ordered")) | ||
183 | args->ar_data = GFS2_DATA_ORDERED; | ||
184 | else { | ||
185 | fs_info(sdp, "invalid value for data\n"); | ||
186 | error = -EINVAL; | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | else { | ||
192 | fs_info(sdp, "unknown option: %s\n", o); | ||
193 | error = -EINVAL; | ||
194 | break; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | if (error) | ||
199 | fs_info(sdp, "invalid mount option(s)\n"); | ||
200 | |||
201 | if (data != data_arg) | ||
202 | kfree(data); | ||
203 | |||
204 | return error; | ||
205 | |||
206 | need_value: | ||
207 | fs_info(sdp, "need value for option %s\n", o); | ||
208 | return -EINVAL; | ||
209 | |||
210 | cant_remount: | ||
211 | fs_info(sdp, "can't remount with option %s\n", o); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | |||