Ejemplo n.º 1
0
/*
 * Deal with a reply when a break-to-level II was sent.
 */
bool downgrade_oplock(files_struct *fsp)
{
	bool ret;
	struct share_mode_lock *lck;
	struct byte_range_lock *brl;

	DEBUG(10, ("downgrade_oplock called for %s\n",
		   fsp_str_dbg(fsp)));

	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
	if (lck == NULL) {
		DEBUG(0,("downgrade_oplock: failed to lock share entry for "
			 "file %s\n", fsp_str_dbg(fsp)));
		return False;
	}
	ret = downgrade_share_oplock(lck, fsp);
	if (!ret) {
		DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
			 "for file %s, %s, file_id %s\n",
			 fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
			 file_id_string_tos(&fsp->file_id)));
	}

	downgrade_file_oplock(fsp);

	brl = brl_get_locks(talloc_tos(), fsp);
	if (brl != NULL) {
		brl_set_have_read_oplocks(brl, true);
		TALLOC_FREE(brl);
	}

	TALLOC_FREE(lck);
	return ret;
}
Ejemplo n.º 2
0
struct byte_range_lock *do_lock(files_struct *fsp,
			uint32 lock_pid,
			SMB_BIG_UINT count,
			SMB_BIG_UINT offset,
			enum brl_type lock_type,
			enum brl_flavour lock_flav,
			BOOL blocking_lock,
			NTSTATUS *perr,
			uint32 *plock_pid)
{
	struct byte_range_lock *br_lck = NULL;

	if (!fsp->can_lock) {
		*perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
		return NULL;
	}

	if (!lp_locking(fsp->conn->params)) {
		*perr = NT_STATUS_OK;
		return NULL;
	}

	/* NOTE! 0 byte long ranges ARE allowed and should be stored  */

	DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
		lock_flav_name(lock_flav), lock_type_name(lock_type),
		(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));

	br_lck = brl_get_locks(NULL, fsp);
	if (!br_lck) {
		*perr = NT_STATUS_NO_MEMORY;
		return NULL;
	}

	*perr = brl_lock(br_lck,
			lock_pid,
			procid_self(),
			offset,
			count, 
			lock_type,
			lock_flav,
			blocking_lock,
			plock_pid);

	if (lock_flav == WINDOWS_LOCK &&
			fsp->current_lock_count != NO_LOCKING_COUNT) {
		/* blocking ie. pending, locks also count here,
		 * as this is an efficiency counter to avoid checking
		 * the lock db. on close. JRA. */

		fsp->current_lock_count++;
	} else {
		/* Notice that this has had a POSIX lock request.
		 * We can't count locks after this so forget them.
		 */
		fsp->current_lock_count = NO_LOCKING_COUNT;
	}

	return br_lck;
}
Ejemplo n.º 3
0
NTSTATUS query_lock(files_struct *fsp,
			uint16 *psmbpid,
			SMB_BIG_UINT *pcount,
			SMB_BIG_UINT *poffset,
			enum brl_type *plock_type,
			enum brl_flavour lock_flav)
{
	struct byte_range_lock *br_lck = NULL;
	NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;

	if (!OPEN_FSP(fsp) || !fsp->can_lock) {
		return NT_STATUS_INVALID_HANDLE;
	}

	if (!lp_locking(SNUM(fsp->conn))) {
		return NT_STATUS_OK;
	}

	br_lck = brl_get_locks(fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	status = brl_lockquery(br_lck,
			psmbpid,
			procid_self(),
			poffset,
			pcount,
			plock_type,
			lock_flav);

	byte_range_lock_destructor(br_lck);
	return status;
}
Ejemplo n.º 4
0
void locking_close_file(struct messaging_context *msg_ctx,
			files_struct *fsp,
			enum file_close_type close_type)
{
	struct byte_range_lock *br_lck;

	if (!lp_locking(fsp->conn->params)) {
		return;
	}

	/* If we have not outstanding locks or pending
	 * locks then we don't need to look in the lock db.
	 */

	if (fsp->current_lock_count == 0) {
		return;
	}

	br_lck = brl_get_locks(talloc_tos(),fsp);

	if (br_lck) {
		cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
		brl_close_fnum(msg_ctx, br_lck);
		TALLOC_FREE(br_lck);
	}
}
Ejemplo n.º 5
0
NTSTATUS do_lock_cancel(files_struct *fsp,
			uint32 lock_pid,
			SMB_BIG_UINT count,
			SMB_BIG_UINT offset,
			enum brl_flavour lock_flav)
{
	BOOL ok = False;
	struct byte_range_lock *br_lck = NULL;
	
	if (!fsp->can_lock) {
		return fsp->is_directory ?
			NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
	}
	
	if (!lp_locking(fsp->conn->params)) {
		return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
	}

	DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
		  (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));

	br_lck = brl_get_locks(NULL, fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	ok = brl_lock_cancel(br_lck,
			lock_pid,
			procid_self(),
			offset,
			count,
			lock_flav);
   
	TALLOC_FREE(br_lck);

	if (!ok) {
		DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
		return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
	}

	if (lock_flav == WINDOWS_LOCK &&
			fsp->current_lock_count != NO_LOCKING_COUNT) {
		SMB_ASSERT(fsp->current_lock_count > 0);
		fsp->current_lock_count--;
	}

	return NT_STATUS_OK;
}
Ejemplo n.º 6
0
NTSTATUS do_lock_cancel(files_struct *fsp,
			uint64 smblctx,
			uint64_t count,
			uint64_t offset,
			enum brl_flavour lock_flav,
			struct blocking_lock_record *blr)
{
	bool ok = False;
	struct byte_range_lock *br_lck = NULL;

	if (!fsp->can_lock) {
		return fsp->is_directory ?
			NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
	}

	if (!lp_locking(fsp->conn->params)) {
		return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
	}

	DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for %s file %s\n",
		  (double)offset, (double)count, fsp_fnum_dbg(fsp),
		  fsp_str_dbg(fsp)));

	br_lck = brl_get_locks(talloc_tos(), fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	ok = brl_lock_cancel(br_lck,
			smblctx,
			messaging_server_id(fsp->conn->sconn->msg_ctx),
			offset,
			count,
			lock_flav,
			blr);

	TALLOC_FREE(br_lck);

	if (!ok) {
		DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
		return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
	}

	decrement_current_lock_count(fsp, lock_flav);
	return NT_STATUS_OK;
}
Ejemplo n.º 7
0
NTSTATUS do_unlock(struct messaging_context *msg_ctx,
			files_struct *fsp,
			uint64_t smblctx,
			uint64_t count,
			uint64_t offset,
			enum brl_flavour lock_flav)
{
	bool ok = False;
	struct byte_range_lock *br_lck = NULL;

	if (!fsp->can_lock) {
		return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
	}

	if (!lp_locking(fsp->conn->params)) {
		return NT_STATUS_OK;
	}

	DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for %s file %s\n",
		  (double)offset, (double)count, fsp_fnum_dbg(fsp),
		  fsp_str_dbg(fsp)));

	br_lck = brl_get_locks(talloc_tos(), fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	ok = brl_unlock(msg_ctx,
			br_lck,
			smblctx,
			messaging_server_id(fsp->conn->sconn->msg_ctx),
			offset,
			count,
			lock_flav);

	TALLOC_FREE(br_lck);

	if (!ok) {
		DEBUG(10,("do_unlock: returning ERRlock.\n" ));
		return NT_STATUS_RANGE_NOT_LOCKED;
	}

	decrement_current_lock_count(fsp, lock_flav);
	return NT_STATUS_OK;
}
Ejemplo n.º 8
0
bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck)
{
	struct share_mode_data *d = lck->data;
	struct byte_range_lock *br_lck;
	uint32_t num_read_oplocks = 0;
	uint32_t i;

	if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
		/*
		 * If we're the only one, we don't need a brlock entry
		 */
		remove_stale_share_mode_entries(d);
		SMB_ASSERT(d->num_share_modes == 1);
		SMB_ASSERT(EXCLUSIVE_OPLOCK_TYPE(d->share_modes[0].op_type));
		return true;
	}

	for (i=0; i<d->num_share_modes; i++) {
		struct share_mode_entry *e = &d->share_modes[i];
		uint32_t e_lease_type = get_lease_type(d, e);

		if (e_lease_type & SMB2_LEASE_READ) {
			num_read_oplocks += 1;
		}
	}

	br_lck = brl_get_locks_readonly(fsp);
	if (br_lck == NULL) {
		return false;
	}
	if (brl_num_read_oplocks(br_lck) == num_read_oplocks) {
		return true;
	}

	br_lck = brl_get_locks(talloc_tos(), fsp);
	if (br_lck == NULL) {
		return false;
	}
	brl_set_num_read_oplocks(br_lck, num_read_oplocks);
	TALLOC_FREE(br_lck);
	return true;
}
Ejemplo n.º 9
0
NTSTATUS do_lock(files_struct *fsp,
			uint16 lock_pid,
			SMB_BIG_UINT count,
			SMB_BIG_UINT offset,
			enum brl_type lock_type,
			enum brl_flavour lock_flav,
			BOOL *my_lock_ctx)
{
	struct byte_range_lock *br_lck = NULL;
	NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;

	if (!OPEN_FSP(fsp) || !fsp->can_lock) {
		return NT_STATUS_INVALID_HANDLE;
	}

	if (!lp_locking(SNUM(fsp->conn))) {
		return NT_STATUS_OK;
	}

	/* NOTE! 0 byte long ranges ARE allowed and should be stored  */

	DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
		lock_flav_name(lock_flav), lock_type_name(lock_type),
		(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));

	br_lck = brl_get_locks(fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	status = brl_lock(br_lck,
			lock_pid,
			procid_self(),
			offset,
			count, 
			lock_type,
			lock_flav,
			my_lock_ctx);

	byte_range_lock_destructor(br_lck);
	return status;
}
Ejemplo n.º 10
0
NTSTATUS do_unlock(files_struct *fsp,
			uint16 lock_pid,
			SMB_BIG_UINT count,
			SMB_BIG_UINT offset,
			enum brl_flavour lock_flav)
{
	BOOL ok = False;
	struct byte_range_lock *br_lck = NULL;
	
