summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/smbd/notify.c9
-rw-r--r--source3/smbd/notify_fam.c36
-rw-r--r--source3/smbd/notify_hash.c1
-rw-r--r--source3/smbd/notify_kernel.c1
-rw-r--r--source3/smbd/oplock.c15
-rw-r--r--source3/smbd/process.c25
7 files changed, 60 insertions, 28 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index dc03ba44d4..fd3c23e575 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1581,6 +1581,7 @@ struct cnotify_fns {
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
int select_time;
+ int notification_fd;
};
#include "smb_macros.h"
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index df3d45d20b..b2d0fc3326 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -206,6 +206,15 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn,
return True;
}
+int change_notify_fd(void)
+{
+ if (cnotify) {
+ return cnotify->notification_fd;
+ }
+
+ return -1;
+}
+
/****************************************************************************
Initialise the change notify subsystem.
****************************************************************************/
diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c
index 413340266e..9f02bfdee9 100644
--- a/source3/smbd/notify_fam.c
+++ b/source3/smbd/notify_fam.c
@@ -63,9 +63,30 @@ static int global_fc_generation;
#define FAM_TRACE 8
#define FAM_TRACE_LOW 10
-#define FAM_NOTIFY_CHECK_TIMEOUT 1 /* secs */
#define FAM_EVENT_DRAIN ((uint32_t)(-1))
+static void * fam_register_notify(connection_struct * conn,
+ char * path,
+ uint32 flags);
+
+static BOOL fam_check_notify(connection_struct * conn,
+ uint16_t vuid,
+ char * path,
+ uint32_t flags,
+ void * data,
+ time_t when);
+
+static void fam_remove_notify(void * data)
+
+static struct cnotify_fns global_fam_notify =
+{
+ fam_register_notify,
+ fam_check_notify,
+ fam_remove_notify,
+ -1,
+ -1
+};
+
/* Turn a FAM event code into a string. Don't rely on specific code values,
* because that might not work across all flavours of FAM.
*/
@@ -110,6 +131,7 @@ fam_check_reconnect(void)
}
}
+ global_fam_notify.notification_fd = FAMCONNECTION_GETFD(&global_fc);
return(True);
}
@@ -420,18 +442,6 @@ fam_remove_notify(void * data)
struct cnotify_fns * fam_notify_init(void)
{
- static struct cnotify_fns global_fam_notify =
- {
- fam_register_notify,
- fam_check_notify,
- fam_remove_notify,
- FAM_NOTIFY_CHECK_TIMEOUT
- };
-
- /* TODO: rather than relying on FAM_NOTIFY_CHECK_TIMEOUT, we should have an
- * API to push the FAM fd into the global server fd set.
- */
-
FAMCONNECTION_GETFD(&global_fc) = -1;
if (!fam_test_connection()) {
diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c
index 859a92a61e..a98a028fae 100644
--- a/source3/smbd/notify_hash.c
+++ b/source3/smbd/notify_hash.c
@@ -230,6 +230,7 @@ struct cnotify_fns *hash_notify_init(void)
cnotify.check_notify = hash_check_notify;
cnotify.remove_notify = hash_remove_notify;
cnotify.select_time = lp_change_notify_timeout();
+ cnotify.notification_fd = -1;
return &cnotify;
}
diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c
index 02abe0b4b6..0c20effc3d 100644
--- a/source3/smbd/notify_kernel.c
+++ b/source3/smbd/notify_kernel.c
@@ -232,6 +232,7 @@ struct cnotify_fns *kernel_notify_init(void)
cnotify.check_notify = kernel_check_notify;
cnotify.remove_notify = kernel_remove_notify;
cnotify.select_time = -1;
+ cnotify.notification_fd = -1;
/* the signal can start off blocked due to a bug in bash */
BlockSignals(False, RT_SIGNAL_NOTIFY);
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 755bcffc7f..41eb809909 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -240,21 +240,16 @@ BOOL downgrade_oplock(files_struct *fsp)
}
/****************************************************************************
- Setup the listening set of file descriptors for an oplock break
- message either from the UDP socket or from the kernel. Returns the maximum
- fd used.
+ Return the fd (if any) used for receiving oplock notifications.
****************************************************************************/
-int setup_oplock_select_set( fd_set *fds)
+int oplock_notify_fd(void)
{
- int maxfd = 0;
-
- if (koplocks && koplocks->notification_fd != -1) {
- FD_SET(koplocks->notification_fd, fds);
- maxfd = MAX(maxfd, koplocks->notification_fd);
+ if (koplocks) {
+ return koplocks->notification_fd;
}
- return maxfd;
+ return -1;
}
/****************************************************************************
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index d646ebe02d..2f19f909f2 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -283,7 +283,7 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
return result;
}
-
+
/****************************************************************************
Do all async processing in here. This includes kernel oplock messages, change
notify events etc.
@@ -319,6 +319,20 @@ static void async_processing(void)
}
/****************************************************************************
+ Add a fd to the set we will be select(2)ing on.
+****************************************************************************/
+
+static int select_on_fd(int fd, int maxfd, fd_set *fds)
+{
+ if (fd != -1) {
+ FD_SET(fd, fds);
+ maxfd = MAX(maxfd, fd);
+ }
+
+ return maxfd;
+}
+
+/****************************************************************************
Do a select on an two fd's - with timeout.
If a local udp message has been pushed onto the
@@ -344,7 +358,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
fd_set fds;
int selrtn;
struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0);
- int maxfd;
+ int maxfd = 0;
smb_read_error = 0;
@@ -437,10 +451,11 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
}
}
- FD_SET(smbd_server_fd(),&fds);
- maxfd = setup_oplock_select_set(&fds);
+ maxfd = select_on_fd(smbd_server_fd(), maxfd, &fds);
+ maxfd = select_on_fd(change_notify_fd(), maxfd, &fds);
+ maxfd = select_on_fd(oplock_notify_fd(), maxfd, &fds);
- selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to);
+ selrtn = sys_select(maxfd+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