GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / staging / lustre / lustre / lov / lov_dev.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * Implementation of cl_device and cl_device_type for LOV layer.
33  *
34  *   Author: Nikita Danilov <nikita.danilov@sun.com>
35  */
36
37 #define DEBUG_SUBSYSTEM S_LOV
38
39 /* class_name2obd() */
40 #include <obd_class.h>
41
42 #include "lov_cl_internal.h"
43 #include "lov_internal.h"
44
45 struct kmem_cache *lov_lock_kmem;
46 struct kmem_cache *lov_object_kmem;
47 struct kmem_cache *lov_thread_kmem;
48 struct kmem_cache *lov_session_kmem;
49
50 struct kmem_cache *lovsub_lock_kmem;
51 struct kmem_cache *lovsub_object_kmem;
52
53 struct lu_kmem_descr lov_caches[] = {
54         {
55                 .ckd_cache = &lov_lock_kmem,
56                 .ckd_name  = "lov_lock_kmem",
57                 .ckd_size  = sizeof(struct lov_lock)
58         },
59         {
60                 .ckd_cache = &lov_object_kmem,
61                 .ckd_name  = "lov_object_kmem",
62                 .ckd_size  = sizeof(struct lov_object)
63         },
64         {
65                 .ckd_cache = &lov_thread_kmem,
66                 .ckd_name  = "lov_thread_kmem",
67                 .ckd_size  = sizeof(struct lov_thread_info)
68         },
69         {
70                 .ckd_cache = &lov_session_kmem,
71                 .ckd_name  = "lov_session_kmem",
72                 .ckd_size  = sizeof(struct lov_session)
73         },
74         {
75                 .ckd_cache = &lovsub_lock_kmem,
76                 .ckd_name  = "lovsub_lock_kmem",
77                 .ckd_size  = sizeof(struct lovsub_lock)
78         },
79         {
80                 .ckd_cache = &lovsub_object_kmem,
81                 .ckd_name  = "lovsub_object_kmem",
82                 .ckd_size  = sizeof(struct lovsub_object)
83         },
84         {
85                 .ckd_cache = NULL
86         }
87 };
88
89 /*****************************************************************************
90  *
91  * Lov device and device type functions.
92  *
93  */
94
95 static void *lov_key_init(const struct lu_context *ctx,
96                           struct lu_context_key *key)
97 {
98         struct lov_thread_info *info;
99
100         info = kmem_cache_zalloc(lov_thread_kmem, GFP_NOFS);
101         if (!info)
102                 info = ERR_PTR(-ENOMEM);
103         return info;
104 }
105
106 static void lov_key_fini(const struct lu_context *ctx,
107                          struct lu_context_key *key, void *data)
108 {
109         struct lov_thread_info *info = data;
110
111         kmem_cache_free(lov_thread_kmem, info);
112 }
113
114 struct lu_context_key lov_key = {
115         .lct_tags = LCT_CL_THREAD,
116         .lct_init = lov_key_init,
117         .lct_fini = lov_key_fini
118 };
119
120 static void *lov_session_key_init(const struct lu_context *ctx,
121                                   struct lu_context_key *key)
122 {
123         struct lov_session *info;
124
125         info = kmem_cache_zalloc(lov_session_kmem, GFP_NOFS);
126         if (!info)
127                 info = ERR_PTR(-ENOMEM);
128         return info;
129 }
130
131 static void lov_session_key_fini(const struct lu_context *ctx,
132                                  struct lu_context_key *key, void *data)
133 {
134         struct lov_session *info = data;
135
136         kmem_cache_free(lov_session_kmem, info);
137 }
138
139 struct lu_context_key lov_session_key = {
140         .lct_tags = LCT_SESSION,
141         .lct_init = lov_session_key_init,
142         .lct_fini = lov_session_key_fini
143 };
144
145 /* type constructor/destructor: lov_type_{init,fini,start,stop}() */
146 LU_TYPE_INIT_FINI(lov, &lov_key, &lov_session_key);
147
148 static struct lu_device *lov_device_fini(const struct lu_env *env,
149                                          struct lu_device *d)
150 {
151         int i;
152         struct lov_device *ld = lu2lov_dev(d);
153
154         LASSERT(ld->ld_lov);
155         if (!ld->ld_target)
156                 return NULL;
157
158         lov_foreach_target(ld, i) {
159                 struct lovsub_device *lsd;
160
161                 lsd = ld->ld_target[i];
162                 if (lsd) {
163                         cl_stack_fini(env, lovsub2cl_dev(lsd));
164                         ld->ld_target[i] = NULL;
165                 }
166         }
167         return NULL;
168 }
169
170 static int lov_device_init(const struct lu_env *env, struct lu_device *d,
171                            const char *name, struct lu_device *next)
172 {
173         struct lov_device *ld = lu2lov_dev(d);
174         int i;
175         int rc = 0;
176
177         LASSERT(d->ld_site);
178         if (!ld->ld_target)
179                 return rc;
180
181         lov_foreach_target(ld, i) {
182                 struct lovsub_device *lsd;
183                 struct cl_device     *cl;
184                 struct lov_tgt_desc  *desc;
185
186                 desc = ld->ld_lov->lov_tgts[i];
187                 if (!desc)
188                         continue;
189
190                 cl = cl_type_setup(env, d->ld_site, &lovsub_device_type,
191                                    desc->ltd_obd->obd_lu_dev);
192                 if (IS_ERR(cl)) {
193                         rc = PTR_ERR(cl);
194                         break;
195                 }
196                 lsd = cl2lovsub_dev(cl);
197                 ld->ld_target[i] = lsd;
198         }
199
200         if (rc)
201                 lov_device_fini(env, d);
202         else
203                 ld->ld_flags |= LOV_DEV_INITIALIZED;
204
205         return rc;
206 }
207
208 static struct lu_device *lov_device_free(const struct lu_env *env,
209                                          struct lu_device *d)
210 {
211         struct lov_device *ld = lu2lov_dev(d);
212
213         cl_device_fini(lu2cl_dev(d));
214         kfree(ld->ld_target);
215         kfree(ld);
216         return NULL;
217 }
218
219 static void lov_cl_del_target(const struct lu_env *env, struct lu_device *dev,
220                               __u32 index)
221 {
222         struct lov_device *ld = lu2lov_dev(dev);
223
224         if (ld->ld_target[index]) {
225                 cl_stack_fini(env, lovsub2cl_dev(ld->ld_target[index]));
226                 ld->ld_target[index] = NULL;
227         }
228 }
229
230 static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev)
231 {
232         int   result;
233         __u32 tgt_size;
234         __u32 sub_size;
235
236         result = 0;
237         tgt_size = dev->ld_lov->lov_tgt_size;
238         sub_size = dev->ld_target_nr;
239         if (sub_size < tgt_size) {
240                 struct lovsub_device    **newd;
241                 const size_t          sz   = sizeof(newd[0]);
242
243                 newd = kcalloc(tgt_size, sz, GFP_NOFS);
244                 if (newd) {
245                         if (sub_size > 0) {
246                                 memcpy(newd, dev->ld_target, sub_size * sz);
247                                 kfree(dev->ld_target);
248                         }
249                         dev->ld_target    = newd;
250                         dev->ld_target_nr = tgt_size;
251                 } else {
252                         result = -ENOMEM;
253                 }
254         }
255         return result;
256 }
257
258 static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev,
259                              __u32 index)
260 {
261         struct obd_device    *obd = dev->ld_obd;
262         struct lov_device    *ld  = lu2lov_dev(dev);
263         struct lov_tgt_desc  *tgt;
264         struct lovsub_device *lsd;
265         struct cl_device     *cl;
266         int rc;
267
268         obd_getref(obd);
269
270         tgt = obd->u.lov.lov_tgts[index];
271
272         if (!tgt->ltd_obd->obd_set_up) {
273                 CERROR("Target %s not set up\n", obd_uuid2str(&tgt->ltd_uuid));
274                 return -EINVAL;
275         }
276
277         rc = lov_expand_targets(env, ld);
278         if (rc == 0 && ld->ld_flags & LOV_DEV_INITIALIZED) {
279                 LASSERT(dev->ld_site);
280
281                 cl = cl_type_setup(env, dev->ld_site, &lovsub_device_type,
282                                    tgt->ltd_obd->obd_lu_dev);
283                 if (!IS_ERR(cl)) {
284                         lsd = cl2lovsub_dev(cl);
285                         ld->ld_target[index] = lsd;
286                 } else {
287                         CERROR("add failed (%d), deleting %s\n", rc,
288                                obd_uuid2str(&tgt->ltd_uuid));
289                         lov_cl_del_target(env, dev, index);
290                         rc = PTR_ERR(cl);
291                 }
292         }
293         obd_putref(obd);
294         return rc;
295 }
296
297 static int lov_process_config(const struct lu_env *env,
298                               struct lu_device *d, struct lustre_cfg *cfg)
299 {
300         struct obd_device *obd = d->ld_obd;
301         int cmd;
302         int rc;
303         int gen;
304         __u32 index;
305
306         obd_getref(obd);
307
308         cmd = cfg->lcfg_command;
309         rc = lov_process_config_base(d->ld_obd, cfg, &index, &gen);
310         if (rc == 0) {
311                 switch (cmd) {
312                 case LCFG_LOV_ADD_OBD:
313                 case LCFG_LOV_ADD_INA:
314                         rc = lov_cl_add_target(env, d, index);
315                         if (rc != 0)
316                                 lov_del_target(d->ld_obd, index, NULL, 0);
317                         break;
318                 case LCFG_LOV_DEL_OBD:
319                         lov_cl_del_target(env, d, index);
320                         break;
321                 }
322         }
323         obd_putref(obd);
324         return rc;
325 }
326
327 static const struct lu_device_operations lov_lu_ops = {
328         .ldo_object_alloc      = lov_object_alloc,
329         .ldo_process_config    = lov_process_config,
330 };
331
332 static struct lu_device *lov_device_alloc(const struct lu_env *env,
333                                           struct lu_device_type *t,
334                                           struct lustre_cfg *cfg)
335 {
336         struct lu_device *d;
337         struct lov_device *ld;
338         struct obd_device *obd;
339         int rc;
340
341         ld = kzalloc(sizeof(*ld), GFP_NOFS);
342         if (!ld)
343                 return ERR_PTR(-ENOMEM);
344
345         cl_device_init(&ld->ld_cl, t);
346         d = lov2lu_dev(ld);
347         d->ld_ops       = &lov_lu_ops;
348
349         /* setup the LOV OBD */
350         obd = class_name2obd(lustre_cfg_string(cfg, 0));
351         LASSERT(obd);
352         rc = lov_setup(obd, cfg);
353         if (rc) {
354                 lov_device_free(env, d);
355                 return ERR_PTR(rc);
356         }
357
358         ld->ld_lov = &obd->u.lov;
359         return d;
360 }
361
362 static const struct lu_device_type_operations lov_device_type_ops = {
363         .ldto_init = lov_type_init,
364         .ldto_fini = lov_type_fini,
365
366         .ldto_start = lov_type_start,
367         .ldto_stop  = lov_type_stop,
368
369         .ldto_device_alloc = lov_device_alloc,
370         .ldto_device_free  = lov_device_free,
371
372         .ldto_device_init    = lov_device_init,
373         .ldto_device_fini    = lov_device_fini
374 };
375
376 struct lu_device_type lov_device_type = {
377         .ldt_tags     = LU_DEVICE_CL,
378         .ldt_name     = LUSTRE_LOV_NAME,
379         .ldt_ops      = &lov_device_type_ops,
380         .ldt_ctx_tags = LCT_CL_THREAD
381 };
382
383 /** @} lov */