svn commit: samba r8962 - in trunk/source: include smbd
vlendec at samba.org
vlendec at samba.org
Tue Aug 2 23:52:44 GMT 2005
Author: vlendec
Date: 2005-08-02 23:52:43 +0000 (Tue, 02 Aug 2005)
New Revision: 8962
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8962
Log:
Add oplock break failure handling
Modified:
trunk/source/include/local.h
trunk/source/include/smb.h
trunk/source/smbd/open.c
trunk/source/smbd/oplock.c
trunk/source/smbd/process.c
Changeset:
Modified: trunk/source/include/local.h
===================================================================
--- trunk/source/include/local.h 2005-08-02 23:43:50 UTC (rev 8961)
+++ trunk/source/include/local.h 2005-08-02 23:52:43 UTC (rev 8962)
@@ -233,9 +233,6 @@
/* Number of microseconds to wait before a sharing violation. */
#define SHARING_VIOLATION_USEC_WAIT 950000
-/* Number of microseconds to wait before an oplock break */
-#define OPLOCK_BREAK_USEC_WAIT 30000000
-
#define MAX_LDAP_REPLICATION_SLEEP_TIME 5000 /* In milliseconds. */
#endif
Modified: trunk/source/include/smb.h
===================================================================
--- trunk/source/include/smb.h 2005-08-02 23:43:50 UTC (rev 8961)
+++ trunk/source/include/smb.h 2005-08-02 23:52:43 UTC (rev 8962)
@@ -443,6 +443,7 @@
time_t last_write_time;
int oplock_type;
int sent_oplock_break;
+ struct timed_event *oplock_timeout;
BOOL level2_around;
int num_waiting_for_level2_inform;
Modified: trunk/source/smbd/open.c
===================================================================
--- trunk/source/smbd/open.c 2005-08-02 23:43:50 UTC (rev 8961)
+++ trunk/source/smbd/open.c 2005-08-02 23:52:43 UTC (rev 8962)
@@ -1593,7 +1593,13 @@
/* delay_for_oplocks might delete the fsp */
open_time = fsp->open_time;
if (delay_for_oplocks(fsp, second_try)) {
- defer_open(&open_time, OPLOCK_BREAK_USEC_WAIT,
+ /* Normally the smbd we asked should respond within
+ * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
+ * the client did, give twice the timeout as a safety
+ * measure here in case the other smbd is stuck
+ * somewhere else. */
+ defer_open(&open_time,
+ (OPLOCK_BREAK_TIMEOUT*2) * 1000000,
fname, dev, inode);
return NULL;
}
Modified: trunk/source/smbd/oplock.c
===================================================================
--- trunk/source/smbd/oplock.c 2005-08-02 23:43:50 UTC (rev 8961)
+++ trunk/source/smbd/oplock.c 2005-08-02 23:52:43 UTC (rev 8962)
@@ -1018,6 +1018,18 @@
return True;
}
+static void oplock_timeout_handler(struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ files_struct *fsp = private_data;
+
+ DEBUG(0, ("Oplock break failed -- replying anyway\n"));
+ global_client_failed_oplock_break = True;
+ remove_oplock(fsp);
+ reply_to_oplock_break_requests(fsp);
+}
+
static void process_oplock_break_message(int msg_type, pid_t src,
void *buf, size_t len)
{
@@ -1115,6 +1127,20 @@
ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg,
&fsp->pending_break_messages,
&fsp->num_pending_break_messages);
+
+ if (fsp->oplock_timeout != NULL) {
+ DEBUG(0, ("Logic problem -- have an oplock event hanging "
+ "around\n"));
+ }
+
+ fsp->oplock_timeout =
+ add_timed_event(NULL,
+ timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
+ oplock_timeout_handler, fsp);
+
+ if (fsp->oplock_timeout == NULL) {
+ DEBUG(0, ("Could not add oplock timeout handler\n"));
+ }
}
static void process_kernel_oplock_break(int msg_type, pid_t src,
@@ -1187,6 +1213,10 @@
SAFE_FREE(fsp->pending_break_messages);
fsp->num_pending_break_messages = 0;
+ if (fsp->oplock_timeout != NULL) {
+ talloc_free(fsp->oplock_timeout);
+ fsp->oplock_timeout = NULL;
+ }
return;
}
Modified: trunk/source/smbd/process.c
===================================================================
--- trunk/source/smbd/process.c 2005-08-02 23:43:50 UTC (rev 8961)
+++ trunk/source/smbd/process.c 2005-08-02 23:52:43 UTC (rev 8962)
@@ -274,6 +274,7 @@
static int timed_event_destructor(void *p)
{
struct timed_event *te = talloc_get_type_abort(p, struct timed_event);
+ DEBUG(10, ("Destroying timed event\n"));
DLIST_REMOVE(timed_events, te);
return 0;
}
@@ -325,13 +326,15 @@
if (timed_events == NULL) {
/* No syscall if there are no events */
+ DEBUG(10, ("run_events: No events\n"));
return;
}
GetTimeOfDay(&now);
- if (timeval_compare(&timed_events->when, &now) < 0) {
+ if (timeval_compare(&now, &timed_events->when) < 0) {
/* Nothing to do yet */
+ DEBUG(10, ("run_events: Nothing to do\n"));
return;
}
@@ -339,26 +342,21 @@
return;
}
-static int timed_events_timeout(void)
+struct timeval timed_events_timeout(void)
{
struct timeval now, timeout;
if (timed_events == NULL) {
- return -1;
+ return timeval_set(SMBD_SELECT_TIMEOUT, 0);
}
now = timeval_current();
timeout = timeval_until(&now, &timed_events->when);
- /* We need that additional millisecond here. Select() under Linux
- * seems to return a bit early, and due to a second
- * setup_select_timeout in timeout_processing and
- * receive_message_or_smb interpreting a zero timeout as "wait
- * indefinitely" we could end up with processing the event *very*
- * late. This can probably change once we don't use milliseconds but
- * struct timevals everywhere. -- vl */
+ DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec,
+ (int)timeout.tv_usec));
- return (timeout.tv_sec * 1000) + ((timeout.tv_usec+999) / 1000) + 1;
+ return timeout;
}
struct idle_event {
@@ -481,17 +479,17 @@
{
fd_set fds;
int selrtn;
- struct timeval to;
- struct timeval *pto;
+ struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0);
int maxfd;
smb_read_error = 0;
again:
- to.tv_sec = timeout / 1000;
- to.tv_usec = (timeout % 1000) * 1000;
- pto = timeout > 0 ? &to : NULL;
+ if (timeout >= 0) {
+ to.tv_sec = timeout / 1000;
+ to.tv_usec = (timeout % 1000) * 1000;
+ }
/*
* Note that this call must be before processing any SMB
@@ -540,9 +538,8 @@
/* Make a more accurate select timeout. */
to.tv_sec = tdif / 1000000;
to.tv_usec = tdif % 1000000;
- pto = &to;
DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
- (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
+ (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
}
}
@@ -581,11 +578,19 @@
*/
goto again;
}
+
+ {
+ struct timeval tmp = timed_events_timeout();
+ to = timeval_min(&to, &tmp);
+ if (timeval_is_zero(&to)) {
+ return True;
+ }
+ }
FD_SET(smbd_server_fd(),&fds);
maxfd = setup_oplock_select_set(&fds);
- selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
+ selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to);
/* if we get EINTR then maybe we have received an oplock
signal - treat this as select returning 1. This is ugly, but
@@ -1431,16 +1436,13 @@
select_timeout *= 1000;
t = change_notify_timeout();
+ DEBUG(10, ("change_notify_timeout: %d\n", t));
if (t != -1)
select_timeout = MIN(select_timeout, t*1000);
if (print_notify_messages_pending())
select_timeout = MIN(select_timeout, 1000);
- t = timed_events_timeout();
- if (t != -1)
- select_timeout = MIN(select_timeout, t);
-
return select_timeout;
}
@@ -1792,7 +1794,7 @@
clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
#endif
- while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
+ while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,-1)) {
if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
More information about the samba-cvs
mailing list