static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval);
+/****************************************************************************
+ Setup the kernel level oplock backchannel for this process.
+****************************************************************************/
+
+BOOL setup_kernel_oplock_pipe(void)
+{
+#if defined(HAVE_KERNEL_OPLOCKS)
+ if(lp_kernel_oplocks()) {
+ int pfd[2];
+
+ if(pipe(pfd) != 0) {
+ DEBUG(0,("setup_kernel_oplock_pipe: Unable to create pipe. Error was %s\n",
+ strerror(errno) ));
+ return False;
+ }
+
+ oplock_pipe_read = pfd[0];
+ oplock_pipe_write = pfd[1];
+ }
+#endif /* HAVE_KERNEL_OPLOCKS */
+ return True;
+}
+
/****************************************************************************
open the oplock IPC socket communication
****************************************************************************/
if (oplock_sock == -1)
{
DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
-address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
+address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno)));
global_oplock_port = 0;
return(False);
}
}
global_oplock_port = ntohs(sock_name.sin_port);
+ if(!setup_kernel_oplock_pipe())
+ return False;
+
DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n",
(int)getpid(), global_oplock_port));
if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \
Error was %s.\n", strerror(errno) ));
+ if(errno == EAGAIN) {
+ /*
+ * Duplicate kernel break message - ignore.
+ */
+ memset(buffer, '\0', KERNEL_OPLOCK_BREAK_MSG_LEN);
+ return True;
+ }
smb_read_error = READ_ERROR;
return False;
}
inode = (SMB_DEV_T)os.os_ino;
DEBUG(5,("receive_local_message: kernel oplock break request received for \
-dev = %x, inode = %0.f\n", (unsigned int)dev, (double)inode ));
+dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ));
/*
* Create a kernel oplock break message.
/* Validate message from address (must be localhost). */
if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
DEBUG(0,("receive_local_message: invalid 'from' address \
-(was %x should be 127.0.0.1\n", from.sin_addr.s_addr));
+(was %lx should be 127.0.0.1\n", (long)from.sin_addr.s_addr));
return False;
}
{
#if defined(HAVE_KERNEL_OPLOCKS)
if(lp_kernel_oplocks()) {
- if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) {
+
+ if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0 ) {
if(errno != EAGAIN) {
DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \
-inode = %0.f. Error was %s\n",
+inode = %.0f. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode,
strerror(errno) ));
} else {
- DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \
-inode = %0.f. Another process had the file open.\n",
- fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode ));
+ DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
+inode = %.0f. Another process had the file open.\n",
+ fsp->fsp_name, fsp->fd_ptr->fd, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode ));
}
return False;
}
+
+ DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n",
+ fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode));
+
}
#endif /* HAVE_KERNEL_OPLOCKS */
static void release_file_oplock(files_struct *fsp)
{
#if defined(HAVE_KERNEL_OPLOCKS)
- if(fsp->granted_oplock && lp_kernel_oplocks())
+
+ if(lp_kernel_oplocks())
{
if( DEBUGLVL( 10 ))
{
}
/*
- * Remove the kernel oplock on this file.
+ * Remote the kernel oplock on this file.
*/
if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0)
dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
- tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
- tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
+ tval.tv_sec = (time_t)IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
+ tval.tv_usec = (long)IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
ptval = &tval;
connection_struct *saved_conn;
int saved_vuid;
pstring saved_dir;
+ int break_counter = OPLOCK_BREAK_RESENDS;
if( DEBUGLVL( 3 ) )
{
*/
saved_conn = fsp->conn;
saved_vuid = current_user.vuid;
- GetWd(saved_dir);
+ dos_GetWd(saved_dir);
unbecome_user();
/* Save the chain fnum. */
file_chain_save();
while(OPEN_FSP(fsp) && fsp->granted_oplock)
{
- if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
+ if(receive_smb(Client,inbuf,
+ (OPLOCK_BREAK_TIMEOUT/OPLOCK_BREAK_RESENDS) * 1000) == False)
{
+
+ /* Isaac suggestd that if a MS client doesn't respond to a
+ oplock break request then we might try resending
+ it. Certainly it's no worse than just dropping the
+ socket! */
+ if (smb_read_error == READ_TIMEOUT && break_counter--) {
+ DEBUG(2, ( "oplock_break resend\n" ) );
+ send_smb(Client, outbuf);
+ continue;
+ }
+
/*
* Die if we got an error.
*/
exit_server("unable to re-become user");
}
/* Including the directory. */
- ChDir(saved_dir);
+ dos_ChDir(saved_dir);
/* Restore the chain fnum. */
file_chain_restore();
DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name));
- if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) {
+ if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break && (fsp->fd_ptr != NULL)) {
/* Try and break the oplock. */
file_fd_struct *fd_ptr = fsp->fd_ptr;
int pfd[2];
pstring tmpname;
- slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid());
- mktemp(tmpname);
+ set_process_capability(KERNEL_OPLOCK_CAPABILITY,True);
+ set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,True);
+
+ slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)getpid());
if(pipe(pfd) != 0) {
DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n",
return;
}
- if((fd = open(tmpname, O_RDWR)) < 0) {
+ if((fd = sys_open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) {
DEBUG(0,("check_kernel_oplocks: Unable to open temp test file %s. Error was %s\n",
tmpname, strerror(errno) ));
unlink( tmpname );
if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) {
DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \
-Disabling kernel oplock supprt.\n" ));
+Disabling kernel oplock support.\n" ));
close(pfd[0]);
close(pfd[1]);
close(fd);
if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
-Disabling kernel oplock supprt.\n" ));
+Disabling kernel oplock support.\n", strerror(errno) ));
close(pfd[0]);
close(pfd[1]);
close(fd);
return;
}
- oplock_pipe_read = pfd[0];
- oplock_pipe_write = pfd[1];
+ close(pfd[0]);
+ close(pfd[1]);
close(fd);
- DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n"));
-
lp_set_kernel_oplocks(True);
+
+ DEBUG(0,("check_kernel_oplocks: Kernel oplocks available and set to %s.\n",
+ lp_kernel_oplocks() ? "True" : "False" ));
+
}
#endif /* HAVE_KERNEL_OPLOCKS */
}