7e001356824e14bcf43d2717aa85ac2cf1730ebf
[linux-2.6.git] / fs / gfs2 / mount.c
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 <linux/gfs2_ondisk.h>
16
17 #include "gfs2.h"
18 #include "lm_interface.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