| 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 |  | 
|---|
| 31 | extern struct blocking_lock_record *blocking_lock_queue; | 
|---|
| 32 |  | 
|---|
| 33 | static uint64_t onefs_get_new_id(void) { | 
|---|
| 34 | static uint64_t id = 0; | 
|---|
| 35 |  | 
|---|
| 36 | id++; | 
|---|
| 37 |  | 
|---|
| 38 | return id; | 
|---|
| 39 | } | 
|---|
| 40 |  | 
|---|
| 41 | enum onefs_cbrl_lock_state {ONEFS_CBRL_NONE, ONEFS_CBRL_ASYNC, ONEFS_CBRL_DONE, | 
|---|
| 42 | ONEFS_CBRL_ERROR}; | 
|---|
| 43 |  | 
|---|
| 44 | struct onefs_cbrl_blr_state { | 
|---|
| 45 | uint64_t id; | 
|---|
| 46 | enum onefs_cbrl_lock_state state; | 
|---|
| 47 | }; | 
|---|
| 48 |  | 
|---|
| 49 | static 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 |  | 
|---|
| 85 | static 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 |  | 
|---|
| 98 | static 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 |  | 
|---|
| 127 | static 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 |  | 
|---|
| 162 | static 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 |  | 
|---|
| 185 | static struct cbrl_event_ops cbrl_ops = | 
|---|
| 186 | {.cbrl_async_success = onefs_cbrl_async_success, | 
|---|
| 187 | .cbrl_async_failure = onefs_cbrl_async_failure}; | 
|---|
| 188 |  | 
|---|
| 189 | static void onefs_cbrl_events_handler(struct event_context *ev, | 
|---|
| 190 | struct fd_event *fde, | 
|---|
| 191 | uint16_t flags, | 
|---|
| 192 | void *private_data) | 
|---|
| 193 | { | 
|---|
| 194 | DEBUG(10, ("onefs_cbrl_events_handler\n")); | 
|---|
| 195 |  | 
|---|
| 196 | if (cbrl_event_dispatcher(&cbrl_ops)) { | 
|---|
| 197 | DEBUG(0, ("cbrl_event_dispatcher failed: %s\n", | 
|---|
| 198 | strerror(errno))); | 
|---|
| 199 | } | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | static void onefs_init_cbrl(void) | 
|---|
| 203 | { | 
|---|
| 204 | static bool init_done = false; | 
|---|
| 205 | static int cbrl_event_fd; | 
|---|
| 206 | static struct fd_event *cbrl_fde; | 
|---|
| 207 |  | 
|---|
| 208 | if (init_done) | 
|---|
| 209 | return; | 
|---|
| 210 |  | 
|---|
| 211 | DEBUG(10, ("onefs_init_cbrl\n")); | 
|---|
| 212 |  | 
|---|
| 213 | /* Register the event channel for CBRL. */ | 
|---|
| 214 | cbrl_event_fd = cbrl_event_register(); | 
|---|
| 215 | if (cbrl_event_fd == -1) { | 
|---|
| 216 | DEBUG(0, ("cbrl_event_register failed: %s\n", | 
|---|
| 217 | strerror(errno))); | 
|---|
| 218 | return; | 
|---|
| 219 | } | 
|---|
| 220 |  | 
|---|
| 221 | DEBUG(10, ("cbrl_event_fd = %d\n", cbrl_event_fd)); | 
|---|
| 222 |  | 
|---|
| 223 | /* Register the CBRL event_fd with samba's event system */ | 
|---|
| 224 | cbrl_fde = event_add_fd(smbd_event_context(), | 
|---|
| 225 | NULL, | 
|---|
| 226 | cbrl_event_fd, | 
|---|
| 227 | EVENT_FD_READ, | 
|---|
| 228 | onefs_cbrl_events_handler, | 
|---|
| 229 | NULL); | 
|---|
| 230 |  | 
|---|
| 231 | init_done = true; | 
|---|
| 232 | return; | 
|---|
| 233 | } | 
|---|
| 234 |  | 
|---|
| 235 | /** | 
|---|
| 236 | * Blocking PID. As far as I can tell, the blocking_pid is only used to tell | 
|---|
| 237 | * whether a posix lock or a CIFS lock blocked us. If it was a posix lock, | 
|---|
| 238 | * Samba polls every 10 seconds, which we don't want. -zkirsch | 
|---|
| 239 | */ | 
|---|
| 240 | #define ONEFS_BLOCKING_PID 0xABCDABCD | 
|---|
| 241 |  | 
|---|
| 242 | /** | 
|---|
| 243 | * @param[in]     br_lck        Contains the fsp. | 
|---|
| 244 | * @param[in]     plock         Lock request. | 
|---|
| 245 | * @param[in]     blocking_lock Only used for figuring out the error. | 
|---|
| 246 | * @param[in,out] blr           The BLR for the already-deferred operation. | 
|---|
| 247 | */ | 
|---|
| 248 | NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle, | 
|---|
| 249 | struct byte_range_lock *br_lck, | 
|---|
| 250 | struct lock_struct *plock, | 
|---|
| 251 | bool blocking_lock, | 
|---|
| 252 | struct blocking_lock_record *blr) | 
|---|
| 253 | { | 
|---|
| 254 | int fd = br_lck->fsp->fh->fd; | 
|---|
| 255 | uint64_t id = 0; | 
|---|
| 256 | enum cbrl_lock_type type; | 
|---|
| 257 | bool async = false; | 
|---|
| 258 | bool pending = false; | 
|---|
| 259 | bool pending_async = false; | 
|---|
| 260 | int error; | 
|---|
| 261 | struct onefs_cbrl_blr_state *bs; | 
|---|
| 262 | NTSTATUS status; | 
|---|
| 263 |  | 
|---|
| 264 | START_PROFILE(syscall_brl_lock); | 
|---|
| 265 |  | 
|---|
| 266 | SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK); | 
|---|
| 267 | SMB_ASSERT(plock->lock_type != UNLOCK_LOCK); | 
|---|
| 268 |  | 
|---|
| 269 | onefs_cbrl_enumerate_blq("onefs_brl_lock_windows"); | 
|---|
| 270 |  | 
|---|
| 271 | /* Will only initialize the first time its called. */ | 
|---|
| 272 | onefs_init_cbrl(); | 
|---|
| 273 |  | 
|---|
| 274 | switch (plock->lock_type) { | 
|---|
| 275 | case WRITE_LOCK: | 
|---|
| 276 | type = CBRL_LK_EX; | 
|---|
| 277 | break; | 
|---|
| 278 | case READ_LOCK: | 
|---|
| 279 | type = CBRL_LK_SH; | 
|---|
| 280 | break; | 
|---|
| 281 | case PENDING_WRITE_LOCK: | 
|---|
| 282 | /* Called when a blocking lock request is added - do an | 
|---|
| 283 | * async lock. */ | 
|---|
| 284 | type = CBRL_LK_EX; | 
|---|
| 285 | pending = true; | 
|---|
| 286 | async = true; | 
|---|
| 287 | break; | 
|---|
| 288 | case PENDING_READ_LOCK: | 
|---|
| 289 | /* Called when a blocking lock request is added - do an | 
|---|
| 290 | * async lock. */ | 
|---|
| 291 | type = CBRL_LK_SH; | 
|---|
| 292 | pending = true; | 
|---|
| 293 | async = true; | 
|---|
| 294 | break; | 
|---|
| 295 | default: | 
|---|
| 296 | /* UNLOCK_LOCK: should only be used for a POSIX_LOCK */ | 
|---|
| 297 | smb_panic("Invalid plock->lock_type passed in to " | 
|---|
| 298 | "onefs_brl_lock_windows"); | 
|---|
| 299 | } | 
|---|
| 300 |  | 
|---|
| 301 | /* Figure out if we're actually doing the lock or a no-op. We need to | 
|---|
| 302 | * do a no-op when process_blocking_lock_queue calls back into us. | 
|---|
| 303 | * | 
|---|
| 304 | * We know process_* is calling into us if a blr is passed in and | 
|---|
| 305 | * pending is false. */ | 
|---|
| 306 | if (!pending && blr) { | 
|---|
| 307 | /* Check the BLR state. */ | 
|---|
| 308 | bs = (struct onefs_cbrl_blr_state *)blr->blr_private; | 
|---|
| 309 | SMB_ASSERT(bs); | 
|---|
| 310 |  | 
|---|
| 311 | /* ASYNC still in progress: The process_* calls will keep | 
|---|
| 312 | * calling even if we haven't gotten the lock. Keep erroring | 
|---|
| 313 | * without calling ifs_cbrl, or getting/setting an id. */ | 
|---|
| 314 | if (bs->state == ONEFS_CBRL_ASYNC) { | 
|---|
| 315 | goto failure; | 
|---|
| 316 | } | 
|---|
| 317 | else if (bs->state == ONEFS_CBRL_ERROR) { | 
|---|
| 318 | END_PROFILE(syscall_brl_lock); | 
|---|
| 319 | return NT_STATUS_NO_MEMORY; | 
|---|
| 320 | } | 
|---|
| 321 |  | 
|---|
| 322 | SMB_ASSERT(bs->state == ONEFS_CBRL_NONE); | 
|---|
| 323 | async = true; | 
|---|
| 324 | } | 
|---|
| 325 |  | 
|---|
| 326 | if (async) { | 
|---|
| 327 | SMB_ASSERT(blocking_lock); | 
|---|
| 328 | SMB_ASSERT(blr); | 
|---|
| 329 | id = onefs_get_new_id(); | 
|---|
| 330 | } | 
|---|
| 331 |  | 
|---|
| 332 | DEBUG(10, ("Calling ifs_cbrl(LOCK)...\n")); | 
|---|
| 333 | error = ifs_cbrl(fd, CBRL_OP_LOCK, type, plock->start, | 
|---|
| 334 | plock->size, async, id, plock->context.smbpid, plock->context.tid, | 
|---|
| 335 | plock->fnum); | 
|---|
| 336 | if (!error) { | 
|---|
| 337 | goto success; | 
|---|
| 338 | } else if (errno == EWOULDBLOCK) { | 
|---|
| 339 | SMB_ASSERT(!async); | 
|---|
| 340 | } else if (errno == EINPROGRESS) { | 
|---|
| 341 | SMB_ASSERT(async); | 
|---|
| 342 |  | 
|---|
| 343 | if (pending) { | 
|---|
| 344 | /* Talloc a new BLR private state. */ | 
|---|
| 345 | blr->blr_private = talloc(blr, struct onefs_cbrl_blr_state); | 
|---|
| 346 | pending_async = true; | 
|---|
| 347 | } | 
|---|
| 348 |  | 
|---|
| 349 | /* Store the new id in the BLR private state. */ | 
|---|
| 350 | bs = (struct onefs_cbrl_blr_state *)blr->blr_private; | 
|---|
| 351 | bs->id = id; | 
|---|
| 352 | bs->state = ONEFS_CBRL_ASYNC; | 
|---|
| 353 | } else { | 
|---|
| 354 | DEBUG(0, ("onefs_brl_lock_windows failure: error=%d (%s).\n", | 
|---|
| 355 | errno, strerror(errno))); | 
|---|
| 356 | } | 
|---|
| 357 |  | 
|---|
| 358 | failure: | 
|---|
| 359 |  | 
|---|
| 360 | END_PROFILE(syscall_brl_lock); | 
|---|
| 361 |  | 
|---|
| 362 | /* Failure - error or async. */ | 
|---|
| 363 | plock->context.smbpid = (uint32) ONEFS_BLOCKING_PID; | 
|---|
| 364 |  | 
|---|
| 365 | if (pending_async) | 
|---|
| 366 | status = NT_STATUS_OK; | 
|---|
| 367 | else | 
|---|
| 368 | status = brl_lock_failed(br_lck->fsp, plock, blocking_lock); | 
|---|
| 369 |  | 
|---|
| 370 | DEBUG(10, ("returning %s.\n", nt_errstr(status))); | 
|---|
| 371 | return status; | 
|---|
| 372 |  | 
|---|
| 373 | success: | 
|---|
| 374 | /* Self contend our own level 2 oplock. The kernel handles | 
|---|
| 375 | * contention of other opener's level 2 oplocks. */ | 
|---|
| 376 | contend_level2_oplocks_begin(br_lck->fsp, | 
|---|
| 377 | LEVEL2_CONTEND_WINDOWS_BRL); | 
|---|
| 378 |  | 
|---|
| 379 | END_PROFILE(syscall_brl_lock); | 
|---|
| 380 |  | 
|---|
| 381 | /* Success. */ | 
|---|
| 382 | onefs_cbrl_enumerate_blq("onefs_brl_unlock_windows"); | 
|---|
| 383 | DEBUG(10, ("returning NT_STATUS_OK.\n")); | 
|---|
| 384 | return NT_STATUS_OK; | 
|---|
| 385 | } | 
|---|
| 386 |  | 
|---|
| 387 | bool onefs_brl_unlock_windows(vfs_handle_struct *handle, | 
|---|
| 388 | struct messaging_context *msg_ctx, | 
|---|
| 389 | struct byte_range_lock *br_lck, | 
|---|
| 390 | const struct lock_struct *plock) | 
|---|
| 391 | { | 
|---|
| 392 | int error; | 
|---|
| 393 | int fd = br_lck->fsp->fh->fd; | 
|---|
| 394 |  | 
|---|
| 395 | START_PROFILE(syscall_brl_unlock); | 
|---|
| 396 |  | 
|---|
| 397 | SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK); | 
|---|
| 398 | SMB_ASSERT(plock->lock_type == UNLOCK_LOCK); | 
|---|
| 399 |  | 
|---|
| 400 | DEBUG(10, ("Calling ifs_cbrl(UNLOCK)...\n")); | 
|---|
| 401 | error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_LK_SH, | 
|---|
| 402 | plock->start, plock->size, false, 0, plock->context.smbpid, | 
|---|
| 403 | plock->context.tid, plock->fnum); | 
|---|
| 404 |  | 
|---|
| 405 | END_PROFILE(syscall_brl_unlock); | 
|---|
| 406 |  | 
|---|
| 407 | if (error) { | 
|---|
| 408 | DEBUG(10, ("returning false.\n")); | 
|---|
| 409 | return false; | 
|---|
| 410 | } | 
|---|
| 411 |  | 
|---|
| 412 | /* For symmetry purposes, end our oplock contention even though its | 
|---|
| 413 | * currently a no-op. */ | 
|---|
| 414 | contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL); | 
|---|
| 415 |  | 
|---|
| 416 | DEBUG(10, ("returning true.\n")); | 
|---|
| 417 | return true; | 
|---|
| 418 |  | 
|---|
| 419 | /* Problem with storing things in TDB: I won't know what BRL to unlock in the TDB. | 
|---|
| 420 | *  - I could fake it? | 
|---|
| 421 | *  - I could send Samba a message with which lock is being unlocked? | 
|---|
| 422 | *  - I could *easily* make the "id" something you always pass in to | 
|---|
| 423 | *  lock, unlock or cancel -- it identifies a lock. Makes sense! | 
|---|
| 424 | */ | 
|---|
| 425 | } | 
|---|
| 426 |  | 
|---|
| 427 | /* Default implementation only calls this on PENDING locks. */ | 
|---|
| 428 | bool onefs_brl_cancel_windows(vfs_handle_struct *handle, | 
|---|
| 429 | struct byte_range_lock *br_lck, | 
|---|
| 430 | struct lock_struct *plock, | 
|---|
| 431 | struct blocking_lock_record *blr) | 
|---|
| 432 | { | 
|---|
| 433 | int error; | 
|---|
| 434 | int fd = br_lck->fsp->fh->fd; | 
|---|
| 435 | struct onefs_cbrl_blr_state *bs; | 
|---|
| 436 |  | 
|---|
| 437 | START_PROFILE(syscall_brl_cancel); | 
|---|
| 438 |  | 
|---|
| 439 | SMB_ASSERT(plock); | 
|---|
| 440 | SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK); | 
|---|
| 441 | SMB_ASSERT(blr); | 
|---|
| 442 |  | 
|---|
| 443 | onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows"); | 
|---|
| 444 |  | 
|---|
| 445 | bs = ((struct onefs_cbrl_blr_state *)blr->blr_private); | 
|---|
| 446 | SMB_ASSERT(bs); | 
|---|
| 447 |  | 
|---|
| 448 | if (bs->state == ONEFS_CBRL_DONE || bs->state == ONEFS_CBRL_ERROR) { | 
|---|
| 449 | /* No-op. */ | 
|---|
| 450 | DEBUG(10, ("State=%d, returning true\n", bs->state)); | 
|---|
| 451 | END_PROFILE(syscall_brl_cancel); | 
|---|
| 452 | return true; | 
|---|
| 453 | } | 
|---|
| 454 |  | 
|---|
| 455 | SMB_ASSERT(bs->state == ONEFS_CBRL_NONE || | 
|---|
| 456 | bs->state == ONEFS_CBRL_ASYNC); | 
|---|
| 457 |  | 
|---|
| 458 | /* A real cancel. */ | 
|---|
| 459 | DEBUG(10, ("Calling ifs_cbrl(CANCEL)...\n")); | 
|---|
| 460 | error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_LK_UNSPEC, plock->start, | 
|---|
| 461 | plock->size, false, bs->id, plock->context.smbpid, | 
|---|
| 462 | plock->context.tid, plock->fnum); | 
|---|
| 463 |  | 
|---|
| 464 | END_PROFILE(syscall_brl_cancel); | 
|---|
| 465 |  | 
|---|
| 466 | if (error) { | 
|---|
| 467 | DEBUG(10, ("returning false\n")); | 
|---|
| 468 | bs->state = ONEFS_CBRL_ERROR; | 
|---|
| 469 | return false; | 
|---|
| 470 | } | 
|---|
| 471 |  | 
|---|
| 472 | bs->state = ONEFS_CBRL_DONE; | 
|---|
| 473 | onefs_cbrl_enumerate_blq("onefs_brl_cancel_windows"); | 
|---|
| 474 | DEBUG(10, ("returning true\n")); | 
|---|
| 475 | return true; | 
|---|
| 476 | } | 
|---|
| 477 |  | 
|---|
| 478 | bool onefs_strict_lock(vfs_handle_struct *handle, | 
|---|
| 479 | files_struct *fsp, | 
|---|
| 480 | struct lock_struct *plock) | 
|---|
| 481 | { | 
|---|
| 482 | int error; | 
|---|
| 483 |  | 
|---|
| 484 | START_PROFILE(syscall_strict_lock); | 
|---|
| 485 |  | 
|---|
| 486 | SMB_ASSERT(plock->lock_type == READ_LOCK || | 
|---|
| 487 | plock->lock_type == WRITE_LOCK); | 
|---|
| 488 |  | 
|---|
| 489 | if (!lp_locking(handle->conn->params) || | 
|---|
| 490 | !lp_strict_locking(handle->conn->params)) { | 
|---|
| 491 | END_PROFILE(syscall_strict_lock); | 
|---|
| 492 | return True; | 
|---|
| 493 | } | 
|---|
| 494 |  | 
|---|
| 495 | if (plock->lock_flav == POSIX_LOCK) { | 
|---|
| 496 | END_PROFILE(syscall_strict_lock); | 
|---|
| 497 | return SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock); | 
|---|
| 498 | } | 
|---|
| 499 |  | 
|---|
| 500 | if (plock->size == 0) { | 
|---|
| 501 | END_PROFILE(syscall_strict_lock); | 
|---|
| 502 | return True; | 
|---|
| 503 | } | 
|---|
| 504 |  | 
|---|
| 505 | error = ifs_cbrl(fsp->fh->fd, CBRL_OP_LOCK, | 
|---|
| 506 | plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR, | 
|---|
| 507 | plock->start, plock->size, 0, 0, plock->context.smbpid, | 
|---|
| 508 | plock->context.tid, plock->fnum); | 
|---|
| 509 |  | 
|---|
| 510 | END_PROFILE(syscall_strict_lock); | 
|---|
| 511 |  | 
|---|
| 512 | return (error == 0); | 
|---|
| 513 | } | 
|---|
| 514 |  | 
|---|
| 515 | void onefs_strict_unlock(vfs_handle_struct *handle, | 
|---|
| 516 | files_struct *fsp, | 
|---|
| 517 | struct lock_struct *plock) | 
|---|
| 518 | { | 
|---|
| 519 | START_PROFILE(syscall_strict_unlock); | 
|---|
| 520 |  | 
|---|
| 521 | SMB_ASSERT(plock->lock_type == READ_LOCK || | 
|---|
| 522 | plock->lock_type == WRITE_LOCK); | 
|---|
| 523 |  | 
|---|
| 524 | if (!lp_locking(handle->conn->params) || | 
|---|
| 525 | !lp_strict_locking(handle->conn->params)) { | 
|---|
| 526 | END_PROFILE(syscall_strict_unlock); | 
|---|
| 527 | return; | 
|---|
| 528 | } | 
|---|
| 529 |  | 
|---|
| 530 | if (plock->lock_flav == POSIX_LOCK) { | 
|---|
| 531 | SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock); | 
|---|
| 532 | END_PROFILE(syscall_strict_unlock); | 
|---|
| 533 | return; | 
|---|
| 534 | } | 
|---|
| 535 |  | 
|---|
| 536 | if (plock->size == 0) { | 
|---|
| 537 | END_PROFILE(syscall_strict_unlock); | 
|---|
| 538 | return; | 
|---|
| 539 | } | 
|---|
| 540 |  | 
|---|
| 541 | if (fsp->fh) { | 
|---|
| 542 | ifs_cbrl(fsp->fh->fd, CBRL_OP_UNLOCK, | 
|---|
| 543 | plock->lock_type == READ_LOCK ? CBRL_LK_RD : CBRL_LK_WR, | 
|---|
| 544 | plock->start, plock->size, 0, 0, plock->context.smbpid, | 
|---|
| 545 | plock->context.tid, plock->fnum); | 
|---|
| 546 | } | 
|---|
| 547 |  | 
|---|
| 548 | END_PROFILE(syscall_strict_unlock); | 
|---|
| 549 | } | 
|---|
| 550 |  | 
|---|
| 551 | /* TODO Optimization: Abstract out brl_get_locks() in the Windows case. | 
|---|
| 552 | * We'll malloc some memory or whatever (can't return NULL), but not actually | 
|---|
| 553 | * touch the TDB. */ | 
|---|
| 554 |  | 
|---|
| 555 | /* XXX brl_locktest: CBRL does not support calling this, but its only for | 
|---|
| 556 | * strict locking. Add empty VOP? */ | 
|---|
| 557 |  | 
|---|
| 558 | /* XXX brl_lockquery: CBRL does not support calling this for WINDOWS LOCKS, but | 
|---|
| 559 | * its only called for POSIX LOCKS. Add empty VOP? */ | 
|---|
| 560 |  | 
|---|
| 561 | /* XXX brl_close_fnum: CBRL will do this automatically. I think this is a NO-OP | 
|---|
| 562 | * for us, we could add an empty VOP. */ | 
|---|
| 563 |  | 
|---|