2001-03-11 03:32:10 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-06-10 18:29:31 +04:00
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 .
*/
2006-05-05 06:06:37 +04:00
# define DBGC_CLASS DBGC_LOCKING
2000-06-10 17:38:07 +04:00
# include "includes.h"
2000-06-11 09:57:58 +04:00
# if HAVE_KERNEL_OPLOCKS_IRIX
2000-06-10 17:38:07 +04:00
static int oplock_pipe_write = - 1 ;
static int oplock_pipe_read = - 1 ;
/****************************************************************************
2001-10-21 01:59:34 +04:00
Test to see if IRIX kernel oplocks work .
2000-06-10 17:38:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2000-06-10 17:38:07 +04:00
static BOOL irix_oplocks_available ( void )
{
int fd ;
int pfd [ 2 ] ;
pstring tmpname ;
2006-03-21 05:56:49 +03:00
set_effective_capability ( KERNEL_OPLOCK_CAPABILITY ) ;
2000-06-10 17:38:07 +04:00
2007-01-16 18:50:25 +03:00
slprintf ( tmpname , sizeof ( tmpname ) - 1 , " %s/koplock.%d " , lp_lockdir ( ) ,
( int ) sys_getpid ( ) ) ;
2000-06-10 17:38:07 +04:00
if ( pipe ( pfd ) ! = 0 ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " check_kernel_oplocks: Unable to create pipe. Error "
" was %s \n " ,
2000-06-10 17:38:07 +04:00
strerror ( errno ) ) ) ;
return False ;
}
if ( ( fd = sys_open ( tmpname , O_RDWR | O_CREAT | O_EXCL | O_TRUNC , 0600 ) ) < 0 ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " check_kernel_oplocks: Unable to open temp test file "
" %s. Error was %s \n " ,
2000-06-10 17:38:07 +04:00
tmpname , strerror ( errno ) ) ) ;
unlink ( tmpname ) ;
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
return False ;
}
unlink ( tmpname ) ;
2002-07-15 14:35:28 +04:00
if ( sys_fcntl_long ( fd , F_OPLKREG , pfd [ 1 ] ) = = - 1 ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " check_kernel_oplocks: Kernel oplocks are not "
" available on this machine. Disabling kernel oplock "
" support. \n " ) ) ;
2000-06-10 17:38:07 +04:00
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
close ( fd ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
if ( sys_fcntl_long ( fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " check_kernel_oplocks: Error when removing kernel "
" oplock. Error was %s. Disabling kernel oplock "
" support. \n " , strerror ( errno ) ) ) ;
2000-06-10 17:38:07 +04:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2005-09-30 21:13:37 +04:00
static files_struct * irix_oplock_receive_message ( fd_set * fds )
2000-06-10 17:38:07 +04:00
{
2000-06-20 04:32:32 +04:00
extern int smb_read_error ;
2001-10-21 01:59:34 +04:00
oplock_stat_t os ;
char dummy ;
files_struct * fsp ;
2006-02-15 02:00:39 +03:00
/* Ensure we only get one call per select fd set. */
2006-02-15 04:05:06 +03:00
FD_CLR ( oplock_pipe_read , fds ) ;
2006-02-15 02:00:39 +03:00
2001-10-21 01:59:34 +04:00
/*
* Read one byte of zero to clear the
* kernel break notify message .
*/
if ( read ( oplock_pipe_read , & dummy , 1 ) ! = 1 ) {
2005-10-01 14:00:07 +04:00
DEBUG ( 0 , ( " irix_oplock_receive_message: read of kernel "
" notification failed. Error was %s. \n " ,
strerror ( errno ) ) ) ;
2001-10-21 01:59:34 +04:00
smb_read_error = READ_ERROR ;
2005-09-30 21:13:37 +04:00
return NULL ;
2001-10-21 01:59:34 +04:00
}
/*
* Do a query to get the
* device and inode of the file that has the break
* request outstanding .
*/
2002-07-15 14:35:28 +04:00
if ( sys_fcntl_ptr ( oplock_pipe_read , F_OPLKSTAT , & os ) < 0 ) {
2005-10-01 14:00:07 +04:00
DEBUG ( 0 , ( " irix_oplock_receive_message: fcntl of kernel "
" notification failed. Error was %s. \n " ,
strerror ( errno ) ) ) ;
2001-10-21 01:59:34 +04:00
if ( errno = = EAGAIN ) {
/*
* Duplicate kernel break message - ignore .
*/
2005-10-01 14:00:07 +04:00
return NULL ;
2001-10-21 01:59:34 +04:00
}
smb_read_error = READ_ERROR ;
2005-09-30 21:13:37 +04:00
return NULL ;
2001-10-21 01:59:34 +04:00
}
/*
* We only have device and inode info here - we have to guess that this
* is the first fsp open with this dev , ino pair .
*/
2005-10-01 14:00:07 +04:00
if ( ( fsp = file_find_di_first ( ( SMB_DEV_T ) os . os_dev ,
( SMB_INO_T ) os . os_ino ) ) = = NULL ) {
DEBUG ( 0 , ( " irix_oplock_receive_message: unable to find open "
" file with dev = %x, inode = %.0f \n " ,
( unsigned int ) os . os_dev , ( double ) os . os_ino ) ) ;
return NULL ;
2001-10-21 01:59:34 +04:00
}
2000-06-10 17:38:07 +04:00
2005-10-01 14:00:07 +04:00
DEBUG ( 5 , ( " irix_oplock_receive_message: kernel oplock break request "
" received for dev = %x, inode = %.0f \n , file_id = %ul " ,
2007-01-16 18:50:25 +03:00
( unsigned int ) fsp - > dev , ( double ) fsp - > inode ,
fsp - > fh - > file_id ) ) ;
2005-09-30 21:13:37 +04:00
return fsp ;
2000-06-10 17:38:07 +04:00
}
/****************************************************************************
Attempt to set an kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2000-06-10 17:38:07 +04:00
static BOOL irix_set_kernel_oplock ( files_struct * fsp , int oplock_type )
{
2005-07-08 11:54:28 +04:00
if ( sys_fcntl_long ( fsp - > fh - > fd , F_OPLKREG , oplock_pipe_write ) = = - 1 ) {
2000-06-10 17:38:07 +04:00
if ( errno ! = EAGAIN ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " irix_set_kernel_oplock: Unable to get "
" kernel oplock on file %s, dev = %x, inode "
" = %.0f, file_id = %ul. Error was %s \n " ,
fsp - > fsp_name , ( unsigned int ) fsp - > dev ,
( double ) fsp - > inode , fsp - > fh - > file_id ,
2000-06-10 17:38:07 +04:00
strerror ( errno ) ) ) ;
} else {
2007-01-16 18:50:25 +03:00
DEBUG ( 5 , ( " irix_set_kernel_oplock: Refused oplock on "
" file %s, fd = %d, dev = %x, inode = %.0f, "
" file_id = %ul. Another process had the file "
" open. \n " ,
fsp - > fsp_name , fsp - > fh - > fd ,
( unsigned int ) fsp - > dev , ( double ) fsp - > inode ,
fsp - > fh - > file_id ) ) ;
2000-06-10 17:38:07 +04:00
}
return False ;
}
2007-01-16 18:50:25 +03:00
DEBUG ( 10 , ( " irix_set_kernel_oplock: got kernel oplock on file %s, dev "
" = %x, inode = %.0f, file_id = %ul \n " ,
fsp - > fsp_name , ( unsigned int ) fsp - > dev , ( double ) fsp - > inode ,
fsp - > fh - > file_id ) ) ;
2000-06-10 17:38:07 +04:00
return True ;
}
/****************************************************************************
Release a kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2000-06-10 17:38:07 +04:00
static void irix_release_kernel_oplock ( files_struct * fsp )
{
if ( DEBUGLVL ( 10 ) ) {
/*
* Check and print out the current kernel
* oplock state of this file .
*/
2005-07-08 11:54:28 +04:00
int state = sys_fcntl_long ( fsp - > fh - > fd , F_OPLKACK , - 1 ) ;
2007-01-16 18:50:25 +03:00
dbgtext ( " irix_release_kernel_oplock: file %s, dev = %x, "
" inode = %.0f file_id = %ul, has kernel oplock state "
" of %x. \n " , fsp - > fsp_name , ( unsigned int ) fsp - > dev ,
2006-05-18 03:15:53 +04:00
( double ) fsp - > inode , fsp - > fh - > file_id , state ) ;
2000-06-10 17:38:07 +04:00
}
/*
* Remove the kernel oplock on this file .
*/
2005-07-08 11:54:28 +04:00
if ( sys_fcntl_long ( fsp - > fh - > fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
2000-06-10 17:38:07 +04:00
if ( DEBUGLVL ( 0 ) ) {
2007-01-16 18:50:25 +03:00
dbgtext ( " irix_release_kernel_oplock: Error when "
" removing kernel oplock on file " ) ;
dbgtext ( " %s, dev = %x, inode = %.0f, file_id = %ul. "
" Error was %s \n " ,
2000-06-10 17:38:07 +04:00
fsp - > fsp_name , ( unsigned int ) fsp - > dev ,
2007-01-16 18:50:25 +03:00
( double ) fsp - > inode , fsp - > fh - > file_id ,
strerror ( errno ) ) ;
2000-06-10 17:38:07 +04:00
}
}
}
/****************************************************************************
2006-02-27 21:48:33 +03:00
See if there is a message waiting in this fd set .
2006-02-15 02:00:39 +03:00
Note that fds MAY BE NULL ! If so we must do our own select .
2000-06-10 17:38:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2000-06-10 17:38:07 +04:00
static BOOL irix_oplock_msg_waiting ( fd_set * fds )
{
2006-02-27 21:48:33 +03:00
int selrtn ;
2006-02-15 02:00:39 +03:00
fd_set myfds ;
struct timeval to ;
2001-10-21 01:59:34 +04:00
if ( oplock_pipe_read = = - 1 )
return False ;
2000-06-10 17:38:07 +04:00
2006-02-15 02:00:39 +03:00
if ( fds ) {
2006-02-15 04:05:06 +03:00
return FD_ISSET ( oplock_pipe_read , fds ) ;
2006-02-15 02:00:39 +03:00
}
/* Do a zero-time select. We just need to find out if there
* are any outstanding messages . We use sys_select_intr as
* we need to ignore any signals . */
2006-02-15 04:05:06 +03:00
FD_ZERO ( & myfds ) ;
FD_SET ( oplock_pipe_read , & myfds ) ;
2006-02-15 02:00:39 +03:00
to = timeval_set ( 0 , 0 ) ;
2006-02-15 04:05:06 +03:00
selrtn = sys_select_intr ( oplock_pipe_read + 1 , & myfds , NULL , NULL , & to ) ;
2006-02-15 02:00:39 +03:00
return ( selrtn = = 1 ) ? True : False ;
2000-06-10 17:38:07 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Setup kernel oplocks .
2000-06-10 17:38:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2000-06-10 17:38:07 +04:00
struct kernel_oplocks * irix_init_kernel_oplocks ( void )
{
int pfd [ 2 ] ;
static struct kernel_oplocks koplocks ;
2001-10-21 01:59:34 +04:00
if ( ! irix_oplocks_available ( ) )
return NULL ;
2000-06-10 17:38:07 +04:00
if ( pipe ( pfd ) ! = 0 ) {
2007-01-16 18:50:25 +03:00
DEBUG ( 0 , ( " setup_kernel_oplock_pipe: Unable to create pipe. "
" Error was %s \n " , strerror ( errno ) ) ) ;
2000-06-10 17:38:07 +04:00
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 . msg_waiting = irix_oplock_msg_waiting ;
koplocks . notification_fd = oplock_pipe_read ;
return & koplocks ;
}
# else
2006-12-12 23:15:47 +03:00
void oplock_irix_dummy ( void ) ;
2000-06-10 17:38:07 +04:00
void oplock_irix_dummy ( void ) { }
# endif /* HAVE_KERNEL_OPLOCKS_IRIX */