Commit | Line | Data |
---|---|---|
b3b94faa DT |
1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | |
3a8a9a10 | 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa DT |
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 | |
e9fc2aa0 | 7 | * of the GNU General Public License version 2. |
b3b94faa DT |
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> | |
5c676f6d | 15 | #include <linux/gfs2_ondisk.h> |
7d308590 | 16 | #include <linux/lm_interface.h> |
b3b94faa DT |
17 | |
18 | #include "gfs2.h" | |
5c676f6d | 19 | #include "incore.h" |
b3b94faa DT |
20 | #include "mount.h" |
21 | #include "sys.h" | |
5c676f6d | 22 | #include "util.h" |
b3b94faa DT |
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 | ||
a91ea69f | 206 | need_value: |
b3b94faa DT |
207 | fs_info(sdp, "need value for option %s\n", o); |
208 | return -EINVAL; | |
209 | ||
a91ea69f | 210 | cant_remount: |
b3b94faa DT |
211 | fs_info(sdp, "can't remount with option %s\n", o); |
212 | return -EINVAL; | |
213 | } | |
214 |