summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-06-12 17:06:00 +0000
committerAndrew Tridgell <tridge@samba.org>2000-06-12 17:06:00 +0000
commitc8de9b8fe14fe1e6e85652d543615dc187949a1a (patch)
tree23b3a6db0f9a180e001cb549858dd74abb620112
parentb2d01bd2dbfed8b35cc324fad42eac562fcad3b4 (diff)
downloadsamba-c8de9b8fe14fe1e6e85652d543615dc187949a1a.tar.gz
samba-c8de9b8fe14fe1e6e85652d543615dc187949a1a.tar.bz2
samba-c8de9b8fe14fe1e6e85652d543615dc187949a1a.zip
enable the Linux change notify code and change some notify debug code
(This used to be commit c6be511fcc1be79619a0184f03d4c33dbfe12f04)
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/smbd/notify.c5
-rw-r--r--source3/smbd/notify_kernel.c51
-rw-r--r--source3/smbd/oplock_linux.c23
4 files changed, 65 insertions, 16 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 091e43bf6d..83c1536b36 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -159,7 +159,7 @@ PROFILE_OBJ = profile/profile.o
OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o
-NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o
+NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o
SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 40867a71ee..c577d0aef3 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -212,7 +212,10 @@ initialise the change notify subsystem
****************************************************************************/
BOOL init_change_notify(void)
{
- cnotify = hash_notify_init();
+#if HAVE_KERNEL_CHANGE_NOTIFY
+ cnotify = kernel_notify_init();
+#endif
+ if (!cnotify) cnotify = hash_notify_init();
if (!cnotify) {
DEBUG(0,("Failed to init change notify system\n"));
diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c
index 7732bc646f..f78198f207 100644
--- a/source3/smbd/notify_kernel.c
+++ b/source3/smbd/notify_kernel.c
@@ -43,6 +43,14 @@ static unsigned signals_processed;
#define RT_SIGNAL_NOTIFY 34
#endif
+#ifndef F_SETSIG
+#define F_SETSIG 10
+#endif
+
+#ifndef F_NOTIFY
+#define F_NOTIFY 1026
+#endif
+
/****************************************************************************
This is the structure to keep the information needed to
determine if a directory has changed.
@@ -73,6 +81,8 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path
if (data->directory_handle != fd_pending) return False;
+ DEBUG(3,("kernel change notify on %s fd=%d\n", path, fd_pending));
+
close(fd_pending);
data->directory_handle = fd_pending = -1;
signals_processed++;
@@ -86,15 +96,17 @@ remove a change notify data structure
static void kernel_remove_notify(void *datap)
{
struct change_data *data = (struct change_data *)datap;
- if (data->directory_handle != -1) {
- if (data->directory_handle == fd_pending) {
- data->directory_handle = fd_pending = -1;
+ int fd = data->directory_handle;
+ if (fd != -1) {
+ if (fd == fd_pending) {
+ fd_pending = -1;
signals_processed++;
BlockSignals(False, RT_SIGNAL_NOTIFY);
}
- close(data->directory_handle);
+ close(fd);
}
free(data);
+ DEBUG(3,("removed kernel change notify fd=%d\n", fd));
}
@@ -107,10 +119,10 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32
int fd;
unsigned long kernel_flags;
- fd = dos_open(fsp->fsp_name, O_RDONLY, 0);
+ fd = dos_open(path, O_RDONLY, 0);
if (fd == -1) {
- DEBUG(3,("Failed to open directory %s for change notify\n", fsp->fsp_name));
+ DEBUG(3,("Failed to open directory %s for change notify\n", path));
return NULL;
}
@@ -120,8 +132,8 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32
}
kernel_flags = 0;
- if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME;
- if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME;
+ if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE;
+ if (flags & FILE_NOTIFY_CHANGE_DIR_NAME) kernel_flags |= DN_RENAME|DN_DELETE;
if (flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) kernel_flags |= DN_MODIFY;
if (flags & FILE_NOTIFY_CHANGE_SIZE) kernel_flags |= DN_MODIFY;
if (flags & FILE_NOTIFY_CHANGE_LAST_WRITE) kernel_flags |= DN_MODIFY;
@@ -133,11 +145,32 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32
return NULL;
}
+ if (fcntl(fd, F_SETOWN, sys_getpid()) == -1) {
+ DEBUG(3,("Failed to set owner for change notify\n"));
+ return NULL;
+ }
+
data.directory_handle = fd;
+ DEBUG(3,("kernel change notify on %s (flags=0x%x) fd=%d\n",
+ path, (int)kernel_flags, fd));
+
return (void *)memdup(&data, sizeof(data));
}
+/****************************************************************************
+see if the kernel supports change notify
+****************************************************************************/
+static BOOL kernel_notify_available(void)
+{
+ int fd, ret;
+ fd = open("/tmp", O_RDONLY);
+ if (fd == -1) return False; /* uggh! */
+ ret = fcntl(fd, F_NOTIFY, 0);
+ close(fd);
+ return ret == 0 || errno != EINVAL;
+}
+
/****************************************************************************
setup kernel based change notify
@@ -147,6 +180,8 @@ struct cnotify_fns *kernel_notify_init(void)
static struct cnotify_fns cnotify;
struct sigaction act;
+ if (!kernel_notify_available()) return NULL;
+
act.sa_handler = NULL;
act.sa_sigaction = signal_handler;
act.sa_flags = SA_SIGINFO;
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index de2a4300a7..c53dd1c57f 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -47,6 +47,10 @@ static int fd_pending; /* the fd of the current pending signal */
#define RT_SIGNAL_LEASE 33
#endif
+#ifndef F_SETSIG
+#define F_SETSIG 10
+#endif
+
/****************************************************************************
handle a LEASE signal, incrementing the signals_received and blocking the signal
****************************************************************************/
@@ -60,8 +64,7 @@ static void signal_handler(int signal, siginfo_t *info, void *unused)
/****************************************************************************
try to gain a linux capability
-****************************************************************************/
-static void set_capability(unsigned capability)
+****************************************************************************/static void set_capability(unsigned capability)
{
#ifndef _LINUX_CAPABILITY_VERSION
#define _LINUX_CAPABILITY_VERSION 0x19980330
@@ -101,6 +104,12 @@ try again
static int linux_setlease(int fd, int leasetype)
{
int ret;
+
+ if (fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
+ DEBUG(3,("Failed to set signal handler for kernel lease\n"));
+ return -1;
+ }
+
ret = fcntl(fd, F_SETLEASE, leasetype);
if (ret == -1 && errno == EACCES) {
set_capability(CAP_LEASE);
@@ -133,7 +142,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l
dev = sbuf.st_dev;
inode = sbuf.st_ino;
- DEBUG(5,("receive_local_message: kernel oplock break request received for \
+ DEBUG(3,("receive_local_message: kernel oplock break request received for \
dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ));
/*
@@ -167,14 +176,14 @@ dev = %x, inode = %.0f\n", (unsigned int)dev, (double)inode ));
static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
if (linux_setlease(fsp->fd, F_WRLCK) == -1) {
- DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
+ DEBUG(3,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
inode = %.0f. (%s)\n",
fsp->fsp_name, fsp->fd,
(unsigned int)fsp->dev, (double)fsp->inode, strerror(errno)));
return False;
}
- DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n",
+ DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f\n",
fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode));
return True;
@@ -226,7 +235,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i
memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode));
memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev));
- DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f\n",
+ DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f\n",
(unsigned int)*dev, (double)*inode));
return True;
@@ -283,6 +292,8 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void)
koplocks.msg_waiting = linux_oplock_msg_waiting;
koplocks.notification_fd = -1;
+ DEBUG(3,("Linux kernel oplocks enabled\n"));
+
return &koplocks;
}