Whamcloud - gitweb
LU-7898 osd: remove unnecessary declarations
[fs/lustre-release.git] / lustre / obdclass / cl_lock.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) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2014, 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  * Client Extent Lock.
37  *
38  *   Author: Nikita Danilov <nikita.danilov@sun.com>
39  *   Author: Jinshan Xiong <jinshan.xiong@intel.com>
40  */
41
42 #define DEBUG_SUBSYSTEM S_CLASS
43
44 #include <linux/list.h>
45 #include <libcfs/libcfs.h>
46 #include <obd_class.h>
47 #include <obd_support.h>
48 #include <lustre_fid.h>
49 #include <cl_object.h>
50 #include "cl_internal.h"
51
52 static void cl_lock_trace0(int level, const struct lu_env *env,
53                            const char *prefix, const struct cl_lock *lock,
54                            const char *func, const int line)
55 {
56         struct cl_object_header *h = cl_object_header(lock->cll_descr.cld_obj);
57         CDEBUG(level, "%s: %p (%p/%d) at %s():%d\n",
58                prefix, lock, env, h->coh_nesting, func, line);
59 }
60 #define cl_lock_trace(level, env, prefix, lock)                         \
61         cl_lock_trace0(level, env, prefix, lock, __FUNCTION__, __LINE__)
62
63 /**
64  * Adds lock slice to the compound lock.
65  *
66  * This is called by cl_object_operations::coo_lock_init() methods to add a
67  * per-layer state to the lock. New state is added at the end of
68  * cl_lock::cll_layers list, that is, it is at the bottom of the stack.
69  *
70  * \see cl_req_slice_add(), cl_page_slice_add(), cl_io_slice_add()
71  */
72 void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice,
73                        struct cl_object *obj,
74                        const struct cl_lock_operations *ops)
75 {
76         ENTRY;
77         slice->cls_lock = lock;
78         list_add_tail(&slice->cls_linkage, &lock->cll_layers);
79         slice->cls_obj = obj;
80         slice->cls_ops = ops;
81         EXIT;
82 }
83 EXPORT_SYMBOL(cl_lock_slice_add);
84
85 void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock)
86 {
87         ENTRY;
88
89         cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock);
90
91         while (!list_empty(&lock->cll_layers)) {
92                 struct cl_lock_slice *slice;
93
94                 slice = list_entry(lock->cll_layers.next,
95                                 struct cl_lock_slice, cls_linkage);
96                 list_del_init(lock->cll_layers.next);
97                 slice->cls_ops->clo_fini(env, slice);
98         }
99         POISON(lock, 0x5a, sizeof(*lock));
100         EXIT;
101 }
102 EXPORT_SYMBOL(cl_lock_fini);
103
104 int cl_lock_init(const struct lu_env *env, struct cl_lock *lock,
105                  const struct cl_io *io)
106 {
107         struct cl_object *obj = lock->cll_descr.cld_obj;
108         struct cl_object *scan;
109         int result = 0;
110         ENTRY;
111
112         /* Make sure cl_lock::cll_descr is initialized. */
113         LASSERT(obj != NULL);
114
115         INIT_LIST_HEAD(&lock->cll_layers);
116         list_for_each_entry(scan, &obj->co_lu.lo_header->loh_layers,
117                             co_lu.lo_linkage) {
118                 result = scan->co_ops->coo_lock_init(env, scan, lock, io);
119                 if (result != 0) {
120                         cl_lock_fini(env, lock);
121                         break;
122                 }
123         }
124         RETURN(result);
125 }
126 EXPORT_SYMBOL(cl_lock_init);
127
128 /**
129  * Returns a slice with a lock, corresponding to the given layer in the
130  * device stack.
131  *
132  * \see cl_page_at()
133  */
134 const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock,
135                                        const struct lu_device_type *dtype)
136 {
137         const struct cl_lock_slice *slice;
138
139         ENTRY;
140
141         list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
142                 if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype)
143                         RETURN(slice);
144         }
145         RETURN(NULL);
146 }
147 EXPORT_SYMBOL(cl_lock_at);
148
149 void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock)
150 {
151         const struct cl_lock_slice *slice;
152         ENTRY;
153
154         cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock);
155         list_for_each_entry_reverse(slice, &lock->cll_layers, cls_linkage) {
156                 if (slice->cls_ops->clo_cancel != NULL)
157                         slice->cls_ops->clo_cancel(env, slice);
158         }
159
160         EXIT;
161 }
162 EXPORT_SYMBOL(cl_lock_cancel);
163
164 /**
165  * Enqueue a lock.
166  * \param anchor: if we need to wait for resources before getting the lock,
167  *                use @anchor for the purpose.
168  * \retval 0  enqueue successfully
169  * \retval <0 error code
170  */
171 int cl_lock_enqueue(const struct lu_env *env, struct cl_io *io,
172                     struct cl_lock *lock, struct cl_sync_io *anchor)
173 {
174         const struct cl_lock_slice      *slice;
175         int                             rc = -ENOSYS;
176
177         ENTRY;
178
179         list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
180                 if (slice->cls_ops->clo_enqueue == NULL)
181                         continue;
182
183                 rc = slice->cls_ops->clo_enqueue(env, slice, io, anchor);
184                 if (rc != 0)
185                         break;
186         }
187         RETURN(rc);
188 }
189 EXPORT_SYMBOL(cl_lock_enqueue);
190
191 /**
192  * Main high-level entry point of cl_lock interface that finds existing or
193  * enqueues new lock matching given description.
194  */
195 int cl_lock_request(const struct lu_env *env, struct cl_io *io,
196                     struct cl_lock *lock)
197 {
198         struct cl_sync_io       *anchor = NULL;
199         __u32                   enq_flags = lock->cll_descr.cld_enq_flags;
200         int                     rc;
201         ENTRY;
202
203         rc = cl_lock_init(env, lock, io);
204         if (rc < 0)
205                 RETURN(rc);
206
207         if ((enq_flags & CEF_ASYNC) && !(enq_flags & CEF_AGL)) {
208                 anchor = &cl_env_info(env)->clt_anchor;
209                 cl_sync_io_init(anchor, 1, cl_sync_io_end);
210         }
211
212         rc = cl_lock_enqueue(env, io, lock, anchor);
213
214         if (anchor != NULL) {
215                 int rc2;
216
217                 /* drop the reference count held at initialization time */
218                 cl_sync_io_note(env, anchor, 0);
219                 rc2 = cl_sync_io_wait(env, anchor, 0);
220                 if (rc2 < 0 && rc == 0)
221                         rc = rc2;
222         }
223
224         if (rc < 0)
225                 cl_lock_release(env, lock);
226         RETURN(rc);
227 }
228 EXPORT_SYMBOL(cl_lock_request);
229
230 /**
231  * Releases a hold and a reference on a lock, obtained by cl_lock_hold().
232  */
233 void cl_lock_release(const struct lu_env *env, struct cl_lock *lock)
234 {
235         ENTRY;
236
237         cl_lock_trace(D_DLMTRACE, env, "release lock", lock);
238         cl_lock_cancel(env, lock);
239         cl_lock_fini(env, lock);
240         EXIT;
241 }
242 EXPORT_SYMBOL(cl_lock_release);
243
244 const char *cl_lock_mode_name(const enum cl_lock_mode mode)
245 {
246         static const char * const names[] = {
247                 [CLM_READ]    = "R",
248                 [CLM_WRITE]   = "W",
249                 [CLM_GROUP]   = "G"
250         };
251         CLASSERT(CLM_MAX == ARRAY_SIZE(names));
252         return names[mode];
253 }
254 EXPORT_SYMBOL(cl_lock_mode_name);
255
256 /**
257  * Prints human readable representation of a lock description.
258  */
259 void cl_lock_descr_print(const struct lu_env *env, void *cookie,
260                          lu_printer_t printer,
261                          const struct cl_lock_descr *descr)
262 {
263         const struct lu_fid  *fid;
264
265         fid = lu_object_fid(&descr->cld_obj->co_lu);
266         (*printer)(env, cookie, DDESCR"@"DFID, PDESCR(descr), PFID(fid));
267 }
268 EXPORT_SYMBOL(cl_lock_descr_print);
269
270 /**
271  * Prints human readable representation of \a lock to the \a f.
272  */
273 void cl_lock_print(const struct lu_env *env, void *cookie,
274                    lu_printer_t printer, const struct cl_lock *lock)
275 {
276         const struct cl_lock_slice *slice;
277
278         (*printer)(env, cookie, "lock@%p", lock);
279         cl_lock_descr_print(env, cookie, printer, &lock->cll_descr);
280         (*printer)(env, cookie, " {\n");
281
282         list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
283                 (*printer)(env, cookie, "    %s@%p: ",
284                            slice->cls_obj->co_lu.lo_dev->ld_type->ldt_name,
285                            slice);
286                 if (slice->cls_ops->clo_print != NULL)
287                         slice->cls_ops->clo_print(env, cookie, printer, slice);
288                 (*printer)(env, cookie, "\n");
289         }
290         (*printer)(env, cookie, "} lock@%p\n", lock);
291 }
292 EXPORT_SYMBOL(cl_lock_print);