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