Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lustre / mds / mds_lov.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  linux/mds/mds_lov.c
5  *  Lustre Metadata Server (mds) handling of striped file data
6  *
7  *  Copyright (C) 2001-2003 Cluster File Systems, Inc.
8  *   Author: Peter Braam <braam@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #define EXPORT_SYMTAB
27 #define DEBUG_SUBSYSTEM S_MDS
28
29 #include <linux/module.h>
30 #include <linux/lustre_mds.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_lov.h>
34 #include <linux/lustre_lib.h>
35 #include <linux/lustre_fsfilt.h>
36
37 #include "mds_internal.h"
38
39 void le_lov_desc_to_cpu (struct lov_desc *ld)
40 {
41         ld->ld_tgt_count = le32_to_cpu (ld->ld_tgt_count);
42         ld->ld_default_stripe_count = le32_to_cpu (ld->ld_default_stripe_count);
43         ld->ld_default_stripe_size = le32_to_cpu (ld->ld_default_stripe_size);
44         ld->ld_pattern = le32_to_cpu (ld->ld_pattern);
45 }
46
47 void cpu_to_le_lov_desc (struct lov_desc *ld)
48 {
49         ld->ld_tgt_count = cpu_to_le32 (ld->ld_tgt_count);
50         ld->ld_default_stripe_count = cpu_to_le32 (ld->ld_default_stripe_count);
51         ld->ld_default_stripe_size = cpu_to_le32 (ld->ld_default_stripe_size);
52         ld->ld_pattern = cpu_to_le32 (ld->ld_pattern);
53 }
54
55 int mds_set_lovdesc(struct obd_device *obd, struct lov_desc *desc,
56                     struct obd_uuid *uuidarray)
57 {
58         struct mds_obd *mds = &obd->u.mds;
59         struct obd_run_ctxt saved;
60         struct file *f;
61         int tgt_count;
62         int rc;
63         int i;
64         struct lov_desc *disk_desc;
65         ENTRY;
66
67         tgt_count = desc->ld_tgt_count;
68         if (desc->ld_default_stripe_count > desc->ld_tgt_count) {
69                 CERROR("default stripe count %u > OST count %u\n",
70                        desc->ld_default_stripe_count, desc->ld_tgt_count);
71                 RETURN(-EINVAL);
72         }
73         if (desc->ld_default_stripe_size & (PAGE_SIZE - 1)) {
74                 CERROR("default stripe size "LPU64" not a multiple of %lu\n",
75                        desc->ld_default_stripe_size, PAGE_SIZE);
76                 RETURN(-EINVAL);
77         }
78         if (desc->ld_default_stripe_offset > desc->ld_tgt_count) {
79                 CERROR("default stripe offset "LPU64" > max OST index %u\n",
80                        desc->ld_default_stripe_offset, desc->ld_tgt_count);
81                 RETURN(-EINVAL);
82         }
83         if (desc->ld_pattern != 0) {
84                 CERROR("stripe pattern %u unknown\n",
85                        desc->ld_pattern);
86                 RETURN(-EINVAL);
87         }
88
89         OBD_ALLOC (disk_desc, sizeof (*disk_desc));
90         if (disk_desc == NULL) {
91                 CERROR ("Can't allocate disk_desc\n");
92                 RETURN (-ENOMEM);
93         }
94
95         *disk_desc = *desc;
96         cpu_to_le_lov_desc (disk_desc);
97
98         rc = 0;
99         push_ctxt(&saved, &mds->mds_ctxt, NULL);
100
101         /* Bug 1186: FIXME: if there is an existing LOVDESC, verify new
102          * tgt_count > old */
103         f = filp_open("LOVDESC", O_CREAT|O_RDWR, 0644);
104         if (IS_ERR(f)) {
105                 CERROR("Cannot open/create LOVDESC file\n");
106                 GOTO(out, rc = PTR_ERR(f));
107         }
108
109         rc = lustre_fwrite(f, (char *)disk_desc, sizeof(*disk_desc), &f->f_pos);
110         if (filp_close(f, 0))
111                 CERROR("Error closing LOVDESC file\n");
112         if (rc != sizeof(*desc)) {
113                 CERROR("Cannot open/create LOVDESC file\n");
114                 if (rc >= 0)
115                         rc = -EIO;
116                 GOTO(out, rc);
117         }
118
119         /* Bug 1186: FIXME: if there is an existing LOVTGTS, verify
120          * existing UUIDs same */
121         f = filp_open("LOVTGTS", O_CREAT|O_RDWR, 0644);
122         if (IS_ERR(f)) {
123                 CERROR("Cannot open/create LOVTGTS file\n");
124                 GOTO(out, rc = PTR_ERR(f));
125         }
126
127         rc = 0;
128         for (i = 0; i < tgt_count ; i++) {
129                 rc = lustre_fwrite(f, uuidarray[i].uuid,
130                                    sizeof(uuidarray[i]), &f->f_pos);
131                 if (rc != sizeof(uuidarray[i])) {
132                         CERROR("cannot write LOV UUID %s (%d)\n",
133                                uuidarray[i].uuid, i);
134                         if (rc >= 0)
135                                 rc = -EIO;
136                         break;
137                 }
138                 rc = 0;
139         }
140         if (filp_close(f, 0))
141                 CERROR("Error closing LOVTGTS file\n");
142
143         memcpy(&mds->mds_lov_desc, desc, sizeof *desc);
144         mds->mds_has_lov_desc = 1;
145         /* XXX the MDS should not really know about this */
146         mds->mds_max_mdsize = lov_mds_md_size(desc->ld_tgt_count);
147         mds->mds_max_cookiesize = desc->ld_tgt_count*sizeof(struct llog_cookie);
148
149 out:
150         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
151         OBD_FREE (disk_desc, sizeof (*disk_desc));
152
153         RETURN(rc);
154 }
155
156 int mds_get_lovdesc(struct mds_obd *mds, struct lov_desc *desc)
157 {
158         struct obd_run_ctxt saved;
159         struct file *f;
160         int rc;
161         ENTRY;
162
163         push_ctxt(&saved, &mds->mds_ctxt, NULL);
164         f = filp_open("LOVDESC", O_RDONLY, 0644);
165         if (IS_ERR(f)) {
166                 CERROR("Cannot open LOVDESC file\n");
167                 GOTO(out, rc = PTR_ERR(f));
168         }
169
170         rc = lustre_fread(f, (char *)desc, sizeof(*desc), &f->f_pos);
171         if (filp_close(f, 0))
172                 CERROR("Error closing LOVDESC file\n");
173
174         if (rc != sizeof(*desc)) {
175                 CERROR("Cannot read LOVDESC file: rc = %d\n", rc);
176                 GOTO(out, rc = -EIO);
177         } else
178                 rc = 0;
179
180         le_lov_desc_to_cpu (desc);              /* convert to my byte order */
181
182         EXIT;
183 out:
184         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
185
186         return rc;
187 }
188
189 int mds_get_lovtgts(struct mds_obd *mds, int tgt_count,
190                     struct obd_uuid *uuidarray)
191 {
192         struct obd_run_ctxt saved;
193         struct file *f;
194         int rc;
195         int rc2;
196
197         push_ctxt(&saved, &mds->mds_ctxt, NULL);
198         f = filp_open("LOVTGTS", O_RDONLY, 0644);
199         if (IS_ERR(f)) {
200                 CERROR("Cannot open LOVTGTS file\n");
201                 GOTO(out, rc = PTR_ERR(f));
202         }
203
204         rc = lustre_fread(f, (char *)uuidarray, tgt_count * sizeof(*uuidarray),
205                           &f->f_pos);
206         rc2 = filp_close(f, 0);
207         if (rc2)
208                 CERROR("Error closing LOVTGTS file: rc = %d\n", rc2);
209
210         if (rc != tgt_count * sizeof(*uuidarray)) {
211                 CERROR("Error reading LOVTGTS file: rc = %d\n", rc);
212                 if (rc >= 0)
213                         rc = -EIO;
214                 GOTO(out, rc);
215         } else
216                 rc = 0;
217         EXIT;
218 out:
219         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
220
221         RETURN(rc);
222 }
223
224 int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
225                   int len, void *karg, void *uarg)
226 {
227         struct obd_device *obd = class_conn2obd(conn);
228         struct obd_ioctl_data *data = karg;
229         struct lov_desc *desc;
230         struct obd_uuid *uuidarray;
231         int count;
232         int rc;
233
234         switch (cmd) {
235         case OBD_IOC_LOV_SET_CONFIG:
236                 desc = (struct lov_desc *)data->ioc_inlbuf1;
237                 if (sizeof(*desc) > data->ioc_inllen1) {
238                         CERROR("descriptor size wrong\n");
239                         RETURN(-EINVAL);
240                 }
241
242                 count = desc->ld_tgt_count;
243                 uuidarray = (struct obd_uuid *)data->ioc_inlbuf2;
244                 if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
245                         CERROR("UUID array size wrong\n");
246                         RETURN(-EINVAL);
247                 }
248                 rc = mds_set_lovdesc(obd, desc, uuidarray);
249
250                 RETURN(rc);
251         case OBD_IOC_LOV_GET_CONFIG:
252                 desc = (struct lov_desc *)data->ioc_inlbuf1;
253                 if (sizeof(*desc) > data->ioc_inllen1) {
254                         CERROR("descriptor size wrong\n");
255                         RETURN(-EINVAL);
256                 }
257
258                 count = desc->ld_tgt_count;
259                 uuidarray = (struct obd_uuid *)data->ioc_inlbuf2;
260                 if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
261                         CERROR("UUID array size wrong\n");
262                         RETURN(-EINVAL);
263                 }
264                 rc = mds_get_lovdesc(&obd->u.mds, desc);
265                 if (desc->ld_tgt_count > count) {
266                         CERROR("UUID array size too small\n");
267                         RETURN(-ENOSPC);
268                 }
269                 rc = mds_get_lovtgts(&obd->u.mds, desc->ld_tgt_count,
270                                      uuidarray);
271
272                 RETURN(rc);
273
274         case OBD_IOC_SET_READONLY: {
275                 BDEVNAME_DECLARE_STORAGE(tmp);
276                 CERROR("setting device %s read-only\n",
277                        ll_bdevname(obd->u.mds.mds_sb->s_dev, tmp));
278                 dev_set_rdonly(obd->u.mds.mds_sb->s_dev, 2);
279                 RETURN(0);
280         }
281
282         case OBD_IOC_ABORT_RECOVERY:
283                 CERROR("aborting recovery for device %s\n", obd->obd_name);
284                 target_abort_recovery(obd);
285                 RETURN(0);
286
287         default:
288                 RETURN(-EINVAL);
289         }
290         RETURN(0);
291 }