Whamcloud - gitweb
Land b1_2 onto HEAD (20040304_171022)
[fs/lustre-release.git] / lustre / ldlm / ldlm_plain.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 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
26 #ifdef __KERNEL__
27 #include <linux/lustre_dlm.h>
28 #include <linux/obd_support.h>
29 #include <linux/lustre_lib.h>
30 #else
31 #include <liblustre.h>
32 #endif
33
34 #include "ldlm_internal.h"
35
36 static inline int
37 ldlm_plain_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         int compat = 1;
44         ENTRY;
45
46         lockmode_verify(req_mode);
47
48         list_for_each(tmp, queue) {
49                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
50
51                 if (req == lock)
52                         RETURN(compat);
53
54                 if (lockmode_compat(lock->l_req_mode, req_mode))
55                         continue;
56
57                 if (!send_cbs)
58                         RETURN(0);
59
60                 compat = 0;
61                 if (lock->l_blocking_ast)
62                         ldlm_add_ast_work_item(lock, req, NULL, 0);
63         }
64
65         RETURN(compat);
66 }
67
68 /* If first_enq is 0 (ie, called from ldlm_reprocess_queue):
69  *   - blocking ASTs have already been sent
70  *   - the caller has already initialized req->lr_tmp
71  *   - must call this function with the ns lock held
72  *
73  * If first_enq is 1 (ie, called from ldlm_lock_enqueue):
74  *   - blocking ASTs have not been sent
75  *   - the caller has NOT initialized req->lr_tmp, so we must
76  *   - must call this function with the ns lock held once */
77 int ldlm_process_plain_lock(struct ldlm_lock *lock, int *flags, int first_enq,
78                             ldlm_error_t *err)
79 {
80         struct ldlm_resource *res = lock->l_resource;
81         struct list_head rpc_list = LIST_HEAD_INIT(rpc_list);
82         int rc;
83         ENTRY;
84
85         LASSERT(list_empty(&res->lr_converting));
86
87         if (!first_enq) {
88                 LASSERT(res->lr_tmp != NULL);
89                 rc = ldlm_plain_compat_queue(&res->lr_granted, lock, 0);
90                 if (!rc)
91                         RETURN(LDLM_ITER_STOP);
92                 rc = ldlm_plain_compat_queue(&res->lr_waiting, lock, 0);
93                 if (!rc)
94                         RETURN(LDLM_ITER_STOP);
95
96                 ldlm_resource_unlink_lock(lock);
97                 ldlm_grant_lock(lock, NULL, 0, 1);
98                 RETURN(LDLM_ITER_CONTINUE);
99         }
100
101  restart:
102         LASSERT(res->lr_tmp == NULL);
103         res->lr_tmp = &rpc_list;
104         rc = ldlm_plain_compat_queue(&res->lr_granted, lock, 1);
105         rc += ldlm_plain_compat_queue(&res->lr_waiting, lock, 1);
106         res->lr_tmp = NULL;
107
108         if (rc != 2) {
109                 /* If either of the compat_queue()s returned 0, then we
110                  * have ASTs to send and must go onto the waiting list.
111                  *
112                  * bug 2322: we used to unlink and re-add here, which was a
113                  * terrible folly -- if we goto restart, we could get
114                  * re-ordered!  Causes deadlock, because ASTs aren't sent! */
115                 if (list_empty(&lock->l_res_link))
116                         ldlm_resource_add_lock(res, &res->lr_waiting, lock);
117                 l_unlock(&res->lr_namespace->ns_lock);
118                 rc = ldlm_run_ast_work(res->lr_namespace, &rpc_list);
119                 l_lock(&res->lr_namespace->ns_lock);
120                 if (rc == -ERESTART)
121                         GOTO(restart, -ERESTART);
122                 *flags |= LDLM_FL_BLOCK_GRANTED;
123         } else {
124                 ldlm_resource_unlink_lock(lock);
125                 ldlm_grant_lock(lock, NULL, 0, 0);
126         }
127         RETURN(0);
128 }