void process_blocking_lock_queue(void) { struct timeval tv_curr = timeval_current(); struct blocking_lock_record *blr, *next = NULL; bool recalc_timeout = False; /* * Go through the queue and see if we can get any of the locks. */ for (blr = blocking_lock_queue; blr; blr = next) { next = blr->next; /* * Go through the remaining locks and try and obtain them. * The call returns True if all locks were obtained successfully * and False if we still need to wait. */ DEBUG(10, ("Processing BLR = %p\n", blr)); if(blocking_lock_record_process(blr)) { struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); DEBUG(10, ("BLR_process returned true: cancelling and " "removing lock. BLR = %p\n", blr)); if (br_lck) { brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, blr->count, blr->lock_flav, blr); TALLOC_FREE(br_lck); } DLIST_REMOVE(blocking_lock_queue, blr); TALLOC_FREE(blr); recalc_timeout = True; continue; } /* * We couldn't get the locks for this record on the list. * If the time has expired, return a lock error. */ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); DEBUG(10, ("Lock timed out! BLR = %p\n", blr)); /* * Lock expired - throw away all previously * obtained locks and return lock error. */ if (br_lck) { DEBUG(5,("process_blocking_lock_queue: " "pending lock fnum = %d for file %s " "timed out.\n", blr->fsp->fnum, blr->fsp->fsp_name )); brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, blr->count, blr->lock_flav, blr); TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(blocking_lock_queue, blr); TALLOC_FREE(blr); recalc_timeout = True; } } if (recalc_timeout) { recalc_brl_timeout(); } }
void process_blocking_lock_queue(struct smbd_server_connection *sconn) { struct timeval tv_curr = timeval_current(); struct blocking_lock_record *blr, *next = NULL; if (sconn->using_smb2) { process_blocking_lock_queue_smb2(sconn, tv_curr); return; } /* * Go through the queue and see if we can get any of the locks. */ for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) { next = blr->next; /* * Go through the remaining locks and try and obtain them. * The call returns True if all locks were obtained successfully * and False if we still need to wait. */ DEBUG(10, ("Processing BLR = %p\n", blr)); /* We use set_current_service so connections with * pending locks are not marked as idle. */ set_current_service(blr->fsp->conn, SVAL(blr->req->inbuf,smb_flg), false); if(blocking_lock_record_process(blr)) { struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); DEBUG(10, ("BLR_process returned true: cancelling and " "removing lock. BLR = %p\n", blr)); if (br_lck) { brl_lock_cancel(br_lck, blr->smblctx, messaging_server_id(sconn->msg_ctx), blr->offset, blr->count, blr->lock_flav, blr); TALLOC_FREE(br_lck); } DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); TALLOC_FREE(blr); continue; } /* * We couldn't get the locks for this record on the list. * If the time has expired, return a lock error. */ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { struct byte_range_lock *br_lck = brl_get_locks( talloc_tos(), blr->fsp); DEBUG(10, ("Lock timed out! BLR = %p\n", blr)); /* * Lock expired - throw away all previously * obtained locks and return lock error. */ if (br_lck) { DEBUG(5,("process_blocking_lock_queue: " "pending lock for %s, file %s " "timed out.\n", fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp))); brl_lock_cancel(br_lck, blr->smblctx, messaging_server_id(sconn->msg_ctx), blr->offset, blr->count, blr->lock_flav, blr); TALLOC_FREE(br_lck); } blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr); TALLOC_FREE(blr); } } recalc_brl_timeout(sconn); }
bool push_blocking_lock_request( struct byte_range_lock *br_lck, struct smb_request *req, files_struct *fsp, int lock_timeout, int lock_num, uint32_t lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, uint64_t offset, uint64_t count, uint32_t blocking_pid) { struct blocking_lock_record *blr; NTSTATUS status; if(req_is_in_chain(req)) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); return False; } /* * Now queue an entry on the blocking lock queue. We setup * the expiration time here. */ blr = talloc(NULL, struct blocking_lock_record); if (blr == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); return False; } blr->next = NULL; blr->prev = NULL; blr->fsp = fsp; if (lock_timeout == -1) { blr->expire_time.tv_sec = 0; blr->expire_time.tv_usec = 0; /* Never expire. */ } else { blr->expire_time = timeval_current_ofs(lock_timeout/1000, (lock_timeout % 1000) * 1000); } blr->lock_num = lock_num; blr->lock_pid = lock_pid; blr->blocking_pid = blocking_pid; blr->lock_flav = lock_flav; blr->lock_type = lock_type; blr->offset = offset; blr->count = count; /* Specific brl_lock() implementations can fill this in. */ blr->blr_private = NULL; /* Add a pending lock record for this. */ status = brl_lock(smbd_messaging_context(), br_lck, lock_pid, procid_self(), offset, count, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, lock_timeout ? True : False, /* blocking_lock. */ NULL, blr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); TALLOC_FREE(blr); return False; } SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd); blr->req = talloc_move(blr, &req); DLIST_ADD_END(blocking_lock_queue, blr, struct blocking_lock_record *); recalc_brl_timeout(); /* Ensure we'll receive messages when this is unlocked. */ if (!blocking_lock_unlock_state) { messaging_register(smbd_messaging_context(), NULL, MSG_SMB_UNLOCK, received_unlock_msg); blocking_lock_unlock_state = true; } DEBUG(3,("push_blocking_lock_request: lock request blocked with " "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", (unsigned int)blr->expire_time.tv_sec, (unsigned int)blr->expire_time.tv_usec, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); return True; }
bool push_blocking_lock_request( struct byte_range_lock *br_lck, struct smb_request *req, files_struct *fsp, int lock_timeout, int lock_num, uint64_t smblctx, enum brl_type lock_type, enum brl_flavour lock_flav, uint64_t offset, uint64_t count, uint64_t blocking_smblctx) { struct smbd_server_connection *sconn = req->sconn; struct blocking_lock_record *blr; NTSTATUS status; if (req->smb2req) { return push_blocking_lock_request_smb2(br_lck, req, fsp, lock_timeout, lock_num, smblctx, lock_type, lock_flav, offset, count, blocking_smblctx); } if(req_is_in_chain(req)) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); return False; } /* * Now queue an entry on the blocking lock queue. We setup * the expiration time here. */ blr = talloc(NULL, struct blocking_lock_record); if (blr == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); return False; } blr->next = NULL; blr->prev = NULL; blr->fsp = fsp; if (lock_timeout == -1) { blr->expire_time.tv_sec = 0; blr->expire_time.tv_usec = 0; /* Never expire. */ } else { blr->expire_time = timeval_current_ofs_msec(lock_timeout); } blr->lock_num = lock_num; blr->smblctx = smblctx; blr->blocking_smblctx = blocking_smblctx; blr->lock_flav = lock_flav; blr->lock_type = lock_type; blr->offset = offset; blr->count = count; /* Specific brl_lock() implementations can fill this in. */ blr->blr_private = NULL; /* Add a pending lock record for this. */ status = brl_lock(req->sconn->msg_ctx, br_lck, smblctx, messaging_server_id(req->sconn->msg_ctx), offset, count, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, True, NULL, blr); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); TALLOC_FREE(blr); return False; } SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd); blr->req = talloc_move(blr, &req); DLIST_ADD_END(sconn->smb1.locks.blocking_lock_queue, blr, struct blocking_lock_record *); recalc_brl_timeout(sconn); /* Ensure we'll receive messages when this is unlocked. */ if (!sconn->smb1.locks.blocking_lock_unlock_state) { messaging_register(sconn->msg_ctx, sconn, MSG_SMB_UNLOCK, received_unlock_msg); sconn->smb1.locks.blocking_lock_unlock_state = true; } DEBUG(3,("push_blocking_lock_request: lock request blocked with " "expiry time (%u sec. %u usec) (+%d msec) for %s, name = %s\n", (unsigned int)blr->expire_time.tv_sec, (unsigned int)blr->expire_time.tv_usec, lock_timeout, fsp_fnum_dbg(blr->fsp), fsp_str_dbg(blr->fsp))); return True; }