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