Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Feb 1998 02:47:29 -0500 (EST)
From:      walter@fortean.com
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/5863: Kernel support for sorted SHUTDOWN :  SHUTDOWN_POWEROFF queues
Message-ID:  <199802270747.CAA24164@callisto.fortean.com>

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

>Number:         5863
>Category:       kern
>Synopsis:       Kernel support for sorted SHUTDOWN & SHUTDOWN_POWEROFF queues
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 26 23:50:00 PST 1998
>Last-Modified:
>Originator:     Bruce M. Walter
>Organization:
Fortean Technologies, Inc
>Release:        FreeBSD 2.2-STABLE i386
>Environment:

	FreeBSD 2.2-STABLE

>Description:

The attached patches add support for a SHUTDOWN_POWEROFF queue which is
run after the SHUTDOWN_POST_SYNC queue.  This provides a safe place for
callouts which want to poweroff the system by whatever means they have
available (UPS and APM would be logical consumers).

The patches also implement ordering all three SHUTDOWN_* queues.

An patch for the at_shutdown.9 man page is also included.

These patches have been tested locally for some time, and are also under
review by Mike Smith.

>How-To-Repeat:

N/A

>Fix:

*** sys/kern/kern_shutdown.c.orig	Sun Aug 10 22:04:14 1997
--- sys/kern/kern_shutdown.c	Wed Feb 11 01:56:25 1998
***************
*** 110,115 ****
--- 110,116 ----
  	struct shutdown_list_element *next;
  	bootlist_fn function;
  	void *arg;
+ 	int priority;
  } *sle_p;
  
  /*
***************
*** 118,123 ****
--- 119,125 ----
   */
  static sle_p shutdown_list1;
  static sle_p shutdown_list2;
+ static sle_p shutdown_list3;
  
  
  static void dumpsys(void);
***************
*** 248,253 ****
--- 250,266 ----
  		ep = ep->next;
  	}
  	splhigh();
+ 
+ 	/*
+ 	 * Ok, now do any last things we need to before cpu death
+ 	 */
+ 	ep = shutdown_list3;
+ 	while (ep) {
+ 		shutdown_list3 = ep->next;
+ 		(*ep->function)(howto, ep->arg);
+ 		ep = ep->next;
+ 	}
+ 
  	if (howto & RB_HALT) {
  		printf("\n");
  		printf("The operating system has halted.\n");
***************
*** 391,397 ****
  }
  
  /*
!  * Two routines to handle adding/deleting items on the
   * shutdown callout lists
   *
   * at_shutdown():
--- 404,410 ----
  }
  
  /*
!  * Three routines to handle adding/deleting items on the
   * shutdown callout lists
   *
   * at_shutdown():
***************
*** 402,408 ****
  int
  at_shutdown(bootlist_fn function, void *arg, int position)
  {
! 	sle_p ep, *epp;
  
  	switch(position) {
  	case SHUTDOWN_PRE_SYNC:
--- 415,436 ----
  int
  at_shutdown(bootlist_fn function, void *arg, int position)
  {
! 	return (at_shutdown_pri(function,arg,position,SHUTDOWN_PRI_DEFAULT));
! }
! 
! /*
!  * Three routines to handle adding/deleting items on the
!  * shutdown callout lists
!  *
!  * at_shutdown_pri():
!  * Take the arguments given and put them onto the shutdown callout list with
!  * the given execution priority.
!  * returns 0 on success.
!  */
! int
! at_shutdown_pri(bootlist_fn function, void *arg, int position, int priority)
! {
! 	sle_p ep, ip, lp, *epp;
  
  	switch(position) {
  	case SHUTDOWN_PRE_SYNC:
***************
*** 411,429 ****
  	case SHUTDOWN_POST_SYNC:
  		epp = &shutdown_list2;
  		break;
  	default:
  		printf("bad exit callout list specified\n");
  		return (EINVAL);
  	}
  	if (rm_at_shutdown(function, arg))
  		printf("exit callout entry already present\n");
  	ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
  	if (ep == NULL)
  		return (ENOMEM);
- 	ep->next = *epp;
  	ep->function = function;
  	ep->arg = arg;
! 	*epp = ep;
  	return (0);
  }
  
