2000-06-10 17:38:07 +04:00
# define OLD_NTDOMAIN 1
/*
Unix SMB / Netbios implementation .
2000-06-10 18:29:31 +04:00
Version 2. x
IRIX kernel oplock processing
2000-06-10 17:38:07 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2000-06-11 09:57:58 +04:00
# if HAVE_KERNEL_OPLOCKS_IRIX
2000-06-10 17:38:07 +04:00
extern int DEBUGLEVEL ;
static int oplock_pipe_write = - 1 ;
static int oplock_pipe_read = - 1 ;
/****************************************************************************
test to see if IRIX kernel oplocks work
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL irix_oplocks_available ( void )
{
int fd ;
int pfd [ 2 ] ;
pstring tmpname ;
oplock_set_capability ( True , False ) ;
slprintf ( tmpname , sizeof ( tmpname ) - 1 , " %s/koplock.%d " , lp_lockdir ( ) , ( int ) sys_getpid ( ) ) ;
if ( pipe ( pfd ) ! = 0 ) {
DEBUG ( 0 , ( " check_kernel_oplocks: Unable to create pipe. Error was %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
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 ) ;
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
return False ;
}
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 support . \ n " ));
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
close ( fd ) ;
return False ;
}
if ( fcntl ( fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
DEBUG ( 0 , ( " check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
Disabling kernel oplock support . \ n " , strerror(errno) ));
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
close ( fd ) ;
return False ;
}
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
close ( fd ) ;
return True ;
}
/****************************************************************************
* Deal with the IRIX kernel < - - > smbd
* oplock break protocol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL irix_oplock_receive_message ( fd_set * fds , char * buffer , int buffer_len )
{
oplock_stat_t os ;
SMB_DEV_T dev ;
SMB_INO_T inode ;
char dummy ;
/*
* Read one byte of zero to clear the
* kernel break notify message .
*/
if ( read ( oplock_pipe_read , & dummy , 1 ) ! = 1 ) {
DEBUG ( 0 , ( " receive_local_message: read of kernel notification failed. \
Error was % s . \ n " , strerror(errno) ));
smb_read_error = READ_ERROR ;
return False ;
}
/*
* Do a query to get the
* device and inode of the file that has the break
* request outstanding .
*/
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 ;
}
dev = ( SMB_DEV_T ) os . os_dev ;
inode = ( SMB_INO_T ) os . os_ino ;
DEBUG ( 5 , ( " receive_local_message: kernel oplock break request received for \
dev = % x , inode = % .0f \ n " , (unsigned int)dev, (double)inode ));
/*
* Create a kernel oplock break message .
*/
/* Setup the message header */
SIVAL ( buffer , OPBRK_CMD_LEN_OFFSET , KERNEL_OPLOCK_BREAK_MSG_LEN ) ;
SSVAL ( buffer , OPBRK_CMD_PORT_OFFSET , 0 ) ;
buffer + = OPBRK_CMD_HEADER_LEN ;
SSVAL ( buffer , OPBRK_MESSAGE_CMD_OFFSET , KERNEL_OPLOCK_BREAK_CMD ) ;
memcpy ( buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET , ( char * ) & dev , sizeof ( dev ) ) ;
memcpy ( buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET , ( char * ) & inode , sizeof ( inode ) ) ;
return True ;
}
/****************************************************************************
Attempt to set an kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL irix_set_kernel_oplock ( files_struct * fsp , int oplock_type )
{
if ( fcntl ( fsp - > fd , F_OPLKREG , oplock_pipe_write ) = = - 1 ) {
if ( errno ! = EAGAIN ) {
DEBUG ( 0 , ( " set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \
inode = % .0f . Error was % s \ n " ,
fsp - > fsp_name , ( unsigned int ) fsp - > dev , ( double ) fsp - > inode ,
strerror ( errno ) ) ) ;
} else {
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 , ( unsigned int ) fsp - > dev , ( double ) fsp - > 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 - > dev , ( double ) fsp - > inode ) ) ;
return True ;
}
/****************************************************************************
Release a kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void irix_release_kernel_oplock ( files_struct * fsp )
{
if ( DEBUGLVL ( 10 ) ) {
/*
* Check and print out the current kernel
* oplock state of this file .
*/
int state = fcntl ( fsp - > fd , F_OPLKACK , - 1 ) ;
dbgtext ( " release_kernel_oplock: file %s, dev = %x, inode = %.0f has kernel \
oplock state of % x . \ n " , fsp->fsp_name, (unsigned int)fsp->dev,
( double ) fsp - > inode , state ) ;
}
/*
* Remove the kernel oplock on this file .
*/
if ( fcntl ( fsp - > fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
if ( DEBUGLVL ( 0 ) ) {
dbgtext ( " release_kernel_oplock: Error when removing kernel oplock on file " ) ;
dbgtext ( " %s, dev = %x, inode = %.0f. Error was %s \n " ,
fsp - > fsp_name , ( unsigned int ) fsp - > dev ,
( double ) fsp - > inode , strerror ( errno ) ) ;
}
}
}
/****************************************************************************
parse a kernel oplock message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL irix_kernel_oplock_parse ( char * msg_start , int msg_len , SMB_INO_T * inode , SMB_DEV_T * dev )
{
/* 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));
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 \
2000-06-11 09:57:58 +04:00
file dev = % x , inode = % .0f \ n " , (unsigned int)*dev, (double)*inode));
2000-06-10 17:38:07 +04:00
return True ;
}
/****************************************************************************
set * maxfd to include oplock read pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL irix_oplock_msg_waiting ( fd_set * fds )
{
if ( oplock_pipe_read = = - 1 ) return False ;
return FD_ISSET ( oplock_pipe_read , fds ) ;
}
/****************************************************************************
setup kernel oplocks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct kernel_oplocks * irix_init_kernel_oplocks ( void )
{
int pfd [ 2 ] ;
static struct kernel_oplocks koplocks ;
if ( ! irix_oplocks_available ( ) ) return NULL ;
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 ] ;
koplocks . receive_message = irix_oplock_receive_message ;
koplocks . set_oplock = irix_set_kernel_oplock ;
koplocks . release_oplock = irix_release_kernel_oplock ;
koplocks . parse_message = irix_kernel_oplock_parse ;
koplocks . msg_waiting = irix_oplock_msg_waiting ;
koplocks . notification_fd = oplock_pipe_read ;
return & koplocks ;
}
# else
void oplock_irix_dummy ( void ) { }
# endif /* HAVE_KERNEL_OPLOCKS_IRIX */
# undef OLD_NTDOMAIN