diff options
Diffstat (limited to 'source3/smbd/oplock_linux.c')
-rw-r--r-- | source3/smbd/oplock_linux.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 85f89c12a0..d946578380 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -22,9 +22,9 @@ #if HAVE_KERNEL_OPLOCKS_LINUX -static SIG_ATOMIC_T signals_received; -#define FD_PENDING_SIZE 100 -static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; +static VOLATILE sig_atomic_t signals_received; +static VOLATILE sig_atomic_t signals_processed; +static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal */ #ifndef F_SETLEASE #define F_SETLEASE 1024 @@ -52,10 +52,9 @@ static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; static void signal_handler(int sig, siginfo_t *info, void *unused) { - if (signals_received < FD_PENDING_SIZE - 1) { - fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd; - signals_received++; - } /* Else signal is lost. */ + BlockSignals(True, sig); + fd_pending = (sig_atomic_t)info->si_fd; + signals_received++; sys_select_signal(); } @@ -125,28 +124,20 @@ static int linux_setlease(int fd, int leasetype) static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) { - int fd; + BOOL ret = True; struct 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 (signals_received > 1) - memmove((void *)&fd_pending_array[0], (void *)&fd_pending_array[1], - sizeof(SIG_ATOMIC_T)*(signals_received-1)); - signals_received--; - /* now we can receive more signals */ - BlockSignals(False, RT_SIGNAL_LEASE); - - if (fsp == NULL) { - DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd)); + if (signals_received == signals_processed) return False; + + if ((fsp = file_find_fd(fd_pending)) == NULL) { + DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd_pending)); + ret = False; + goto out; } - DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \ -dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode, - fd, fsp->file_id)); + DEBUG(3,("receive_local_message: kernel oplock break request received for \ +dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode )); /* * Create a kernel oplock break message. @@ -164,7 +155,13 @@ dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (doubl memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - return True; + out: + /* now we can receive more signals */ + fd_pending = (sig_atomic_t)-1; + signals_processed++; + BlockSignals(False, RT_SIGNAL_LEASE); + + return ret; } /**************************************************************************** @@ -174,14 +171,14 @@ dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (doubl static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if (linux_setlease(fsp->fd, F_WRLCK) == -1) { - DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ + DEBUG(3,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. (%s)\n", fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno))); return False; } - DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", + DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id)); return True; @@ -199,7 +196,7 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fd, F_GETLEASE, 0); - dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ + dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, state ); } @@ -209,7 +206,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, */ if (linux_setlease(fsp->fd, F_UNLCK) == -1) { if (DEBUGLVL(0)) { - dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " ); + dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " ); dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id, strerror(errno) ); @@ -247,7 +244,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i static BOOL linux_oplock_msg_waiting(fd_set *fds) { - return signals_received != 0; + return signals_processed != signals_received; } /**************************************************************************** |