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 + -
显示快捷键?