diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/mount.c | 239 |
1 files changed, 143 insertions, 96 deletions
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 32caecd20300..4864659555d4 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
14 | #include <linux/gfs2_ondisk.h> | 14 | #include <linux/gfs2_ondisk.h> |
15 | #include <linux/lm_interface.h> | 15 | #include <linux/lm_interface.h> |
16 | #include <linux/parser.h> | ||
16 | 17 | ||
17 | #include "gfs2.h" | 18 | #include "gfs2.h" |
18 | #include "incore.h" | 19 | #include "incore.h" |
@@ -20,6 +21,52 @@ | |||
20 | #include "sys.h" | 21 | #include "sys.h" |
21 | #include "util.h" | 22 | #include "util.h" |
22 | 23 | ||
24 | enum { | ||
25 | Opt_lockproto, | ||
26 | Opt_locktable, | ||
27 | Opt_hostdata, | ||
28 | Opt_spectator, | ||
29 | Opt_ignore_local_fs, | ||
30 | Opt_localflocks, | ||
31 | Opt_localcaching, | ||
32 | Opt_debug, | ||
33 | Opt_nodebug, | ||
34 | Opt_upgrade, | ||
35 | Opt_num_glockd, | ||
36 | Opt_acl, | ||
37 | Opt_noacl, | ||
38 | Opt_quota_off, | ||
39 | Opt_quota_account, | ||
40 | Opt_quota_on, | ||
41 | Opt_suiddir, | ||
42 | Opt_nosuiddir, | ||
43 | Opt_data_writeback, | ||
44 | Opt_data_ordered, | ||
45 | }; | ||
46 | |||
47 | static match_table_t tokens = { | ||
48 | {Opt_lockproto, "lockproto=%s"}, | ||
49 | {Opt_locktable, "locktable=%s"}, | ||
50 | {Opt_hostdata, "hostdata=%s"}, | ||
51 | {Opt_spectator, "spectator"}, | ||
52 | {Opt_ignore_local_fs, "ignore_local_fs"}, | ||
53 | {Opt_localflocks, "localflocks"}, | ||
54 | {Opt_localcaching, "localcaching"}, | ||
55 | {Opt_debug, "debug"}, | ||
56 | {Opt_nodebug, "nodebug"}, | ||
57 | {Opt_upgrade, "upgrade"}, | ||
58 | {Opt_num_glockd, "num_glockd=%d"}, | ||
59 | {Opt_acl, "acl"}, | ||
60 | {Opt_noacl, "noacl"}, | ||
61 | {Opt_quota_off, "quota=off"}, | ||
62 | {Opt_quota_account, "quota=account"}, | ||
63 | {Opt_quota_on, "quota=on"}, | ||
64 | {Opt_suiddir, "suiddir"}, | ||
65 | {Opt_nosuiddir, "nosuiddir"}, | ||
66 | {Opt_data_writeback, "data=writeback"}, | ||
67 | {Opt_data_ordered, "data=ordered"} | ||
68 | }; | ||
69 | |||
23 | /** | 70 | /** |
24 | * gfs2_mount_args - Parse mount options | 71 | * gfs2_mount_args - Parse mount options |
25 | * @sdp: | 72 | * @sdp: |
@@ -54,146 +101,150 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
54 | process them */ | 101 | process them */ |
55 | 102 | ||
56 | for (options = data; (o = strsep(&options, ",")); ) { | 103 | for (options = data; (o = strsep(&options, ",")); ) { |
104 | int token, option; | ||
105 | substring_t tmp[MAX_OPT_ARGS]; | ||
106 | |||
57 | if (!*o) | 107 | if (!*o) |
58 | continue; | 108 | continue; |
59 | 109 | ||
60 | v = strchr(o, '='); | 110 | token = match_token(o, tokens, tmp); |
61 | if (v) | 111 | switch (token) { |
62 | *v++ = 0; | 112 | case Opt_lockproto: |
113 | v = match_strdup(&tmp[0]); | ||
114 | if (!v) { | ||
115 | fs_info(sdp, "no memory for lockproto\n"); | ||
116 | error = -ENOMEM; | ||
117 | goto out_error; | ||
118 | } | ||
63 | 119 | ||
64 | if (!strcmp(o, "lockproto")) { | 120 | if (remount && strcmp(v, args->ar_lockproto)) { |
65 | if (!v) | 121 | kfree(v); |
66 | goto need_value; | ||
67 | if (remount && strcmp(v, args->ar_lockproto)) | ||
68 | goto cant_remount; | 122 | goto cant_remount; |
123 | } | ||
124 | |||
69 | strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); | 125 | strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); |
70 | args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; | 126 | args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; |
71 | } | 127 | kfree(v); |
128 | break; | ||
129 | case Opt_locktable: | ||
130 | v = match_strdup(&tmp[0]); | ||
131 | if (!v) { | ||
132 | fs_info(sdp, "no memory for locktable\n"); | ||
133 | error = -ENOMEM; | ||
134 | goto out_error; | ||
135 | } | ||
72 | 136 | ||
73 | else if (!strcmp(o, "locktable")) { | 137 | if (remount && strcmp(v, args->ar_locktable)) { |
74 | if (!v) | 138 | kfree(v); |
75 | goto need_value; | ||
76 | if (remount && strcmp(v, args->ar_locktable)) | ||
77 | goto cant_remount; | 139 | goto cant_remount; |
140 | } | ||
141 | |||
78 | strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); | 142 | strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); |
79 | args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; | 143 | args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; |
80 | } | 144 | kfree(v); |
145 | break; | ||
146 | case Opt_hostdata: | ||
147 | v = match_strdup(&tmp[0]); | ||
148 | if (!v) { | ||
149 | fs_info(sdp, "no memory for hostdata\n"); | ||
150 | error = -ENOMEM; | ||
151 | goto out_error; | ||
152 | } | ||
81 | 153 | ||
82 | else if (!strcmp(o, "hostdata")) { | 154 | if (remount && strcmp(v, args->ar_hostdata)) { |
83 | if (!v) | 155 | kfree(v); |
84 | goto need_value; | ||
85 | if (remount && strcmp(v, args->ar_hostdata)) | ||
86 | goto cant_remount; | 156 | goto cant_remount; |
157 | } | ||
158 | |||
87 | strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); | 159 | strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); |
88 | args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; | 160 | args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; |
89 | } | 161 | kfree(v); |
90 | 162 | break; | |
91 | else if (!strcmp(o, "spectator")) { | 163 | case Opt_spectator: |
92 | if (remount && !args->ar_spectator) | 164 | if (remount && !args->ar_spectator) |
93 | goto cant_remount; | 165 | goto cant_remount; |
94 | args->ar_spectator = 1; | 166 | args->ar_spectator = 1; |
95 | sdp->sd_vfs->s_flags |= MS_RDONLY; | 167 | sdp->sd_vfs->s_flags |= MS_RDONLY; |
96 | } | 168 | break; |
97 | 169 | case Opt_ignore_local_fs: | |
98 | else if (!strcmp(o, "ignore_local_fs")) { | ||
99 | if (remount && !args->ar_ignore_local_fs) | 170 | if (remount && !args->ar_ignore_local_fs) |
100 | goto cant_remount; | 171 | goto cant_remount; |
101 | args->ar_ignore_local_fs = 1; | 172 | args->ar_ignore_local_fs = 1; |
102 | } | 173 | break; |
103 | 174 | case Opt_localflocks: | |
104 | else if (!strcmp(o, "localflocks")) { | ||
105 | if (remount && !args->ar_localflocks) | 175 | if (remount && !args->ar_localflocks) |
106 | goto cant_remount; | 176 | goto cant_remount; |
107 | args->ar_localflocks = 1; | 177 | args->ar_localflocks = 1; |
108 | } | 178 | break; |
109 | 179 | case Opt_localcaching: | |
110 | else if (!strcmp(o, "localcaching")) { | ||
111 | if (remount && !args->ar_localcaching) | 180 | if (remount && !args->ar_localcaching) |
112 | goto cant_remount; | 181 | goto cant_remount; |
113 | args->ar_localcaching = 1; | 182 | args->ar_localcaching = 1; |
114 | } | 183 | break; |
115 | 184 | case Opt_debug: | |
116 | else if (!strcmp(o, "debug")) | ||
117 | args->ar_debug = 1; | 185 | args->ar_debug = 1; |
118 | 186 | break; | |
119 | else if (!strcmp(o, "nodebug")) | 187 | case Opt_nodebug: |
120 | args->ar_debug = 0; | 188 | args->ar_debug = 0; |
121 | 189 | break; | |
122 | else if (!strcmp(o, "upgrade")) { | 190 | case Opt_upgrade: |
123 | if (remount && !args->ar_upgrade) | 191 | if (remount && !args->ar_upgrade) |
124 | goto cant_remount; | 192 | goto cant_remount; |
125 | args->ar_upgrade = 1; | 193 | args->ar_upgrade = 1; |
126 | } | 194 | break; |
195 | case Opt_num_glockd: | ||
196 | if ((error = match_int(&tmp[0], &option))) { | ||
197 | fs_info(sdp, "problem getting num_glockd\n"); | ||
198 | goto out_error; | ||
199 | } | ||
127 | 200 | ||
128 | else if (!strcmp(o, "num_glockd")) { | 201 | if (remount && option != args->ar_num_glockd) |
129 | unsigned int x; | ||
130 | if (!v) | ||
131 | goto need_value; | ||
132 | sscanf(v, "%u", &x); | ||
133 | if (remount && x != args->ar_num_glockd) | ||
134 | goto cant_remount; | 202 | goto cant_remount; |
135 | if (!x || x > GFS2_GLOCKD_MAX) { | 203 | if (!option || option > GFS2_GLOCKD_MAX) { |
136 | fs_info(sdp, "0 < num_glockd <= %u (not %u)\n", | 204 | fs_info(sdp, "0 < num_glockd <= %u (not %u)\n", |
137 | GFS2_GLOCKD_MAX, x); | 205 | GFS2_GLOCKD_MAX, option); |
138 | error = -EINVAL; | 206 | error = -EINVAL; |
139 | break; | 207 | goto out_error; |
140 | } | 208 | } |
141 | args->ar_num_glockd = x; | 209 | args->ar_num_glockd = option; |
142 | } | 210 | break; |
143 | 211 | case Opt_acl: | |
144 | else if (!strcmp(o, "acl")) { | ||
145 | args->ar_posix_acl = 1; | 212 | args->ar_posix_acl = 1; |
146 | sdp->sd_vfs->s_flags |= MS_POSIXACL; | 213 | sdp->sd_vfs->s_flags |= MS_POSIXACL; |
147 | } | 214 | break; |
148 | 215 | case Opt_noacl: | |
149 | else if (!strcmp(o, "noacl")) { | ||
150 | args->ar_posix_acl = 0; | 216 | args->ar_posix_acl = 0; |
151 | sdp->sd_vfs->s_flags &= ~MS_POSIXACL; | 217 | sdp->sd_vfs->s_flags &= ~MS_POSIXACL; |
152 | } | 218 | break; |
153 | 219 | case Opt_quota_off: | |
154 | else if (!strcmp(o, "quota")) { | 220 | args->ar_quota = GFS2_QUOTA_OFF; |
155 | if (!v) | 221 | break; |
156 | goto need_value; | 222 | case Opt_quota_account: |
157 | if (!strcmp(v, "off")) | 223 | args->ar_quota = GFS2_QUOTA_ACCOUNT; |
158 | args->ar_quota = GFS2_QUOTA_OFF; | 224 | break; |
159 | else if (!strcmp(v, "account")) | 225 | case Opt_quota_on: |
160 | args->ar_quota = GFS2_QUOTA_ACCOUNT; | 226 | args->ar_quota = GFS2_QUOTA_ON; |
161 | else if (!strcmp(v, "on")) | 227 | break; |
162 | args->ar_quota = GFS2_QUOTA_ON; | 228 | case Opt_suiddir: |
163 | else { | ||
164 | fs_info(sdp, "invalid value for quota\n"); | ||
165 | error = -EINVAL; | ||
166 | break; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | else if (!strcmp(o, "suiddir")) | ||
171 | args->ar_suiddir = 1; | 229 | args->ar_suiddir = 1; |
172 | 230 | break; | |
173 | else if (!strcmp(o, "nosuiddir")) | 231 | case Opt_nosuiddir: |
174 | args->ar_suiddir = 0; | 232 | args->ar_suiddir = 0; |
175 | 233 | break; | |
176 | else if (!strcmp(o, "data")) { | 234 | case Opt_data_writeback: |
177 | if (!v) | 235 | args->ar_data = GFS2_DATA_WRITEBACK; |
178 | goto need_value; | 236 | break; |
179 | if (!strcmp(v, "writeback")) | 237 | case Opt_data_ordered: |
180 | args->ar_data = GFS2_DATA_WRITEBACK; | 238 | args->ar_data = GFS2_DATA_ORDERED; |
181 | else if (!strcmp(v, "ordered")) | 239 | break; |
182 | args->ar_data = GFS2_DATA_ORDERED; | 240 | default: |
183 | else { | ||
184 | fs_info(sdp, "invalid value for data\n"); | ||
185 | error = -EINVAL; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | else { | ||
191 | fs_info(sdp, "unknown option: %s\n", o); | 241 | fs_info(sdp, "unknown option: %s\n", o); |
192 | error = -EINVAL; | 242 | error = -EINVAL; |
193 | break; | 243 | goto out_error; |
194 | } | 244 | } |
195 | } | 245 | } |
196 | 246 | ||
247 | out_error: | ||
197 | if (error) | 248 | if (error) |
198 | fs_info(sdp, "invalid mount option(s)\n"); | 249 | fs_info(sdp, "invalid mount option(s)\n"); |
199 | 250 | ||
@@ -202,10 +253,6 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
202 | 253 | ||
203 | return error; | 254 | return error; |
204 | 255 | ||
205 | need_value: | ||
206 | fs_info(sdp, "need value for option %s\n", o); | ||
207 | return -EINVAL; | ||
208 | |||
209 | cant_remount: | 256 | cant_remount: |
210 | fs_info(sdp, "can't remount with option %s\n", o); | 257 | fs_info(sdp, "can't remount with option %s\n", o); |
211 | return -EINVAL; | 258 | return -EINVAL; |