On Thu, May 11, 2006 at 04:06:37PM -0700, Jeremy Allison wrote:
> On Thu, May 11, 2006 at 03:54:17PM -0700, Jeremy Allison wrote:
> > 
> > Do you see the change notify replies happening followed by the
> > change notify setups ? I bet I know what it is....
> > 
> > Because AIX doesn't have kernel change notify when the change
> > notify setup comes (which happens after every delete) it causes a
> > directory rescan at that point - after *each* delete !
> 
> I think I can code around this. The key is to ensure that
> setting "change notify timeout" to zero turns off change
> notify except for renames and deletes. Also make it a per-share
> parameter so it can be set to zero for "large" directories...
> 
> Give me a day or so on this.

Ok - here is the patch. Bill - if you could test this on
AIX by setting the (now per-share) parameter :

"change notify timeout = 0" 

on the share definition that holds a large number of files,
you might find a speed up. I can see the effect it has here
when I disable the kernel and FAM based change notify.

Jeremy.
Index: smbd/service.c
===================================================================
--- smbd/service.c      (revision 15550)
+++ smbd/service.c      (working copy)
@@ -930,6 +930,9 @@
                dbgtext( "(pid %d)\n", (int)sys_getpid() );
        }
        
+       /* Setup the minimum value for a change notify wait time (seconds). */
+       set_change_notify_timeout(lp_change_notify_timeout(snum));
+
        /* we've finished with the user stuff - go back to root */
        change_to_root_user();
        return(conn);
Index: smbd/notify.c
===================================================================
--- smbd/notify.c       (revision 15550)
+++ smbd/notify.c       (working copy)
@@ -135,9 +135,21 @@
 }
 
 /****************************************************************************
- Return true if there are pending change notifies.
+ Set the current change notify timeout to the lowest value across all service
+ values.
 ****************************************************************************/
 
+void set_change_notify_timeout(int val)
+{
+       if (val > 0) {
+               cnotify->select_time = MIN(cnotify->select_time, val);
+       }
+}
+
+/****************************************************************************
+ Longest time to sleep for before doing a change notify scan.
+****************************************************************************/
+
 int change_notify_timeout(void)
 {
        return cnotify->select_time;
Index: smbd/notify_hash.c
===================================================================
--- smbd/notify_hash.c  (revision 15550)
+++ smbd/notify_hash.c  (working copy)
@@ -81,6 +81,11 @@
                 return True;
         }
 
+       if (lp_change_notify_timeout(SNUM(conn)) <= 0) {
+               /* It change notify timeout has been disabled, never scan the 
directory. */
+               return True;
+       }
+
        /*
         * If we are to watch for changes that are only stored
         * in inodes of files, not in the directory inode, we must
@@ -179,10 +184,18 @@
 {
        struct change_data *data = (struct change_data *)datap;
        struct change_data data2;
+       int cnto = lp_change_notify_timeout(SNUM(conn));
 
-       if (t && t < data->last_check_time + lp_change_notify_timeout())
+       if (t && cnto <= 0) {
+               /* Change notify turned off on this share.
+                * Only scan when (t==0) - we think something changed. */
                return False;
+       }
 
+       if (t && t < data->last_check_time + cnto) {
+               return False;
+       }
+
        if (!change_to_user(conn,vuid))
                return True;
        if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) {
@@ -201,8 +214,9 @@
                return True;
        }
 
-       if (t)
+       if (t) {
                data->last_check_time = t;
+       }
 
        change_to_root_user();
 
@@ -229,7 +243,7 @@
        cnotify.register_notify = hash_register_notify;
        cnotify.check_notify = hash_check_notify;
        cnotify.remove_notify = hash_remove_notify;
-       cnotify.select_time = lp_change_notify_timeout();
+       cnotify.select_time = 60; /* Start with 1 minute default. */
        cnotify.notification_fd = -1;
 
        return &cnotify;
Index: param/loadparm.c
===================================================================
--- param/loadparm.c    (revision 15550)
+++ param/loadparm.c    (working copy)
@@ -220,7 +220,6 @@
        int lm_interval;
        int announce_as;        /* This is initialised in init_globals */
        int machine_password_timeout;
-       int change_notify_timeout;
        int map_to_guest;
        int oplock_break_wait_time;
        int winbind_cache_time;
@@ -449,6 +448,7 @@
        int iAioReadSize;
        int iAioWriteSize;
        int iMap_readonly;
+       int ichange_notify_timeout;
        param_opt_struct *param_opt;
 
        char dummy[3];          /* for alignment */
@@ -587,6 +587,7 @@
        0,                      /* iAioReadSize */
        0,                      /* iAioWriteSize */
        MAP_READONLY_YES,       /* iMap_readonly */
+       60,                     /* ichange_notify_timeout = 1 minute default. */
        
        NULL,                   /* Parametric options */
 
@@ -996,7 +997,7 @@
        {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
 
        {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, 
FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-       {"change notify timeout", P_INTEGER, P_GLOBAL, 
&Globals.change_notify_timeout, NULL, NULL, FLAG_ADVANCED}, 
+       {"change notify timeout", P_INTEGER, P_LOCAL, 
&sDefault.ichange_notify_timeout, NULL, NULL, FLAG_ADVANCED}, 
        {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, 
FLAG_ADVANCED}, 
        {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, 
FLAG_ADVANCED}, 
        {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, 
FLAG_ADVANCED}, 
@@ -1507,7 +1508,6 @@
        Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
        Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
        Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days 
default. */
-       Globals.change_notify_timeout = 60;     /* 1 minute default. */
        Globals.bKernelChangeNotify = True;     /* On if we have it. */
        Globals.bFamChangeNotify = True;        /* On if we have it. */
        Globals.lm_announce = 2;        /* = Auto: send only if LM clients 
found */
@@ -1934,7 +1934,6 @@
 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
 FN_GLOBAL_INTEGER(lp_machine_password_timeout, 
&Globals.machine_password_timeout)
-FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
@@ -2066,6 +2065,7 @@
 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
+FN_LOCAL_INTEGER(lp_change_notify_timeout, ichange_notify_timeout)
 FN_LOCAL_CHAR(lp_magicchar, magic_char)
 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
-- 
To unsubscribe from this list go to the following URL and read the
instructions:  https://lists.samba.org/mailman/listinfo/samba

Reply via email to