1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

First cut at kernel oplocks. This should have no effect unless runnin

on a machine that supports them in autoconf.

Move various functions out of lib/util.c into smbd/process.c
and smbd/oplock.c where they belong.

Jeremy.
This commit is contained in:
Jeremy Allison -
parent 24b8a757ae
commit c3c5e13f85
16 changed files with 807 additions and 500 deletions

View File

@ -65,3 +65,4 @@
#undef SIZEOF_OFF_T
#undef STAT_STATVFS64
#undef HAVE_LIBREADLINE
#undef HAVE_KERNEL_OPLOCKS

187
source/configure vendored
View File

@ -4164,18 +4164,53 @@ EOF
fi
echo $ac_n "checking for kernel oplock type definitions""... $ac_c" 1>&6
echo "configure:4169: checking for kernel oplock type definitions" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_KERNEL_OPLOCKS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 4175 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <fcntl.h>
int main() {
oplock_stat_t t; t.os_state = OP_REVOKE; t.os_dev = 1; t.os_ino = 1;
; return 0; }
EOF
if { (eval echo configure:4183: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
samba_cv_HAVE_KERNEL_OPLOCKS=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
samba_cv_HAVE_KERNEL_OPLOCKS=no
fi
rm -f conftest*
fi
echo "$ac_t""$samba_cv_HAVE_KERNEL_OPLOCKS" 1>&6
if test x"$samba_cv_HAVE_KERNEL_OPLOCKS" = x"yes"; then
cat >> confdefs.h <<\EOF
#define HAVE_KERNEL_OPLOCKS 1
EOF
fi
echo $ac_n "checking for test routines""... $ac_c" 1>&6
echo "configure:4170: checking for test routines" >&5
echo "configure:4205: checking for test routines" >&5
if test "$cross_compiling" = yes; then
echo "configure: warning: cannot run when cross-compiling" 1>&2
else
cat > conftest.$ac_ext <<EOF
#line 4175 "configure"
#line 4210 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/trivial.c"
EOF
if { (eval echo configure:4179: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
echo "$ac_t""yes" 1>&6
else
@ -4189,7 +4224,7 @@ fi
echo $ac_n "checking for ftruncate extend""... $ac_c" 1>&6
echo "configure:4193: checking for ftruncate extend" >&5
echo "configure:4228: checking for ftruncate extend" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_FTRUNCATE_EXTEND'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4198,11 +4233,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_FTRUNCATE_EXTEND=cross
else
cat > conftest.$ac_ext <<EOF
#line 4202 "configure"
#line 4237 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/ftruncate.c"
EOF
if { (eval echo configure:4206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_FTRUNCATE_EXTEND=yes
else
@ -4225,7 +4260,7 @@ EOF
fi
echo $ac_n "checking for broken getgroups""... $ac_c" 1>&6
echo "configure:4229: checking for broken getgroups" >&5
echo "configure:4264: checking for broken getgroups" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_BROKEN_GETGROUPS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4234,11 +4269,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_BROKEN_GETGROUPS=cross
else
cat > conftest.$ac_ext <<EOF
#line 4238 "configure"
#line 4273 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/getgroups.c"
EOF
if { (eval echo configure:4242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_BROKEN_GETGROUPS=yes
else
@ -4261,7 +4296,7 @@ EOF
fi
echo $ac_n "checking whether getpass should be replaced""... $ac_c" 1>&6
echo "configure:4265: checking whether getpass should be replaced" >&5
echo "configure:4300: checking whether getpass should be replaced" >&5
if eval "test \"`echo '$''{'samba_cv_REPLACE_GETPASS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4269,7 +4304,7 @@ else
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I${srcdir-.}/include -I${srcdir-.}/ubiqx"
cat > conftest.$ac_ext <<EOF
#line 4273 "configure"
#line 4308 "configure"
#include "confdefs.h"
#define REPLACE_GETPASS 1
@ -4282,7 +4317,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:4286: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:4321: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
samba_cv_REPLACE_GETPASS=yes
else
@ -4305,7 +4340,7 @@ EOF
fi
echo $ac_n "checking for broken inet_ntoa""... $ac_c" 1>&6
echo "configure:4309: checking for broken inet_ntoa" >&5
echo "configure:4344: checking for broken inet_ntoa" >&5
if eval "test \"`echo '$''{'samba_cv_REPLACE_INET_NTOA'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4314,7 +4349,7 @@ if test "$cross_compiling" = yes; then
samba_cv_REPLACE_INET_NTOA=cross
else
cat > conftest.$ac_ext <<EOF
#line 4318 "configure"
#line 4353 "configure"
#include "confdefs.h"
#include <stdio.h>
@ -4326,7 +4361,7 @@ if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
exit(1);}
EOF
if { (eval echo configure:4330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4365: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_REPLACE_INET_NTOA=yes
else
@ -4349,7 +4384,7 @@ EOF
fi
echo $ac_n "checking for root""... $ac_c" 1>&6
echo "configure:4353: checking for root" >&5
echo "configure:4388: checking for root" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_ROOT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4358,11 +4393,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_ROOT=cross
else
cat > conftest.$ac_ext <<EOF
#line 4362 "configure"
#line 4397 "configure"
#include "confdefs.h"
main() { exit(getuid() != 0); }
EOF
if { (eval echo configure:4366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_ROOT=yes
else
@ -4388,7 +4423,7 @@ fi
netmask=no;
echo $ac_n "checking for netmask ifconf""... $ac_c" 1>&6
echo "configure:4392: checking for netmask ifconf" >&5
echo "configure:4427: checking for netmask ifconf" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_NETMASK_IFCONF'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4397,14 +4432,14 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_NETMASK_IFCONF=cross
else
cat > conftest.$ac_ext <<EOF
#line 4401 "configure"
#line 4436 "configure"
#include "confdefs.h"
#define HAVE_NETMASK_IFCONF 1
#define AUTOCONF 1
#include "${srcdir-.}/lib/netmask.c"
EOF
if { (eval echo configure:4408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4443: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_NETMASK_IFCONF=yes
else
@ -4428,7 +4463,7 @@ fi
if test $netmask = no; then
echo $ac_n "checking for netmask ifreq""... $ac_c" 1>&6
echo "configure:4432: checking for netmask ifreq" >&5
echo "configure:4467: checking for netmask ifreq" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_NETMASK_IFREQ'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4437,14 +4472,14 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_NETMASK_IFREQ=cross
else
cat > conftest.$ac_ext <<EOF
#line 4441 "configure"
#line 4476 "configure"
#include "confdefs.h"
#define HAVE_NETMASK_IFREQ 1
#define AUTOCONF 1
#include "${srcdir-.}/lib/netmask.c"
EOF
if { (eval echo configure:4448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4483: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_NETMASK_IFREQ=yes
else
@ -4469,7 +4504,7 @@ fi
if test $netmask = no; then
echo $ac_n "checking for netmask AIX""... $ac_c" 1>&6
echo "configure:4473: checking for netmask AIX" >&5
echo "configure:4508: checking for netmask AIX" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_NETMASK_AIX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4478,14 +4513,14 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_NETMASK_AIX=cross
else
cat > conftest.$ac_ext <<EOF
#line 4482 "configure"
#line 4517 "configure"
#include "confdefs.h"
#define HAVE_NETMASK_AIX 1
#define AUTOCONF 1
#include "${srcdir-.}/lib/netmask.c"
EOF
if { (eval echo configure:4489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_NETMASK_AIX=yes
else
@ -4509,7 +4544,7 @@ fi
fi
echo $ac_n "checking for trapdoor seteuid""... $ac_c" 1>&6
echo "configure:4513: checking for trapdoor seteuid" >&5
echo "configure:4548: checking for trapdoor seteuid" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_TRAPDOOR_UID'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4518,11 +4553,11 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 4522 "configure"
#line 4557 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/trapdoor.c"
EOF
if { (eval echo configure:4526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_TRAPDOOR_UID=no
else
@ -4545,7 +4580,7 @@ EOF
fi
echo $ac_n "checking for shared mmap""... $ac_c" 1>&6
echo "configure:4549: checking for shared mmap" >&5
echo "configure:4584: checking for shared mmap" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_SHARED_MMAP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4554,11 +4589,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_SHARED_MMAP=cross
else
cat > conftest.$ac_ext <<EOF
#line 4558 "configure"
#line 4593 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/shared_mmap.c"
EOF
if { (eval echo configure:4562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_SHARED_MMAP=yes
else
@ -4581,7 +4616,7 @@ EOF
fi
echo $ac_n "checking for fcntl locking""... $ac_c" 1>&6
echo "configure:4585: checking for fcntl locking" >&5
echo "configure:4620: checking for fcntl locking" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_FCNTL_LOCK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4590,11 +4625,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_FCNTL_LOCK=cross
else
cat > conftest.$ac_ext <<EOF
#line 4594 "configure"
#line 4629 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/fcntl_lock.c"
EOF
if { (eval echo configure:4598: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_FCNTL_LOCK=yes
else
@ -4617,7 +4652,7 @@ EOF
fi
echo $ac_n "checking for 64 bit fcntl locking""... $ac_c" 1>&6
echo "configure:4621: checking for 64 bit fcntl locking" >&5
echo "configure:4656: checking for 64 bit fcntl locking" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_STRUCT_FLOCK64'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4626,7 +4661,7 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_STRUCT_FLOCK64=cross
else
cat > conftest.$ac_ext <<EOF
#line 4630 "configure"
#line 4665 "configure"
#include "confdefs.h"
#include <stdio.h>
@ -4647,7 +4682,7 @@ exit(1);
#endif
}
EOF
if { (eval echo configure:4651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4686: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_STRUCT_FLOCK64=yes
else
@ -4670,7 +4705,7 @@ EOF
fi
echo $ac_n "checking for sysv ipc""... $ac_c" 1>&6
echo "configure:4674: checking for sysv ipc" >&5
echo "configure:4709: checking for sysv ipc" >&5
if eval "test \"`echo '$''{'samba_cv_HAVE_SYSV_IPC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4679,11 +4714,11 @@ if test "$cross_compiling" = yes; then
samba_cv_HAVE_SYSV_IPC=cross
else
cat > conftest.$ac_ext <<EOF
#line 4683 "configure"
#line 4718 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/sysv_ipc.c"
EOF
if { (eval echo configure:4687: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4722: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
samba_cv_HAVE_SYSV_IPC=yes
else
@ -4708,7 +4743,7 @@ fi
#################################################
# check for the AFS filesystem
echo $ac_n "checking whether to use AFS""... $ac_c" 1>&6
echo "configure:4712: checking whether to use AFS" >&5
echo "configure:4747: checking whether to use AFS" >&5
# Check whether --with-afs or --without-afs was given.
if test "${with_afs+set}" = set; then
withval="$with_afs"
@ -4734,7 +4769,7 @@ fi
#################################################
# check for the DFS auth system
echo $ac_n "checking whether to use DFS auth""... $ac_c" 1>&6
echo "configure:4738: checking whether to use DFS auth" >&5
echo "configure:4773: checking whether to use DFS auth" >&5
# Check whether --with-dfs or --without-dfs was given.
if test "${with_dfs+set}" = set; then
withval="$with_dfs"
@ -4759,7 +4794,7 @@ fi
#################################################
# check for automount support
echo $ac_n "checking whether to use AUTOMOUNT""... $ac_c" 1>&6
echo "configure:4763: checking whether to use AUTOMOUNT" >&5
echo "configure:4798: checking whether to use AUTOMOUNT" >&5
# Check whether --with-automount or --without-automount was given.
if test "${with_automount+set}" = set; then
withval="$with_automount"
@ -4784,7 +4819,7 @@ fi
#################################################
# check for a LDAP password database
echo $ac_n "checking whether to use LDAP password database""... $ac_c" 1>&6
echo "configure:4788: checking whether to use LDAP password database" >&5
echo "configure:4823: checking whether to use LDAP password database" >&5
# Check whether --with-ldap or --without-ldap was given.
if test "${with_ldap+set}" = set; then
withval="$with_ldap"
@ -4809,7 +4844,7 @@ fi
#################################################
# check for a NISPLUS password database
echo $ac_n "checking whether to use NISPLUS password database""... $ac_c" 1>&6
echo "configure:4813: checking whether to use NISPLUS password database" >&5
echo "configure:4848: checking whether to use NISPLUS password database" >&5
# Check whether --with-nisplus or --without-nisplus was given.
if test "${with_nisplus+set}" = set; then
withval="$with_nisplus"
@ -4834,7 +4869,7 @@ fi
#################################################
# check for a NISPLUS_HOME support
echo $ac_n "checking whether to use NISPLUS_HOME""... $ac_c" 1>&6
echo "configure:4838: checking whether to use NISPLUS_HOME" >&5
echo "configure:4873: checking whether to use NISPLUS_HOME" >&5
# Check whether --with-nisplus-home or --without-nisplus-home was given.
if test "${with_nisplus_home+set}" = set; then
withval="$with_nisplus_home"
@ -4859,7 +4894,7 @@ fi
#################################################
# check for the secure socket layer
echo $ac_n "checking whether to use SSL""... $ac_c" 1>&6
echo "configure:4863: checking whether to use SSL" >&5
echo "configure:4898: checking whether to use SSL" >&5
# Check whether --with-ssl or --without-ssl was given.
if test "${with_ssl+set}" = set; then
withval="$with_ssl"
@ -4884,7 +4919,7 @@ fi
#################################################
# check for experimental mmap support
echo $ac_n "checking whether to use MMAP""... $ac_c" 1>&6
echo "configure:4888: checking whether to use MMAP" >&5
echo "configure:4923: checking whether to use MMAP" >&5
# Check whether --with-mmap or --without-mmap was given.
if test "${with_mmap+set}" = set; then
withval="$with_mmap"
@ -4909,7 +4944,7 @@ fi
#################################################
# check for syslog logging
echo $ac_n "checking whether to use syslog logging""... $ac_c" 1>&6
echo "configure:4913: checking whether to use syslog logging" >&5
echo "configure:4948: checking whether to use syslog logging" >&5
# Check whether --with-syslog or --without-syslog was given.
if test "${with_syslog+set}" = set; then
withval="$with_syslog"
@ -4934,7 +4969,7 @@ fi
#################################################
# check for experimental netatalk resource fork support
echo $ac_n "checking whether to support netatalk""... $ac_c" 1>&6
echo "configure:4938: checking whether to support netatalk" >&5
echo "configure:4973: checking whether to support netatalk" >&5
# Check whether --with-netatalk or --without-netatalk was given.
if test "${with_netatalk+set}" = set; then
withval="$with_netatalk"
@ -4960,14 +4995,14 @@ fi
#################################################
# these tests are taken from the GNU fileutils package
echo "checking how to get filesystem space usage" 1>&6
echo "configure:4964: checking how to get filesystem space usage" >&5
echo "configure:4999: checking how to get filesystem space usage" >&5
space=no
# Test for statvfs64.
if test $space = no; then
# SVR4
echo $ac_n "checking statvfs64 function (SVR4)""... $ac_c" 1>&6
echo "configure:4971: checking statvfs64 function (SVR4)" >&5
echo "configure:5006: checking statvfs64 function (SVR4)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs64'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4975,7 +5010,7 @@ else
fu_cv_sys_stat_statvfs64=cross
else
cat > conftest.$ac_ext <<EOF
#line 4979 "configure"
#line 5014 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -4986,7 +5021,7 @@ else
exit (statfs64 (".", &fsd));
}
EOF
if { (eval echo configure:4990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5025: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_statvfs64=yes
else
@ -5019,12 +5054,12 @@ fi
if test $space = no; then
# SVR4
echo $ac_n "checking statvfs function (SVR4)""... $ac_c" 1>&6
echo "configure:5023: checking statvfs function (SVR4)" >&5
echo "configure:5058: checking statvfs function (SVR4)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5028 "configure"
#line 5063 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/statvfs.h>
@ -5032,7 +5067,7 @@ int main() {
struct statvfs fsd; statvfs (0, &fsd);
; return 0; }
EOF
if { (eval echo configure:5036: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:5071: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
fu_cv_sys_stat_statvfs=yes
else
@ -5057,7 +5092,7 @@ fi
if test $space = no; then
# DEC Alpha running OSF/1
echo $ac_n "checking for 3-argument statfs function (DEC OSF/1)""... $ac_c" 1>&6
echo "configure:5061: checking for 3-argument statfs function (DEC OSF/1)" >&5
echo "configure:5096: checking for 3-argument statfs function (DEC OSF/1)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs3_osf1'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5065,7 +5100,7 @@ else
fu_cv_sys_stat_statfs3_osf1=no
else
cat > conftest.$ac_ext <<EOF
#line 5069 "configure"
#line 5104 "configure"
#include "confdefs.h"
#include <sys/param.h>
@ -5078,7 +5113,7 @@ else
exit (statfs (".", &fsd, sizeof (struct statfs)));
}
EOF
if { (eval echo configure:5082: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_statfs3_osf1=yes
else
@ -5105,7 +5140,7 @@ fi
if test $space = no; then
# AIX
echo $ac_n "checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)""... $ac_c" 1>&6
echo "configure:5109: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5
echo "configure:5144: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_bsize'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5113,7 +5148,7 @@ else
fu_cv_sys_stat_statfs2_bsize=no
else
cat > conftest.$ac_ext <<EOF
#line 5117 "configure"
#line 5152 "configure"
#include "confdefs.h"
#ifdef HAVE_SYS_PARAM_H
@ -5132,7 +5167,7 @@ else
exit (statfs (".", &fsd));
}
EOF
if { (eval echo configure:5136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5171: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_statfs2_bsize=yes
else
@ -5159,7 +5194,7 @@ fi
if test $space = no; then
# SVR3
echo $ac_n "checking for four-argument statfs (AIX-3.2.5, SVR3)""... $ac_c" 1>&6
echo "configure:5163: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5
echo "configure:5198: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs4'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5167,7 +5202,7 @@ else
fu_cv_sys_stat_statfs4=no
else
cat > conftest.$ac_ext <<EOF
#line 5171 "configure"
#line 5206 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/statfs.h>
@ -5177,7 +5212,7 @@ else
exit (statfs (".", &fsd, sizeof fsd, 0));
}
EOF
if { (eval echo configure:5181: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_statfs4=yes
else
@ -5204,7 +5239,7 @@ fi
if test $space = no; then
# 4.4BSD and NetBSD
echo $ac_n "checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)""... $ac_c" 1>&6
echo "configure:5208: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5
echo "configure:5243: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_fsize'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5212,7 +5247,7 @@ else
fu_cv_sys_stat_statfs2_fsize=no
else
cat > conftest.$ac_ext <<EOF
#line 5216 "configure"
#line 5251 "configure"
#include "confdefs.h"
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
@ -5228,7 +5263,7 @@ else
exit (statfs (".", &fsd));
}
EOF
if { (eval echo configure:5232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5267: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_statfs2_fsize=yes
else
@ -5255,7 +5290,7 @@ fi
if test $space = no; then
# Ultrix
echo $ac_n "checking for two-argument statfs with struct fs_data (Ultrix)""... $ac_c" 1>&6
echo "configure:5259: checking for two-argument statfs with struct fs_data (Ultrix)" >&5
echo "configure:5294: checking for two-argument statfs with struct fs_data (Ultrix)" >&5
if eval "test \"`echo '$''{'fu_cv_sys_stat_fs_data'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5263,7 +5298,7 @@ else
fu_cv_sys_stat_fs_data=no
else
cat > conftest.$ac_ext <<EOF
#line 5267 "configure"
#line 5302 "configure"
#include "confdefs.h"
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
@ -5283,7 +5318,7 @@ else
exit (statfs (".", &fsd) != 1);
}
EOF
if { (eval echo configure:5287: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5322: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
fu_cv_sys_stat_fs_data=yes
else
@ -5312,11 +5347,11 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 5316 "configure"
#line 5351 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/summary.c"
EOF
if { (eval echo configure:5320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
echo "configure OK";
else

View File

@ -277,6 +277,15 @@ if test x"$samba_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF)
fi
AC_CACHE_CHECK([for kernel oplock type definitions],samba_cv_HAVE_KERNEL_OPLOCKS,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <fcntl.h>],
[oplock_stat_t t; t.os_state = OP_REVOKE; t.os_dev = 1; t.os_ino = 1;],
samba_cv_HAVE_KERNEL_OPLOCKS=yes,samba_cv_HAVE_KERNEL_OPLOCKS=no)])
if test x"$samba_cv_HAVE_KERNEL_OPLOCKS" = x"yes"; then
AC_DEFINE(HAVE_KERNEL_OPLOCKS)
fi
AC_MSG_CHECKING([for test routines])
AC_TRY_RUN([#include "${srcdir-.}/tests/trivial.c"],

View File

@ -122,6 +122,7 @@
#undef SIZEOF_OFF_T
#undef STAT_STATVFS64
#undef HAVE_LIBREADLINE
#undef HAVE_KERNEL_OPLOCKS
/* The number of bytes in a int. */
#undef SIZEOF_INT

View File

@ -276,11 +276,6 @@ SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,
ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout);
BOOL receive_smb(int fd,char *buffer, unsigned int timeout);
BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout);
BOOL receive_local_message(int fd, char *buffer, int buffer_len, unsigned int timeout);
BOOL push_oplock_pending_smb_message(char *buf, int msg_len);
BOOL receive_message_or_smb(int smbfd, int oplock_fd,
char *buffer, int buffer_len,
int timeout, BOOL *got_smb);
BOOL send_smb(int fd,char *buffer);
int name_extract(char *buf,int ofs,char *name);
int name_len( char *s );
@ -1809,11 +1804,14 @@ BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op);
/*The following definitions come from smbd/oplock.c */
BOOL open_oplock_ipc(void);
BOOL process_local_message(int sock, char *buffer, int buf_size);
BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout);
BOOL set_file_oplock(files_struct *fsp);
int setup_oplock_select_set( fd_set *fds);
BOOL process_local_message(char *buffer, int buf_size);
BOOL request_oplock_break(share_mode_entry *share_entry,
SMB_DEV_T dev, SMB_INO_T inode);
BOOL attempt_close_oplocked_file(files_struct *fsp);
void check_kernel_oplocks(BOOL *have_oplocks);
void check_kernel_oplocks(void);
/*The following definitions come from smbd/password.c */
@ -1857,7 +1855,8 @@ void invalidate_read_prediction(int fd);
/*The following definitions come from smbd/process.c */
BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout);
BOOL push_oplock_pending_smb_message(char *buf, int msg_len);
BOOL receive_next_smb(char *inbuf, int bufsize, int timeout);
void process_smb(char *inbuf, char *outbuf);
char *smb_fn_name(int type);
void construct_reply_common(char *inbuf,char *outbuf);

View File

@ -1538,11 +1538,11 @@ extern int unix_ERR_code;
* Loopback command offsets.
*/
#define UDP_CMD_LEN_OFFSET 0
#define UDP_CMD_PORT_OFFSET 4
#define UDP_CMD_HEADER_LEN 6
#define OPBRK_CMD_LEN_OFFSET 0
#define OPBRK_CMD_PORT_OFFSET 4
#define OPBRK_CMD_HEADER_LEN 6
#define UDP_MESSAGE_CMD_OFFSET 0
#define OPBRK_MESSAGE_CMD_OFFSET 0
/*
* Oplock break command code to send over the udp socket.
@ -1563,6 +1563,24 @@ extern int unix_ERR_code;
#define OPLOCK_BREAK_INODE_OFFSET (OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T))
#define OPLOCK_BREAK_MSG_LEN (OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T))
#if defined(HAVE_KERNEL_OPLOCKS)
/*
* Oplock break command code sent via the kernel interface.
*
* Form of this is :
*
* 0 2 2+devsize 2+devsize+inodesize
* +----+--------+--------+
* | cmd| dev | inode |
* +----+--------+--------+
*/
#define KERNEL_OPLOCK_BREAK_CMD 0x2
#define KERNEL_OPLOCK_BREAK_DEV_OFFSET 2
#define KERNEL_OPLOCK_BREAK_INODE_OFFSET (KERNEL_OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T))
#define KERNEL_OPLOCK_BREAK_MSG_LEN (KERNEL_OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T))
#endif /* HAVE_KERNEL_OPLOCKS */
#define CMD_REPLY 0x8000

View File

@ -2231,224 +2231,6 @@ BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
return ret;
}
/****************************************************************************
read a message from a udp fd.
The timeout is in milliseconds
****************************************************************************/
BOOL receive_local_message(int fd, char *buffer, int buffer_len, unsigned int timeout)
{
struct sockaddr_in from;
int fromlen = sizeof(from);
int32 msg_len = 0;
smb_read_error = 0;
if(timeout != 0)
{
struct timeval to;
fd_set fds;
int selrtn;
FD_ZERO(&fds);
FD_SET(fd,&fds);
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(fd+1,&fds,&to);
/* Check if error */
if(selrtn == -1)
{
/* something is wrong. Maybe the socket is dead? */
smb_read_error = READ_ERROR;
return False;
}
/* Did we timeout ? */
if (selrtn == 0)
{
smb_read_error = READ_TIMEOUT;
return False;
}
}
/*
* Read a loopback udp message.
*/
msg_len = recvfrom(fd, &buffer[UDP_CMD_HEADER_LEN],
buffer_len - UDP_CMD_HEADER_LEN, 0,
(struct sockaddr *)&from, &fromlen);
if(msg_len < 0)
{
DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno)));
return False;
}
/* Validate message length. */
if(msg_len > (buffer_len - UDP_CMD_HEADER_LEN))
{
DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n",
msg_len,
buffer_len - UDP_CMD_HEADER_LEN));
return False;
}
/* Validate message from address (must be localhost). */
if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK))
{
DEBUG(0,("receive_local_message: invalid 'from' address \
(was %x should be 127.0.0.1\n", from.sin_addr.s_addr));
return False;
}
/* Setup the message header */
SIVAL(buffer,UDP_CMD_LEN_OFFSET,msg_len);
SSVAL(buffer,UDP_CMD_PORT_OFFSET,ntohs(from.sin_port));
return True;
}
/****************************************************************************
structure to hold a linked list of local messages.
for processing.
****************************************************************************/
typedef struct {
ubi_slNode msg_next;
char *msg_buf;
int msg_len;
} pending_message_list;
static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
/****************************************************************************
Function to push a message onto the tail of a linked list of smb messages ready
for processing.
****************************************************************************/
static BOOL push_local_message(ubi_slList *list_head, char *buf, int msg_len)
{
pending_message_list *msg = (pending_message_list *)
malloc(sizeof(pending_message_list));
if(msg == NULL)
{
DEBUG(0,("push_local_message: malloc fail (1)\n"));
return False;
}
msg->msg_buf = (char *)malloc(msg_len);
if(msg->msg_buf == NULL)
{
DEBUG(0,("push_local_message: malloc fail (2)\n"));
free((char *)msg);
return False;
}
memcpy(msg->msg_buf, buf, msg_len);
msg->msg_len = msg_len;
ubi_slAddTail( list_head, msg);
return True;
}
/****************************************************************************
Function to push a smb message onto a linked list of local smb messages ready
for processing.
****************************************************************************/
BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
{
return push_local_message(&smb_oplock_queue, buf, msg_len);
}
/****************************************************************************
Do a select on an two fd's - with timeout.
If a local udp message has been pushed onto the
queue (this can only happen during oplock break
processing) return this first.
If a pending smb message has been pushed onto the
queue (this can only happen during oplock break
processing) return this next.
If the first smbfd is ready then read an smb from it.
if the second (loopback UDP) fd is ready then read a message
from it and setup the buffer header to identify the length
and from address.
Returns False on timeout or error.
Else returns True.
The timeout is in milli seconds
****************************************************************************/
BOOL receive_message_or_smb(int smbfd, int oplock_fd,
char *buffer, int buffer_len,
int timeout, BOOL *got_smb)
{
fd_set fds;
int selrtn;
struct timeval to;
smb_read_error = 0;
*got_smb = False;
/*
* Check to see if we already have a message on the smb queue.
* If so - copy and return it.
*/
if(ubi_slCount(&smb_oplock_queue) != 0)
{
pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
/* Free the message we just copied. */
free((char *)msg->msg_buf);
free((char *)msg);
*got_smb = True;
DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
return True;
}
FD_ZERO(&fds);
FD_SET(smbfd,&fds);
FD_SET(oplock_fd,&fds);
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(MAX(smbfd,oplock_fd)+1,&fds,timeout>0?&to:NULL);
/* Check if error */
if(selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */
smb_read_error = READ_ERROR;
return False;
}
/* Did we timeout ? */
if (selrtn == 0) {
smb_read_error = READ_TIMEOUT;
return False;
}
if (FD_ISSET(smbfd,&fds))
{
*got_smb = True;
return receive_smb(smbfd, buffer, 0);
}
else
{
return receive_local_message(oplock_fd, buffer, buffer_len, 0);
}
}
/****************************************************************************
send an smb to a fd
****************************************************************************/

View File

@ -917,7 +917,7 @@ static void init_globals(void)
* smbd will check after starting to see if this value
* should be set to "true" or not.
*/
Globals.bKernelOplocks = False;
lp_set_kernel_oplocks(False);
/*
* This must be done last as it checks the value in

View File

@ -290,31 +290,33 @@ void file_close_user(int vuid)
/****************************************************************************
find a fsp given a device, inode and timevalue
Find a fsp given a device, inode and timevalue
If this is from a kernel oplock break request then tval may be NULL.
****************************************************************************/
files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
{
int count=0;
files_struct *fsp;
#ifdef USE_FILES_ARRAY
for(count = 0; count < MAX_FNUMS; count++) {
if((fsp = Files[count]) == NULL)
continue;
if (fsp->open &&
fsp->fd_ptr->dev == dev &&
fsp->fd_ptr->inode == inode &&
fsp->open_time.tv_sec == tval->tv_sec &&
fsp->open_time.tv_usec == tval->tv_usec)
return fsp;
}
for(count = 0; count < MAX_FNUMS; count++) {
if((fsp = Files[count]) == NULL)
continue;
if (fsp->open &&
fsp->fd_ptr->dev == dev &&
fsp->fd_ptr->inode == inode &&
(tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True) &&
(tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True))
return fsp;
}
#else
for (fsp=Files;fsp;fsp=fsp->next,count++) {
if (fsp->open &&
fsp->fd_ptr->dev == dev &&
fsp->fd_ptr->inode == inode &&
fsp->open_time.tv_sec == tval->tv_sec &&
fsp->open_time.tv_usec == tval->tv_usec) {
(tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) &&
(tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) {
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}

View File

@ -60,7 +60,6 @@ extern fstring global_myworkgroup;
#define QNLEN 12 /* queue name maximum length */
extern int Client;
extern int oplock_sock;
extern int smb_read_error;
static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
@ -3660,7 +3659,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
BOOL ret;
int pcnt,poff,dcnt,doff,pdisp,ddisp;
ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
if(ret) {

View File

@ -25,7 +25,6 @@
extern int DEBUGLEVEL;
extern int Protocol;
extern int Client;
extern int oplock_sock;
extern int smb_read_error;
extern int global_oplock_break;
extern int chain_size;
@ -1365,8 +1364,7 @@ due to being in oplock break state.\n" ));
while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
BOOL ret;
ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
SMB_SECONDARY_WAIT);
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
outsize = set_message(outbuf,0,0,True);

View File

@ -24,8 +24,7 @@
extern int DEBUGLEVEL;
extern pstring sesssetup_user;
extern int global_oplocks_open;
extern uint16 oplock_port;
extern uint16 global_oplock_port;
/****************************************************************************
@ -917,38 +916,23 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
if (lp_share_modes(SNUM(conn)))
{
uint16 port = 0;
/* JRA. Currently this only services Exlcusive and batch
oplocks (no other opens on this file). This needs to
be extended to level II oplocks (multiple reader
oplocks). */
if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
!IS_VETO_OPLOCK_PATH(conn,fname))
!IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) )
{
#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));
port = global_oplock_port;
}
else
{
port = 0;
oplock_request = 0;
}
set_share_mode(token, fsp, port, oplock_request);
}

View File

@ -24,22 +24,21 @@
extern int DEBUGLEVEL;
/* Oplock ipc UDP socket. */
int oplock_sock = -1;
uint16 oplock_port = 0;
static int oplock_sock = -1;
uint16 global_oplock_port = 0;
#if defined(HAVE_KERNEL_OPLOCKS)
static int oplock_pipes[2];
static int oplock_pipe_read = -1;
static int oplock_pipe_write = -1;
#endif /* HAVE_KERNEL_OPLOCKS */
/* Current number of oplocks we have outstanding. */
int32 global_oplocks_open = 0;
BOOL global_oplock_break = False;
extern int smb_read_error;
static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval);
/****************************************************************************
open the oplock IPC socket communication
****************************************************************************/
@ -56,7 +55,7 @@ BOOL open_oplock_ipc(void)
{
DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
oplock_port = 0;
global_oplock_port = 0;
return(False);
}
@ -67,39 +66,332 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
strerror(errno)));
close(oplock_sock);
oplock_sock = -1;
oplock_port = 0;
global_oplock_port = 0;
return False;
}
oplock_port = ntohs(sock_name.sin_port);
global_oplock_port = ntohs(sock_name.sin_port);
DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n",
(int)getpid(), oplock_port));
DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n",
(int)getpid(), global_oplock_port));
return True;
}
/****************************************************************************
process an oplock break message.
Read an oplock break message from the either the oplock UDP fd
or the kernel oplock pipe fd (if kernel oplocks are supported).
If timeout is zero then *fds contains the file descriptors that
are ready to be read and acted upon. If timeout is non-zero then
*fds contains the file descriptors to be selected on for read.
The timeout is in milliseconds
****************************************************************************/
BOOL process_local_message(int sock, char *buffer, int buf_size)
BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout)
{
struct sockaddr_in from;
int fromlen = sizeof(from);
int32 msg_len = 0;
smb_read_error = 0;
if(timeout != 0) {
struct timeval to;
int selrtn;
int maxfd = oplock_sock;
#if defined(HAVE_KERNEL_OPLOCKS)
if(lp_kernel_oplocks())
maxfd = MAX(maxfd, oplock_pipe_read);
#endif /* HAVE_KERNEL_OPLOCKS */
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(maxfd+1,fds,&to);
/* Check if error */
if(selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */
smb_read_error = READ_ERROR;
return False;
}
/* Did we timeout ? */
if (selrtn == 0) {
smb_read_error = READ_TIMEOUT;
return False;
}
}
#if defined(HAVE_KERNEL_OPLOCKS)
if(FD_ISSET(oplock_pipe_read,fds)) {
/*
* Deal with the kernel <--> smbd
* oplock break protocol.
*/
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) ));
smb_read_error = READ_ERROR;
return False;
}
dev = (SMB_DEV_T)os.os_dev;
inode = (SMB_DEV_T)os.os_ino;
DEBUG(5,("receive_local_message: kernel oplock break request received for \
dev = %x, inode = %0.f\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);
SIVAL(buffer,KERNEL_OPLOCK_BREAK_DEV_OFFSET,dev);
#ifdef LARGE_SMB_INO_T
SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode & 0xFFFFFFFF);
SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET+4, (inode >> 32 ) & 0xFFFFFFFF );
#else /* LARGE_SMB_INO_T */
SIVAL(buffer,KERNEL_OPLOCK_BREAK_INODE_OFFSET,inode);
#endif /* LARGE_SMB_INO_T */
return True;
}
#endif /* HAVE_KERNEL_OPLOCKS */
/*
* From here down we deal with the smbd <--> smbd
* oplock break protocol only.
*/
/*
* Read a loopback udp message.
*/
msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN],
buffer_len - OPBRK_CMD_HEADER_LEN, 0,
(struct sockaddr *)&from, &fromlen);
if(msg_len < 0) {
DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno)));
return False;
}
/* Validate message length. */
if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) {
DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n",
msg_len,
buffer_len - OPBRK_CMD_HEADER_LEN));
return False;
}
/* Validate message from address (must be localhost). */
if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
DEBUG(0,("receive_local_message: invalid 'from' address \
(was %x should be 127.0.0.1\n", from.sin_addr.s_addr));
return False;
}
/* Setup the message header */
SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len);
SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port));
return True;
}
/****************************************************************************
Attempt to set an oplock on a file. Always succeeds if kernel oplocks are
disabled (just sets flags). Returns True if oplock set.
****************************************************************************/
BOOL set_file_oplock(files_struct *fsp)
{
#if defined(HAVE_KERNEL_OPLOCKS)
if(lp_kernel_oplocks()) {
if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) {
if(errno != EAGAIN) {
DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \
inode = %0.f. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode,
strerror(errno) ));
} else {
DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \
inode = %0.f. Another process had the file open.\n",
fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode ));
}
return False;
}
}
#endif /* HAVE_KERNEL_OPLOCKS */
DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f\n",
fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode));
fsp->granted_oplock = True;
fsp->sent_oplock_break = False;
global_oplocks_open++;
return True;
}
/****************************************************************************
Attempt to release an oplock on a file. Always succeeds if kernel oplocks are
disabled (just clears flags).
****************************************************************************/
static void release_file_oplock(files_struct *fsp)
{
#if defined(HAVE_KERNEL_OPLOCKS)
if(fsp->granted_oplock && lp_kernel_oplocks())
{
if( DEBUGLVL( 10 ))
{
/*
* Check and print out the current kernel
* oplock state of this file.
*/
int state = fcntl(fsp->fd_ptr->fd, F_OPLKACK, -1);
dbgtext("release_file_oplock: file %s, dev = %x, inode = %.0f has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev,
(double)fsp->fd_ptr->inode, state );
}
/*
* Remove the kernel oplock on this file.
*/
if(fcntl(fsp->fd_ptr->fd, F_OPLKACK, OP_REVOKE) < 0)
{
if( DEBUGLVL( 0 ))
{
dbgtext("release_file_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev,
(double)fsp->fd_ptr->inode, strerror(errno) );
}
}
}
#endif /* HAVE_KERNEL_OPLOCKS */
fsp->granted_oplock = False;
fsp->sent_oplock_break = False;
global_oplocks_open--;
}
/****************************************************************************
Setup the listening set of file descriptors for an oplock break
message either from the UDP socket or from the kernel. Returns the maximum
fd used.
****************************************************************************/
int setup_oplock_select_set( fd_set *fds)
{
int maxfd = oplock_sock;
FD_SET(oplock_sock,fds);
#if defined(HAVE_KERNEL_OPLOCKS)
if(lp_kernel_oplocks()) {
FD_SET(oplock_pipe_read,fds);
maxfd = MAX(maxfd,oplock_pipe_read);
}
#endif /* HAVE_KERNEL_OPLOCKS */
return maxfd;
}
/****************************************************************************
Process an oplock break message - whether it came from the UDP socket
or from the kernel.
****************************************************************************/
BOOL process_local_message(char *buffer, int buf_size)
{
int32 msg_len;
uint16 from_port;
char *msg_start;
SMB_DEV_T dev;
SMB_INO_T inode;
uint32 remotepid;
struct timeval tval;
struct timeval *ptval = NULL;
msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET);
msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET);
from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET);
msg_start = &buffer[UDP_CMD_HEADER_LEN];
msg_start = &buffer[OPBRK_CMD_HEADER_LEN];
DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n",
msg_len, from_port));
/* Switch on message command - currently OPLOCK_BREAK_CMD is the
only valid request. */
/*
* Pull the info out of the requesting packet.
*/
switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET))
switch(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET))
{
#if defined(HAVE_KERNEL_OPLOCKS)
case KERNEL_OPLOCK_BREAK_CMD:
/* 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;
}
{
/*
* Warning - beware of SMB_INO_T <> 4 bytes. !!
*/
#ifdef LARGE_SMB_INO_T
SMB_INO_T inode_low = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET);
SMB_INO_T inode_high = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET + 4);
inode = inode_low | (inode_high << 32);
#else /* LARGE_SMB_INO_T */
inode = IVAL(msg_start, KERNEL_OPLOCK_BREAK_INODE_OFFSET);
#endif /* LARGE_SMB_INO_T */
dev = IVAL(msg_start,KERNEL_OPLOCK_BREAK_DEV_OFFSET);
ptval = NULL;
DEBUG(5,("process_local_message: kernel oplock break request for \
file dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode));
}
break;
#endif /* HAVE_KERNEL_OPLOCKS */
case OPLOCK_BREAK_CMD:
/* Ensure that the msg length is correct. */
if(msg_len != OPLOCK_BREAK_MSG_LEN)
@ -109,71 +401,31 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
return False;
}
{
uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
/*
* Warning - beware of SMB_INO_T <> 4 bytes. !!
*/
#ifdef LARGE_SMB_INO_T
SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4);
SMB_INO_T inode = inode_low | (inode_high << 32);
inode = inode_low | (inode_high << 32);
#else /* LARGE_SMB_INO_T */
SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
#endif /* LARGE_SMB_INO_T */
struct timeval tval;
struct sockaddr_in toaddr;
dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
ptval = &tval;
remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
DEBUG(5,("process_local_message: oplock break request from \
pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode));
/*
* If we have no record of any currently open oplocks,
* it's not an error, as a close command may have
* just been issued on the file that was oplocked.
* Just return success in this case.
*/
if(global_oplocks_open != 0)
{
if(oplock_break(dev, inode, &tval) == False)
{
DEBUG(0,("process_local_message: oplock break failed - \
not returning udp message.\n"));
return False;
}
}
else
{
DEBUG(3,("process_local_message: oplock break requested with no outstanding \
oplocks. Returning success.\n"));
}
/* Send the message back after OR'ing in the 'REPLY' bit. */
SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
bzero((char *)&toaddr,sizeof(toaddr));
toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
toaddr.sin_port = htons(from_port);
toaddr.sin_family = AF_INET;
if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
(struct sockaddr *)&toaddr, sizeof(toaddr)) < 0)
{
DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
remotepid, strerror(errno)));
return False;
}
DEBUG(5,("process_local_message: oplock break reply sent to \
pid %d, port %d, for file dev = %x, inode = %.0f\n",
remotepid, from_port, (unsigned int)dev, (double)inode));
}
break;
/*
* Keep this as a debug case - eventually we can remove it.
*/
@ -189,19 +441,20 @@ reply - dumping info.\n"));
}
{
uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
SMB_DEV_T dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
/*
* Warning - beware of SMB_INO_T <> 4 bytes. !!
*/
#ifdef LARGE_SMB_INO_T
SMB_INO_T inode_low = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
SMB_INO_T inode_high = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET + 4);
SMB_INO_T inode = inode_low | (inode_high << 32);
inode = inode_low | (inode_high << 32);
#else /* LARGE_SMB_INO_T */
SMB_INO_T inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
#endif /* LARGE_SMB_INO_T */
remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
DEBUG(0,("process_local_message: unsolicited oplock break reply from \
pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)dev, (double)inode));
@ -213,12 +466,67 @@ pid %d, port %d, dev = %x, inode = %.0f\n", remotepid, from_port, (unsigned int)
(unsigned int)SVAL(msg_start,0)));
return False;
}
/*
* Now actually process the break request.
*/
if(global_oplocks_open != 0)
{
if(oplock_break(dev, inode, ptval) == False)
{
DEBUG(0,("process_local_message: oplock break failed.\n"));
return False;
}
}
else
{
/*
* If we have no record of any currently open oplocks,
* it's not an error, as a close command may have
* just been issued on the file that was oplocked.
* Just log a message and return success in this case.
*/
DEBUG(3,("process_local_message: oplock break requested with no outstanding \
oplocks. Returning success.\n"));
}
/*
* Do the appropriate reply - none in the kernel case.
*/
if(SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET) == OPLOCK_BREAK_CMD)
{
struct sockaddr_in toaddr;
/* Send the message back after OR'ing in the 'REPLY' bit. */
SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
bzero((char *)&toaddr,sizeof(toaddr));
toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
toaddr.sin_port = htons(from_port);
toaddr.sin_family = AF_INET;
if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
(struct sockaddr *)&toaddr, sizeof(toaddr)) < 0)
{
DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
remotepid, strerror(errno)));
return False;
}
DEBUG(5,("process_local_message: oplock break reply sent to \
pid %d, port %d, for file dev = %x, inode = %.0f\n",
remotepid, from_port, (unsigned int)dev, (double)inode));
}
return True;
}
/****************************************************************************
Process an oplock break directly.
****************************************************************************/
static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
{
extern struct current_user current_user;
@ -233,10 +541,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
pstring saved_dir;
if( DEBUGLVL( 3 ) )
{
{
dbgtext( "oplock_break: called for dev = %x, inode = %.0f.\n", (unsigned int)dev, (double)inode );
dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open );
}
}
/* We need to search the file open table for the
entry containing this dev and inode, and ensure
@ -247,11 +555,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
{
/* The file could have been closed in the meantime - return success. */
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "oplock_break: cannot find open file with " );
dbgtext( "dev = %x, inode = %.0f ", (unsigned int)dev, (double)inode);
dbgtext( "allowing break to succeed.\n" );
}
}
return True;
}
@ -267,11 +575,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
if(!fsp->granted_oplock)
{
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "oplock_break: file %s ", fsp->fsp_name );
dbgtext( "(dev = %x, inode = %.0f) has no oplock.\n", (unsigned int)dev, (double)inode );
dbgtext( "Allowing break to succeed regardless.\n" );
}
}
return True;
}
@ -279,11 +587,11 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
if (fsp->sent_oplock_break)
{
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "oplock_break: ERROR: oplock_break already sent for " );
dbgtext( "file %s ", fsp->fsp_name);
dbgtext( "(dev = %x, inode = %.0f)\n", (unsigned int)dev, (double)inode );
}
}
/* We have to fail the open here as we cannot send another oplock break on
this file whilst we are awaiting a response from the client - neither
@ -403,7 +711,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT );
dbgtext( "oplock_break failed for file %s ", fsp->fsp_name );
dbgtext( "(dev = %x, inode = %.0f).\n", (unsigned int)dev, (double)inode );
}
shutdown_server = True;
break;
@ -453,10 +760,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
{
/* The lockingX reply will have removed the oplock flag
from the sharemode. */
/* Paranoia.... */
fsp->granted_oplock = False;
fsp->sent_oplock_break = False;
global_oplocks_open--;
release_file_oplock(fsp);
}
/* Santity check - remove this later. JRA */
@ -467,12 +771,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
exit_server("oplock_break: global_oplocks_open < 0");
}
if( DEBUGLVL( 3 ) )
{
{
dbgtext( "oplock_break: returning success for " );
dbgtext( "dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode );
dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open );
}
}
return True;
}
@ -494,10 +799,10 @@ BOOL request_oplock_break(share_mode_entry *share_entry,
if(pid == share_entry->pid)
{
/* We are breaking our own oplock, make sure it's us. */
if(share_entry->op_port != oplock_port)
if(share_entry->op_port != global_oplock_port)
{
DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
should be %d\n", pid, share_entry->op_port, oplock_port));
should be %d\n", pid, share_entry->op_port, global_oplock_port));
return False;
}
@ -510,7 +815,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
/* We need to send a OPLOCK_BREAK_CMD message to the
port in the share mode entry. */
SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
@ -532,24 +837,23 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
addr_out.sin_family = AF_INET;
if( DEBUGLVL( 3 ) )
{
{
dbgtext( "request_oplock_break: sending a oplock break message to " );
dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port );
dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode );
}
}
if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
(struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
{
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "request_oplock_break: failed when sending a oplock " );
dbgtext( "break message to pid %d ", share_entry->pid );
dbgtext( "on port %d ", share_entry->op_port );
dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode );
dbgtext( "Error was %s\n", strerror(errno) );
}
}
return False;
}
@ -565,24 +869,32 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
while(time_left >= 0)
{
char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
int32 reply_msg_len;
uint16 reply_from_port;
char *reply_msg_start;
fd_set fds;
if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
FD_ZERO(&fds);
FD_SET(oplock_sock,&fds);
#if defined(HAVE_KERNEL_OPLOCKS)
if(lp_kernel_oplocks())
FD_SET(oplock_pipe_read,&fds);
#endif /* HAVE_KERNEL_OPLOCKS */
if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply),
time_left ? time_left * 1000 : 1) == False)
{
if(smb_read_error == READ_TIMEOUT)
{
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "request_oplock_break: no response received to oplock " );
dbgtext( "break request to pid %d ", share_entry->pid );
dbgtext( "on port %d ", share_entry->op_port );
dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode );
}
}
/*
* This is a hack to make handling of failing clients more robust.
* If a oplock break response message is not received in the timeout
@ -594,25 +906,30 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
}
else
if( DEBUGLVL( 0 ) )
{
{
dbgtext( "request_oplock_break: error in response received " );
dbgtext( "to oplock break request to pid %d ", share_entry->pid );
dbgtext( "on port %d ", share_entry->op_port );
dbgtext( "for dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode );
dbgtext( "Error was (%s).\n", strerror(errno) );
}
}
return False;
}
reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET);
reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET);
reply_msg_len = IVAL(op_break_reply,OPBRK_CMD_LEN_OFFSET);
reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET);
reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN];
reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN];
#if defined(HAVE_KERNEL_OPLOCKS)
if((reply_msg_len != OPLOCK_BREAK_MSG_LEN) && (reply_msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN))
#else
if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
#endif
{
/* Ignore it. */
DEBUG( 0, ( "request_oplock_break: invalid message length received." ) );
DEBUG( 0, ( "request_oplock_break: invalid message length (%d) received.", reply_msg_len ) );
DEBUGADD( 0, ( " Ignoring.\n" ) );
continue;
}
@ -621,7 +938,8 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
* Test to see if this is the reply we are awaiting.
*/
if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) &&
if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) &&
((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == OPLOCK_BREAK_CMD) &&
(reply_from_port == share_entry->op_port) &&
(memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET],
&op_break_msg[OPLOCK_BREAK_PID_OFFSET],
@ -635,7 +953,11 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
else
{
/*
* This is another message - probably a break request.
* This is another message - a break request.
* Note that both kernel oplock break requests
* and UDP inter-smbd oplock break requests will
* be processed here.
*
* Process it to prevent potential deadlock.
* Note that the code in switch_message() prevents
* us from recursing into here as any SMB requests
@ -644,7 +966,7 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
* JRA.
*/
process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply));
process_local_message(op_break_reply, sizeof(op_break_reply));
}
time_left -= (time(NULL) - start_time);
@ -655,7 +977,6 @@ should be %d\n", pid, share_entry->op_port, oplock_port));
return True;
}
/****************************************************************************
Attempt to break an oplock on a file (if oplocked).
Returns True if the file was closed as a result of
@ -681,12 +1002,13 @@ BOOL attempt_close_oplocked_file(files_struct *fsp)
return False;
}
void check_kernel_oplocks(BOOL *have_oplocks)
/****************************************************************************
Init function to check if kernel level oplocks are available.
****************************************************************************/
void check_kernel_oplocks(void)
{
static BOOL done;
int fd;
int pfd[2];
pstring tmpname;
/*
* We only do this check once on startup.
@ -696,45 +1018,59 @@ void check_kernel_oplocks(BOOL *have_oplocks)
return;
done = True;
*have_oplocks = False;
lp_set_kernel_oplocks(False);
#if defined(HAVE_KERNEL_OPLOCKS)
slprintf( tmpname, sizeof(tmpname)-1, "/tmp/ot.%d.XXXXXX", getpid());
mktemp(tmpname);
{
int fd;
int pfd[2];
pstring tmpname;
if(pipe(pfd) != 0) {
DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error was %s\n",
strerror(errno) ));
return;
}
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;
}
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. \
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(pfd[0]);
close(pfd[1]);
close(fd);
return;
}
if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
Disabling kernel oplock supprt.\n" ));
close(pfd[0]);
close(pfd[1]);
close(fd);
return;
}
oplock_pipe_read = pfd[0];
oplock_pipe_write = pfd[1];
close(fd);
return;
DEBUG(3,("check_kernel_oplocks: Kernel oplocks enabled.\n"));
lp_set_kernel_oplocks(True);
}
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 */
}