	if (!lp_locking(SNUM(fsp->conn))) {
		return NT_STATUS_OK;
	}
	
	if (!OPEN_FSP(fsp) || !fsp->can_lock) {
		return NT_STATUS_INVALID_HANDLE;
	}
	
	DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
		  (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));

	br_lck = brl_get_locks(fsp);
	if (!br_lck) {
		return NT_STATUS_NO_MEMORY;
	}

	ok = brl_unlock(br_lck,
			lock_pid,
			procid_self(),
			offset,
			count,
			lock_flav);
   
	byte_range_lock_destructor(br_lck);

	if (!ok) {
		DEBUG(10,("do_unlock: returning ERRlock.\n" ));
		return NT_STATUS_RANGE_NOT_LOCKED;
	}

	return NT_STATUS_OK;
}
Ejemplo n.º 11
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);
	}
}
Ejemplo n.º 12
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);
	}
}
Ejemplo n.º 13
0
void locking_close_file(files_struct *fsp)
{
	struct byte_range_lock *br_lck;
	struct process_id pid = procid_self();

	if (!lp_locking(SNUM(fsp->conn)))
		return;

	/*
	 * Just release all the brl locks, no need to release individually.
	 */

	br_lck = brl_get_locks(fsp);
	if (br_lck) {
		brl_close_fnum(br_lck, pid);
		byte_range_lock_destructor(br_lck);
	}

	if(lp_posix_locking(SNUM(fsp->conn))) {
	 	/* Release all the POSIX locks.*/
		posix_locking_close_file(fsp);

	}
}
Ejemplo n.º 14
0
void locking_close_file(files_struct *fsp)
{
	struct byte_range_lock *br_lck;

	if (!lp_locking(fsp->conn->params)) {
		return;
	}

	/* If we have not outstanding locks or pending
	 * locks then we don't need to look in the lock db.
	 */

	if (fsp->current_lock_count == 0) {
		return;
	}

	br_lck = brl_get_locks(NULL,fsp);

	if (br_lck) {
		cancel_pending_lock_requests_by_fid(fsp, br_lck);
		brl_close_fnum(br_lck);
		TALLOC_FREE(br_lck);
	}
}
Ejemplo n.º 15
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();
	}
}
Ejemplo n.º 16
0
BOOL is_locked(files_struct *fsp,
		SMB_BIG_UINT count,
		SMB_BIG_UINT offset, 
		enum brl_type lock_type)
{
	int snum = SNUM(fsp->conn);
	int strict_locking = lp_strict_locking(snum);
	enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
	BOOL ret = True;
	
	if (count == 0) {
		return False;
	}

	if (!lp_locking(snum) || !strict_locking) {
		return False;
	}

