Exemple #1
0
static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
						 void *private_data,
						 uint32_t msg_type,
						 struct server_id server_id,
						 DATA_BLOB *data)
{
	NTSTATUS err;
	const char *msg = (const char *)data->data;
	struct blocking_lock_record *blr;

	if (data->data == NULL) {
		smb_panic("process_blocking_lock_cancel_message: null msg");
	}

	if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
		DEBUG(0, ("process_blocking_lock_cancel_message: "
			  "Got invalid msg len %d\n", (int)data->length));
		smb_panic("process_blocking_lock_cancel_message: bad msg");
        }

	memcpy(&blr, msg, sizeof(blr));
	memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));

	DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
		nt_errstr(err) ));

	blocking_lock_reply_error(blr, err);
	DLIST_REMOVE(blocking_lock_cancelled_queue, blr);
	TALLOC_FREE(blr);
}
Exemple #2
0
static BOOL process_lock(blocking_lock_record *blr)
{
	char *outbuf = OutBuffer;
	char *inbuf = blr->inbuf;
	int outsize;
	SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
	NTSTATUS status;
	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
	files_struct *fsp = blr->fsp;
	BOOL my_lock_ctx = False;

	count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
	offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);

	errno = 0;
	status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
	if (NT_STATUS_IS_ERR(status)) {
		if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
			!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
			/*
			 * We have other than a "can't get lock"
			 * error. Send an error.
			 * Return True so we get dequeued.
			 */
			
			blocking_lock_reply_error(blr, status);
			return True;
		}
		/*
		 * Still can't get the lock - keep waiting.
		 */
		DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n",
			  fsp->fsp_name));
		return False;
	}

	/*
	 * Success - we got the lock.
	 */
	
	DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n",
		 fsp->fsp_name, fsp->fnum, (double)offset, (double)count));
	
	construct_reply_common(inbuf, outbuf);
	outsize = set_message(outbuf,0,0,True);
	send_blocking_reply(outbuf,outsize);
	return True;
}
Exemple #3
0
void remove_pending_lock_requests_by_mid_smb1(
	struct smbd_server_connection *sconn, uint64_t mid)
{
	struct blocking_lock_record *blr, *next = NULL;

	for(blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
		files_struct *fsp;
		struct byte_range_lock *br_lck;

		next = blr->next;

		if (blr->req->mid != mid) {
			continue;
		}

		fsp = blr->fsp;
		br_lck = brl_get_locks(talloc_tos(), fsp);

		if (br_lck) {
			DEBUG(10, ("remove_pending_lock_requests_by_mid_smb1 - "
				   "removing request type %d for file %s, %s\n",
				   blr->req->cmd, fsp_str_dbg(fsp),
				   fsp_fnum_dbg(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);
	}
}
Exemple #4
0
void remove_pending_lock_requests_by_mid(int mid)
{
	struct blocking_lock_record *blr, *next = NULL;

	for(blr = blocking_lock_queue; blr; blr = next) {
		files_struct *fsp;
		struct byte_range_lock *br_lck;

		next = blr->next;

		if (blr->req->mid != mid) {
			continue;
		}

		fsp = blr->fsp;
		br_lck = brl_get_locks(talloc_tos(), fsp);

		if (br_lck) {
			DEBUG(10, ("remove_pending_lock_requests_by_mid - "
				   "removing request type %d for file %s fnum "
				   "= %d\n", blr->req->cmd, fsp->fsp_name,
				   fsp->fnum ));

			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);
	}
}
Exemple #5
0
static bool process_trans2(struct blocking_lock_record *blr)
{
	char params[2];
	NTSTATUS status;
	struct byte_range_lock *br_lck = do_lock(
						blr->fsp->conn->sconn->msg_ctx,
						blr->fsp,
						blr->smblctx,
						blr->count,
						blr->offset,
						blr->lock_type,
						blr->lock_flav,
						True,
						&status,
						&blr->blocking_smblctx,
						blr);
	TALLOC_FREE(br_lck);

	if (!NT_STATUS_IS_OK(status)) {
		if (ERROR_WAS_LOCK_DENIED(status)) {
			/* Still can't get the lock, just keep waiting. */
			return False;
		}
		/*
		 * We have other than a "can't get lock"
		 * error. Send an error and return True so we get dequeued.
		 */
		blocking_lock_reply_error(blr, status);
		return True;
	}

	/* We finally got the lock, return success. */

	SSVAL(params,0,0);
	/* Fake up max_data_bytes here - we know it fits. */
	send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
	return True;
}
Exemple #6
0
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();
	}
}
Exemple #7
0
static bool process_lockingX(struct blocking_lock_record *blr)
{
	unsigned char locktype = CVAL(blr->req->vwv+3, 0);
	files_struct *fsp = blr->fsp;
	uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
	uint16 num_locks = SVAL(blr->req->vwv+7, 0);
	uint64_t count = (uint64_t)0, offset = (uint64_t)0;
	uint32 lock_pid;
	bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
	uint8_t *data;
	NTSTATUS status = NT_STATUS_OK;

	data = (uint8_t *)blr->req->buf
		+ ((large_file_format ? 20 : 10)*num_ulocks);

	/* 
	 * Data now points at the beginning of the list
	 * of smb_lkrng structs.
	 */

	for(; blr->lock_num < num_locks; blr->lock_num++) {
		struct byte_range_lock *br_lck = NULL;
		bool err;

		lock_pid = get_lock_pid( data, blr->lock_num, large_file_format);
		count = get_lock_count( data, blr->lock_num, large_file_format);
		offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);

		/*
		 * We know err cannot be set as if it was the lock
		 * request would never have been queued. JRA.
		 */
		errno = 0;
		br_lck = do_lock(smbd_messaging_context(),
				fsp,
				lock_pid,
				count,
				offset, 
				((locktype & LOCKING_ANDX_SHARED_LOCK) ?
					READ_LOCK : WRITE_LOCK),
				WINDOWS_LOCK,
				True,
				&status,
				&blr->blocking_pid,
				blr);

		TALLOC_FREE(br_lck);

		if (NT_STATUS_IS_ERR(status)) {
			break;
		}
	}

