enable the Linux change notify code and change some notify debug code
authorAndrew Tridgell <tridge@samba.org>
Mon, 12 Jun 2000 17:06:00 +0000 (17:06 +0000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 12 Jun 2000 17:06:00 +0000 (17:06 +0000)
source/Makefile.in
source/smbd/notify.c
source/smbd/notify_kernel.c
source/smbd/oplock_linux.c

index 091e43bf6dab04ce3f9e6ce4229b69a14d309749..83c1536b3682d6a306265604d8e0363a876720cf 100644 (file)
@@ -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 \
index 40867a71eeb652e13afa48e0a32eb547f18962f1..c577d0aef32f884962aea2441516ce0090003727 100644 (file)
@@ -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"));
index 7732bc646fa6a0df450dbac9a2f5b2d41807ae72..f78198f207905250e68b5df0841e7ba9459b4969 100644 (file)
@@ -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;
index de2a4300a7a0d2c8967faed337d359bea8deae83..c53dd1c57f553eb1f0579edf684972f2ea4f6a7d 100644 (file)
@@ -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;
 }