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