static struct blocking_lock_record *onefs_cbrl_find_blr(uint64_t id) { struct blocking_lock_record *blr; struct onefs_cbrl_blr_state *bs; onefs_cbrl_enumerate_blq("onefs_cbrl_find_blr"); for (blr = blocking_lock_queue; blr; blr = blr->next) { bs = (struct onefs_cbrl_blr_state *)blr->blr_private; /* We don't control all of the BLRs on the BLQ. */ if (bs == NULL) continue; if (bs->id == id) { DEBUG(10, ("found %s\n", onefs_cbrl_blr_state_str(blr))); break; } } if (blr == NULL) { DEBUG(5, ("Could not find CBRL BLR for id %llu\n", id)); return NULL; } return blr; }
static struct blocking_lock_record *onefs_cbrl_find_blr(uint64_t id) { struct smbd_server_connection *sconn = smbd_server_conn; struct blocking_lock_record *blr; struct onefs_cbrl_blr_state *bs; onefs_cbrl_enumerate_blq("onefs_cbrl_find_blr"); if (sconn->using_smb2) { struct smbd_smb2_request *smb2req; for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) { blr = get_pending_smb2req_blr(smb2req); if (!blr) { continue; } bs = (struct onefs_cbrl_blr_state *)blr->blr_private; if (bs == NULL) { continue; } if (bs->id == id) { DEBUG(10, ("found %s\n", onefs_cbrl_blr_state_str(blr))); break; } } } else { for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) { bs = (struct onefs_cbrl_blr_state *)blr->blr_private; /* We don't control all of the BLRs on the BLQ. */ if (bs == NULL) continue; if (bs->id == id) { DEBUG(10, ("found %s\n", onefs_cbrl_blr_state_str(blr))); break; } } } if (blr == NULL) { DEBUG(5, ("Could not find CBRL BLR for id %llu\n", id)); return NULL; } return blr; }
/** * @param[in] br_lck Contains the fsp. * @param[in] plock Lock request. * @param[in] blocking_lock Only used for figuring out the error. * @param[in,out] blr The BLR for the already-deferred operation. */ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle, struct byte_range_lock *br_lck, struct lock_struct *plock, bool blocking_lock, struct blocking_lock_record *blr) { int fd = br_lck->fsp->fh->fd; uint64_t id = 0; enum cbrl_lock_type type; bool async = false; bool pending = false; bool pending_async = false; int error; struct onefs_cbrl_blr_state *bs; NTSTATUS status; START_PROFILE(syscall_brl_lock); SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK); SMB_ASSERT(plock->lock_type != UNLOCK_LOCK); onefs_cbrl_enumerate_blq("onefs_brl_lock_windows"); /* Will only initialize the first time its called. */ onefs_init_cbrl(); switch (plock->lock_type) { case WRITE_LOCK: type = CBRL_LK_EX; break; case READ_LOCK: type = CBRL_LK_SH; break; case PENDING_WRITE_LOCK: /* Called when a blocking lock request is added - do an * async lock. */ type = CBRL_LK_EX; pending = true; async = true; break; case PENDING_READ_LOCK: /* Called when a blocking lock request is added - do an * async lock. */ type = CBRL_LK_SH; pending = true; async = true; break; default: /* UNLOCK_LOCK: should only be used for a POSIX_LOCK */ smb_panic("Invalid plock->lock_type passed in to " "onefs_brl_lock_windows"); } /* Figure out if we're actually doing the lock or a no-op. We need to * do a no-op when process_blocking_lock_queue calls back into us. * * We know process_* is calling into us if a blr is passed in and * pending is false. */ if (!pending && blr) { /* Check the BLR state. */ bs = (struct onefs_cbrl_blr_state *)blr->blr_private; SMB_ASSERT(bs); /* ASYNC still in progress: The process_* calls will keep * calling even if we haven't gotten the lock. Keep erroring * without calling ifs_cbrl, or getting/setting an id. */ if (bs->state == ONEFS_CBRL_ASYNC) { goto failure; } else if (bs->state == ONEFS_CBRL_ERROR) { END_PROFILE(syscall_brl_lock); return NT_STATUS_NO_MEMORY; } SMB_ASSERT(bs->state == ONEFS_CBRL_NONE); async = true; } if (async) { SMB_ASSERT(blocking_lock); SMB_ASSERT(blr); id = onefs_get_new_id(); } DEBUG(10, ("Calling ifs_cbrl(LOCK)...\n")); error = ifs_cbrl(fd, CBRL_OP_LOCK, type, plock->start, plock->size, async, id, plock->context.smbpid, plock->context.tid, plock->fnum); if (!error) { goto success; } else if (errno == EWOULDBLOCK) { SMB_ASSERT(!async); } else if (errno == EINPROGRESS) { SMB_ASSERT(async); if (pending) { /* Talloc a new BLR private state. */ blr->blr_private = talloc(blr, struct onefs_cbrl_blr_state); pending_async = true; } /* Store the new id in the BLR private state. */ bs = (struct onefs_cbrl_blr_state *)blr->blr_private; bs->id = id; bs->state = ONEFS_CBRL_ASYNC; } else {