Whamcloud - gitweb
- merge 0.7rc1 from b_devel to HEAD (20030612 merge point)
[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
36 void le_lov_desc_to_cpu (struct lov_desc *ld)
37 {
38         ld->ld_tgt_count = le32_to_cpu (ld->ld_tgt_count);
39         ld->ld_default_stripe_count = le32_to_cpu (ld->ld_default_stripe_count);
40         ld->ld_default_stripe_size = le32_to_cpu (ld->ld_default_stripe_size);
41         ld->ld_pattern = le32_to_cpu (ld->ld_pattern);
42 }
43
44 void cpu_to_le_lov_desc (struct lov_desc *ld)
45 {
46         ld->ld_tgt_count = cpu_to_le32 (ld->ld_tgt_count);
47         ld->ld_default_stripe_count = cpu_to_le32 (ld->ld_default_stripe_count);
48         ld->ld_default_stripe_size = cpu_to_le32 (ld->ld_default_stripe_size);
49         ld->ld_pattern = cpu_to_le32 (ld->ld_pattern);
50 }
51
52 int mds_set_lovdesc(struct obd_device *obd, struct lov_desc *desc,
53                     struct obd_uuid *uuidarray)
54 {
55         struct mds_obd *mds = &obd->u.mds;
56         struct obd_run_ctxt saved;
57         struct file *f;
58         int tgt_count;
59         int rc;
60         int i;
61         struct lov_desc *disk_desc;
62         ENTRY;
63
64         tgt_count = desc->ld_tgt_count;
65         if (desc->ld_default_stripe_count > desc->ld_tgt_count) {
66                 CERROR("default stripe count %u > OST count %u\n",
67                        desc->ld_default_stripe_count, desc->ld_tgt_count);
68                 RETURN(-EINVAL);
69         }
70         if (desc->ld_default_stripe_size & (PAGE_SIZE - 1)) {
71                 CERROR("default stripe size "LPU64" not a multiple of %lu\n",
72                        desc->ld_default_stripe_size, PAGE_SIZE);
73                 RETURN(-EINVAL);
74         }
75         if (desc->ld_default_stripe_offset > desc->ld_tgt_count) {
76                 CERROR("default stripe offset "LPU64" > max OST index %u\n",
77                        desc->ld_default_stripe_offset, desc->ld_tgt_count);
78                 RETURN(-EINVAL);
79         }
80         if (desc->ld_pattern != 0) {
81                 CERROR("stripe pattern %u unknown\n",
82                        desc->ld_pattern);
83                 RETURN(-EINVAL);
84         }
85
86         OBD_ALLOC (disk_desc, sizeof (*disk_desc));
87         if (disk_desc == NULL) {
88                 CERROR ("Can't allocate disk_desc\n");
89                 RETURN (-ENOMEM);
90         }
91
92         *disk_desc = *desc;
93         cpu_to_le_lov_desc (disk_desc);
94
95         rc = 0;
96         push_ctxt(&saved, &mds->mds_ctxt, NULL);
97
98         /* Bug 1186: FIXME: if there is an existing LOVDESC, verify new
99          * tgt_count > old */
100         f = filp_open("LOVDESC", O_CREAT|O_RDWR, 0644);
101         if (IS_ERR(f)) {
102                 CERROR("Cannot open/create LOVDESC file\n");
103                 GOTO(out, rc = PTR_ERR(f));
104         }
105
106         rc = lustre_fwrite(f, (char *)disk_desc, sizeof(*disk_desc), &f->f_pos);
107         if (filp_close(f, 0))
108                 CERROR("Error closing LOVDESC file\n");
109         if (rc != sizeof(*desc)) {
110                 CERROR("Cannot open/create LOVDESC file\n");
111                 if (rc >= 0)
112                         rc = -EIO;
113                 GOTO(out, rc);
114         }
115
116         /* Bug 1186: FIXME: if there is an existing LOVTGTS, verify
117          * existing UUIDs same */
118         f = filp_open("LOVTGTS", O_CREAT|O_RDWR, 0644);
119         if (IS_ERR(f)) {
120                 CERROR("Cannot open/create LOVTGTS file\n");
121                 GOTO(out, rc = PTR_ERR(f));
122         }
123
124         rc = 0;
125         for (i = 0; i < tgt_count ; i++) {
126                 rc = lustre_fwrite(f, uuidarray[i].uuid,
127                                    sizeof(uuidarray[i]), &f->f_pos);
128                 if (rc != sizeof(uuidarray[i])) {
129                         CERROR("cannot write LOV UUID %s (%d)\n",
130                                uuidarray[i].uuid, i);
131                         if (rc >= 0)
132                                 rc = -EIO;
133                         break;
134                 }
135                 rc = 0;
136         }
137         if (filp_close(f, 0))
138                 CERROR("Error closing LOVTGTS file\n");
139
140         memcpy(&mds->mds_lov_desc, desc, sizeof *desc);
141         mds->mds_has_lov_desc = 1;
142         /* XXX the MDS should not really know about this */
143         mds->mds_max_mdsize = lov_mds_md_size(desc->ld_tgt_count);
144
145 out:
146         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
147         OBD_FREE (disk_desc, sizeof (*disk_desc));
148
149         RETURN(rc);
150 }
151
152 int mds_get_lovdesc(struct mds_obd *mds, struct lov_desc *desc)
153 {
154         struct obd_run_ctxt saved;
155         struct file *f;
156         int rc;
157         ENTRY;
158
159         push_ctxt(&saved, &mds->mds_ctxt, NULL);
160         f = filp_open("LOVDESC", O_RDONLY, 0644);
161         if (IS_ERR(f)) {
162                 CERROR("Cannot open LOVDESC file\n");
163                 GOTO(out, rc = PTR_ERR(f));
164         }
165
166         rc = lustre_fread(f, (char *)desc, sizeof(*desc), &f->f_pos);
167         if (filp_close(f, 0))
168                 CERROR("Error closing LOVDESC file\n");
169
170         if (rc != sizeof(*desc)) {
171                 CERROR("Cannot read LOVDESC file: rc = %d\n", rc);
172                 GOTO(out, rc = -EIO);
173         } else
174                 rc = 0;
175
176         le_lov_desc_to_cpu (desc);              /* convert to my byte order */
177
178         EXIT;
179 out:
180         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
181
182         return rc;
183 }
184
185 int mds_get_lovtgts(struct mds_obd *mds, int tgt_count,struct obd_uuid *uuidarray)
186 {
187         struct obd_run_ctxt saved;
188         struct file *f;
189         int rc;
190         int rc2;
191
192         push_ctxt(&saved, &mds->mds_ctxt, NULL);
193         f = filp_open("LOVTGTS", O_RDONLY, 0644);
194         if (IS_ERR(f)) {
195                 CERROR("Cannot open LOVTGTS file\n");
196                 GOTO(out, rc = PTR_ERR(f));
197         }
198
199         rc = lustre_fread(f, (char *)uuidarray, tgt_count * sizeof(*uuidarray),
200                           &f->f_pos);
201         rc2 = filp_close(f, 0);
202         if (rc2)
203                 CERROR("Error closing LOVTGTS file: rc = %d\n", rc2);
204
205         if (rc != tgt_count * sizeof(*uuidarray)) {
206                 CERROR("Error reading LOVTGTS file: rc = %d\n", rc);
207                 if (rc >= 0)
208                         rc = -EIO;
209                 GOTO(out, rc);
210         } else
211                 rc = 0;
212         EXIT;
213 out:
214         pop_ctxt(&saved, &mds->mds_ctxt, NULL);
215
216         RETURN(rc);
217 }
218
219 int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
220                   int len, void *karg, void *uarg)
221 {
222         struct obd_device *obd = class_conn2obd(conn);
223         struct obd_ioctl_data *data = karg;
224         struct lov_desc *desc;
225         struct obd_uuid *uuidarray;
226         int count;
227         int rc;
228
229         switch (cmd) {
230         case OBD_IOC_LOV_SET_CONFIG:
231                 desc = (struct lov_desc *)data->ioc_inlbuf1;
232                 if (sizeof(*desc) > data->ioc_inllen1) {
233                         CERROR("descriptor size wrong\n");
234                         RETURN(-EINVAL);
235                 }
236
237                 count = desc->ld_tgt_count;
238                 uuidarray = (struct obd_uuid *)data->ioc_inlbuf2;
239                 if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
240                         CERROR("UUID array size wrong\n");
241                         RETURN(-EINVAL);
242                 }
243                 rc = mds_set_lovdesc(obd, desc, uuidarray);
244
245                 RETURN(rc);
246         case OBD_IOC_LOV_GET_CONFIG:
247                 desc = (struct lov_desc *)data->ioc_inlbuf1;
248                 if (sizeof(*desc) > data->ioc_inllen1) {
249                         CERROR("descriptor size wrong\n");
250                         RETURN(-EINVAL);
251                 }
252
253                 count = desc->ld_tgt_count;
254                 uuidarray = (struct obd_uuid *)data->ioc_inlbuf2;
255                 if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
256                         CERROR("UUID array size wrong\n");
257                         RETURN(-EINVAL);
258                 }
259                 rc = mds_get_lovdesc(&obd->u.mds, desc);
260                 if (desc->ld_tgt_count > count) {
261                         CERROR("UUID array size too small\n");
262                         RETURN(-ENOSPC);
263                 }
264                 rc = mds_get_lovtgts(&obd->u.mds, desc->ld_tgt_count,
265                                      uuidarray);
266
267                 RETURN(rc);
268
269         case OBD_IOC_SET_READONLY:
270                 CERROR("setting device %s read-only\n",
271                        ll_bdevname(obd->u.mds.mds_sb->s_dev));
272 #ifdef CONFIG_DEV_RDONLY
273                 dev_set_rdonly(obd->u.mds.mds_sb->s_dev, 2);
274 #endif
275                 RETURN(0);
276
277         case OBD_IOC_ABORT_RECOVERY:
278                 CERROR("aborting recovery for device %s\n", obd->obd_name);
279                 target_abort_recovery(obd);
280                 RETURN(0);
281
282         default:
283                 RETURN(-EINVAL);
284         }
285         RETURN(0);
286 }