	if (strict_locking == Auto) {
		if  (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
			DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
			ret = False;
		} else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
			   (lock_type == READ_LOCK)) {
			DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
			ret = False;
		} else {
			struct byte_range_lock *br_lck = brl_get_locks(fsp);
			if (!br_lck) {
				return False;
			}
			ret = !brl_locktest(br_lck,
					global_smbpid,
					procid_self(),
					offset,
					count,
					lock_type,
					lock_flav);
			byte_range_lock_destructor(br_lck);
		}
	} else {
		struct byte_range_lock *br_lck = brl_get_locks(fsp);
		if (!br_lck) {
			return False;
		}
		ret = !brl_locktest(br_lck,
				global_smbpid,
				procid_self(),
				offset,
				count,
				lock_type,
				lock_flav);
		byte_range_lock_destructor(br_lck);
	}

	DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
			lock_flav_name(lock_flav),
			(double)offset, (double)count, ret ? "locked" : "unlocked",
			fsp->fnum, fsp->fsp_name ));

	return ret;
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
0
bool remove_oplock(files_struct *fsp)
{
	bool ret;
	struct share_mode_lock *lck;

	DEBUG(10, ("remove_oplock called for %s\n",
		   fsp_str_dbg(fsp)));

	/* Remove the oplock flag from the sharemode. */
	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
	if (lck == NULL) {
		DEBUG(0,("remove_oplock: failed to lock share entry for "
			 "file %s\n", fsp_str_dbg(fsp)));
		return False;
	}

	if (fsp->oplock_type == LEVEL_II_OPLOCK) {

		/*
		 * If we're the only LEVEL_II holder, we have to remove the
		 * have_read_oplocks from the brlock entry
		 */

		struct share_mode_data *data = lck->data;
		uint32_t i, num_level2;

		num_level2 = 0;
		for (i=0; i<data->num_share_modes; i++) {
			if (data->share_modes[i].op_type == LEVEL_II_OPLOCK) {
				num_level2 += 1;
			}
			if (num_level2 > 1) {
				/*
				 * No need to count them all...
				 */
				break;
			}
		}

		if (num_level2 == 1) {
			/*
			 * That's only us. We are dropping that level2 oplock,
			 * so remove the brlock flag.
			 */
			struct byte_range_lock *brl;

			brl = brl_get_locks(talloc_tos(), fsp);
			if (brl) {
				brl_set_have_read_oplocks(brl, false);
				TALLOC_FREE(brl);
			}
		}
	}

	ret = remove_share_oplock(lck, fsp);
	if (!ret) {
		DEBUG(0,("remove_oplock: failed to remove share oplock for "
			 "file %s, %s, %s\n",
			 fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
			 file_id_string_tos(&fsp->file_id)));
	}
	release_file_oplock(fsp);
	TALLOC_FREE(lck);
	return ret;
}
Ejemplo n.º 19
0
struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
			files_struct *fsp,
			uint64_t smblctx,
			uint64_t count,
			uint64_t offset,
			enum brl_type lock_type,
			enum brl_flavour lock_flav,
			bool blocking_lock,
			NTSTATUS *perr,
			uint64_t *psmblctx,
			struct blocking_lock_record *blr)
{
	struct byte_range_lock *br_lck = NULL;

	/* silently return ok on print files as we don't do locking there */
	if (fsp->print_file) {
		*perr = NT_STATUS_OK;
		return NULL;
	}

	if (!fsp->can_lock) {
		*perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
		return NULL;
	}

	if (!lp_locking(fsp->conn->params)) {
		*perr = NT_STATUS_OK;
		return NULL;
	}

	/* NOTE! 0 byte long ranges ARE allowed and should be stored  */

	DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f "
		"blocking_lock=%s requested for %s file %s\n",
		lock_flav_name(lock_flav), lock_type_name(lock_type),
		(double)offset, (double)count, blocking_lock ? "true" :
		"false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));

	br_lck = brl_get_locks(talloc_tos(), fsp);
	if (!br_lck) {
		*perr = NT_STATUS_NO_MEMORY;
		return NULL;
	}

	*perr = brl_lock(msg_ctx,
			br_lck,
			smblctx,
			messaging_server_id(fsp->conn->sconn->msg_ctx),
			offset,
			count,
			lock_type,
			lock_flav,
			blocking_lock,
			psmblctx,
			blr);

	DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));

	increment_current_lock_count(fsp, lock_flav);
	return br_lck;
}