blocking.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 703 行 · 第 1/2 页

C
703
字号
	set_message_end(outbuf, p+nread);		DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n",		   fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) );		send_blocking_reply(outbuf,outsize);	return True;}/**************************************************************************** Attempt to finish off getting all pending blocking locks for a lock call. Returns True if we want to be removed from the list.*****************************************************************************/static BOOL process_lock(blocking_lock_record *blr){	char *outbuf = get_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;}/**************************************************************************** Attempt to finish off getting all pending blocking locks for a lockingX call. Returns True if we want to be removed from the list.*****************************************************************************/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;}/**************************************************************************** Process a blocking lock SMB. Returns True if we want to be removed from the list.*****************************************************************************/static BOOL blocking_lock_record_process(blocking_lock_record *blr){	switch(blr->com_type) {		case SMBlock:			return process_lock(blr);		case SMBlockread:			return process_lockread(blr);		case SMBlockingX:			return process_lockingX(blr);		default:			DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));			exit_server("PANIC - unknown type on blocking lock queue");	}	return False; /* Keep compiler happy. */}/**************************************************************************** Delete entries by fnum from the blocking lock pending queue.*****************************************************************************/void remove_pending_lock_requests_by_fid(files_struct *fsp){	blocking_lock_record *blr, *next = NULL;	for(blr = blocking_lock_queue; blr; blr = next) {		next = blr->next;		if(blr->fsp->fnum == fsp->fnum) {			DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));			brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,				blr->lock_pid, procid_self(), blr->fsp->conn->cnum,				blr->offset, blr->count, True, NULL, NULL);			free_blocking_lock_record(blr);		}	}}/**************************************************************************** Delete entries by mid from the blocking lock pending queue. Always send reply.*****************************************************************************/void remove_pending_lock_requests_by_mid(int mid){	blocking_lock_record *blr, *next = NULL;	for(blr = blocking_lock_queue; blr; blr = next) {		next = blr->next;		if(SVAL(blr->inbuf,smb_mid) == mid) {			files_struct *fsp = blr->fsp;			DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));			blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);			brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,				blr->lock_pid, procid_self(), blr->fsp->conn->cnum,				blr->offset, blr->count, True, NULL, NULL);			free_blocking_lock_record(blr);		}	}}/****************************************************************************  Set a flag as an unlock request affects one of our pending locks.*****************************************************************************/static void received_unlock_msg(int msg_type, struct process_id src,				void *buf, size_t len){	DEBUG(10,("received_unlock_msg\n"));	process_blocking_lock_queue(time(NULL));}/**************************************************************************** Return the number of seconds to the next blocking locks timeout, or default_timeout*****************************************************************************/unsigned blocking_locks_timeout(unsigned default_timeout){	unsigned timeout = default_timeout;	time_t t;	blocking_lock_record *blr = blocking_lock_queue;	/* note that we avoid the time() syscall if there are no blocking locks */	if (!blr)		return timeout;	t = time(NULL);	for (; blr; blr = blr->next) {		if ((blr->expire_time != (time_t)-1) &&					(timeout > (blr->expire_time - t))) {			timeout = blr->expire_time - t;		}	}	if (timeout < 1)		timeout = 1;	return timeout;}/**************************************************************************** Process the blocking lock queue. Note that this is only called as root.*****************************************************************************/void process_blocking_lock_queue(time_t t){	blocking_lock_record *blr, *next = NULL;	/*	 * Go through the queue and see if we can get any of the locks.	 */	for (blr = blocking_lock_queue; blr; blr = next) {		connection_struct *conn = NULL;		uint16 vuid;		files_struct *fsp = NULL;		next = blr->next;		/*		 * Ensure we don't have any old chain_fsp values		 * sitting around....		 */		chain_size = 0;		file_chain_reset();		fsp = blr->fsp;		conn = conn_find(SVAL(blr->inbuf,smb_tid));		vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID :				SVAL(blr->inbuf,smb_uid);		DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",			fsp->fnum, fsp->fsp_name ));		if((blr->expire_time != -1) && (blr->expire_time <= t)) {			/*			 * Lock expired - throw away all previously			 * obtained locks and return lock error.			 */			DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",				fsp->fnum, fsp->fsp_name ));			brl_unlock(fsp->dev, fsp->inode, fsp->fnum,				blr->lock_pid, procid_self(), conn->cnum,				blr->offset, blr->count, True, NULL, NULL);			blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);			free_blocking_lock_record(blr);			continue;		}		if(!change_to_user(conn,vuid)) {			DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",				vuid ));			/*			 * Remove the entry and return an error to the client.			 */			blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);			brl_unlock(fsp->dev, fsp->inode, fsp->fnum,					blr->lock_pid, procid_self(), conn->cnum,					blr->offset, blr->count, True, NULL, NULL);			free_blocking_lock_record(blr);			continue;		}		if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {			DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));			/*			 * Remove the entry and return an error to the client.			 */			blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);			brl_unlock(fsp->dev, fsp->inode, fsp->fnum,					blr->lock_pid, procid_self(), conn->cnum,					blr->offset, blr->count, True, NULL, NULL);			free_blocking_lock_record(blr);			change_to_root_user();			continue;		}		/*		 * 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.		 */		if(blocking_lock_record_process(blr)) {			brl_unlock(fsp->dev, fsp->inode, fsp->fnum,					blr->lock_pid, procid_self(), conn->cnum,					blr->offset, blr->count, True, NULL, NULL);			free_blocking_lock_record(blr);		}		change_to_root_user();	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?