Merge branch 'master'
[linux-2.6] / 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 <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