Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / fs / gfs2 / mount.c
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/slab.h>
11 #include <linux/spinlock.h>
12 #include <linux/completion.h>
13 #include <linux/buffer_head.h>
14 #include <linux/gfs2_ondisk.h>
15 #include <linux/lm_interface.h>
16
17 #include "gfs2.h"
18 #include "incore.h"
19 #include "mount.h"
20 #include "sys.h"
21 #include "util.h"
22
23 /**
24  * gfs2_mount_args - Parse mount options
25  * @sdp:
26  * @data:
27  *
28  * Return: errno
29  */
30
31 int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
32 {
33         struct gfs2_args *args = &sdp->sd_args;
34         char *data = data_arg;
35         char *options, *o, *v;
36         int error = 0;
37
38         if (!remount) {
39                 /*  If someone preloaded options, use those instead  */
40                 spin_lock(&gfs2_sys_margs_lock);
41                 if (gfs2_sys_margs) {
42                         data = gfs2_sys_margs;
43                         gfs2_sys_margs = NULL;
44                 }
45                 spin_unlock(&gfs2_sys_margs_lock);
46
47                 /*  Set some defaults  */
48                 args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
49                 args->ar_quota = GFS2_QUOTA_DEFAULT;
50                 args->ar_data = GFS2_DATA_DEFAULT;
51         }
52
53         /* Split the options into tokens with the "," character and
54            process them */
55
56         for (options = data; (o = strsep(&options, ",")); ) {
57                 if (!*o)
58                         continue;
59
60                 v = strchr(o, '=');
61                 if (v)
62                         *v++ = 0;
63
64                 if (!strcmp(o, "lockproto")) {
65                         if (!v)
66                                 goto need_value;
67                         if (remount && strcmp(v, args->ar_lockproto))
68                                 goto cant_remount;
69                         strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN);
70                         args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0;
71                 }
72
73                 else if (!strcmp(o, "locktable")) {
74                         if (!v)
75                                 goto need_value;
76                         if (remount && strcmp(v, args->ar_locktable))
77                                 goto cant_remount;
78                         strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN);
79                         args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0;
80                 }
81
82                 else if (!strcmp(o, "hostdata")) {
83                         if (!v)
84                                 goto need_value;
85                         if (remount && strcmp(v, args->ar_hostdata))
86                                 goto cant_remount;
87                         strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN);
88                         args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0;
89                 }
90
91                 else if (!strcmp(o, "spectator")) {
92                         if (remount && !args->ar_spectator)
93                                 goto cant_remount;
94                         args->ar_spectator = 1;
95                         sdp->sd_vfs->s_flags |= MS_RDONLY;
96                 }
97
98                 else if (!strcmp(o, "ignore_local_fs")) {
99                         if (remount && !args->ar_ignore_local_fs)
100                                 goto cant_remount;
101                         args->ar_ignore_local_fs = 1;
102                 }
103
104                 else if (!strcmp(o, "localflocks")) {
105                         if (remount && !args->ar_localflocks)
106                                 goto cant_remount;
107                         args->ar_localflocks = 1;
108                 }
109
110                 else if (!strcmp(o, "localcaching")) {
111                         if (remount && !args->ar_localcaching)
112                                 goto cant_remount;
113                         args->ar_localcaching = 1;
114                 }
115
116                 else if (!strcmp(o, "debug"))
117                         args->ar_debug = 1;
118
119                 else if (!strcmp(o, "nodebug"))
120                         args->ar_debug = 0;
121
122                 else if (!strcmp(o, "upgrade")) {
123                         if (remount && !args->ar_upgrade)
124                                 goto cant_remount;
125                         args->ar_upgrade = 1;
126                 }
127
128                 else if (!strcmp(o, "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;
135                         if (!x || x > GFS2_GLOCKD_MAX) {
136                                 fs_info(sdp, "0 < num_glockd <= %u  (not %u)\n",
137                                         GFS2_GLOCKD_MAX, x);
138                                 error = -EINVAL;
139                                 break;
140                         }
141                         args->ar_num_glockd = x;
142                 }
143
144                 else if (!strcmp(o, "acl")) {
145                         args->ar_posix_acl = 1;
146                         sdp->sd_vfs->s_flags |= MS_POSIXACL;
147                 }
148
149                 else if (!strcmp(o, "noacl")) {
150                         args->ar_posix_acl = 0;
151                         sdp->sd_vfs->s_flags &= ~MS_POSIXACL;
152                 }
153
154                 else if (!strcmp(o, "quota")) {
155                         if (!v)
156                                 goto need_value;
157                         if (!strcmp(v, "off"))
158                                 args->ar_quota = GFS2_QUOTA_OFF;
159                         else if (!strcmp(v, "account"))
160                                 args->ar_quota = GFS2_QUOTA_ACCOUNT;
161                         else if (!strcmp(v, "on"))
162                                 args->ar_quota = GFS2_QUOTA_ON;
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;
172
173                 else if (!strcmp(o, "nosuiddir"))
174                         args->ar_suiddir = 0;
175
176                 else if (!strcmp(o, "data")) {
177                         if (!v)
178                                 goto need_value;
179                         if (!strcmp(v, "writeback"))
180                                 args->ar_data = GFS2_DATA_WRITEBACK;
181                         else if (!strcmp(v, "ordered"))
182                                 args->ar_data = GFS2_DATA_ORDERED;
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);
192                         error = -EINVAL;
193                         break;
194                 }
195         }
196
197         if (error)
198                 fs_info(sdp, "invalid mount option(s)\n");
199
200         if (data != data_arg)
201                 kfree(data);
202
203         return error;
204
205 need_value:
206         fs_info(sdp, "need value for option %s\n", o);
207         return -EINVAL;
208
209 cant_remount:
210         fs_info(sdp, "can't remount with option %s\n", o);
211         return -EINVAL;
212 }
213