Index: ip_vs_sync.c =================================================================== RCS file: /home/wensong/cvsroot/ipvs/ip_vs_sync.c,v retrieving revision 1.6 diff -u -r1.6 ip_vs_sync.c --- ip_vs_sync.c 11 Jul 2002 14:26:41 -0000 1.6 +++ ip_vs_sync.c 25 Jul 2002 10:07:32 -0000 @@ -132,7 +132,7 @@ { struct ip_vs_sync_buff *sb; - spin_lock(&ip_vs_sync_lock); + spin_lock_bh(&ip_vs_sync_lock); if (list_empty(&ip_vs_sync_queue)) { sb = NULL; } else { @@ -141,7 +141,7 @@ list); list_del(&sb->list); } - spin_unlock(&ip_vs_sync_lock); + spin_unlock_bh(&ip_vs_sync_lock); return sb; } @@ -180,13 +180,13 @@ { struct ip_vs_sync_buff *sb; - spin_lock(&curr_sb_lock); + spin_lock_bh(&curr_sb_lock); if (curr_sb && (jiffies - curr_sb->firstuse > time)) { sb = curr_sb; curr_sb = NULL; } else sb = NULL; - spin_unlock(&curr_sb_lock); + spin_unlock_bh(&curr_sb_lock); return sb; } @@ -561,7 +561,7 @@ static int errno; static DECLARE_WAIT_QUEUE_HEAD(sync_wait); -static int sync_pid = 0; +static pid_t sync_pid = 0; static DECLARE_WAIT_QUEUE_HEAD(stop_sync_wait); static int stop_sync = 0; @@ -586,7 +586,7 @@ ip_vs_sync_buff_release(sb); } - /* check if entries stay in curr_sb for a while */ + /* check if entries stay in curr_sb for 2 seconds */ if ((sb = get_curr_sync_buff(2*HZ))) { m = sb->mesg; if (ip_vs_send_async(sock, (char *)m, @@ -607,12 +607,12 @@ while ((sb=sb_dequeue())) { ip_vs_sync_buff_release(sb); } - spin_lock(&curr_sb_lock); + spin_lock_bh(&curr_sb_lock); if (curr_sb) { ip_vs_sync_buff_release(curr_sb); curr_sb = NULL; } - spin_unlock(&curr_sb_lock); + spin_unlock_bh(&curr_sb_lock); /* release the sending multicast socket */ sock_release(sock); @@ -667,15 +667,11 @@ DECLARE_WAITQUEUE(wait, current); mm_segment_t oldmm; - MOD_INC_USE_COUNT; daemonize(); oldmm = get_fs(); set_fs(KERNEL_DS); - sync_pid = current->pid; - IP_VS_INFO("sync thread started.\n"); - if (ip_vs_sync_state == IP_VS_STATE_MASTER) sprintf(current->comm, "ipvs syncmaster"); else if (ip_vs_sync_state == IP_VS_STATE_BACKUP) @@ -704,14 +700,10 @@ remove_wait_queue(&sync_wait, &wait); /* thread exits */ - sync_pid = 0; - IP_VS_INFO("sync thread stopped!\n"); - stop_sync = 0; wake_up(&stop_sync_wait); set_fs(oldmm); - MOD_DEC_USE_COUNT; return 0; } @@ -721,13 +713,18 @@ if (sync_pid) return -EEXIST; + MOD_INC_USE_COUNT; + IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid); IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %d bytes\n", sizeof(struct ip_vs_sync_conn)); + ip_vs_sync_state = state; strcpy(ip_vs_mcast_ifn, mcast_ifn); - if (kernel_thread(sync_thread, NULL, 0) < 0) + if ((sync_pid = kernel_thread(sync_thread, NULL, 0)) < 0) IP_VS_BUG(); + + IP_VS_INFO("sync thread started.\n"); return 0; } @@ -735,10 +732,12 @@ int stop_sync_thread(void) { DECLARE_WAITQUEUE(wait, current); + pid_t pid; if (!sync_pid) return -ESRCH; + IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid); IP_VS_INFO("stopping sync thread %d ...\n", sync_pid); __set_current_state(TASK_UNINTERRUPTIBLE); @@ -750,13 +749,19 @@ __set_current_state(TASK_RUNNING); remove_wait_queue(&stop_sync_wait, &wait); - /* it is probably not correct here. we need use sys_wait4, but need - to patch the kernel to export sys_wait4, check it later... - sys_wait4(sync_pid, NULL, __WCLONE, NULL); */ - waitpid(sync_pid, NULL, __WCLONE); + /* When the same process start/stop the sync thread (in this case + the parent process of the sync thread is this process, instead + of the init process), must reap the sync thread here. */ + pid = waitpid(sync_pid, NULL, __WCLONE|WNOHANG); + if (pid > 0 && pid != sync_pid) + IP_VS_ERR("waitpid bug!\n"); if (stop_sync) IP_VS_BUG(); + + IP_VS_INFO("sync thread stopped!\n"); + sync_pid = 0; + MOD_DEC_USE_COUNT; return 0; }