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