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.c | |
parent | 6de513cef43ad83ecd1823bde5a4e05c22224b0f (diff) | |
download | samba-b2d01bd2dbfed8b35cc324fad42eac562fcad3b4.tar.gz samba-b2d01bd2dbfed8b35cc324fad42eac562fcad3b4.tar.xz 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.c')
-rw-r--r-- | source3/smbd/oplock.c | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 5e63b4d4ff5..59c3c83f6f9 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -71,44 +71,47 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou smb_read_error = 0; if(timeout != 0) { - struct timeval to; - int selrtn; - int maxfd = oplock_sock; + struct timeval to; + int selrtn; + int maxfd = oplock_sock; - if (koplocks && koplocks->notification_fd != -1) { - FD_SET(koplocks->notification_fd, fds); - } + if (koplocks && koplocks->notification_fd != -1) { + FD_SET(koplocks->notification_fd, fds); + maxfd = MAX(maxfd, koplocks->notification_fd); + } - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; - selrtn = sys_select(maxfd+1,fds,&to); + selrtn = sys_select(maxfd+1,fds,&to); - if (selrtn == -1 && errno == EINTR) { - /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(fds)) { - return koplocks->receive_message(fds, buffer, buffer_len); - } - } + if (selrtn == -1 && errno == EINTR) { + /* could be a kernel oplock interrupt */ + if (koplocks && koplocks->msg_waiting(fds)) { + return koplocks->receive_message(fds, buffer, buffer_len); + } + } - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } + /* Check if error */ + if(selrtn == -1) { + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return False; + } - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } + /* Did we timeout ? */ + if (selrtn == 0) { + smb_read_error = READ_TIMEOUT; + return False; + } } if (koplocks && koplocks->msg_waiting(fds)) { return koplocks->receive_message(fds, buffer, buffer_len); } + if (!FD_ISSET(oplock_sock, fds)) return False; + /* * From here down we deal with the smbd <--> smbd * oplock break protocol only. |