--- 439,482 ----
  	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);
  	}
+ 	if ((priority < SHUTDOWN_PRI_MAX) || (priority > SHUTDOWN_PRI_MIN)) {
+ 		printf("bad callout priority specified\n");
+ 		return (EINVAL);
+ 	}
  	if (rm_at_shutdown(function, arg))
  		printf("exit callout entry already present\n");
  	ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
  	if (ep == NULL)
  		return (ENOMEM);
  	ep->function = function;
  	ep->arg = arg;
! 	ep->priority = priority;
! 
! 	lp = NULL;
! 	ip = *epp;
! 	if (*epp) {
! 		while (ip) {
! 			if (ip->priority >= priority)
! 				break;
! 			lp = ip;
! 			ip = ip->next;
! 		}
! 	}
! 	if (lp) {
! 		ep->next = lp->next;
! 		lp->next = ep;
! 	} else {
! 		ep->next = ip;
! 		*epp = ep;
! 	}
! 
  	return (0);
  }
  
***************
*** 451,456 ****
--- 504,521 ----
  		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)) {
*** sys/sys/systm.h.orig	Sun Aug 10 22:04:12 1997
--- sys/sys/systm.h	Wed Feb 11 01:56:41 1998
***************
*** 168,176 ****
--- 168,181 ----
  /* shutdown callout list definitions */
  typedef void (*bootlist_fn)(int,void *);
  int at_shutdown(bootlist_fn function, void *arg, int);
+ int at_shutdown_pri(bootlist_fn function, void *arg, int, int);
  int rm_at_shutdown(bootlist_fn function, void *arg);
  #define SHUTDOWN_PRE_SYNC 0
  #define SHUTDOWN_POST_SYNC 1
+ #define SHUTDOWN_POWEROFF 2
+ #define SHUTDOWN_PRI_MAX 1
+ #define SHUTDOWN_PRI_MIN 10000
+ #define SHUTDOWN_PRI_DEFAULT 5000
  
  /* forking */ /* XXX not yet */
  typedef void (*forklist_fn)(struct proc *parent,struct proc *child,int flags);
*** share/man/man9/at_shutdown.9.orig	Fri Feb 14 02:53:01 1997
--- share/man/man9/at_shutdown.9	Wed Feb 18 11:35:59 1998
***************
*** 25,35 ****
  .\"
  .\" $Id: at_shutdown.9,v 1.4.2.1 1997/02/14 07:53:01 mpp Exp $
  .\" "
! .Dd August 15, 1996
  .Os
  .Dt AT_SHUTDOWN 9
  .Sh NAME
  .Nm at_shutdown ,
  .Nm rm_at_shutdown
  .Nd ask that a function be run at shutdown.
  .Sh SYNOPSIS
--- 25,36 ----
  .\"
  .\" $Id: at_shutdown.9,v 1.4.2.1 1997/02/14 07:53:01 mpp Exp $
  .\" "
! .Dd February 18, 1998
  .Os
  .Dt AT_SHUTDOWN 9
  .Sh NAME
  .Nm at_shutdown ,
+ .Nm at_shutdown_pri ,
  .Nm rm_at_shutdown
  .Nd ask that a function be run at shutdown.
  .Sh SYNOPSIS
***************
*** 41,58 ****
  .Ft int
  .Fn at_shutdown "bootlist_fn func" "void *arg" "int when"
  .Ft int
  .Fn rm_at_shutdown "bootlist_fn func" "void *arg"
  .Sh DESCRIPTION
  The
  .Nm at_shutdown
! facility allows a kernel module to ensure that it is notified
! at system shutdown.
  The function
  .Fa func
  is called with the flags indicating boot type, and the opaque argument
  .Fa arg
  when the system is shut down.
  .Pp
  If the requirement for notification is removed, then the function 
  .Fn rm_at_shutdown
  must be called with the exact
--- 42,95 ----
  .Ft int
  .Fn at_shutdown "bootlist_fn func" "void *arg" "int when"
  .Ft int
+ .Fn at_shutdown_pri "bootlist_fn func" "void *arg" "int when" "int priority"
+ .Ft int
  .Fn rm_at_shutdown "bootlist_fn func" "void *arg"
  .Sh DESCRIPTION
  The
  .Nm at_shutdown
! and
! .Nm at_shutdown_pri
! facilities allows a kernel module to ensure that it is notified at system
! shutdown.  There are three ordered shutdown queues, one run before the
! final sync, one run after, and one run with the intent of powering off the
! system (if possible).
! .Pp
  The function
  .Fa func
  is called with the flags indicating boot type, and the opaque argument
  .Fa arg
  when the system is shut down.
  .Pp
+ The argument
+ .Fa when
+ should be one of 
+ .Dv SHUTDOWN_PRE_SYNC ,
+ .Dv SHUTDOWN_POST_SYNC
+ or
+ .Dv SHUTDOWN_POWEROFF
+ to specify which queue should be used.
+ .Pp
+ The
+ .Fa priority
+ argument is an integer value between
+ .Dv SHUTDOWN_PRI_MAX
+ and
+ .Dv SHUTDOWN_PRI_MIN
+ by which the shutdown queue is sorted.  Smaller
+ .Fa priority
+ values are executed first.  Functions with identical priorities are
+ executed on a last-added, first-executed basis.
+ .Pp
+ For backwards compatibility any functions added via the
+ .Fn at_shutdown
+ interface will be added with a priority of
+ .Dv SHUTDOWN_PRI_DEFAULT
+ which represents a midpoint between
+ .Dv SHUTDOWN_PRI_MAX
+ and
+ .Dv SHUTDOWN_PRI_MIN .
+ .Pp
  If the requirement for notification is removed, then the function 
  .Fn rm_at_shutdown
  must be called with the exact
***************
*** 60,80 ****
  and
  .Fa arg
  arguments as the corresponding call to
! .Fn at_shutdown .
! There are two shutdown queues, one run before the final sync and one after.
! The last argument to 
! .Fa at_shutdown
! should be one of 
! .Dv SHUTDOWN_PRE_SYNC
  or
! .Dv SHUTDOWN_POST_SYNC
! to specify which queue should be used.
  .Fn rm_at_shutdown
! will remove an entry from either queue.
  .Pp
  .Sh RETURN VALUES
  .Fn at_shutdown
! returns an error code, 0 meaning success. 
  .Fn rm_at_shutdown
  returns the number of items removed (should be 0 or 1).
  .Sh SEE ALSO
--- 97,114 ----
  and
  .Fa arg
  arguments as the corresponding call to
! .Fn at_shutdown
  or
! .Fn at_shutdown_pri .
  .Fn rm_at_shutdown
! will remove an entry from any of the queues.
  .Pp
  .Sh RETURN VALUES
  .Fn at_shutdown
! and
! .Fn at_shutdown_pri
! both return an error code, 0 meaning success. 
! 
  .Fn rm_at_shutdown
  returns the number of items removed (should be 0 or 1).
  .Sh SEE ALSO
***************
*** 88,98 ****
  functions
  appeared in
  .Fx 2.2 .
  .Sh BUGS
! Since the shutdown queue is not sorted
! and items are added to the head, order of execution 
! is reversed to that of insertion.
  .Sh AUTHORS
  The function was written by
! .ie t Julian Elischer (julian@freebsd.org)
  .el Julian Elischer  (julian@freebsd.org)
--- 122,142 ----
  functions
  appeared in
  .Fx 2.2 .
+ .Pp
+ The
+ .Fn at_shutdown_pri
+ function appeared in
+ .Fx 2.2.6 .
  .Sh BUGS
! Although the shutdown queues are ordered by
! .Fa priority
! this priority is assigned by the interface consumers and may not
! reflect sanity.
  .Sh AUTHORS
  The function was written by
! .ie t Julian Elischer  (julian@freebsd.org)
  .el Julian Elischer  (julian@freebsd.org)
+ .Pp
+ Ordered execution added by
+ .ie t Bruce Walter  (walter@fortean.com)
+ .el Bruce Walter  (walter@fortean.com)
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802270747.CAA24164>