Whamcloud - gitweb
land b_inodebits
[fs/lustre-release.git] / lustre / ldlm / ldlm_inodebits.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002, 2003, 2004 Cluster File Systems, Inc.
5  *   Author: Peter Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define DEBUG_SUBSYSTEM S_LDLM
25 #ifndef __KERNEL__
26 # include <liblustre.h>
27 #endif
28
29 #include <linux/lustre_dlm.h>
30 #include <linux/obd_support.h>
31 #include <linux/lustre_lib.h>
32
33 #include "ldlm_internal.h"
34
35 /* Determine if the lock is compatible with all locks on the queue. */
36 static int
37 ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
38                             int send_cbs)
39 {
40         struct list_head *tmp;
41         struct ldlm_lock *lock;
42         ldlm_mode_t req_mode = req->l_req_mode;
43         __u64 req_bits = req->l_policy_data.l_inodebits.bits;
44         int compat = 1;
45         ENTRY;
46
47         LASSERT(req_bits); /* There is no sence in lock with no bits set,
48                               I think. Also such a lock would be compatible
49                                with any other bit lock */
50         list_for_each(tmp, queue) {
51                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
52
53                 if (req == lock)
54                         RETURN(compat);
55
56                 /* locks are compatible, bits don't matter */
57                 if (lockmode_compat(lock->l_req_mode, req_mode))
58                         continue;
59
60                 /* if bits don't overlap skip it */
61                 if (!(lock->l_policy_data.l_inodebits.bits & req_bits))
62                         continue;
63
64                 if (!send_cbs)
65                         RETURN(0);
66
67                 compat = 0;
68                 if (lock->l_blocking_ast)
69                         ldlm_add_ast_work_item(lock, req, NULL, 0);
70         }
71
72         RETURN(compat);
73 }
74
75 /* If first_enq is 0 (ie, called from ldlm_reprocess_queue):
76   *   - blocking ASTs have already been sent
77   *   - the caller has already initialized req->lr_tmp
78   *   - must call this function with the ns lock held
79   *
80   * If first_enq is 1 (ie, called from ldlm_lock_enqueue):
81   *   - blocking ASTs have not been sent
82   *   - the caller has NOT initialized req->lr_tmp, so we must
83   *   - must call this function with the ns lock held once */
84 int ldlm_process_inodebits_lock(struct ldlm_lock *lock, int *flags,
85                                 int first_enq, ldlm_error_t *err)
86 {
87         struct ldlm_resource *res = lock->l_resource;
88         struct list_head rpc_list = LIST_HEAD_INIT(rpc_list);
89         int rc;
90         ENTRY;
91
92         LASSERT(list_empty(&res->lr_converting));
93
94         if (!first_enq) {
95                 LASSERT(res->lr_tmp != NULL);
96                 rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, 0);
97                 if (!rc)
98                         RETURN(LDLM_ITER_STOP);
99                 rc = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, 0);
100                 if (!rc)
101                         RETURN(LDLM_ITER_STOP);
102
103                 ldlm_resource_unlink_lock(lock);
104                 ldlm_grant_lock(lock, NULL, 0, 1);
105                 RETURN(LDLM_ITER_CONTINUE);
106         }
107
108  restart:
109         LASSERT(res->lr_tmp == NULL);
110         res->lr_tmp = &rpc_list;
111         rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, 1);
112         rc += ldlm_inodebits_compat_queue(&res->lr_waiting, lock, 1);
113         res->lr_tmp = NULL;
114
115         if (rc != 2) {
116                 /* If either of the compat_queue()s returned 0, then we
117                  * have ASTs to send and must go onto the waiting list.
118                  *
119                  * bug 2322: we used to unlink and re-add here, which was a
120                  * terrible folly -- if we goto restart, we could get
121                  * re-ordered!  Causes deadlock, because ASTs aren't sent! */
122                 if (list_empty(&lock->l_res_link))
123                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
124                 l_unlock(&res->lr_namespace->ns_lock);
125                 rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
126                 l_lock(&res->lr_namespace->ns_lock);
127                 if (rc == -ERESTART)
128                         GOTO(restart, -ERESTART);
129                 *flags |= LDLM_FL_BLOCK_GRANTED;
130         } else {
131                 ldlm_resource_unlink_lock(lock);
132                 ldlm_grant_lock(lock, NULL, 0, 0);
133         }
134         RETURN(0);
135 }