summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-02-27 01:04:34 +0000
committerJeremy Allison <jra@samba.org>2003-02-27 01:04:34 +0000
commit766928bbba1e597c9c2b12458dd8d37e6080593e (patch)
tree4bb92d6006f323f26c7144098be15c0b6f95250a /source/smbd
parent1cba3ceae1637974272e595260933985d84942d4 (diff)
downloadsamba-766928bbba1e597c9c2b12458dd8d37e6080593e.tar.gz
samba-766928bbba1e597c9c2b12458dd8d37e6080593e.tar.xz
samba-766928bbba1e597c9c2b12458dd8d37e6080593e.zip
Fix to allow blocking lock notification to be done rapidly (no wait
for smb -> smb lock release). Adds new PENDING_LOCK type to lockdb (does not interfere with existing locks). Jeremy.
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/blocking.c78
-rw-r--r--source/smbd/process.c7
-rw-r--r--source/smbd/reply.c7
3 files changed, 82 insertions, 10 deletions
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index 14239272c29..581ce43f911 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
Blocking Locking functions
- Copyright (C) Jeremy Allison 1998
+ Copyright (C) Jeremy Allison 1998-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,6 +33,9 @@ typedef struct {
files_struct *fsp;
time_t expire_time;
int lock_num;
+ SMB_BIG_UINT offset;
+ SMB_BIG_UINT count;
+ uint16 lock_pid;
char *inbuf;
int length;
} blocking_lock_record;
@@ -77,13 +80,18 @@ static BOOL in_chained_smb(void)
return (chain_size != 0);
}
+static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len);
+
/****************************************************************************
Function to push a blocking lock request onto the lock queue.
****************************************************************************/
-BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num)
+BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
+ int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count)
{
+ static BOOL set_lock_msg;
blocking_lock_record *blr;
+ NTSTATUS status;
if(in_chained_smb() ) {
DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n"));
@@ -110,11 +118,31 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int
blr->fsp = get_fsp_from_pkt(inbuf);
blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
blr->lock_num = lock_num;
+ blr->lock_pid = lock_pid;
+ blr->offset = offset;
+ blr->count = count;
memcpy(blr->inbuf, inbuf, length);
blr->length = length;
+ /* Add a pending lock record for this. */
+ status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
+ lock_pid, sys_getpid(), blr->fsp->conn->cnum,
+ offset, count,
+ PENDING_LOCK);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
+ free_blocking_lock_record(blr);
+ return False;
+ }
+
ubi_slAddTail(&blocking_lock_queue, blr);
+ /* Ensure we'll receive messages when this is unlocked. */
+ if (!set_lock_msg) {
+ message_register(MSG_SMB_UNLOCK, received_unlock_msg);
+ set_lock_msg = True;
+ }
DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \
for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout,
@@ -493,6 +521,10 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp)
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, sys_getpid(), blr->fsp->conn->cnum,
+ blr->offset, blr->count, True);
+
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
continue;
@@ -520,6 +552,9 @@ void remove_pending_lock_requests_by_mid(int mid)
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
blocking_lock_reply_error(blr,NT_STATUS_CANCELLED);
+ brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
+ blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
+ blr->offset, blr->count, True);
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
continue;
@@ -531,8 +566,19 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
}
/****************************************************************************
+ Set a flag as an unlock request affects one of our pending locks.
+*****************************************************************************/
+
+static void received_unlock_msg(int msg_type, pid_t 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;
@@ -540,22 +586,21 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue);
/* note that we avoid the time() syscall if there are no blocking locks */
- if (!blr) {
+ if (!blr)
return timeout;
- }
t = time(NULL);
while (blr) {
- if (timeout > (blr->expire_time - t)) {
+ if ((blr->expire_time != (time_t)-1) &&
+ (timeout > (blr->expire_time - t))) {
timeout = blr->expire_time - t;
}
blr = (blocking_lock_record *)ubi_slNext(blr);
}
- if (timeout < 1) {
+ if (timeout < 1)
timeout = 1;
- }
return timeout;
}
@@ -604,6 +649,10 @@ void process_blocking_lock_queue(time_t t)
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, sys_getpid(), conn->cnum,
+ blr->offset, blr->count, True);
+
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
@@ -617,6 +666,11 @@ void process_blocking_lock_queue(time_t t)
* 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, sys_getpid(), conn->cnum,
+ blr->offset, blr->count, True);
+
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
continue;
@@ -628,6 +682,11 @@ void process_blocking_lock_queue(time_t t)
* 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, sys_getpid(), conn->cnum,
+ blr->offset, blr->count, True);
+
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
change_to_root_user();
@@ -641,6 +700,11 @@ void process_blocking_lock_queue(time_t t)
*/
if(blocking_lock_record_process(blr)) {
+
+ brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
+ blr->lock_pid, sys_getpid(), conn->cnum,
+ blr->offset, blr->count, True);
+
free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
change_to_root_user();
diff --git a/source/smbd/process.c b/source/smbd/process.c
index c002abad162..57bc236eef5 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -1271,6 +1271,13 @@ void smbd_process(void)
lp_talloc_free();
main_loop_talloc_free();
+ /* Did someone ask for immediate checks on things like blocking locks ? */
+ if (select_timeout == 0) {
+ if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
+ return;
+ num_smbs = 0; /* Reset smb counter. */
+ }
+
while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 580878fe320..71e880476cf 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -1609,7 +1609,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, -1, 0)) {
+ if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
+ (SMB_BIG_UINT)numtoread)) {
END_PROFILE(SMBlockread);
return -1;
}
@@ -2514,7 +2515,7 @@ int reply_lock(connection_struct *conn,
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, -1, 0)) {
+ if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
END_PROFILE(SMBlock);
return -1;
}
@@ -3955,7 +3956,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
+ if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
END_PROFILE(SMBlockingX);
return -1;
}