2001-03-11 00:32:10 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
2000-06-10 14:29:31 +00:00
IRIX kernel oplock processing
2000-06-10 13:38:07 +00: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
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2000-06-10 13:38:07 +00:00
( 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
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-06-10 13:38:07 +00:00
*/
2006-05-05 02:06:37 +00:00
# define DBGC_CLASS DBGC_LOCKING
2000-06-10 13:38:07 +00:00
# include "includes.h"
2000-06-11 05:57:58 +00:00
# if HAVE_KERNEL_OPLOCKS_IRIX
2000-06-10 13:38:07 +00:00
static int oplock_pipe_write = - 1 ;
static int oplock_pipe_read = - 1 ;
/****************************************************************************
2001-10-20 21:59:34 +00:00
Test to see if IRIX kernel oplocks work .
2000-06-10 13:38:07 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-20 21:59:34 +00:00
2007-10-18 17:40:25 -07:00
static bool irix_oplocks_available ( void )
2000-06-10 13:38:07 +00:00
{
int fd ;
int pfd [ 2 ] ;
2007-09-14 01:07:57 +00:00
TALLOC_CTX * ctx = talloc_stackframe ( ) ;
char * tmpname = NULL ;
2000-06-10 13:38:07 +00:00
2006-03-21 02:56:49 +00:00
set_effective_capability ( KERNEL_OPLOCK_CAPABILITY ) ;
2000-06-10 13:38:07 +00:00
2007-09-14 01:07:57 +00:00
tmpname = talloc_asprintf ( ctx ,
" %s/koplock.%d " ,
lp_lockdir ( ) ,
( int ) sys_getpid ( ) ) ;
if ( ! tmpname ) {
TALLOC_FREE ( ctx ) ;
return False ;
}
2000-06-10 13:38:07 +00:00
if ( pipe ( pfd ) ! = 0 ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " check_kernel_oplocks: Unable to create pipe. Error "
" was %s \n " ,
2000-06-10 13:38:07 +00:00
strerror ( errno ) ) ) ;
2007-09-14 01:07:57 +00:00
TALLOC_FREE ( ctx ) ;
2000-06-10 13:38:07 +00:00
return False ;
}
if ( ( fd = sys_open ( tmpname , O_RDWR | O_CREAT | O_EXCL | O_TRUNC , 0600 ) ) < 0 ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " check_kernel_oplocks: Unable to open temp test file "
" %s. Error was %s \n " ,
2000-06-10 13:38:07 +00:00
tmpname , strerror ( errno ) ) ) ;
unlink ( tmpname ) ;
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
2007-09-14 01:07:57 +00:00
TALLOC_FREE ( ctx ) ;
2000-06-10 13:38:07 +00:00
return False ;
}
unlink ( tmpname ) ;
2007-09-14 01:07:57 +00:00
TALLOC_FREE ( ctx ) ;
2002-07-15 10:35:28 +00:00
if ( sys_fcntl_long ( fd , F_OPLKREG , pfd [ 1 ] ) = = - 1 ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " check_kernel_oplocks: Kernel oplocks are not "
" available on this machine. Disabling kernel oplock "
" support. \n " ) ) ;
2000-06-10 13:38:07 +00:00
close ( pfd [ 0 ] ) ;
close ( pfd [ 1 ] ) ;
close ( fd ) ;
return False ;
}
2002-07-15 10:35:28 +00:00
if ( sys_fcntl_long ( fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " check_kernel_oplocks: Error when removing kernel "
" oplock. Error was %s. Disabling kernel oplock "
" support. \n " , strerror ( errno ) ) ) ;
2000-06-10 13:38:07 +00: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-20 21:59:34 +00:00
2005-09-30 17:13:37 +00:00
static files_struct * irix_oplock_receive_message ( fd_set * fds )
2000-06-10 13:38:07 +00:00
{
2001-10-20 21:59:34 +00:00
oplock_stat_t os ;
char dummy ;
2007-08-07 14:06:27 +00:00
struct file_id fileid ;
2001-10-20 21:59:34 +00:00
files_struct * fsp ;
2006-02-14 23:00:39 +00:00
/* Ensure we only get one call per select fd set. */
2006-02-15 01:05:06 +00:00
FD_CLR ( oplock_pipe_read , fds ) ;
2006-02-14 23:00:39 +00:00
2001-10-20 21:59:34 +00:00
/*
* Read one byte of zero to clear the
* kernel break notify message .
*/
if ( read ( oplock_pipe_read , & dummy , 1 ) ! = 1 ) {
2005-10-01 10:00:07 +00:00
DEBUG ( 0 , ( " irix_oplock_receive_message: read of kernel "
" notification failed. Error was %s. \n " ,
strerror ( errno ) ) ) ;
2005-09-30 17:13:37 +00:00
return NULL ;
2001-10-20 21:59:34 +00:00
}
/*
* Do a query to get the
* device and inode of the file that has the break
* request outstanding .
*/
2002-07-15 10:35:28 +00:00
if ( sys_fcntl_ptr ( oplock_pipe_read , F_OPLKSTAT , & os ) < 0 ) {
2005-10-01 10:00:07 +00:00
DEBUG ( 0 , ( " irix_oplock_receive_message: fcntl of kernel "
" notification failed. Error was %s. \n " ,
strerror ( errno ) ) ) ;
2001-10-20 21:59:34 +00:00
if ( errno = = EAGAIN ) {
/*
* Duplicate kernel break message - ignore .
*/
2005-10-01 10:00:07 +00:00
return NULL ;
2001-10-20 21:59:34 +00:00
}
2005-09-30 17:13:37 +00:00
return NULL ;
2001-10-20 21:59:34 +00: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 .
2007-08-07 14:06:27 +00:00
*
* NOTE : this doesn ' t work if any VFS modules overloads
* the file_id_create ( ) hook !
2001-10-20 21:59:34 +00:00
*/
2007-08-07 14:06:27 +00:00
fileid = file_id_create_dev ( ( SMB_DEV_T ) os . os_dev ,
( SMB_INO_T ) os . os_ino ) ;
if ( ( fsp = file_find_di_first ( fileid ) ) = = NULL ) {
2005-10-01 10:00:07 +00:00
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-20 21:59:34 +00:00
}
2000-06-10 13:38:07 +00:00
2005-10-01 10:00:07 +00:00
DEBUG ( 5 , ( " irix_oplock_receive_message: kernel oplock break request "
2007-05-29 09:30:34 +00:00
" received for file_id %s gen_id = %ul " ,
2007-09-10 10:56:07 +00:00
file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id ) ) ;
2005-09-30 17:13:37 +00:00
return fsp ;
2000-06-10 13:38:07 +00:00
}
/****************************************************************************
Attempt to set an kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-20 21:59:34 +00:00
2007-10-18 17:40:25 -07:00
static bool irix_set_kernel_oplock ( files_struct * fsp , int oplock_type )
2000-06-10 13:38:07 +00:00
{
2005-07-08 07:54:28 +00:00
if ( sys_fcntl_long ( fsp - > fh - > fd , F_OPLKREG , oplock_pipe_write ) = = - 1 ) {
2000-06-10 13:38:07 +00:00
if ( errno ! = EAGAIN ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " irix_set_kernel_oplock: Unable to get "
2007-05-29 09:30:34 +00:00
" kernel oplock on file %s, file_id %s "
" gen_id = %ul. Error was %s \n " ,
2007-09-10 10:56:07 +00:00
fsp - > fsp_name , file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id ,
2000-06-10 13:38:07 +00:00
strerror ( errno ) ) ) ;
} else {
2007-01-16 15:50:25 +00:00
DEBUG ( 5 , ( " irix_set_kernel_oplock: Refused oplock on "
2007-05-29 09:30:34 +00:00
" file %s, fd = %d, file_id = 5s, "
" gen_id = %ul. Another process had the file "
2007-01-16 15:50:25 +00:00
" open. \n " ,
fsp - > fsp_name , fsp - > fh - > fd ,
2007-09-10 10:56:07 +00:00
file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id ) ) ;
2000-06-10 13:38:07 +00:00
}
return False ;
}
2007-05-29 09:30:34 +00:00
DEBUG ( 10 , ( " irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
" gen_id = %ul \n " ,
2007-09-10 10:56:07 +00:00
fsp - > fsp_name , file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id ) ) ;
2000-06-10 13:38:07 +00:00
return True ;
}
/****************************************************************************
Release a kernel oplock on a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-20 21:59:34 +00:00
2000-06-10 13:38:07 +00: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 07:54:28 +00:00
int state = sys_fcntl_long ( fsp - > fh - > fd , F_OPLKACK , - 1 ) ;
2007-05-29 09:30:34 +00:00
dbgtext ( " irix_release_kernel_oplock: file %s, file_id = %s "
" gen_id = %ul, has kernel oplock state "
2007-09-10 10:56:07 +00:00
" of %x. \n " , fsp - > fsp_name , file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id , state ) ;
2000-06-10 13:38:07 +00:00
}
/*
* Remove the kernel oplock on this file .
*/
2005-07-08 07:54:28 +00:00
if ( sys_fcntl_long ( fsp - > fh - > fd , F_OPLKACK , OP_REVOKE ) < 0 ) {
2000-06-10 13:38:07 +00:00
if ( DEBUGLVL ( 0 ) ) {
2007-01-16 15:50:25 +00:00
dbgtext ( " irix_release_kernel_oplock: Error when "
" removing kernel oplock on file " ) ;
2007-05-29 09:30:34 +00:00
dbgtext ( " %s, file_id = %s gen_id = %ul. "
2007-01-16 15:50:25 +00:00
" Error was %s \n " ,
2007-09-10 10:56:07 +00:00
fsp - > fsp_name , file_id_string_tos ( & fsp - > file_id ) ,
2007-05-29 09:30:34 +00:00
fsp - > fh - > gen_id ,
2007-01-16 15:50:25 +00:00
strerror ( errno ) ) ;
2000-06-10 13:38:07 +00:00
}
}
}
/****************************************************************************
2006-02-27 18:48:33 +00:00
See if there is a message waiting in this fd set .
2006-02-14 23:00:39 +00:00
Note that fds MAY BE NULL ! If so we must do our own select .
2000-06-10 13:38:07 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-20 21:59:34 +00:00
2007-10-18 17:40:25 -07:00
static bool irix_oplock_msg_waiting ( fd_set * fds )
2000-06-10 13:38:07 +00:00
{
2006-02-27 18:48:33 +00:00
int selrtn ;
2006-02-14 23:00:39 +00:00
fd_set myfds ;
struct timeval to ;
2001-10-20 21:59:34 +00:00
if ( oplock_pipe_read = = - 1 )
return False ;
2000-06-10 13:38:07 +00:00
2006-02-14 23:00:39 +00:00
if ( fds ) {
2006-02-15 01:05:06 +00:00
return FD_ISSET ( oplock_pipe_read , fds ) ;
2006-02-14 23:00:39 +00: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 01:05:06 +00:00
FD_ZERO ( & myfds ) ;
FD_SET ( oplock_pipe_read , & myfds ) ;
2006-02-14 23:00:39 +00:00
to = timeval_set ( 0 , 0 ) ;
2006-02-15 01:05:06 +00:00
selrtn = sys_select_intr ( oplock_pipe_read + 1 , & myfds , NULL , NULL , & to ) ;
2006-02-14 23:00:39 +00:00
return ( selrtn = = 1 ) ? True : False ;
2000-06-10 13:38:07 +00:00
}
/****************************************************************************
2001-10-20 21:59:34 +00:00
Setup kernel oplocks .
2000-06-10 13:38:07 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-20 21:59:34 +00:00
2000-06-10 13:38:07 +00:00
struct kernel_oplocks * irix_init_kernel_oplocks ( void )
{
int pfd [ 2 ] ;
static struct kernel_oplocks koplocks ;
2001-10-20 21:59:34 +00:00
if ( ! irix_oplocks_available ( ) )
return NULL ;
2000-06-10 13:38:07 +00:00
if ( pipe ( pfd ) ! = 0 ) {
2007-01-16 15:50:25 +00:00
DEBUG ( 0 , ( " setup_kernel_oplock_pipe: Unable to create pipe. "
" Error was %s \n " , strerror ( errno ) ) ) ;
2000-06-10 13:38:07 +00: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 20:15:47 +00:00
void oplock_irix_dummy ( void ) ;
2000-06-10 13:38:07 +00:00
void oplock_irix_dummy ( void ) { }
# endif /* HAVE_KERNEL_OPLOCKS_IRIX */