summaryrefslogtreecommitdiffstats
path: root/source/smbd/oplock.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-06-12 15:53:31 +0000
committerAndrew Tridgell <tridge@samba.org>2000-06-12 15:53:31 +0000
commit44766c39e0027c762bee8b33b12c621c109a3267 (patch)
treef2d2b7d7ef5464056d88d0fdc2f66f75fa609875 /source/smbd/oplock.c
parentabf06fa90ba49f6a1ec5458d056f8b8cf20b6512 (diff)
downloadsamba-44766c39e0027c762bee8b33b12c621c109a3267.tar.gz
samba-44766c39e0027c762bee8b33b12c621c109a3267.tar.xz
samba-44766c39e0027c762bee8b33b12c621c109a3267.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!
Diffstat (limited to 'source/smbd/oplock.c')
-rw-r--r--source/smbd/oplock.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 5e63b4d4ff5..59c3c83f6f9 100644
--- a/source/smbd/oplock.c
+++ b/source/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.