summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-01-23 10:08:44 +0100
committerStefan Metzmacher <metze@samba.org>2009-01-27 15:28:10 +0100
commit52f6a4436f9da439fc687894b329898833af7ff8 (patch)
tree7d42835050b9876ae520fa4e02a9f697052bb79c /source3
parent4a2271349503933776f9d2791edfcb874a2c7261 (diff)
downloadsamba-52f6a4436f9da439fc687894b329898833af7ff8.tar.gz
samba-52f6a4436f9da439fc687894b329898833af7ff8.tar.bz2
samba-52f6a4436f9da439fc687894b329898833af7ff8.zip
s3:smbd: make kernel oplocks event driven
And use signal events for Linux oplocks. metze
Diffstat (limited to 'source3')
-rw-r--r--source3/include/proto.h4
-rw-r--r--source3/include/smb.h2
-rw-r--r--source3/smbd/globals.c9
-rw-r--r--source3/smbd/globals.h6
-rw-r--r--source3/smbd/oplock.c64
-rw-r--r--source3/smbd/oplock_irix.c15
-rw-r--r--source3/smbd/oplock_linux.c66
-rw-r--r--source3/smbd/process.c74
8 files changed, 34 insertions, 206 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 1713760666..ae49290539 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -7018,13 +7018,11 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
/* The following definitions come from smbd/oplock.c */
int32 get_number_of_exclusive_open_oplocks(void);
-bool oplock_message_waiting(void);
-void process_kernel_oplocks(struct messaging_context *msg_ctx);
+void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp);
bool set_file_oplock(files_struct *fsp, int oplock_type);
void release_file_oplock(files_struct *fsp);
bool remove_oplock(files_struct *fsp);
bool downgrade_oplock(files_struct *fsp);
-int oplock_notify_fd(void);
void reply_to_oplock_break_requests(files_struct *fsp);
void release_level_2_oplocks_on_change(files_struct *fsp);
void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index aa2db693a3..3f71cde395 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1680,12 +1680,10 @@ struct kernel_oplocks {
/* if a kernel does support oplocks then a structure of the following
typee is used to describe how to interact with the kernel */
struct kernel_oplocks_ops {
- files_struct * (*receive_message)(struct kernel_oplocks *ctx);
bool (*set_oplock)(struct kernel_oplocks *ctx,
files_struct *fsp, int oplock_type);
void (*release_oplock)(struct kernel_oplocks *ctx,
files_struct *fsp);
- bool (*msg_waiting)(struct kernel_oplocks *ctx);
};
#include "smb_macros.h"
diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c
index 28b5a709bd..3f8cb411e5 100644
--- a/source3/smbd/globals.c
+++ b/source3/smbd/globals.c
@@ -169,11 +169,6 @@ struct vfs_init_function_entry *backends = NULL;
char *sparse_buf = NULL;
char *LastDir = NULL;
-#if HAVE_KERNEL_OPLOCKS_LINUX
-SIG_ATOMIC_T oplock_signals_received = 0;
-SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE];
-#endif
-
/* Current number of oplocks we have outstanding. */
int32_t exclusive_oplocks_open = 0;
int32_t level_II_oplocks_open = 0;
@@ -201,8 +196,4 @@ void smbd_init_globals(void)
ZERO_STRUCT(conn_ctx_stack);
ZERO_STRUCT(sec_ctx_stack);
-
-#if HAVE_KERNEL_OPLOCKS_LINUX
- ZERO_STRUCT(fd_pending_array);
-#endif
}
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 283425caf7..6ac92ed3dd 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -181,12 +181,6 @@ extern struct vfs_init_function_entry *backends;
extern char *sparse_buf;
extern char *LastDir;
-#if HAVE_KERNEL_OPLOCKS_LINUX
-extern SIG_ATOMIC_T oplock_signals_received;
-#define FD_PENDING_SIZE 100
-extern SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE];
-#endif
-
/* Current number of oplocks we have outstanding. */
extern int32_t exclusive_oplocks_open;
extern int32_t level_II_oplocks_open;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index e4b5016538..788d2f7238 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -32,61 +32,23 @@ int32 get_number_of_exclusive_open_oplocks(void)
return exclusive_oplocks_open;
}
-/****************************************************************************
- Return True if an oplock message is pending.
-****************************************************************************/
-
-bool oplock_message_waiting(void)
-{
- if (koplocks && koplocks->ops->msg_waiting(koplocks)) {
- return True;
- }
-
- return False;
-}
-
-/****************************************************************************
- Find out if there are any kernel oplock messages waiting and process them
- if so. pfds is the fd_set from the main select loop (which contains any
- kernel oplock fd if that's what the system uses (IRIX). If may be NULL if
- we're calling this in a shutting down state.
-****************************************************************************/
-
-void process_kernel_oplocks(struct messaging_context *msg_ctx)
+/*
+ * helper function used by the kernel oplock backends to post the break message
+ */
+void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
{
- /*
- * We need to check for kernel oplocks before going into the select
- * here, as the EINTR generated by the linux kernel oplock may have
- * already been eaten. JRA.
- */
-
- if (!koplocks) {
- return;
- }
+ uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
- while (koplocks->ops->msg_waiting(koplocks)) {
- files_struct *fsp;
- char msg[MSG_SMB_KERNEL_BREAK_SIZE];
+ /* Put the kernel break info into the message. */
+ push_file_id_16((char *)msg, &fsp->file_id);
+ SIVAL(msg,16,fsp->fh->gen_id);
- fsp = koplocks->ops->receive_message(koplocks);
+ /* Don't need to be root here as we're only ever
+ sending to ourselves. */
- if (fsp == NULL) {
- DEBUG(3, ("Kernel oplock message announced, but none "
- "received\n"));
- return;
- }
-
- /* Put the kernel break info into the message. */
- push_file_id_16(msg, &fsp->file_id);
- SIVAL(msg,16,fsp->fh->gen_id);
-
- /* Don't need to be root here as we're only ever
- sending to ourselves. */
-
- messaging_send_buf(msg_ctx, procid_self(),
- MSG_SMB_KERNEL_BREAK,
- (uint8 *)&msg, MSG_SMB_KERNEL_BREAK_SIZE);
- }
+ messaging_send_buf(msg_ctx, procid_self(),
+ MSG_SMB_KERNEL_BREAK,
+ msg, MSG_SMB_KERNEL_BREAK_SIZE);
}
/****************************************************************************
diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c
index 0cfa960425..d7f45e67de 100644
--- a/source3/smbd/oplock_irix.c
+++ b/source3/smbd/oplock_irix.c
@@ -252,13 +252,6 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx,
}
}
-static bool irix_oplock_msg_waiting(struct kernel_oplocks *_ctx)
-{
- struct irix_oplocks_context *ctx = talloc_get_type(_ctx->private_data,
- struct irix_oplocks_context);
- return ctx->pending;
-}
-
static void irix_oplocks_read_fde_handler(struct event_context *ev,
struct fd_event *fde,
uint16_t flags,
@@ -266,10 +259,10 @@ static void irix_oplocks_read_fde_handler(struct event_context *ev,
{
struct irix_oplocks_context *ctx = talloc_get_type(private_data,
struct irix_oplocks_context);
+ files_struct *fsp;
- ctx->pending = true;
- process_kernel_oplocks(smbd_messaging_context());
- ctx->pending = false;
+ fsp = irix_oplock_receive_message(ctx->ctx);
+ break_kernel_oplock(smbd_messaging_context(), fsp);
}
/****************************************************************************
@@ -277,10 +270,8 @@ static void irix_oplocks_read_fde_handler(struct event_context *ev,
****************************************************************************/
static const struct kernel_oplocks_ops irix_koplocks = {
- .receive_message = irix_oplock_receive_message,
.set_oplock = irix_set_kernel_oplock,
.release_oplock = irix_release_kernel_oplock,
- .msg_waiting = irix_oplock_msg_waiting
};
struct kernel_oplocks *irix_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index 8087167ff4..51cce0ed48 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -43,19 +43,6 @@
#define F_SETSIG 10
#endif
-/****************************************************************************
- Handle a LEASE signal, incrementing the signals_received and blocking the signal.
-****************************************************************************/
-
-static void signal_handler(int sig, siginfo_t *info, void *unused)
-{
- if (oplock_signals_received < FD_PENDING_SIZE - 1) {
- fd_pending_array[oplock_signals_received] = (SIG_ATOMIC_T)info->si_fd;
- oplock_signals_received++;
- } /* Else signal is lost. */
- sys_select_signal(RT_SIGNAL_LEASE);
-}
-
/*
* public function to get linux lease capability. Needed by some VFS modules (eg. gpfs.c)
*/
@@ -101,24 +88,17 @@ int linux_setlease(int fd, int leasetype)
* oplock break protocol.
****************************************************************************/
-static files_struct *linux_oplock_receive_message(struct kernel_oplocks *ctx)
+static void linux_oplock_signal_handler(struct tevent_context *ev_ctx,
+ struct tevent_signal *se,
+ int signum, int count,
+ void *_info, void *private_data)
{
- int fd;
+ siginfo_t *info = (siginfo_t *)_info;
+ int fd = info->si_fd;
files_struct *fsp;
- BlockSignals(True, RT_SIGNAL_LEASE);
- fd = fd_pending_array[0];
fsp = file_find_fd(fd);
- fd_pending_array[0] = (SIG_ATOMIC_T)-1;
- if (oplock_signals_received > 1)
- memmove(CONST_DISCARD(void *, &fd_pending_array[0]),
- CONST_DISCARD(void *, &fd_pending_array[1]),
- sizeof(SIG_ATOMIC_T)*(oplock_signals_received-1));
- oplock_signals_received--;
- /* now we can receive more signals */
- BlockSignals(False, RT_SIGNAL_LEASE);
-
- return fsp;
+ break_kernel_oplock(smbd_messaging_context(), fsp);
}
/****************************************************************************
@@ -180,15 +160,6 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx,
}
/****************************************************************************
- See if a oplock message is waiting.
-****************************************************************************/
-
-static bool linux_oplock_msg_waiting(struct kernel_oplocks *ctx)
-{
- return oplock_signals_received != 0;
-}
-
-/****************************************************************************
See if the kernel supports oplocks.
****************************************************************************/
@@ -208,16 +179,14 @@ static bool linux_oplocks_available(void)
****************************************************************************/
static const struct kernel_oplocks_ops linux_koplocks = {
- .receive_message = linux_oplock_receive_message,
.set_oplock = linux_set_kernel_oplock,
.release_oplock = linux_release_kernel_oplock,
- .msg_waiting = linux_oplock_msg_waiting
};
struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
{
- struct sigaction act;
struct kernel_oplocks *ctx;
+ struct tevent_signal *se;
if (!linux_oplocks_available()) {
DEBUG(3,("Linux kernel oplocks not available\n"));
@@ -232,19 +201,18 @@ struct kernel_oplocks *linux_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
ctx->ops = &linux_koplocks;
- ZERO_STRUCT(act);
-
- act.sa_handler = NULL;
- act.sa_sigaction = signal_handler;
- act.sa_flags = SA_SIGINFO;
- sigemptyset( &act.sa_mask );
- if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) {
- DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n"));
+ se = tevent_add_signal(smbd_event_context(),
+ ctx,
+ RT_SIGNAL_LEASE, SA_SIGINFO,
+ linux_oplock_signal_handler,
+ ctx);
+ if (!se) {
+ DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler"));
+ TALLOC_FREE(ctx);
return NULL;
}
- /* the signal can start off blocked due to a bug in bash */
- BlockSignals(False, RT_SIGNAL_LEASE);
+ ctx->private_data = se;
DEBUG(3,("Linux kernel oplocks enabled\n"));
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 9527d94825..d617ef1915 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -742,46 +742,6 @@ void smbd_setup_sig_hup_handler(void)
}
}
-/****************************************************************************
- Do all async processing in here. This includes kernel oplock messages, change
- notify events etc.
-****************************************************************************/
-
-static void async_processing(void)
-{
- DEBUG(10,("async_processing: Doing async processing.\n"));
-
- process_aio_queue();
-
- process_kernel_oplocks(smbd_messaging_context());
-
- /* Do the aio check again after receive_local_message as it does a
- select and may have eaten our signal. */
- /* Is this till true? -- vl */
- process_aio_queue();
-}
-
-/****************************************************************************
- Do a select on an two fd's - with timeout.
-
- If a local udp message has been pushed onto the
- queue (this can only happen during oplock break
- processing) call async_processing()
-
- If a pending smb message has been pushed onto the
- queue (this can only happen during oplock break
- processing) return this next.
-
- If the first smbfd is ready then read an smb from it.
- if the second (loopback UDP) fd is ready then read a message
- from it and setup the buffer header to identify the length
- and from address.
- Returns False on timeout or error.
- Else returns True.
-
-The timeout is in milliseconds
-****************************************************************************/
-
static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
{
fd_set r_fds, w_fds;
@@ -800,26 +760,6 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *
FD_ZERO(&w_fds);
/*
- * Ensure we process oplock break messages by preference.
- * We have to do this before the select, after the select
- * and if the select returns EINTR. This is due to the fact
- * that the selects called from async_processing can eat an EINTR
- * caused by a signal (we can't take the break message there).
- * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
- */
-
- if (oplock_message_waiting()) {
- DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
- async_processing();
- /*
- * After async processing we must go and do the select again, as
- * the state of the flag in fds for the server file descriptor is
- * indeterminate - we may have done I/O on it in the oplock processing. JRA.
- */
- return NT_STATUS_RETRY;
- }
-
- /*
* Are there any timed events waiting ? If so, ensure we don't
* select for longer than it would take to wait for them.
*/
@@ -852,20 +792,6 @@ static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *
return NT_STATUS_RETRY;
}
- /* if we get EINTR then maybe we have received an oplock
- signal - treat this as select returning 1. This is ugly, but
- is the best we can do until the oplock code knows more about
- signals */
- if (selrtn == -1 && errno == EINTR) {
- async_processing();
- /*
- * After async processing we must go and do the select again, as
- * the state of the flag in fds for the server file descriptor is
- * indeterminate - we may have done I/O on it in the oplock processing. JRA.
- */
- return NT_STATUS_RETRY;
- }
-
/* Check if error */
if (selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */