static bool recalc_brl_timeout(void) { struct blocking_lock_record *blr; struct timeval next_timeout; TALLOC_FREE(brl_timeout); next_timeout = timeval_zero(); for (blr = blocking_lock_queue; blr; blr = blr->next) { if (timeval_is_zero(&blr->expire_time)) { /* * If we're blocked on pid 0xFFFFFFFF this is * a POSIX lock, so calculate a timeout of * 10 seconds into the future. */ if (blr->blocking_pid == 0xFFFFFFFF) { struct timeval psx_to = timeval_current_ofs(10, 0); next_timeout = timeval_brl_min(&next_timeout, &psx_to); } continue; } next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time); } if (timeval_is_zero(&next_timeout)) { DEBUG(10, ("Next timeout = Infinite.\n")); return True; } if (DEBUGLVL(10)) { struct timeval cur, from_now; cur = timeval_current(); from_now = timeval_until(&cur, &next_timeout); DEBUG(10, ("Next timeout = %d.%d seconds from now.\n", (int)from_now.tv_sec, (int)from_now.tv_usec)); } if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL, next_timeout, brl_timeout_fn, NULL))) { return False; } return True; }
static bool recalc_brl_timeout(struct smbd_server_connection *sconn) { struct blocking_lock_record *blr; struct timeval next_timeout; int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5); TALLOC_FREE(sconn->smb1.locks.brl_timeout); next_timeout = timeval_zero(); for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = blr->next) { if (timeval_is_zero(&blr->expire_time)) { /* * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is * a POSIX lock, so calculate a timeout of * 10 seconds into the future. */ if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) { struct timeval psx_to = timeval_current_ofs(10, 0); next_timeout = timeval_brl_min(&next_timeout, &psx_to); } continue; } next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time); } if (timeval_is_zero(&next_timeout)) { DEBUG(10, ("Next timeout = Infinite.\n")); return True; } /* to account for unclean shutdowns by clients we need a maximum timeout that we use for checking pending locks. If we have any pending locks at all, then check if the pending lock can continue at least every brl:recalctime seconds (default 5 seconds). This saves us needing to do a message_send_all() in the SIGCHLD handler in the parent daemon. That message_send_all() caused O(n^2) work to be done when IP failovers happened in clustered Samba, which could make the entire system unusable for many minutes. */ if (max_brl_timeout > 0) { struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0); next_timeout = timeval_min(&next_timeout, &min_to); } if (DEBUGLVL(10)) { struct timeval cur, from_now; cur = timeval_current(); from_now = timeval_until(&cur, &next_timeout); DEBUG(10, ("Next timeout = %d.%d seconds from now.\n", (int)from_now.tv_sec, (int)from_now.tv_usec)); } sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx, NULL, next_timeout, brl_timeout_fn, sconn); if (sconn->smb1.locks.brl_timeout == NULL) { return False; } return True; }