source: vendor/current/source3/modules/onefs_cbrl.c@ 590

Last change on this file since 590 was 414, checked in by Herwig Bauernfeind, 16 years ago

Samba 3.5.0: Initial import

File size: 14.3 KB
Line 
1/*
2 * Unix SMB/CIFS implementation.
3 * Support for OneFS system interfaces.
4 *
5 * Copyright (C) Zack Kirsch, 2009
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "includes.h"
22#include "onefs.h"
23
24#include <ifs/ifs_syscalls.h>
25#include <sys/isi_cifs_brl.h>
26#include <isi_ecs/isi_ecs_cbrl.h>
27
28#undef DBGC_CLASS
29#define DBGC_CLASS DBGC_LOCKING
30
31extern struct blocking_lock_record *blocking_lock_queue;
32
33static uint64_t onefs_get_new_id(void) {
34 static uint64_t id = 0;
35
36 id++;
37
38 return id;
39}
40
41enum onefs_cbrl_lock_state {ONEFS_CBRL_NONE, ONEFS_CBRL_ASYNC, ONEFS_CBRL_DONE,
42 ONEFS_CBRL_ERROR};
43
44struct onefs_cbrl_blr_state {
45 uint64_t id;
46 enum onefs_cbrl_lock_state state;
47};
48
49static char *onefs_cbrl_blr_state_str(const struct blocking_lock_record *blr)
50{
51 static fstring result;
52 struct onefs_cbrl_blr_state *bs;
53
54 SMB_ASSERT(blr);
55
56 bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
57
58 if (bs == NULL) {
59 fstrcpy(result, "NULL CBRL BLR state - Posix lock?");
60 return result;
61 }
62
63 switch (bs->state) {
64 case ONEFS_CBRL_NONE:
65 fstr_sprintf(result, "CBRL BLR id=%llu: state=NONE", bs->id);
66 break;
67 case ONEFS_CBRL_ASYNC:
68 fstr_sprintf(result, "CBRL BLR id=%llu: state=ASYNC", bs->id);
69 break;
70 case ONEFS_CBRL_DONE:
71 fstr_sprintf(result, "CBRL BLR id=%llu: state=DONE", bs->id);
72 break;
73 case ONEFS_CBRL_ERROR:
74 fstr_sprintf(result, "CBRL BLR id=%llu: state=ERROR", bs->id);
75 break;
76 default:
77 fstr_sprintf(result, "CBRL BLR id=%llu: unknown state %d",
78 bs->id, bs->state);
79 break;
80 }
81
82 return result;
83}
84
85static void onefs_cbrl_enumerate_blq(const char *fn)
86{
87 struct blocking_lock_record *blr;
88
89 if (DEBUGLVL(10))
90 return;
91
92 DEBUG(10, ("CBRL BLR records (%s):\n", fn));
93
94 for (blr = blocking_lock_queue; blr; blr = blr->next)
95 DEBUGADD(10, ("%s\n", onefs_cbrl_blr_state_str(blr)));
96}
97
98static struct blocking_lock_record *onefs_cbrl_find_blr(uint64_t id)
99{
100 struct blocking_lock_record *blr;
101 struct onefs_cbrl_blr_state *bs;
102
103 onefs_cbrl_enumerate_blq("onefs_cbrl_find_blr");
104
105 for (blr = blocking_lock_queue; blr; blr = blr->next) {
106 bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
107
108 /* We don't control all of the BLRs on the BLQ. */
109 if (bs == NULL)
110 continue;
111
112 if (bs->id == id) {
113 DEBUG(10, ("found %s\n",
114 onefs_cbrl_blr_state_str(blr)));
115 break;
116 }
117 }
118
119 if (blr == NULL) {
120 DEBUG(5, ("Could not find CBRL BLR for id %llu\n", id));
121 return NULL;
122 }
123
124 return blr;
125}
126
127static void onefs_cbrl_async_success(uint64_t id)
128{
129 struct blocking_lock_record *blr;
130 struct onefs_cbrl_blr_state *bs;
131 uint16 num_locks;
132
133 DEBUG(10, ("CBRL async success!\n"));
134
135 /* Find BLR with id. Its okay not to find one (race with cancel) */
136 blr = onefs_cbrl_find_blr(id);
137 if (blr == NULL)
138 return;
139
140 bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
141 SMB_ASSERT(bs);
142 SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
143
144 blr->lock_num++;
145
146 num_locks = SVAL(blr->req->vwv+7, 0);
147
148 if (blr->lock_num == num_locks)
149 bs->state = ONEFS_CBRL_DONE;
150 else
151 bs->state = ONEFS_CBRL_NONE;
152
153 /* Self contend our own level 2 oplock. The kernel handles
154 * contention of other opener's level 2 oplocks. */
155 contend_level2_oplocks_begin(blr->fsp,
156 LEVEL2_CONTEND_WINDOWS_BRL);
157
158 /* Process the queue, to try the next lock or finish up. */
159 process_blocking_lock_queue();
160}
161
162static void onefs_cbrl_async_failure(uint64_t id)
163{
164 struct blocking_lock_record *blr;
165 struct onefs_cbrl_blr_state *bs;
166
167 DEBUG(10, ("CBRL async failure!\n"));
168
169 /* Find BLR with id. Its okay not to find one (race with cancel) */
170 blr = onefs_cbrl_find_blr(id);
171 if (blr == NULL)
172 return;
173
174 bs = (struct onefs_cbrl_blr_state *)blr->blr_private;
175 SMB_ASSERT(bs);
176
177 SMB_ASSERT(bs->state == ONEFS_CBRL_ASYNC);
178 bs->state = ONEFS_CBRL_ERROR;
179
180 /* Process the queue. It will end up trying to retake the same lock,
181 * see the error in onefs_cbrl_lock_windows() and fail. */
182 process_blocking_lock_queue();
183}
184
185static struct cbrl_event_ops cbrl_ops =
186 {.cbrl_async_success = onefs_cbrl_async_success,
187 .cbrl_async_failure = onefs_cbrl_async_failure};
188