	if(blr->lock_num == num_locks) {
		/*
		 * Success - we got all the locks.
		 */

		DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n",
			 fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) );

		reply_lockingX_success(blr);
		return True;
	}

	if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
	    !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
		/*
		 * We have other than a "can't get lock"
		 * error. Free any locks we had and return an error.
		 * Return True so we get dequeued.
		 */
		blocking_lock_reply_error(blr, status);
		return True;
	}

	/*
	 * Still can't get all the locks - keep waiting.
	 */

	DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
Waiting....\n", 
		  blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum));

	return False;
}
Exemple #8
0
static BOOL process_lockingX(blocking_lock_record *blr)
{
	char *inbuf = blr->inbuf;
	unsigned char locktype = CVAL(inbuf,smb_vwv3);
	files_struct *fsp = blr->fsp;
	connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
	uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
	uint16 num_locks = SVAL(inbuf,smb_vwv7);
	SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
	uint16 lock_pid;
	BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
	char *data;
	BOOL my_lock_ctx = False;
	NTSTATUS status = NT_STATUS_OK;

	data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks);

	/* 
	 * Data now points at the beginning of the list
	 * of smb_lkrng structs.
	 */
	
	for(; blr->lock_num < num_locks; blr->lock_num++) {
		BOOL err;

		lock_pid = get_lock_pid( data, blr->lock_num, large_file_format);
		count = get_lock_count( data, blr->lock_num, large_file_format);
		offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
		
		/*
		 * We know err cannot be set as if it was the lock
		 * request would never have been queued. JRA.
		 */
		errno = 0;
		status = do_lock_spin(fsp,conn,lock_pid,count,offset, 
				 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
		if (NT_STATUS_IS_ERR(status)) break;
	}

	if(blr->lock_num == num_locks) {
		/*
		 * Success - we got all the locks.
		 */
		
		DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n",
			 fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) );

		reply_lockingX_success(blr);
		return True;
	} else if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
			!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
			/*
			 * We have other than a "can't get lock"
			 * error. Free any locks we had and return an error.
			 * Return True so we get dequeued.
			 */
		
		blocking_lock_reply_error(blr, status);
		return True;
	}

	/*
	 * Still can't get all the locks - keep waiting.
	 */
	
	DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
Waiting....\n", 
		  blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum));
	
	return False;
}
Exemple #9
0
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);
}