summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/events.h11
-rw-r--r--source4/include/messages.h1
-rw-r--r--source4/ldap_server/ldap_server.c6
-rw-r--r--source4/lib/basic.mk3
-rw-r--r--source4/lib/events.c23
-rw-r--r--source4/lib/messaging/messaging.c51
-rw-r--r--source4/lib/time.c141
-rw-r--r--source4/lib/unix_privs.c69
-rw-r--r--source4/libcli/raw/clitransport.c16
-rw-r--r--source4/libcli/raw/libcliraw.h2
-rw-r--r--source4/librpc/rpc/dcerpc_sock.c2
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c5
-rw-r--r--source4/ntvfs/common/brlock.c7
-rw-r--r--source4/ntvfs/common/opendb.c122
-rw-r--r--source4/ntvfs/posix/pvfs_lock.c7
-rw-r--r--source4/ntvfs/posix/pvfs_open.c254
-rw-r--r--source4/ntvfs/posix/pvfs_wait.c12
-rw-r--r--source4/ntvfs/posix/vfs_posix.h2
-rw-r--r--source4/rpc_server/dcerpc_server.c13
-rw-r--r--source4/rpc_server/dcerpc_sock.c12
-rw-r--r--source4/smb_server/smb_server.c9
-rw-r--r--source4/smbd/process_model.h6
-rw-r--r--source4/smbd/process_single.c5
-rw-r--r--source4/smbd/process_standard.c2
-rw-r--r--source4/smbd/service.c18
-rw-r--r--source4/smbd/service.h8
-rw-r--r--source4/torture/basic/dir.c7
-rw-r--r--source4/torture/gentest.c2
-rw-r--r--source4/torture/local/messaging.c10
-rw-r--r--source4/torture/local/talloc.c29
-rw-r--r--source4/torture/nbench/nbench.c11
-rw-r--r--source4/torture/nbench/nbio.c7
-rw-r--r--source4/torture/raw/mux.c21
-rw-r--r--source4/torture/raw/open.c9
-rw-r--r--source4/torture/torture.c30
-rw-r--r--source4/torture/torture_util.c15
36 files changed, 726 insertions, 222 deletions
diff --git a/source4/include/events.h b/source4/include/events.h
index c44acc77ae..36fedc6e8b 100644
--- a/source4/include/events.h
+++ b/source4/include/events.h
@@ -28,7 +28,8 @@ struct event_context {
struct fd_event *next, *prev;
int fd;
uint16_t flags; /* see EVENT_FD_* flags */
- void (*handler)(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags);
+ void (*handler)(struct event_context *ev, struct fd_event *fde,
+ struct timeval t, uint16_t flags);
void *private;
int ref_count;
} *fd_events;
@@ -36,8 +37,9 @@ struct event_context {
/* list of timed events */
struct timed_event {
struct timed_event *next, *prev;
- time_t next_event;
- void (*handler)(struct event_context *ev, struct timed_event *te, time_t t);
+ struct timeval next_event;
+ void (*handler)(struct event_context *ev, struct timed_event *te,
+ struct timeval t);
void *private;
int ref_count;
} *timed_events;
@@ -45,7 +47,8 @@ struct event_context {
/* list of loop events - called on each select() */
struct loop_event {
struct loop_event *next, *prev;
- void (*handler)(struct event_context *ev, struct loop_event *le, time_t t);
+ void (*handler)(struct event_context *ev, struct loop_event *le,
+ struct timeval t);
void *private;
int ref_count;
} *loop_events;
diff --git a/source4/include/messages.h b/source4/include/messages.h
index 96c1e81a31..48376efa03 100644
--- a/source4/include/messages.h
+++ b/source4/include/messages.h
@@ -29,5 +29,6 @@ struct messaging_context;
#define MSG_PING 2
#define MSG_PONG 3
#define MSG_BRL_RETRY 4
+#define MSG_PVFS_RETRY_OPEN 5
#endif
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 3b4ccb6b73..9338baa165 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -440,7 +440,7 @@ NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn)
/*
called when a LDAP socket becomes readable
*/
-static void ldapsrv_recv(struct server_connection *conn, time_t t,
+static void ldapsrv_recv(struct server_connection *conn, struct timeval t,
uint16_t flags)
{
struct ldapsrv_connection *ldap_conn = conn->private_data;
@@ -536,7 +536,7 @@ static void ldapsrv_recv(struct server_connection *conn, time_t t,
/*
called when a LDAP socket becomes writable
*/
-static void ldapsrv_send(struct server_connection *conn, time_t t,
+static void ldapsrv_send(struct server_connection *conn, struct timeval t,
uint16_t flags)
{
struct ldapsrv_connection *ldap_conn = conn->private_data;
@@ -558,7 +558,7 @@ static void ldapsrv_send(struct server_connection *conn, time_t t,
/*
called when connection is idle
*/
-static void ldapsrv_idle(struct server_connection *conn, time_t t)
+static void ldapsrv_idle(struct server_connection *conn, struct timeval t)
{
DEBUG(10,("ldapsrv_idle: not implemented!\n"));
return;
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk
index e7d710eec6..827aa0a57c 100644
--- a/source4/lib/basic.mk
+++ b/source4/lib/basic.mk
@@ -72,7 +72,8 @@ ADD_OBJ_FILES = \
lib/events.o \
lib/db_wrap.o \
lib/server_mutex.o \
- lib/idtree.o
+ lib/idtree.o \
+ lib/unix_privs.o
REQUIRED_SUBSYSTEMS = \
LIBTDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO
# End SUBSYSTEM LIBBASIC
diff --git a/source4/lib/events.c b/source4/lib/events.c
index f53a244c6d..0ca6b66598 100644
--- a/source4/lib/events.c
+++ b/source4/lib/events.c
@@ -285,15 +285,14 @@ void event_loop_exit(struct event_context *ev, int code)
*/
int event_loop_once(struct event_context *ev)
{
- time_t t;
fd_set r_fds, w_fds;
struct fd_event *fe;
struct loop_event *le;
struct timed_event *te;
int selrtn;
- struct timeval tval;
+ struct timeval tval, t;
- t = time(NULL);
+ t = timeval_current();
/* the loop events are called on each loop. Be careful to allow the
event to remove itself */
@@ -310,7 +309,6 @@ int event_loop_once(struct event_context *ev)
le = next;
}
- ZERO_STRUCT(tval);
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
@@ -336,17 +334,12 @@ int event_loop_once(struct event_context *ev)
/* start with a reasonable max timeout */
tval.tv_sec = 600;
+ tval.tv_usec = 0;
/* work out the right timeout for all timed events */
for (te=ev->timed_events;te;te=te->next) {
- int timeout = te->next_event - t;
- if (timeout < 0) {
- timeout = 0;
- }
- if (te->ref_count &&
- timeout < tval.tv_sec) {
- tval.tv_sec = timeout;
- }
+ struct timeval tv = timeval_diff(&te->next_event, &t);
+ tval = timeval_min(&tv, &tval);
}
/* only do a select() if there're fd_events
@@ -368,7 +361,7 @@ int event_loop_once(struct event_context *ev)
*/
selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval);
- t = time(NULL);
+ t = timeval_current();
if (selrtn == -1 && errno == EBADF) {
/* the socket is dead! this should never
@@ -404,11 +397,11 @@ int event_loop_once(struct event_context *ev)
if (te->ref_count == 0) {
DLIST_REMOVE(ev->timed_events, te);
talloc_free(te);
- } else if (te->next_event <= t) {
+ } else if (timeval_compare(&te->next_event, &t) >= 0) {
te->ref_count++;
te->handler(ev, te, t);
te->ref_count--;
- if (te->next_event <= t) {
+ if (timeval_compare(&te->next_event, &t) >= 0) {
/* the handler didn't set a time for the
next event - remove the event */
event_remove_timed(ev, te);
diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index f862b2d505..041554a7c0 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -29,6 +29,9 @@
/* change the message version with any incompatible changes in the protocol */
#define MESSAGING_VERSION 1
+/* the number of microseconds to backoff in retrying to send a message */
+#define MESSAGING_BACKOFF 250000
+
struct messaging_context {
servid_t server_id;
struct socket_context *sock;
@@ -119,7 +122,7 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r
handle IO for a single message
*/
static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
struct messaging_rec *rec = fde->private;
struct messaging_context *msg = rec->msg;
@@ -200,7 +203,7 @@ static int rec_destructor(void *ptr)
handle a new incoming connection
*/
static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
struct messaging_context *msg = fde->private;
struct messaging_rec *rec;
@@ -272,7 +275,7 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void
handle IO for sending a message
*/
static void messaging_send_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
struct messaging_rec *rec = fde->private;
NTSTATUS status;
@@ -324,19 +327,33 @@ static void messaging_send_handler(struct event_context *ev, struct fd_event *fd
/*
+ wrapper around socket_connect with raised privileges
+*/
+static NTSTATUS try_connect(struct messaging_rec *rec)
+{
+ NTSTATUS status;
+ void *priv = root_privileges();
+ status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0);
+ talloc_free(priv);
+ return status;
+}
+
+
+/*
when the servers listen queue is full we use this to backoff the message
*/
-static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, time_t t)
+static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te,
+ struct timeval t)
{
struct messaging_rec *rec = te->private;
struct messaging_context *msg = rec->msg;
NTSTATUS status;
struct fd_event fde;
- status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0);
+ status = try_connect(rec);
if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
/* backoff again */
- te->next_event = t+1;
+ te->next_event = timeval_add(&t, 0, MESSAGING_BACKOFF);
return;
}
@@ -356,7 +373,7 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve
talloc_set_destructor(rec, rec_destructor);
- messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE);
+ messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
}
@@ -396,11 +413,11 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t
rec->path = messaging_path(rec, server);
- status = socket_connect(rec->sock, NULL, 0, rec->path, 0, 0);
+ status = try_connect(rec);
if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
/* backoff on this message - the servers listen queue is full */
struct timed_event te;
- te.next_event = time(NULL)+1;
+ te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF);
te.handler = messaging_backoff_handler;
te.private = rec;
event_add_timed(msg->event.ev, &te);
@@ -421,11 +438,25 @@ NTSTATUS messaging_send(struct messaging_context *msg, servid_t server, uint32_t
talloc_set_destructor(rec, rec_destructor);
- messaging_send_handler(msg->event.ev, rec->fde, 0, EVENT_FD_WRITE);
+ messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
return NT_STATUS_OK;
}
+/*
+ Send a message to a particular server, with the message containing a single pointer
+*/
+NTSTATUS messaging_send_ptr(struct messaging_context *msg, servid_t server,
+ uint32_t msg_type, void *ptr)
+{
+ DATA_BLOB blob;
+
+ blob.data = (void *)&ptr;
+ blob.length = sizeof(void *);
+
+ return messaging_send(msg, server, msg_type, &blob);
+}
+
/*
destroy the messaging context
diff --git a/source4/lib/time.c b/source4/lib/time.c
index cfceebf9cb..9e6da2cfa6 100644
--- a/source4/lib/time.c
+++ b/source4/lib/time.c
@@ -386,9 +386,144 @@ NTTIME nttime_from_string(const char *s)
return strtoull(s, NULL, 0);
}
-int64_t usec_time_diff(struct timeval *larget, struct timeval *smallt)
+/*
+ return (tv1 - tv2) in microseconds
+*/
+int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2)
+{
+ int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
+ return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
+}
+
+
+/*
+ return a zero timeval
+*/
+struct timeval timeval_zero(void)
{
- int64_t sec_diff = larget->tv_sec - smallt->tv_sec;
- return (sec_diff * 1000000) + (int64_t)(larget->tv_usec - smallt->tv_usec);
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ return tv;
}
+/*
+ return a timeval for the current time
+*/
+struct timeval timeval_current(void)
+{
+ struct timeval tv;
+ GetTimeOfDay(&tv);
+ return tv;
+}
+
+/*
+ return a timeval struct with the given elements
+*/
+struct timeval timeval_set(uint32_t secs, uint32_t usecs)
+{
+ struct timeval tv;
+ tv.tv_sec = secs;
+ tv.tv_usec = usecs;
+ return tv;
+}
+
+
+/*
+ return a timeval ofs microseconds after tv
+*/
+struct timeval timeval_add(struct timeval *tv, uint32_t secs, uint32_t usecs)
+{
+ struct timeval tv2 = *tv;
+ const uint_t million = 1000000;
+ tv2.tv_sec += secs;
+ tv2.tv_usec += usecs;
+ tv2.tv_sec += tv2.tv_usec / million;
+ tv2.tv_usec = tv2.tv_usec % million;
+ return tv2;
+}
+
+/*
+ return the sum of two timeval structures
+*/
+struct timeval timeval_sum(struct timeval *tv1, struct timeval *tv2)
+{
+ return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
+}
+
+/*
+ return a timeval secs/usecs into the future
+*/
+struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
+{
+ struct timeval tv = timeval_current();
+ return timeval_add(&tv, secs, usecs);
+}
+
+/*
+ compare two timeval structures.
+ Return 1 if tv2 > tv1
+ Return 0 if tv2 == tv1
+ Return -1 if tv2 < tv1
+*/
+int timeval_compare(struct timeval *tv1, struct timeval *tv2)
+{
+ if (tv2->tv_sec > tv1->tv_sec) return 1;
+ if (tv2->tv_sec < tv1->tv_sec) return -1;
+ if (tv2->tv_usec > tv1->tv_usec) return 1;
+ if (tv2->tv_usec < tv1->tv_usec) return -1;
+ return 0;
+}
+
+/*
+ return True if a timer is in the past
+*/
+BOOL timeval_expired(struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ if (tv2.tv_sec > tv->tv_sec) return True;
+ if (tv2.tv_sec < tv->tv_sec) return False;
+ return (tv2.tv_usec >= tv->tv_usec);
+}
+
+/*
+ return the number of seconds elapsed since a given time
+*/
+double timeval_elapsed(struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ return (tv2.tv_sec - tv->tv_sec) +
+ (tv2.tv_usec - tv->tv_usec)*1.0e-6;
+}
+
+/*
+ return the lesser of two timevals
+*/
+struct timeval timeval_min(struct timeval *tv1, struct timeval *tv2)
+{
+ if (tv1->tv_sec < tv2->tv_sec) return *tv1;
+ if (tv1->tv_sec > tv2->tv_sec) return *tv2;
+ if (tv1->tv_usec < tv2->tv_usec) return *tv1;
+ return *tv2;
+}
+
+/*
+ return the difference between two timevals as a timeval
+ if tv2 comes after tv1, then return a zero timeval
+ (this is *tv1 - *tv2)
+*/
+struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2)
+{
+ struct timeval t;
+ if (timeval_compare(tv1, tv2) >= 0) {
+ return timeval_zero();
+ }
+ t.tv_sec = tv1->tv_sec - tv2->tv_sec;
+ if (tv2->tv_usec > tv1->tv_usec) {
+ t.tv_sec--;
+ t.tv_usec = 1000000 - (tv2->tv_usec - tv1->tv_usec);
+ } else {
+ t.tv_usec = tv1->tv_usec - tv2->tv_usec;
+ }
+ return t;
+}
diff --git a/source4/lib/unix_privs.c b/source4/lib/unix_privs.c
new file mode 100644
index 0000000000..c65f490aeb
--- /dev/null
+++ b/source4/lib/unix_privs.c
@@ -0,0 +1,69 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ gain/lose root privileges
+
+ Copyright (C) Andrew Tridgell 2004
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/passwd.h"
+
+/*
+ there are times when smbd needs to temporarily gain root privileges
+ to do some operation. To do this you call root_privileges(), which
+ returns a talloc handle. To restore your previous privileges
+ talloc_free() this pointer.
+
+ Note that this call is considered successful even if it does not
+ manage to gain too privileges, but it will call smb_abort() if it
+ fails to restore the privileges afterwards. The logic is that
+ failing to gain root access can be caught by whatever operation
+ needs to be run as root failing, but failing to lose the root
+ privileges is dangerous.
+
+ This also means that this code is safe to be called from completely
+ unprivileged processes.
+*/
+
+struct saved_state {
+ uid_t uid;
+};
+
+static int privileges_destructor(void *ptr)
+{
+ struct saved_state *s = ptr;
+ if (geteuid() != s->uid &&
+ seteuid(s->uid) != 0) {
+ smb_panic("Failed to restore privileges");
+ }
+ return 0;
+}
+
+void *root_privileges(void)
+{
+ struct saved_state *s;
+ s = talloc_p(NULL, struct saved_state);
+ if (!s) return NULL;
+ s->uid = geteuid();
+ if (s->uid != 0) {
+ seteuid(0);
+ }
+ talloc_set_destructor(s, privileges_destructor);
+ return s;
+}
+
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index 00e52f3a14..52cb4d8beb 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -33,7 +33,7 @@ static void smbcli_transport_process_send(struct smbcli_transport *transport);
an event has happened on the socket
*/
static void smbcli_transport_event_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
struct smbcli_transport *transport = fde->private;
@@ -233,21 +233,21 @@ again:
}
static void idle_handler(struct event_context *ev,
- struct timed_event *te, time_t t)
+ struct timed_event *te, struct timeval t)
{
struct smbcli_transport *transport = te->private;
- te->next_event = t + transport->idle.period;
+ te->next_event = timeval_add(&te->next_event, 0, transport->idle.period);
transport->idle.func(transport, transport->idle.private);
}
/*
setup the idle handler for a transport
- the period is in seconds
+ the period is in microseconds
*/
void smbcli_transport_idle_handler(struct smbcli_transport *transport,
- void (*idle_func)(struct smbcli_transport *, void *),
- uint_t period,
- void *private)
+ void (*idle_func)(struct smbcli_transport *, void *),
+ uint64_t period,
+ void *private)
{
struct timed_event te;
transport->idle.func = idle_func;
@@ -258,7 +258,7 @@ void smbcli_transport_idle_handler(struct smbcli_transport *transport,
event_remove_timed(transport->event.ctx, transport->event.te);
}
- te.next_event = time(NULL) + period;
+ te.next_event = timeval_current_ofs(0, period);
te.handler = idle_handler;
te.private = transport;
transport->event.te = event_add_timed(transport->event.ctx, &te);
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index 9b03ab713b..b00af846b7 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -114,7 +114,7 @@ struct smbcli_transport {
uint_t readbraw_pending:1;
/* an idle function - if this is defined then it will be
- called once every period seconds while we are waiting
+ called once every period microseconds while we are waiting
for a packet */
struct {
void (*func)(struct smbcli_transport *, void *);
diff --git a/source4/librpc/rpc/dcerpc_sock.c b/source4/librpc/rpc/dcerpc_sock.c
index 41fde60ea0..26464884bc 100644
--- a/source4/librpc/rpc/dcerpc_sock.c
+++ b/source4/librpc/rpc/dcerpc_sock.c
@@ -190,7 +190,7 @@ static void sock_process_recv(struct dcerpc_pipe *p)
called when a IO is triggered by the events system
*/
static void sock_io_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
struct dcerpc_pipe *p = fde->private;
struct sock_private *sock = p->transport.private;
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c
index 4fd5650f9b..3e9899cb8c 100644
--- a/source4/ntvfs/cifs/vfs_cifs.c
+++ b/source4/ntvfs/cifs/vfs_cifs.c
@@ -78,7 +78,8 @@ static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin
/*
a handler for read events on a connection to a backend server
*/
-static void cifs_socket_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
+static void cifs_socket_handler(struct event_context *ev, struct fd_event *fde,
+ struct timeval t, uint16_t flags)
{
struct cvfs_private *private = fde->private;
struct smbsrv_tcon *tcon = private->tcon;
@@ -149,7 +150,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
/* we need to receive oplock break requests from the server */
smbcli_oplock_handler(private->transport, oplock_handler, private);
- smbcli_transport_idle_handler(private->transport, idle_func, 1, private);
+ smbcli_transport_idle_handler(private->transport, idle_func, 50000, private);
private->transport->event.fde->handler = cifs_socket_handler;
private->transport->event.fde->private = private;
diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c
index d1df0413ce..6fae7c6e4c 100644
--- a/source4/ntvfs/common/brlock.c
+++ b/source4/ntvfs/common/brlock.c
@@ -333,17 +333,14 @@ static void brl_notify_unlock(struct brl_context *brl,
for (i=0;i<count;i++) {
if (locks[i].lock_type >= PENDING_READ_LOCK &&
brl_overlap(&locks[i], removed_lock)) {
- DATA_BLOB data;
-
if (last_notice != -1 && brl_overlap(&locks[i], &locks[last_notice])) {
continue;
}
if (locks[i].lock_type == PENDING_WRITE_LOCK) {
last_notice = i;
}
- data.data = (void *)&locks[i].notify_ptr;
- data.length = sizeof(void *);
- messaging_send(brl->messaging_ctx, locks[i].context.server, MSG_BRL_RETRY, &data);
+ messaging_send_ptr(brl->messaging_ctx, locks[i].context.server,
+ MSG_BRL_RETRY, locks[i].notify_ptr);
}
}
}
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index 5dc68e5382..39d4f37ec2 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -39,6 +39,7 @@
*/
#include "includes.h"
+#include "messages.h"
struct odb_context {
struct tdb_wrap *w;
@@ -58,6 +59,8 @@ struct odb_entry {
uint32_t share_access;
uint32_t create_options;
uint32_t access_mask;
+ void *notify_ptr;
+ BOOL pending;
};
@@ -152,6 +155,8 @@ static BOOL share_conflict(struct odb_entry *e1, struct odb_entry *e2)
{
#define CHECK_MASK(am, sa, right, share) if (((am) & (right)) && !((sa) & (share))) return True
+ if (e1->pending || e2->pending) return False;
+
/* if either open involves no read.write or delete access then
it can't conflict */
if (!(e1->access_mask & (SA_RIGHT_FILE_WRITE_APPEND |
@@ -219,6 +224,8 @@ NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
+ e.notify_ptr = NULL;
+ e.pending = False;
/* check the existing file opens to see if they
conflict */
@@ -255,6 +262,56 @@ NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum,
/*
+ register a pending open file in the open files database
+*/
+NTSTATUS odb_open_file_pending(struct odb_lock *lck, void *private)
+{
+ struct odb_context *odb = lck->odb;
+ TDB_DATA dbuf;
+ struct odb_entry e;
+ char *tp;
+ struct odb_entry *elist;
+ int count;
+
+ dbuf = tdb_fetch(odb->w->tdb, lck->key);
+
+ e.server = odb->server;
+ e.tid = odb->tid;
+ e.fnum = 0;
+ e.share_access = 0;
+ e.create_options = 0;
+ e.access_mask = 0;
+ e.notify_ptr = private;
+ e.pending = True;
+
+ /* check the existing file opens to see if they
+ conflict */
+ elist = (struct odb_entry *)dbuf.dptr;
+ count = dbuf.dsize / sizeof(struct odb_entry);
+
+ tp = Realloc(dbuf.dptr, (count+1) * sizeof(struct odb_entry));
+ if (tp == NULL) {
+ if (dbuf.dptr) free(dbuf.dptr);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dbuf.dptr = tp;
+ dbuf.dsize = (count+1) * sizeof(struct odb_entry);
+
+ memcpy(dbuf.dptr + (count*sizeof(struct odb_entry)),
+ &e, sizeof(struct odb_entry));
+
+ if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) {
+ free(dbuf.dptr);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ free(dbuf.dptr);
+ return NT_STATUS_OK;
+}
+
+
+/*
remove a opendb entry
*/
NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
@@ -274,6 +331,15 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
elist = (struct odb_entry *)dbuf.dptr;
count = dbuf.dsize / sizeof(struct odb_entry);
+ /* send any pending notifications */
+ for (i=0;i<count;i++) {
+ if (elist[i].pending) {
+ messaging_send_ptr(odb->messaging_ctx, elist[i].server,
+ MSG_PVFS_RETRY_OPEN, elist[i].notify_ptr);
+
+ }
+ }
+
/* find the entry, and delete it */
for (i=0;i<count;i++) {
if (fnum == elist[i].fnum &&
@@ -309,6 +375,60 @@ NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum)
/*
+ remove a pending opendb entry
+*/
+NTSTATUS odb_remove_pending(struct odb_lock *lck, void *private)
+{
+ struct odb_context *odb = lck->odb;
+ TDB_DATA dbuf;
+ struct odb_entry *elist;
+ int i, count;
+ NTSTATUS status;
+
+ dbuf = tdb_fetch(odb->w->tdb, lck->key);
+
+ if (dbuf.dptr == NULL) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ elist = (struct odb_entry *)dbuf.dptr;
+ count = dbuf.dsize / sizeof(struct odb_entry);
+
+ /* find the entry, and delete it */
+ for (i=0;i<count;i++) {
+ if (private == elist[i].notify_ptr &&
+ odb->server == elist[i].server &&
+ odb->tid == elist[i].tid) {
+ if (i < count-1) {
+ memmove(elist+i, elist+i+1,
+ (count - (i+1)) * sizeof(struct odb_entry));
+ }
+ break;
+ }
+ }
+
+ status = NT_STATUS_OK;
+
+ if (i == count) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ } else if (count == 1) {
+ if (tdb_delete(odb->w->tdb, lck->key) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ } else {
+ dbuf.dsize = (count-1) * sizeof(struct odb_entry);
+ if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) {
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
+ free(dbuf.dptr);
+
+ return status;
+}
+
+
+/*
update create options on an open file
*/
NTSTATUS odb_set_create_options(struct odb_lock *lck,
@@ -386,6 +506,8 @@ NTSTATUS odb_can_open(struct odb_context *odb, DATA_BLOB *key,
e.share_access = share_access;
e.create_options = create_options;
e.access_mask = access_mask;
+ e.notify_ptr = NULL;
+ e.pending = False;
for (i=0;i<count;i++) {
if (share_conflict(elist+i, &e)) {
diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c
index 2668eec004..82ac9ebad5 100644
--- a/source4/ntvfs/posix/pvfs_lock.c
+++ b/source4/ntvfs/posix/pvfs_lock.c
@@ -56,7 +56,7 @@ struct pvfs_pending_lock {
struct smbsrv_request *req;
int pending_lock;
void *wait_handle;
- time_t end_time;
+ struct timeval end_time;
};
/*
@@ -301,8 +301,9 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
pending->f = f;
pending->req = req;
- /* round up to the nearest second */
- pending->end_time = time(NULL) + ((lck->lockx.in.timeout+999)/1000);
+ pending->end_time =
+ timeval_current_ofs(lck->lockx.in.timeout/1000,
+ 1000*(lck->lockx.in.timeout%1000));
}
if (lck->lockx.in.mode & LOCKING_ANDX_SHARED_LOCK) {
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index f3ef72f4ed..8ad6ad0389 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -25,6 +25,7 @@
#include "system/time.h"
#include "system/filesys.h"
#include "dlinklist.h"
+#include "messages.h"
/*
create file handles with convenient numbers for sniffers
@@ -33,6 +34,8 @@
#define PVFS_MIN_NEW_FNUM 0x200
#define PVFS_MIN_DIR_FNUM 0x300
+#define SHARING_VIOLATION_DELAY 1000000
+
/*
find open file handle given fnum
*/
@@ -125,7 +128,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX);
if (fnum == -1) {
- talloc_free(f);
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
@@ -228,10 +230,12 @@ static int pvfs_fd_destructor(void *p)
return 0;
}
- status = odb_close_file(lck, f->fnum);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
- f->name->full_name, nt_errstr(status)));
+ if (f->have_opendb_entry) {
+ status = odb_close_file(lck, f->fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
+ f->name->full_name, nt_errstr(status)));
+ }
}
talloc_free(lck);
@@ -370,6 +374,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
f->access_mask = access_mask;
f->seek_offset = 0;
f->position = 0;
+ f->have_opendb_entry = True;
DLIST_ADD(pvfs->open_files, f);
@@ -399,13 +404,173 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
/*
+ open am existing file - called from both the open retry code
+ and the main open code
+*/
+NTSTATUS pvfs_open_existing(struct pvfs_file *f,
+ union smb_open *io,
+ int open_flags)
+{
+ int fd;
+ NTSTATUS status;
+
+ /* do the actual open */
+ fd = open(f->name->full_name, open_flags);
+ if (fd == -1) {
+ return pvfs_map_errno(f->pvfs, errno);
+ }
+
+ f->fd = fd;
+
+ /* re-resolve the open fd */
+ status = pvfs_resolve_name_fd(f->pvfs, fd, f->name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ io->generic.out.oplock_level = NO_OPLOCK;
+ io->generic.out.fnum = f->fnum;
+ io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
+ io->generic.out.create_time = f->name->dos.create_time;
+ io->generic.out.access_time = f->name->dos.access_time;
+ io->generic.out.write_time = f->name->dos.write_time;
+ io->generic.out.change_time = f->name->dos.change_time;
+ io->generic.out.attrib = f->name->dos.attrib;
+ io->generic.out.alloc_size = f->name->dos.alloc_size;
+ io->generic.out.size = f->name->st.st_size;
+ io->generic.out.file_type = FILE_TYPE_DISK;
+ io->generic.out.ipc_state = 0;
+ io->generic.out.is_directory = 0;
+
+ /* success - keep the file handle */
+ talloc_steal(f->pvfs, f);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ state of a pending open retry
+*/
+struct pvfs_open_retry {
+ union smb_open *io;
+ struct pvfs_file *f;
+ struct smbsrv_request *req;
+ void *wait_handle;
+ struct timeval end_time;
+ int open_flags;
+};
+
+/* destroy a pending open request */
+static int pvfs_retry_destructor(void *ptr)
+{
+ struct pvfs_open_retry *r = ptr;
+ struct odb_lock *lck;
+ lck = odb_lock(r->req, r->f->pvfs->odb_context, &r->f->locking_key);
+ if (lck != NULL) {
+ odb_remove_pending(lck, r);
+ }
+ return 0;
+}
+
+/*
+ retry an open
+*/
+static void pvfs_open_retry(void *private, BOOL timed_out)
+{
+ struct pvfs_open_retry *r = private;
+ struct odb_lock *lck;
+ struct pvfs_file *f = r->f;
+ struct smbsrv_request *req = r->req;
+ NTSTATUS status;
+
+ lck = odb_lock(req, f->pvfs->odb_context, &f->locking_key);
+ if (lck == NULL) {
+ req->async_states->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ req->async_states->send_fn(req);
+ return;
+ }
+
+ /* see if we are allowed to open at the same time as existing opens */
+ status = odb_open_file(lck, f->fnum, f->share_access,
+ f->create_options, f->access_mask);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && !timed_out) {
+ talloc_free(lck);
+ return;
+ }
+
+ talloc_free(r->wait_handle);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ req->async_states->status = status;
+ req->async_states->send_fn(req);
+ return;
+ }
+
+ f->have_opendb_entry = True;
+
+ /* do the rest of the open work */
+ status = pvfs_open_existing(f, r->io, r->open_flags);
+
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(f->pvfs, f);
+ }
+
+ req->async_states->status = status;
+ req->async_states->send_fn(req);
+}
+
+/*
+ setup for a open retry after a sharing violation
+*/
+static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req,
+ union smb_open *io,
+ struct pvfs_file *f,
+ struct odb_lock *lck,
+ int open_flags)
+{
+ struct pvfs_open_retry *r;
+ struct pvfs_state *pvfs = f->pvfs;
+ NTSTATUS status;
+
+ r = talloc_p(req, struct pvfs_open_retry);
+ if (r == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ r->io = io;
+ r->f = f;
+ r->req = req;
+ r->end_time = timeval_current_ofs(0, SHARING_VIOLATION_DELAY);
+ r->open_flags = open_flags;
+
+ /* setup a pending lock */
+ status = odb_open_file_pending(lck, r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, r->end_time,
+ pvfs_open_retry, r);
+ if (r->wait_handle == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ talloc_free(lck);
+ talloc_steal(pvfs, req);
+
+ talloc_set_destructor(r, pvfs_retry_destructor);
+
+ return NT_STATUS_OK;
+}
+
+/*
open a file
*/
NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
struct smbsrv_request *req, union smb_open *io)
{
struct pvfs_state *pvfs = ntvfs->private_data;
- int fd, flags;
+ int flags;
struct pvfs_filename *name;
struct pvfs_file *f;
NTSTATUS status;
@@ -539,11 +704,26 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
+ f->fnum = fnum;
+ f->fd = -1;
+ f->name = talloc_steal(f, name);
+ f->session = req->session;
+ f->smbpid = req->smbpid;
+ f->pvfs = pvfs;
+ f->pending_list = NULL;
+ f->lock_count = 0;
+ f->create_options = io->generic.in.create_options;
+ f->share_access = io->generic.in.share_access;
+ f->access_mask = access_mask;
+ f->seek_offset = 0;
+ f->position = 0;
+ f->have_opendb_entry = False;
+
/* form the lock context used for byte range locking and
opendb locking */
status = pvfs_locking_key(name, f, &f->locking_key);
if (!NT_STATUS_IS_OK(status)) {
- idr_remove(pvfs->idtree_fnum, fnum);
+ idr_remove(pvfs->idtree_fnum, f->fnum);
return status;
}
@@ -558,65 +738,31 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- /* see if we are allowed to open at the same time as existing opens */
- status = odb_open_file(lck, fnum, share_access, create_options, access_mask);
- if (!NT_STATUS_IS_OK(status)) {
- idr_remove(pvfs->idtree_fnum, fnum);
- return status;
- }
-
- f->fnum = fnum;
- f->fd = -1;
- f->name = talloc_steal(f, name);
- f->session = req->session;
- f->smbpid = req->smbpid;
- f->pvfs = pvfs;
- f->pending_list = NULL;
- f->lock_count = 0;
- f->create_options = io->generic.in.create_options;
- f->share_access = io->generic.in.share_access;
- f->access_mask = access_mask;
- f->seek_offset = 0;
- f->position = 0;
-
DLIST_ADD(pvfs->open_files, f);
/* setup a destructor to avoid file descriptor leaks on
abnormal termination */
talloc_set_destructor(f, pvfs_fd_destructor);
- /* do the actual open */
- fd = open(name->full_name, flags);
- if (fd == -1) {
- return pvfs_map_errno(pvfs, errno);
- }
- f->fd = fd;
+ /* see if we are allowed to open at the same time as existing opens */
+ status = odb_open_file(lck, f->fnum, share_access, create_options, access_mask);
+
+ /* on a sharing violation we need to retry when the file is closed by
+ the other user, or after 1 second */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) &&
+ (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
+ return pvfs_open_setup_retry(req, io, f, lck, flags);
+ }
- /* re-resolve the open fd */
- status = pvfs_resolve_name_fd(pvfs, fd, name);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- io->generic.out.oplock_level = NO_OPLOCK;
- io->generic.out.fnum = f->fnum;
- io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
- io->generic.out.create_time = name->dos.create_time;
- io->generic.out.access_time = name->dos.access_time;
- io->generic.out.write_time = name->dos.write_time;
- io->generic.out.change_time = name->dos.change_time;
- io->generic.out.attrib = name->dos.attrib;
- io->generic.out.alloc_size = name->dos.alloc_size;
- io->generic.out.size = name->st.st_size;
- io->generic.out.file_type = FILE_TYPE_DISK;
- io->generic.out.ipc_state = 0;
- io->generic.out.is_directory = 0;
-
- /* success - keep the file handle */
- talloc_steal(pvfs, f);
+ f->have_opendb_entry = True;
- return NT_STATUS_OK;
+ /* do the rest of the open work */
+ return pvfs_open_existing(f, io, flags);
}
@@ -677,7 +823,6 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
for (f=pvfs->open_files;f;f=next) {
next = f->next;
if (f->session == req->session) {
- DLIST_REMOVE(pvfs->open_files, f);
talloc_free(f);
}
}
@@ -698,7 +843,6 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
for (f=pvfs->open_files;f;f=next) {
next = f->next;
if (f->smbpid == req->smbpid) {
- DLIST_REMOVE(pvfs->open_files, f);
talloc_free(f);
}
}
diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c
index f01bd0ea18..0faab8ef55 100644
--- a/source4/ntvfs/posix/pvfs_wait.c
+++ b/source4/ntvfs/posix/pvfs_wait.c
@@ -58,10 +58,9 @@ static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uin
struct pvfs_wait *pwait = private;
struct smbsrv_request *req;
- /* we need to check that this one is for us. This sender sends
- the private pointer as the body of the message. This might
- seem a little unusual, but as the pointer is guaranteed
- unique for this server, it is a good token */
+ /* we need to check that this one is for us. See
+ messaging_send_ptr() for the other side of this.
+ */
if (data->length != sizeof(void *) ||
*(void **)data->data != pwait->private) {
return;
@@ -82,7 +81,8 @@ static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uin
/*
receive a timeout on a message wait
*/
-static void pvfs_wait_timeout(struct event_context *ev, struct timed_event *te, time_t t)
+static void pvfs_wait_timeout(struct event_context *ev,
+ struct timed_event *te, struct timeval t)
{
struct pvfs_wait *pwait = te->private;
struct smbsrv_request *req = pwait->req;
@@ -116,7 +116,7 @@ static int pvfs_wait_destructor(void *ptr)
void *pvfs_wait_message(struct pvfs_state *pvfs,
struct smbsrv_request *req,
int msg_type,
- time_t end_time,
+ struct timeval end_time,
void (*fn)(void *, BOOL),
void *private)
{
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 530a2deae3..265649f5a3 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -112,6 +112,8 @@ struct pvfs_file {
/* yes, we need 2 independent positions ... */
uint64_t seek_offset;
uint64_t position;
+
+ BOOL have_opendb_entry;
};
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index f9e2d8d28e..3aeb7033d1 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1057,21 +1057,18 @@ static void dcesrv_accept(struct server_connection *srv_conn)
dcesrv_sock_accept(srv_conn);
}
-static void dcesrv_recv(struct server_connection *srv_conn, time_t t, uint16_t flags)
+static void dcesrv_recv(struct server_connection *srv_conn,
+ struct timeval t, uint16_t flags)
{
dcesrv_sock_recv(srv_conn, t, flags);
}
-static void dcesrv_send(struct server_connection *srv_conn, time_t t, uint16_t flags)
+static void dcesrv_send(struct server_connection *srv_conn,
+ struct timeval t, uint16_t flags)
{
dcesrv_sock_send(srv_conn, t, flags);
}
-static void dcesrv_idle(struct server_connection *srv_conn, time_t t)
-{
- dcesrv_sock_idle(srv_conn, t);
-}
-
static void dcesrv_close(struct server_connection *srv_conn, const char *reason)
{
dcesrv_sock_close(srv_conn, reason);
@@ -1190,7 +1187,7 @@ static const struct server_service_ops dcesrv_ops = {
.accept_connection = dcesrv_accept,
.recv_handler = dcesrv_recv,
.send_handler = dcesrv_send,
- .idle_handler = dcesrv_idle,
+ .idle_handler = NULL,
.close_connection = dcesrv_close,
.service_exit = dcesrv_exit,
};
diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c
index 544082471e..f8d0bbfc6d 100644
--- a/source4/rpc_server/dcerpc_sock.c
+++ b/source4/rpc_server/dcerpc_sock.c
@@ -248,7 +248,7 @@ void dcesrv_sock_accept(struct server_connection *conn)
return;
}
-void dcesrv_sock_recv(struct server_connection *conn, time_t t, uint16_t flags)
+void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
{
NTSTATUS status;
struct dcesrv_connection *dce_conn = conn->private_data;
@@ -288,7 +288,7 @@ void dcesrv_sock_recv(struct server_connection *conn, time_t t, uint16_t flags)
return;
}
-void dcesrv_sock_send(struct server_connection *conn, time_t t, uint16_t flags)
+void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t flags)
{
struct dcesrv_connection *dce_conn = conn->private_data;
NTSTATUS status;
@@ -308,14 +308,6 @@ void dcesrv_sock_send(struct server_connection *conn, time_t t, uint16_t flags)
return;
}
-void dcesrv_sock_idle(struct server_connection *conn, time_t t)
-{
- DEBUG(10,("dcesrv_sock_idle\n"));
- conn->event.idle->next_event = t + 5;
-
- return;
-}
-
void dcesrv_sock_close(struct server_connection *conn, const char *reason)
{
struct dcesrv_connection *dce_conn = conn->private_data;
diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c
index e1eb4e3179..861186a8d7 100644
--- a/source4/smb_server/smb_server.c
+++ b/source4/smb_server/smb_server.c
@@ -723,7 +723,7 @@ static void smbsrv_init(struct server_service *service, const struct model_ops *
/*
called when a SMB socket becomes readable
*/
-static void smbsrv_recv(struct server_connection *conn, time_t t, uint16_t flags)
+static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
{
struct smbsrv_connection *smb_conn = conn->private_data;
NTSTATUS status;
@@ -744,7 +744,7 @@ static void smbsrv_recv(struct server_connection *conn, time_t t, uint16_t flags
/*
called when a SMB socket becomes writable
*/
-static void smbsrv_send(struct server_connection *conn, time_t t, uint16_t flags)
+static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16_t flags)
{
struct smbsrv_connection *smb_conn = conn->private_data;
@@ -787,11 +787,10 @@ static void smbsrv_send(struct server_connection *conn, time_t t, uint16_t flags
/*
called when connection is idle
*/
-static void smbsrv_idle(struct server_connection *conn, time_t t)
+static void smbsrv_idle(struct server_connection *conn, struct timeval t)
{
DEBUG(10,("smbsrv_idle: not implemented!\n"));
- conn->event.idle->next_event = t + 5;
-
+ conn->event.idle->next_event = timeval_add(&t, 5, 0);
return;
}
diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h
index 79373d8a39..92d92a70ad 100644
--- a/source4/smbd/process_model.h
+++ b/source4/smbd/process_model.h
@@ -40,10 +40,12 @@ struct model_ops {
void (*model_startup)(void);
/* function to accept new connection */
- void (*accept_connection)(struct event_context *, struct fd_event *, time_t, uint16_t);
+ void (*accept_connection)(struct event_context *, struct fd_event *,
+ struct timeval t, uint16_t);
/* function to terminate a connection */
- void (*terminate_connection)(struct server_connection *srv_conn, const char *reason);
+ void (*terminate_connection)(struct server_connection *srv_conn,
+ const char *reason);
/* function to exit server */
void (*exit_server)(struct server_context *srv_ctx, const char *reason);
diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c
index 6ce0479b0c..66074d166d 100644
--- a/source4/smbd/process_single.c
+++ b/source4/smbd/process_single.c
@@ -38,7 +38,8 @@ static void single_start_server(void)
/*
called when a listening socket becomes readable
*/
-static void single_accept_connection(struct event_context *ev, struct fd_event *srv_fde, time_t t, uint16_t flags)
+static void single_accept_connection(struct event_context *ev, struct fd_event *srv_fde,
+ struct timeval t, uint16_t flags)
{
NTSTATUS status;
struct socket_context *sock;
@@ -55,7 +56,7 @@ static void single_accept_connection(struct event_context *ev, struct fd_event *
conn = server_setup_connection(ev, server_socket, sock, t, socket_get_fd(sock));
if (!conn) {
- DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n"));
+ DEBUG(0,("server_setup_connection failed\n"));
return;
}
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c
index 3741ce1b46..c794605dc5 100644
--- a/source4/smbd/process_standard.c
+++ b/source4/smbd/process_standard.c
@@ -39,7 +39,7 @@ static void standard_model_startup(void)
called when a listening socket becomes readable
*/
static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde,
- time_t t, uint16_t flags)
+ struct timeval t, uint16_t flags)
{
NTSTATUS status;
struct socket_context *sock;
diff --git a/source4/smbd/service.c b/source4/smbd/service.c
index 6d2f9a8149..767d310e2b 100644
--- a/source4/smbd/service.c
+++ b/source4/smbd/service.c
@@ -205,7 +205,7 @@ static int server_destructor(void *ptr)
struct server_connection *server_setup_connection(struct event_context *ev,
struct server_socket *server_socket,
struct socket_context *sock,
- time_t t,
+ struct timeval t,
servid_t server_id)
{
struct fd_event fde;
@@ -226,13 +226,13 @@ struct server_connection *server_setup_connection(struct event_context *ev,
fde.handler = server_io_handler;
idle.private = srv_conn;
- idle.next_event = t + SERVER_DEFAULT_IDLE_TIME;
+ idle.next_event = timeval_add(&t, SERVER_DEFAULT_IDLE_TIME, 0);
idle.handler = server_idle_handler;
srv_conn->event.ctx = ev;
srv_conn->event.fde = &fde;
srv_conn->event.idle = &idle;
- srv_conn->event.idle_time = SERVER_DEFAULT_IDLE_TIME;
+ srv_conn->event.idle_time = timeval_set(SERVER_DEFAULT_IDLE_TIME, 0);
srv_conn->server_socket = server_socket;
srv_conn->service = server_socket->service;
@@ -269,11 +269,12 @@ void server_terminate_connection(struct server_connection *srv_conn, const char
srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
}
-void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
+void server_io_handler(struct event_context *ev, struct fd_event *fde,
+ struct timeval t, uint16_t flags)
{
struct server_connection *conn = fde->private;
- conn->event.idle->next_event = t + conn->event.idle_time;
+ conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
if (flags & EVENT_FD_WRITE) {
conn->service->ops->send_handler(conn, t, flags);
@@ -286,13 +287,14 @@ void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t,
}
-void server_idle_handler(struct event_context *ev, struct timed_event *idle, time_t t)
+void server_idle_handler(struct event_context *ev, struct timed_event *idle,
+ struct timeval t)
{
struct server_connection *conn = idle->private;
- conn->event.idle->next_event = t + conn->event.idle_time;
+ conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
- conn->service->ops->idle_handler(conn,t);
+ conn->service->ops->idle_handler(conn, t);
}
/*
return the operations structure for a named backend of the specified type
diff --git a/source4/smbd/service.h b/source4/smbd/service.h
index 2ac1988f3d..5bb43a74fa 100644
--- a/source4/smbd/service.h
+++ b/source4/smbd/service.h
@@ -48,13 +48,13 @@ struct server_service_ops {
void (*accept_connection)(struct server_connection *);
/* function to accept new connection */
- void (*recv_handler)(struct server_connection *, time_t, uint16_t);
+ void (*recv_handler)(struct server_connection *, struct timeval, uint16_t);
/* function to accept new connection */
- void (*send_handler)(struct server_connection *, time_t, uint16_t);
+ void (*send_handler)(struct server_connection *, struct timeval, uint16_t);
/* function to accept new connection */
- void (*idle_handler)(struct server_connection *, time_t);
+ void (*idle_handler)(struct server_connection *, struct timeval);
/* function to close a connection */
void (*close_connection)(struct server_connection *, const char *reason);
@@ -114,7 +114,7 @@ struct server_connection {
struct event_context *ctx;
struct fd_event *fde;
struct timed_event *idle;
- time_t idle_time;
+ struct timeval idle_time;
} event;
servid_t server_id;
diff --git a/source4/torture/basic/dir.c b/source4/torture/basic/dir.c
index 5d3ac8d1de..7921b3eb03 100644
--- a/source4/torture/basic/dir.c
+++ b/source4/torture/basic/dir.c
@@ -35,9 +35,9 @@ BOOL torture_dirtest1(void)
int i;
struct smbcli_state *cli;
int fnum;
- double t1;
BOOL correct = True;
extern int torture_numops;
+ struct timeval tv;
printf("starting dirtest1\n");
@@ -48,6 +48,7 @@ BOOL torture_dirtest1(void)
printf("Creating %d random filenames\n", torture_numops);
srandom(0);
+ tv = timeval_current();
for (i=0;i<torture_numops;i++) {
char *fname;
asprintf(&fname, "\\%x", (int)random());
@@ -61,13 +62,11 @@ BOOL torture_dirtest1(void)
free(fname);
}
- t1 = end_timer();
-
printf("Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL));
printf("Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL));
printf("Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL));
- printf("dirtest core %g seconds\n", end_timer() - t1);
+ printf("dirtest core %g seconds\n", timeval_elapsed(&tv));
srandom(0);
for (i=0;i<torture_numops;i++) {
diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c
index 07ad0929de..310dec1bc7 100644
--- a/source4/torture/gentest.c
+++ b/source4/torture/gentest.c
@@ -189,7 +189,7 @@ static BOOL connect_servers(void)
}
smbcli_oplock_handler(servers[i].cli[j]->transport, oplock_handler, NULL);
- smbcli_transport_idle_handler(servers[i].cli[j]->transport, idle_func, 1, NULL);
+ smbcli_transport_idle_handler(servers[i].cli[j]->transport, idle_func, 50000, NULL);
}
}
diff --git a/source4/torture/local/messaging.c b/source4/torture/local/messaging.c
index c0dab06cca..303ffa8fe9 100644
--- a/source4/torture/local/messaging.c
+++ b/source4/torture/local/messaging.c
@@ -58,6 +58,7 @@ static BOOL test_ping_speed(TALLOC_CTX *mem_ctx)
int ping_count = 0;
int pong_count = 0;
BOOL ret = True;
+ struct timeval tv;
if (fork() == 0) {
struct messaging_context *msg_ctx2 = messaging_init(mem_ctx, 1, ev);
@@ -83,10 +84,10 @@ static BOOL test_ping_speed(TALLOC_CTX *mem_ctx)
messaging_register(msg_ctx, &pong_count, MY_PONG, pong_message);
- start_timer();
+ tv = timeval_current();
printf("Sending pings for 10 seconds\n");
- while (end_timer() < 10.0) {
+ while (timeval_elapsed(&tv) < 10.0) {
DATA_BLOB data;
NTSTATUS status1, status2;
@@ -113,7 +114,7 @@ static BOOL test_ping_speed(TALLOC_CTX *mem_ctx)
printf("waiting for %d remaining replies (done %d)\n",
ping_count - pong_count, pong_count);
- while (end_timer() < 30 && pong_count < ping_count) {
+ while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
event_loop_once(ev);
}
@@ -125,7 +126,8 @@ static BOOL test_ping_speed(TALLOC_CTX *mem_ctx)
ret = False;
}
- printf("ping rate of %.0f messages/sec\n", (ping_count+pong_count)/end_timer());
+ printf("ping rate of %.0f messages/sec\n",
+ (ping_count+pong_count)/timeval_elapsed(&tv));
talloc_free(msg_ctx);
diff --git a/source4/torture/local/talloc.c b/source4/torture/local/talloc.c
index 332312200a..348b037753 100644
--- a/source4/torture/local/talloc.c
+++ b/source4/torture/local/talloc.c
@@ -36,18 +36,18 @@
#ifdef _STANDALONE_
typedef enum {False=0,True=1} BOOL;
-static struct timeval tp1,tp2;
-
-static void start_timer(void)
+static struct timeval current_time(void)
{
- gettimeofday(&tp1,NULL);
+ struct timeval tv;
+ GetTimeOfDay(&tv);
+ return tv;
}
-static double end_timer(void)
+static double elapsed_time(struct timeval *tv)
{
- gettimeofday(&tp2,NULL);
- return((tp2.tv_sec - tp1.tv_sec) +
- (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+ struct timeval tv2 = current_time();
+ return (tv2.tv_sec - tv->tv_sec) +
+ (tv2.tv_usec - tv->tv_usec)*1.0e-6;
}
#endif /* _STANDALONE_ */
@@ -642,10 +642,11 @@ static BOOL test_speed(void)
{
void *ctx = talloc(NULL, 0);
unsigned count;
+ struct timeval tv;
printf("MEASURING TALLOC VS MALLOC SPEED\n");
- start_timer();
+ tv = timeval_current();
count = 0;
do {
void *p1, *p2, *p3;
@@ -654,13 +655,13 @@ static BOOL test_speed(void)
p3 = talloc(p1, 300);
talloc_free(p1);
count += 3;
- } while (end_timer() < 5.0);
+ } while (timeval_elapsed(&tv) < 5.0);
- printf("talloc: %.0f ops/sec\n", count/end_timer());
+ printf("talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
talloc_free(ctx);
- start_timer();
+ tv = timeval_current();
count = 0;
do {
void *p1, *p2, *p3;
@@ -671,9 +672,9 @@ static BOOL test_speed(void)
free(p2);
free(p3);
count += 3;
- } while (end_timer() < 5.0);
+ } while (timeval_elapsed(&tv) < 5.0);
- printf("malloc: %.0f ops/sec\n", count/end_timer());
+ printf("malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
return True;
}
diff --git a/source4/torture/nbench/nbench.c b/source4/torture/nbench/nbench.c
index 0b4bf4bbf1..1c90658f49 100644
--- a/source4/torture/nbench/nbench.c
+++ b/source4/torture/nbench/nbench.c
@@ -37,6 +37,9 @@ static BOOL run_netbench(struct smbcli_state *cli, int client)
fstring params[20];
const char *p;
BOOL correct = True;
+ struct timeval tv;
+
+ tv = timeval_current();
nb_setup(cli, client, warmup);
@@ -52,15 +55,15 @@ static BOOL run_netbench(struct smbcli_state *cli, int client)
again:
while (fgets(line, sizeof(line)-1, f)) {
NTSTATUS status;
- double t = end_timer();
- if (warmup && t >= warmup) {
+ if (warmup &&
+ timeval_elapsed(&tv) >= warmup) {
warmup = 0;
nb_warmup_done();
- start_timer();
+ tv = timeval_current();
}
- if (end_timer() >= timelimit) {
+ if (timeval_elapsed(&tv) >= timelimit) {
goto done;
}
diff --git a/source4/torture/nbench/nbio.c b/source4/torture/nbench/nbio.c
index 98b1c08c97..98967f2523 100644
--- a/source4/torture/nbench/nbio.c
+++ b/source4/torture/nbench/nbio.c
@@ -31,6 +31,7 @@ static int nbio_id;
static int nprocs;
static BOOL bypass_io;
static int warmup;
+static struct timeval tv;
struct ftable {
struct ftable *next, *prev;
@@ -76,7 +77,7 @@ void nb_alarm(int sig)
if (!children[i].done) num_clients++;
}
- t = end_timer();
+ t = timeval_elapsed(&tv);
if (warmup) {
printf("%4d %8d %.2f MB/sec warmup %.0f sec \n",
@@ -91,7 +92,7 @@ void nb_alarm(int sig)
}
if (warmup && t >= warmup) {
- start_timer();
+ tv = timeval_current();
warmup = 0;
}
@@ -156,7 +157,7 @@ void nb_setup(struct smbcli_state *cli, int id, int warmupt)
warmup = warmupt;
nbio_id = id;
c = cli;
- start_timer();
+ tv = timeval_current();
if (children) {
children[nbio_id].done = 0;
}
diff --git a/source4/torture/raw/mux.c b/source4/torture/raw/mux.c
index c184fb79a7..c02045817e 100644
--- a/source4/torture/raw/mux.c
+++ b/source4/torture/raw/mux.c
@@ -42,6 +42,8 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
int fnum;
BOOL ret = True;
struct smbcli_request *req;
+ struct timeval tv;
+ double d;
printf("testing multiplexed open/open/close\n");
@@ -64,14 +66,25 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
CHECK_STATUS(status, NT_STATUS_OK);
fnum = io.ntcreatex.out.fnum;
+ tv = timeval_current();
+
/* send an open that will conflict */
io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
+ d = timeval_elapsed(&tv);
+ if (d < 0.5 || d > 1.5) {
+ printf("bad timeout for conflict - %.2f should be 1.0\n", d);
+ ret = False;
+ } else {
+ printf("open delay %.2f\n", d);
+ }
+
/*
same request, but async
*/
+ tv = timeval_current();
req = smb_raw_open_send(cli->tree, &io);
/* and close the file */
@@ -81,6 +94,14 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
status = smb_raw_open_recv(req, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_OK);
+ d = timeval_elapsed(&tv);
+ if (d > 0.25) {
+ printf("bad timeout for async conflict - %.2f should be <0.25\n", d);
+ ret = False;
+ } else {
+ printf("async open delay %.2f\n", d);
+ }
+
smbcli_close(cli->tree, io.ntcreatex.out.fnum);
done:
diff --git a/source4/torture/raw/open.c b/source4/torture/raw/open.c
index 81681bbd74..c810984900 100644
--- a/source4/torture/raw/open.c
+++ b/source4/torture/raw/open.c
@@ -266,6 +266,7 @@ static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
int fnum = -1, fnum2;
BOOL ret = True;
int i;
+ struct timeval tv;
struct {
uint16_t open_func;
BOOL with_file;
@@ -398,13 +399,13 @@ static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
fnum = io.openx.out.fnum;
io.openx.in.timeout = 20000;
- start_timer();
+ tv = timeval_current();
io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
status = smb_raw_open(cli->tree, mem_ctx, &io);
CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
- if (end_timer() > 3) {
- printf("(%s) Incorrect timing in openx with timeout - waited %d seconds\n",
- __location__, (int)end_timer());
+ if (timeval_elapsed(&tv) > 3.0) {
+ printf("(%s) Incorrect timing in openx with timeout - waited %.2f seconds\n",
+ __location__, timeval_elapsed(&tv));
ret = False;
}
smbcli_close(cli->tree, fnum);
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index 656607d934..19dc311dd9 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -937,22 +937,19 @@ static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
int fnum = -1;
do {
- struct timeval tv_start, tv_end;
- GetTimeOfDay(&tv_start);
+ struct timeval tv;
+ tv = timeval_current();
fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
NTCREATEX_DISP_OPEN_IF, 0, 0);
if (fnum != -1) {
break;
}
- GetTimeOfDay(&tv_end);
if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
- /* Sharing violation errors need to be 1 second apart. */
- int64_t tdif = usec_time_diff(&tv_end, &tv_start);
- if (tdif < 500000 || tdif > 1500000) {
- fprintf(stderr,"Timing incorrect %lld.%lld for share violation\n",
- tdif / (int64_t)1000000,
- tdif % (int64_t)1000000);
+ double e = timeval_elapsed(&tv);
+ if (e < 0.5 || e > 1.5) {
+ fprintf(stderr,"Timing incorrect %.2f violation\n",
+ e);
}
}
} while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
@@ -2269,6 +2266,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result
char **unc_list = NULL;
const char *p;
int num_unc_names = 0;
+ struct timeval tv;
synccount = 0;
@@ -2300,7 +2298,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result
child_status_out[i] = True;
}
- start_timer();
+ tv = timeval_current();
for (i=0;i<torture_nprocs;i++) {
procnum = i;
@@ -2364,18 +2362,18 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result
}
if (synccount == torture_nprocs) break;
msleep(100);
- } while (end_timer() < start_time_limit);
+ } while (timeval_elapsed(&tv) < start_time_limit);
if (synccount != torture_nprocs) {
printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
*result = False;
- return end_timer();
+ return timeval_elapsed(&tv);
}
printf("Starting %d clients\n", torture_nprocs);
/* start the client load */
- start_timer();
+ tv = timeval_current();
for (i=0;i<torture_nprocs;i++) {
child_status[i] = 0;
}
@@ -2398,7 +2396,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result
*result = False;
}
}
- return end_timer();
+ return timeval_elapsed(&tv);
}
#define FLAG_MULTIPROC 1
@@ -2557,12 +2555,12 @@ static BOOL run_test(const char *name)
}
} else {
- start_timer();
+ struct timeval tv = timeval_current();
if (!torture_ops[i].fn()) {
ret = False;
printf("TEST %s FAILED!\n", torture_ops[i].name);
}
- t = end_timer();
+ t = timeval_elapsed(&tv);
}
printf("%s took %g secs\n\n", torture_ops[i].name, t);
}
diff --git a/source4/torture/torture_util.c b/source4/torture/torture_util.c
index 0c0464507d..22aa9ffedd 100644
--- a/source4/torture/torture_util.c
+++ b/source4/torture/torture_util.c
@@ -24,21 +24,6 @@
#include "system/time.h"
-static struct timeval tp1,tp2;
-
-void start_timer(void)
-{
- gettimeofday(&tp1,NULL);
-}
-
-double end_timer(void)
-{
- gettimeofday(&tp2,NULL);
- return((tp2.tv_sec - tp1.tv_sec) +
- (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
-}
-
-
/*
create a directory, returning a handle to it
*/