View File

@ -47,7 +47,6 @@ extern pstring sesssetup_user;
extern char *last_inbuf;
extern char *InBuffer;
extern char *OutBuffer;
extern int oplock_sock;
extern int smb_read_error;
extern BOOL reload_after_sighup;
extern BOOL global_machine_pasword_needs_changing;
@ -55,24 +54,168 @@ extern fstring global_myworkgroup;
extern pstring global_myname;
extern int max_send;
/****************************************************************************
structure to hold a linked list of queued messages.
for processing.
****************************************************************************/
typedef struct {
ubi_slNode msg_next;
char *msg_buf;
int msg_len;
} pending_message_list;
static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
/****************************************************************************
Function to push a message onto the tail of a linked list of smb messages ready
for processing.
****************************************************************************/
static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
{
pending_message_list *msg = (pending_message_list *)
malloc(sizeof(pending_message_list));
if(msg == NULL)
{
DEBUG(0,("push_message: malloc fail (1)\n"));
return False;
}
msg->msg_buf = (char *)malloc(msg_len);
if(msg->msg_buf == NULL)
{
DEBUG(0,("push_message: malloc fail (2)\n"));
free((char *)msg);
return False;
}
memcpy(msg->msg_buf, buf, msg_len);
msg->msg_len = msg_len;
ubi_slAddTail( list_head, msg);
return True;
}
/****************************************************************************
Function to push a smb message onto a linked list of local smb messages ready
for processing.
****************************************************************************/
BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
{
return push_message(&smb_oplock_queue, buf, msg_len);
}
/****************************************************************************
Do a select on an two fd's - with timeout.
If a local udp message has been pushed onto the
queue (this can only happen during oplock break
processing) return this first.
If a pending smb message has been pushed onto the
queue (this can only happen during oplock break
processing) return this next.
If the first smbfd is ready then read an smb from it.
if the second (loopback UDP) fd is ready then read a message
from it and setup the buffer header to identify the length
and from address.
Returns False on timeout or error.
Else returns True.
The timeout is in milli seconds
****************************************************************************/
static BOOL receive_message_or_smb(char *buffer, int buffer_len,
int timeout, BOOL *got_smb)
{
extern int Client;
fd_set fds;
int selrtn;
struct timeval to;
int maxfd;
smb_read_error = 0;
*got_smb = False;
/*
* Check to see if we already have a message on the smb queue.
* If so - copy and return it.
*/
if(ubi_slCount(&smb_oplock_queue) != 0)
{
pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
/* Free the message we just copied. */
free((char *)msg->msg_buf);
free((char *)msg);
*got_smb = True;
DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
return True;
}
/*
* Setup the select read fd set.
*/
FD_ZERO(&fds);
FD_SET(Client,&fds);
maxfd = setup_oplock_select_set(&fds);
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(MAX(maxfd,Client)+1,&fds,timeout>0?&to:NULL);
/* Check if error */
if(selrtn == -1) {
/* something is wrong. Maybe the socket is dead? */
smb_read_error = READ_ERROR;
return False;
}
/* Did we timeout ? */
if (selrtn == 0) {
smb_read_error = READ_TIMEOUT;
return False;
}
if (FD_ISSET(Client,&fds))
{
*got_smb = True;
return receive_smb(Client, buffer, 0);
}
else
{
return receive_local_message(&fds, buffer, buffer_len, 0);
}
}
/****************************************************************************
Get the next SMB packet, doing the local message processing automatically.
****************************************************************************/
BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout)
BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
{
BOOL got_smb = False;
BOOL ret;
do
{
ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize,
timeout,&got_smb);
ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
if(ret && !got_smb)
{
/* Deal with oplock break requests from other smbd's. */
process_local_message(oplock_sock, inbuf, bufsize);
process_local_message(inbuf, bufsize);
continue;
}
@ -644,8 +787,8 @@ void smbd_process(void)
errno = 0;
for (counter=SMBD_SELECT_LOOP;
!receive_message_or_smb(Client,oplock_sock,
InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb);
!receive_message_or_smb(InBuffer,BUFFER_SIZE,
SMBD_SELECT_LOOP*1000,&got_smb);
counter += SMBD_SELECT_LOOP)
{
time_t t;
@ -792,6 +935,6 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
if(got_smb)
process_smb(InBuffer, OutBuffer);
else
process_local_message(oplock_sock, InBuffer, BUFFER_SIZE);
process_local_message(InBuffer, BUFFER_SIZE);
}
}

View File

@ -700,6 +700,8 @@ static void usage(char *pname)
if( !open_oplock_ipc() )
exit(1);
check_kernel_oplocks();
smbd_process();
close_sockets();

View File

@ -28,7 +28,6 @@ extern int DEBUGLEVEL;
extern int Protocol;
extern BOOL case_sensitive;
extern int Client;
extern int oplock_sock;
extern int smb_read_error;
extern fstring local_machine;
extern int global_oplock_break;
@ -1922,8 +1921,7 @@ int reply_trans2(connection_struct *conn,
num_params_sofar < total_params) {
BOOL ret;
ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
SMB_SECONDARY_WAIT);
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
if ((ret &&
(CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {