/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* RCM module providing support for swap areas
* during reconfiguration operations.
*/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <thread.h>
#include <synch.h>
#include <strings.h>
#include <assert.h>
#include <errno.h>
#include <libintl.h>
#include "rcm_module.h"
/* cache flags */
/* LP64 hard code */
typedef struct swap_file {
int cache_flags;
} swap_file_t;
/* swap file may have multiple swap areas */
typedef struct swap_area {
int cache_flags;
} swap_area_t;
static int swap_register(rcm_handle_t *);
static int swap_unregister(rcm_handle_t *);
char **, char **, nvlist_t *, rcm_info_t **);
uint_t, char **, rcm_info_t **);
char **, rcm_info_t **);
char **, rcm_info_t **);
char **, rcm_info_t **);
char **, rcm_info_t **);
static int alloc_usage(char **);
static void cache_insert(swap_file_t *);
static swap_file_t *cache_lookup(char *);
static void cache_remove(swap_file_t *);
static void free_cache(void);
static int get_dumpdev(char []);
static void log_cmd_status(int);
static int swap_add(swap_file_t *, char **);
static int swap_delete(swap_file_t *, char **);
static swap_file_t *swap_file_alloc(char *);
static void swap_file_free(swap_file_t *);
static swaptbl_t *sys_swaptbl(void);
static int update_cache(rcm_handle_t *);
{
NULL,
NULL,
};
struct rcm_mod_ops *
{
return (&swap_ops);
}
const char *
{
return ("RCM Swap module 1.5");
}
int
{
free_cache();
(void) mutex_destroy(&cache_lock);
return (RCM_SUCCESS);
}
static int
{
return (update_cache(hdl));
}
static int
{
(void) mutex_lock(&cache_lock);
}
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
/*ARGSUSED*/
static int
{
(void) mutex_lock(&cache_lock);
rsrcname);
(void) mutex_unlock(&cache_lock);
return (RCM_FAILURE);
}
(void) mutex_unlock(&cache_lock);
(void) alloc_usage(infostr);
return (RCM_SUCCESS);
}
/*
* Remove swap space to maintain availability of anonymous pages
* during device suspension. Swap will be reconfigured upon resume.
* Fail if operation will unconfigure dump device.
*/
/*ARGSUSED*/
static int
{
int rv;
return (RCM_SUCCESS);
(void) mutex_lock(&cache_lock);
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
(void) mutex_unlock(&cache_lock);
return (rv);
}
/*ARGSUSED*/
static int
{
int rv;
(void) mutex_lock(&cache_lock);
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
(void) mutex_unlock(&cache_lock);
return (rv);
}
/*
* By default, reject offline request. If forced, attempt to
* delete swap. Fail if operation will unconfigure dump device.
*/
/*ARGSUSED*/
static int
{
int rv;
return (RCM_SUCCESS);
(void) mutex_lock(&cache_lock);
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
(void) mutex_unlock(&cache_lock);
return (rv);
}
/* default reject */
(void) mutex_unlock(&cache_lock);
(void) alloc_usage(errstr);
return (RCM_FAILURE);
}
/*ARGSUSED*/
static int
{
int rv;
(void) mutex_lock(&cache_lock);
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
(void) mutex_unlock(&cache_lock);
return (rv);
}
/*ARGSUSED*/
static int
{
(void) mutex_lock(&cache_lock);
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
/* RCM framework handles unregistration */
(void) mutex_unlock(&cache_lock);
return (RCM_SUCCESS);
}
/*
* Delete all swap areas for swap file.
* Invoke swap(1M) instead of swapctl(2) to
* handle relocation of dump device.
* If dump device is configured, fail if
* unable to relocate dump.
*
* Call with cache_lock held.
*/
static int
{
int stat;
have_dump = 0;
/* swap(1M) is not idempotent */
continue;
}
rv = RCM_FAILURE;
goto out;
}
/*
* Fail on removal of dump device.
*/
if (have_dump == 0)
continue;
if (get_dumpdev(dumpdev) != 0) {
"check for removal of dump device\n");
} else if (dumpdev[0] == '\0') {
"attempting recovery\n");
/*
* Restore dump
*/
"failed to restore dump\n");
} else {
}
rv = RCM_FAILURE;
goto out;
}
}
out:
return (rv);
}
/*
* Invoke swap(1M) to add each registered swap area.
*
* Call with cache_lock held.
*/
static int
{
(2 * MAXOFFSET_STRLEN)];
int stat;
/* swap(1M) is not idempotent */
continue;
}
rv = RCM_FAILURE;
break;
} else {
}
}
return (rv);
}
static int
{
int i;
"current swap configuration\n");
return (RCM_FAILURE);
}
(void) mutex_lock(&cache_lock);
/*
* cache pass 1 - mark everyone stale
*/
}
}
/*
* add new entries
*/
continue;
}
/*
* assure swap_file_t
*/
NULL) {
return (RCM_FAILURE);
}
} else {
}
/*
* assure swap_area_t
*/
return (RCM_FAILURE);
}
} else {
}
}
/*
* cache pass 2
*
* swap_file_t - skip offlined, register new, unregister/remove stale
* swap_area_t - skip offlined, remove stale
*/
continue;
}
continue;
}
}
continue;
}
RCM_SUCCESS) {
}
continue;
}
continue;
}
RCM_SUCCESS) {
rv = RCM_FAILURE;
} else {
}
}
(void) mutex_unlock(&cache_lock);
return (rv);
}
/*
* Returns system swap table.
*/
static swaptbl_t *
{
char *cp;
int i, n;
return (NULL);
return (NULL);
for (i = 0; i < n; i++) {
cp += MAXPATHLEN;
}
return (NULL);
}
/* mismatch, try again */
return (sys_swaptbl());
}
return (swt);
}
static int
{
int fd;
int rv = 0;
char *err;
return (-1);
}
dumpdev[0] = '\0';
} else {
rv = -1;
}
}
return (rv);
}
static void
free_cache(void)
{
(void) mutex_lock(&cache_lock);
}
(void) mutex_unlock(&cache_lock);
}
/*
* Call with cache_lock held.
*/
static void
{
}
}
/*
* Call with cache_lock held.
*/
static void
{
}
/*
* Call with cache_lock held.
*/
static swap_file_t *
{
return (sf);
}
}
return (NULL);
}
/*
* Call with cache_lock held.
*/
static void
{
}
} else {
}
}
/*
* Call with cache_lock held.
*/
static void
{
}
/*
* Call with cache_lock held.
*/
static void
{
}
} else {
}
}
static swap_file_t *
{
return (NULL);
}
return (sf);
}
static swap_area_t *
{
return (NULL);
}
return (sa);
}
/*
* Call with cache_lock held.
*/
static swap_area_t *
{
return (sa);
}
}
return (NULL);
}
/*
* All-purpose usage string.
*/
static int
{
return (-1);
}
return (0);
}
static void
{
char *err;
if (stat == -1) {
WEXITSTATUS(stat));
} else {
}
}