summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/open.c20
-rw-r--r--source3/smbd/oplock.c61
2 files changed, 76 insertions, 5 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 394c7be3f8..abbc0d6741 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -687,7 +687,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode,
open a file with a share mode
****************************************************************************/
void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
- mode_t mode,int oplock_request, int *Access,int *action)
+ mode_t mode,int *oplock_request, int *Access,int *action)
{
int flags=0;
int flags2=0;
@@ -922,24 +922,34 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
be extended to level II oplocks (multiple reader
oplocks). */
- if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
+ if((*oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
!IS_VETO_OPLOCK_PATH(conn,fname))
{
+#if defined(HAVE_KERNEL_OPLOCKS)
+ /*
+ * Try and get a *real* oplock on this file.
+ * If we fail, set the port and oplock request to
+ * zero so that we don't tell other SMB's that we
+ * got an oplock.
+ */
+ if(lp_kernel_oplocks())
+#endif /* HAVE_KERNEL_OPLOCKS */
+
fsp->granted_oplock = True;
fsp->sent_oplock_break = False;
global_oplocks_open++;
port = oplock_port;
DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode));
+dev = %x, inode = %.0f\n", *oplock_request, fname, (unsigned int)dev, (double)inode));
}
else
{
port = 0;
- oplock_request = 0;
+ *oplock_request = 0;
}
- set_share_mode(token, fsp, port, oplock_request);
+ set_share_mode(token, fsp, port, *oplock_request);
}
if ((flags2&O_TRUNC) && file_existed)
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 348e29dbe2..962043380d 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -26,7 +26,11 @@ extern int DEBUGLEVEL;
/* Oplock ipc UDP socket. */
int oplock_sock = -1;
uint16 oplock_port = 0;
+#if defined(HAVE_KERNEL_OPLOCKS)
+static int oplock_pipes[2];
+#endif /* HAVE_KERNEL_OPLOCKS */
+int oplock
/* Current number of oplocks we have outstanding. */
int32 global_oplocks_open = 0;
BOOL global_oplock_break = False;
@@ -678,3 +682,60 @@ BOOL attempt_close_oplocked_file(files_struct *fsp)
return False;
}
+void check_kernel_oplocks(BOOL *have_oplocks)
+{
+ static BOOL done;
+ int fd;
+ int pfd[2];
+ pstring tmpname;
+
+ /*
+ * We only do this check once on startup.
+ */
+
+ if(done)
+ return;
+
+ done = True;
+ *have_oplocks = False
+
+#if defined(HAVE_KERNEL_OPLOCKS)
+ slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid());
+ mktemp(tmpname);
+
+ if(pipe(pfd) != 0) {
+ DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n",
+ strerror(errno) ));
+ return;
+ }
+
+ if((fd = open(tmpname, O_RDWR)) < 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;
+ }
+
+ 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" ));
+ close(pfd[0]);
+ close(pfd[1]);
+ close(fd);
+ return;
+ }
+
+ fcntl(fd, F_OPLKACK, OP_REVOKE);
+ close(pfd[0]);
+ close(pfd[1]);
+ close(fd);
+
+ DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n"));
+
+ *have_oplocks = True;
+#endif /* HAVE_KERNEL_OPLOCKS */
+}