Whamcloud - gitweb
LU-3030 build: Update Master Copyrights pre 2.4 split
[fs/lustre-release.git] / lustre / obdclass / llog_obd.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #define DEBUG_SUBSYSTEM S_LOG
38
39 #ifndef __KERNEL__
40 #include <liblustre.h>
41 #endif
42
43 #include <obd_class.h>
44 #include <lustre_log.h>
45 #include "llog_internal.h"
46
47 /* helper functions for calling the llog obd methods */
48 static struct llog_ctxt* llog_new_ctxt(struct obd_device *obd)
49 {
50         struct llog_ctxt *ctxt;
51
52         OBD_ALLOC_PTR(ctxt);
53         if (!ctxt)
54                 return NULL;
55
56         ctxt->loc_obd = obd;
57         cfs_atomic_set(&ctxt->loc_refcount, 1);
58
59         return ctxt;
60 }
61
62 static void llog_ctxt_destroy(struct llog_ctxt *ctxt)
63 {
64         if (ctxt->loc_exp) {
65                 class_export_put(ctxt->loc_exp);
66                 ctxt->loc_exp = NULL;
67         }
68         if (ctxt->loc_imp) {
69                 class_import_put(ctxt->loc_imp);
70                 ctxt->loc_imp = NULL;
71         }
72         OBD_FREE_PTR(ctxt);
73 }
74
75 int __llog_ctxt_put(const struct lu_env *env, struct llog_ctxt *ctxt)
76 {
77         struct obd_llog_group *olg = ctxt->loc_olg;
78         struct obd_device *obd;
79         int rc = 0;
80
81         spin_lock(&olg->olg_lock);
82         if (!cfs_atomic_dec_and_test(&ctxt->loc_refcount)) {
83                 spin_unlock(&olg->olg_lock);
84                 return rc;
85         }
86         olg->olg_ctxts[ctxt->loc_idx] = NULL;
87         spin_unlock(&olg->olg_lock);
88
89         obd = ctxt->loc_obd;
90         spin_lock(&obd->obd_dev_lock);
91         /* sync with llog ctxt user thread */
92         spin_unlock(&obd->obd_dev_lock);
93
94         /* obd->obd_starting is needed for the case of cleanup
95          * in error case while obd is starting up. */
96         LASSERTF(obd->obd_starting == 1 ||
97                  obd->obd_stopping == 1 || obd->obd_set_up == 0,
98                  "wrong obd state: %d/%d/%d\n", !!obd->obd_starting,
99                  !!obd->obd_stopping, !!obd->obd_set_up);
100
101         /* cleanup the llog ctxt here */
102         if (CTXTP(ctxt, cleanup))
103                 rc = CTXTP(ctxt, cleanup)(env, ctxt);
104
105         llog_ctxt_destroy(ctxt);
106         cfs_waitq_signal(&olg->olg_waitq);
107         return rc;
108 }
109 EXPORT_SYMBOL(__llog_ctxt_put);
110
111 int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
112 {
113         struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
114         struct obd_llog_group *olg;
115         int rc, idx;
116         ENTRY;
117
118         LASSERT(ctxt != NULL);
119         LASSERT(ctxt != LP_POISON);
120
121         olg = ctxt->loc_olg;
122         LASSERT(olg != NULL);
123         LASSERT(olg != LP_POISON);
124
125         idx = ctxt->loc_idx;
126
127         /*
128          * Banlance the ctxt get when calling llog_cleanup()
129          */
130         LASSERT(cfs_atomic_read(&ctxt->loc_refcount) < LI_POISON);
131         LASSERT(cfs_atomic_read(&ctxt->loc_refcount) > 1);
132         llog_ctxt_put(ctxt);
133
134         /*
135          * Try to free the ctxt.
136          */
137         rc = __llog_ctxt_put(env, ctxt);
138         if (rc)
139                 CERROR("Error %d while cleaning up ctxt %p\n",
140                        rc, ctxt);
141
142         l_wait_event(olg->olg_waitq,
143                      llog_group_ctxt_null(olg, idx), &lwi);
144
145         RETURN(rc);
146 }
147 EXPORT_SYMBOL(llog_cleanup);
148
149 int llog_setup(const struct lu_env *env, struct obd_device *obd,
150                struct obd_llog_group *olg, int index,
151                struct obd_device *disk_obd, struct llog_operations *op)
152 {
153         struct llog_ctxt *ctxt;
154         int rc = 0;
155         ENTRY;
156
157         if (index < 0 || index >= LLOG_MAX_CTXTS)
158                 RETURN(-EINVAL);
159
160         LASSERT(olg != NULL);
161
162         ctxt = llog_new_ctxt(obd);
163         if (!ctxt)
164                 RETURN(-ENOMEM);
165
166         ctxt->loc_obd = obd;
167         ctxt->loc_olg = olg;
168         ctxt->loc_idx = index;
169         ctxt->loc_logops = op;
170         mutex_init(&ctxt->loc_mutex);
171         ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
172         ctxt->loc_flags = LLOG_CTXT_FLAG_UNINITIALIZED;
173
174         rc = llog_group_set_ctxt(olg, ctxt, index);
175         if (rc) {
176                 llog_ctxt_destroy(ctxt);
177                 if (rc == -EEXIST) {
178                         ctxt = llog_group_get_ctxt(olg, index);
179                         if (ctxt) {
180                                 /*
181                                  * mds_lov_update_desc() might call here multiple
182                                  * times. So if the llog is already set up then
183                                  * don't to do it again. 
184                                  */
185                                 CDEBUG(D_CONFIG, "obd %s ctxt %d already set up\n",
186                                        obd->obd_name, index);
187                                 LASSERT(ctxt->loc_olg == olg);
188                                 LASSERT(ctxt->loc_obd == obd);
189                                 LASSERT(ctxt->loc_exp == disk_obd->obd_self_export);
190                                 LASSERT(ctxt->loc_logops == op);
191                                 llog_ctxt_put(ctxt);
192                         }
193                         rc = 0;
194                 }
195                 RETURN(rc);
196         }
197
198         if (op->lop_setup) {
199                 if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LLOG_SETUP))
200                         rc = -EOPNOTSUPP;
201                 else
202                         rc = op->lop_setup(env, obd, olg, index, disk_obd);
203         }
204
205         if (rc) {
206                 CERROR("%s: ctxt %d lop_setup=%p failed: rc = %d\n",
207                        obd->obd_name, index, op->lop_setup, rc);
208                 llog_group_clear_ctxt(olg, index);
209                 llog_ctxt_destroy(ctxt);
210         } else {
211                 CDEBUG(D_CONFIG, "obd %s ctxt %d is initialized\n",
212                        obd->obd_name, index);
213                 ctxt->loc_flags &= ~LLOG_CTXT_FLAG_UNINITIALIZED;
214         }
215
216         RETURN(rc);
217 }
218 EXPORT_SYMBOL(llog_setup);
219
220 int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp, int flags)
221 {
222         int rc = 0;
223         ENTRY;
224
225         if (!ctxt)
226                 RETURN(0);
227
228         if (CTXTP(ctxt, sync))
229                 rc = CTXTP(ctxt, sync)(ctxt, exp, flags);
230
231         RETURN(rc);
232 }
233 EXPORT_SYMBOL(llog_sync);
234
235 int llog_obd_add(const struct lu_env *env, struct llog_ctxt *ctxt,
236                  struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
237                  struct llog_cookie *logcookies, int numcookies)
238 {
239         int raised, rc;
240         ENTRY;
241
242         if (!ctxt) {
243                 CERROR("No ctxt\n");
244                 RETURN(-ENODEV);
245         }
246
247         if (ctxt->loc_flags & LLOG_CTXT_FLAG_UNINITIALIZED)
248                 RETURN(-ENXIO);
249
250         CTXT_CHECK_OP(ctxt, obd_add, -EOPNOTSUPP);
251         raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
252         if (!raised)
253                 cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
254         rc = CTXTP(ctxt, obd_add)(env, ctxt, rec, lsm, logcookies,
255                                   numcookies);
256         if (!raised)
257                 cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
258         RETURN(rc);
259 }
260 EXPORT_SYMBOL(llog_obd_add);
261
262 int llog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt,
263                 struct lov_stripe_md *lsm, int count,
264                 struct llog_cookie *cookies, int flags)
265 {
266         int rc;
267         ENTRY;
268
269         if (!ctxt) {
270                 CERROR("No ctxt\n");
271                 RETURN(-ENODEV);
272         }
273
274         CTXT_CHECK_OP(ctxt, cancel, -EOPNOTSUPP);
275         rc = CTXTP(ctxt, cancel)(env, ctxt, lsm, count, cookies, flags);
276         RETURN(rc);
277 }
278 EXPORT_SYMBOL(llog_cancel);
279
280 int obd_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
281                   struct obd_device *disk_obd, int *index)
282 {
283         int rc;
284         ENTRY;
285         OBD_CHECK_DT_OP(obd, llog_init, 0);
286         OBD_COUNTER_INCREMENT(obd, llog_init);
287
288         rc = OBP(obd, llog_init)(obd, olg, disk_obd, index);
289         RETURN(rc);
290 }
291 EXPORT_SYMBOL(obd_llog_init);
292
293 int obd_llog_finish(struct obd_device *obd, int count)
294 {
295         int rc;
296         ENTRY;
297         OBD_CHECK_DT_OP(obd, llog_finish, 0);
298         OBD_COUNTER_INCREMENT(obd, llog_finish);
299
300         rc = OBP(obd, llog_finish)(obd, count);
301         RETURN(rc);
302 }
303 EXPORT_SYMBOL(obd_llog_finish);
304
305 /* context key constructor/destructor: llog_key_init, llog_key_fini */
306 LU_KEY_INIT_FINI(llog, struct llog_thread_info);
307 /* context key: llog_thread_key */
308 LU_CONTEXT_KEY_DEFINE(llog, LCT_MD_THREAD | LCT_MG_THREAD | LCT_LOCAL);
309 LU_KEY_INIT_GENERIC(llog);
310 EXPORT_SYMBOL(llog_thread_key);
311
312 int llog_info_init(void)
313 {
314         llog_key_init_generic(&llog_thread_key, NULL);
315         lu_context_key_register(&llog_thread_key);
316         return 0;
317 }
318
319 void llog_info_fini(void)
320 {
321         lu_context_key_degister(&llog_thread_key);
322 }