diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-06-12 15:53:31 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-06-12 15:53:31 +0000 |
commit | b2d01bd2dbfed8b35cc324fad42eac562fcad3b4 (patch) | |
tree | 6d2708c53b61bbd441d7c4a65945b65d543b2f73 /source3/smbd/oplock_linux.c | |
parent | 6de513cef43ad83ecd1823bde5a4e05c22224b0f (diff) | |
download | samba-b2d01bd2dbfed8b35cc324fad42eac562fcad3b4.tar.gz samba-b2d01bd2dbfed8b35cc324fad42eac562fcad3b4.tar.bz2 samba-b2d01bd2dbfed8b35cc324fad42eac562fcad3b4.zip |
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
(This used to be commit 44766c39e0027c762bee8b33b12c621c109a3267)
Diffstat (limited to 'source3/smbd/oplock_linux.c')
-rw-r--r-- | source3/smbd/oplock_linux.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 46290683d2..de2a4300a7 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -29,7 +29,7 @@ extern int DEBUGLEVEL; static unsigned signals_received; static unsigned signals_processed; -static int fd_pending; /* the fd of the current pending SIGIO */ +static int fd_pending; /* the fd of the current pending signal */ #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -43,14 +43,19 @@ static int fd_pending; /* the fd of the current pending SIGIO */ #define CAP_LEASE 28 #endif +#ifndef RT_SIGNAL_LEASE +#define RT_SIGNAL_LEASE 33 +#endif + /**************************************************************************** -handle a SIGIO, incrementing the signals_received and blocking SIGIO +handle a LEASE signal, incrementing the signals_received and blocking the signal ****************************************************************************/ -static void sigio_handler(int signal, siginfo_t *info, void *unused) +static void signal_handler(int signal, siginfo_t *info, void *unused) { + BlockSignals(True, signal); fd_pending = info->si_fd; signals_received++; - BlockSignals(True, SIGIO); + sys_select_signal(); } /**************************************************************************** @@ -150,7 +155,7 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode )); /* now we can receive more signals */ fd_pending = -1; signals_processed++; - BlockSignals(False, SIGIO); + BlockSignals(False, RT_SIGNAL_LEASE); return True; } @@ -213,16 +218,16 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i { /* Ensure that the msg length is correct. */ if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); + DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", + msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); return False; } memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - DEBUG(5,("process_local_message: kernel oplock break request for \ -file dev = %x, inode = %.0f\n", (unsigned int)*dev, (double)*inode)); + DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n", + (unsigned int)*dev, (double)*inode)); return True; } @@ -264,10 +269,10 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) } act.sa_handler = NULL; - act.sa_sigaction = sigio_handler; + act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &act, NULL) != 0) { - DEBUG(0,("Failed to setup SIGIO handler\n")); + if (sigaction(RT_SIGNAL_LEASE, &act, NULL) != 0) { + DEBUG(0,("Failed to setup RT_SIGNAL_LEASE handler\n")); return NULL; } |