1
0
mirror of https://github.com/samba-team/samba.git synced 2025-10-29 04:23:51 +03:00
Files
samba-mirror/source/smbd/oplock_irix.c
Volker Lendecke 9b10dbbd5d r23183: Check in a change made by Tridge:
This replaces the internal explicit dev/ino file id representation by a
"struct file_id". This is necessary as cluster file systems and NFS
don't necessarily assign the same device number to the shared file
system. With this structure in place we can now easily add different
schemes to map a file to a unique 64-bit device node.

Jeremy, you might note that I did not change the external interface of
smb_share_modes.c.

Volker
2007-10-10 12:22:52 -05:00

290 lines
8.0 KiB
C

/*
Unix SMB/CIFS implementation.
IRIX kernel oplock processing
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 02139, USA.
*/
#define DBGC_CLASS DBGC_LOCKING
#include "includes.h"
#if HAVE_KERNEL_OPLOCKS_IRIX
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;
set_effective_capability(KERNEL_OPLOCK_CAPABILITY);
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(sys_fcntl_long(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(sys_fcntl_long(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 files_struct *irix_oplock_receive_message(fd_set *fds)
{
extern int smb_read_error;
oplock_stat_t os;
char dummy;
files_struct *fsp;
/* Ensure we only get one call per select fd set. */
FD_CLR(oplock_pipe_read, fds);
/*
* Read one byte of zero to clear the
* kernel break notify message.
*/
if(read(oplock_pipe_read, &dummy, 1) != 1) {
DEBUG(0,("irix_oplock_receive_message: read of kernel "
"notification failed. Error was %s.\n",
strerror(errno) ));
smb_read_error = READ_ERROR;
return NULL;
}
/*
* Do a query to get the
* device and inode of the file that has the break
* request outstanding.
*/
if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
DEBUG(0,("irix_oplock_receive_message: fcntl of kernel "
"notification failed. Error was %s.\n",
strerror(errno) ));
if(errno == EAGAIN) {
/*
* Duplicate kernel break message - ignore.
*/
return NULL;
}
smb_read_error = READ_ERROR;
return NULL;
}
/*
* We only have device and inode info here - we have to guess that this
* is the first fsp open with this dev,ino pair.
*/
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;
}
DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
"received for file_id %s gen_id = %ul",
file_id_static_string(&fsp->file_id),
fsp->fh->gen_id ));
return fsp;
}
/****************************************************************************
Attempt to set an kernel oplock on a file.
****************************************************************************/
static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) {
if(errno != EAGAIN) {
DEBUG(0,("irix_set_kernel_oplock: Unable to get "
"kernel oplock on file %s, file_id %s "
"gen_id = %ul. Error was %s\n",
fsp->fsp_name, file_id_static_string(&fsp->file_id),
fsp->fh->gen_id,
strerror(errno) ));
} else {
DEBUG(5,("irix_set_kernel_oplock: Refused oplock on "
"file %s, fd = %d, file_id = 5s, "
"gen_id = %ul. Another process had the file "
"open.\n",
fsp->fsp_name, fsp->fh->fd,
file_id_static_string(&fsp->file_id),
fsp->fh->gen_id ));
}
return False;
}
DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
"gen_id = %ul\n",
fsp->fsp_name, file_id_static_string(&fsp->file_id),
fsp->fh->gen_id));
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 = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
dbgtext("irix_release_kernel_oplock: file %s, file_id = %s"
"gen_id = %ul, has kernel oplock state "
"of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id),
fsp->fh->gen_id, state );
}
/*
* Remove the kernel oplock on this file.
*/
if(sys_fcntl_long(fsp->fh->fd, F_OPLKACK, OP_REVOKE) < 0) {
if( DEBUGLVL( 0 )) {
dbgtext("irix_release_kernel_oplock: Error when "
"removing kernel oplock on file " );
dbgtext("%s, file_id = %s gen_id = %ul. "
"Error was %s\n",
fsp->fsp_name, file_id_static_string(&fsp->file_id),
fsp->fh->gen_id,
strerror(errno) );
}
}
}
/****************************************************************************
See if there is a message waiting in this fd set.
Note that fds MAY BE NULL ! If so we must do our own select.
****************************************************************************/
static BOOL irix_oplock_msg_waiting(fd_set *fds)
{
int selrtn;
fd_set myfds;
struct timeval to;
if (oplock_pipe_read == -1)
return False;
if (fds) {
return FD_ISSET(oplock_pipe_read, fds);
}
/* 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. */
FD_ZERO(&myfds);
FD_SET(oplock_pipe_read, &myfds);
to = timeval_set(0, 0);
selrtn = sys_select_intr(oplock_pipe_read+1,&myfds,NULL,NULL,&to);
return (selrtn == 1) ? True : False;
}
/****************************************************************************
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.msg_waiting = irix_oplock_msg_waiting;
koplocks.notification_fd = oplock_pipe_read;
return &koplocks;
}
#else
void oplock_irix_dummy(void);
void oplock_irix_dummy(void) {}
#endif /* HAVE_KERNEL_OPLOCKS_IRIX */