Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jan 1998 17:20:16 +0200 (EET)
From:      Calin Andrian <calin@ibd.dbio.ro>
To:        freebsd-hackers@FreeBSD.ORG
Subject:   Kernel patches for POWEROFF
Message-ID:  <Pine.BSF.3.96.980121170836.325A-100000@ibd.dbio.ro>

next in thread | raw e-mail | index | archive | help

While playing with my APC back-ups I was advised by Bruce M. Walter that
the POST_SYNC queue is not the safe place for a poweroff routine. The
way to do it is to patch the kernel. The patches follow.

The new, improved and packed with these diffs APC Back-UPS monitor
is now: ftp://ftp.dbio.ro/pub/FreeBSD/local/apcb-0.2.tgz

Sorry for respawning so rapidly.

WHAT THE DIFFS CHANGE:

at_shutdown() has a new queue named SHUTDOWN_POWEROFF which calls functions
that are supposed to turn off the power (after POST_SYNC queue is done).
This happens when /sbin/reboot and its links are run with -p switch.
Maybe it should have been a single function not a whole queue, but the
list ops were already there, so...

/sbin/reboot no longer defines RB_HALT when called with -p switch.
This means that if the poweroff fails, the system reboots for /sbin/reboot
and halts for /sbin/halt. For example, if the APC back-ups has AC input,
you cannot shut down the UPS (it ignores you). So, if the power was
restored after you committed the system shutdown, the system restarts
immediately. The original /sbin/reboot didn't allow this.
If you don't want to reboot, use /sbin/halt !

DIFFS: (3 pcs)

*** /usr/src/sys/kern/kern_shutdown.c.orig	Wed Jan 21 12:53:39 1998
--- /usr/src/sys/kern/kern_shutdown.c	Wed Jan 21 13:13:45 1998
***************
*** 118,123 ****
--- 118,124 ----
   */
  static sle_p shutdown_list1;
  static sle_p shutdown_list2;
+ static sle_p shutdown_list3;
  
  
  static void dumpsys(void);
***************
*** 247,252 ****
--- 248,265 ----
  		(*ep->function)(howto, ep->arg);
  		ep = ep->next;
  	}
+ 	if (howto & RB_POWEROFF) {
+ 		printf("\nTurning off power...\n");
+ 		DELAY(1000 * 1000);
+ 		ep = shutdown_list3;
+ 		while (ep) {
+ 			shutdown_list3 = ep->next;
+ 			(*ep->function)(howto, ep->arg);
+ 			ep = ep->next;
+ 		}
+ 		DELAY(5000 * 1000);	/* Wait 5 secs for power off */
+ 					/* Continue if power off failed */
+ 	}
  	splhigh();
  	if (howto & RB_HALT) {
  		printf("\n");
***************
*** 411,416 ****
--- 424,432 ----
  	case SHUTDOWN_POST_SYNC:
  		epp = &shutdown_list2;
  		break;
+ 	case SHUTDOWN_POWEROFF:
+ 		epp = &shutdown_list3;
+ 		break;
  	default:
  		printf("bad exit callout list specified\n");
  		return (EINVAL);
***************
*** 451,456 ****
--- 467,484 ----
  		ep = *epp;
  	}
  	epp = &shutdown_list2;
+ 	ep = *epp;
+ 	while (ep) {
+ 		if ((ep->function == function) && (ep->arg == arg)) {
+ 			*epp = ep->next;
+ 			free(ep, M_TEMP);
+ 			count++;
+ 		} else {
+ 			epp = &ep->next;
+ 		}
+ 		ep = *epp;
+ 	}
+ 	epp = &shutdown_list3;
  	ep = *epp;
  	while (ep) {
  		if ((ep->function == function) && (ep->arg == arg)) {

*** /usr/src/sbin/reboot/reboot.c.orig	Wed Jan 21 13:09:08 1998
--- /usr/src/sbin/reboot/reboot.c	Wed Jan 21 13:09:36 1998
***************
*** 85,91 ****
  			break;
  		case 'p':
  			pflag = 1;
! 			howto |= (RB_POWEROFF | RB_HALT);
  			break;
  		case 'q':
  			qflag = 1;
--- 85,91 ----
  			break;
  		case 'p':
  			pflag = 1;
! 			howto |= RB_POWEROFF;
  			break;
  		case 'q':
  			qflag = 1;

*** /usr/src/sys/sys/systm.h.orig	Wed Jan 21 13:11:56 1998
--- /usr/src/sys/sys/systm.h	Wed Jan 21 13:11:27 1998
***************
*** 171,176 ****
--- 171,177 ----
  int rm_at_shutdown(bootlist_fn function, void *arg);
  #define SHUTDOWN_PRE_SYNC 0
  #define SHUTDOWN_POST_SYNC 1
+ #define SHUTDOWN_POWEROFF 2
  
  /* forking */ /* XXX not yet */
  typedef void (*forklist_fn)(struct proc *parent,struct proc *child,int flags);




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980121170836.325A-100000>