/*
* 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.
* Copyright (c) 2011 Bayard G. Bell. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
*/
#include <sys/sysmacros.h>
#ifndef lint
#endif /* lint */
extern int md_status;
extern md_krwlock_t md_unit_array_rw;
extern mdq_anchor_t md_done_daemon;
extern int md_in_upgrade;
#ifdef DEBUG
/*
* ROUTINES FOR TESTING:
*/
static int
{
extern int _init_ioctl();
return (_init_ioctl());
}
static int
{
extern int _fini_ioctl();
int err = 0;
err = _fini_ioctl();
return (err);
}
#endif /* DEBUG */
/*
* BEGIN RELEASE DEBUG
* The following routines remain in the released product for testability
*/
int
{
int rv = 0;
}
} else {
}
return (rv);
}
static void
int flag,
void *private)
{
}
/*
* END RELEASE DEBUG
*/
/*
* COMMON MEMORY ALLOCATION ROUTINES (so that we can discover leaks)
*/
void *
{
}
void *
{
}
void
{
if (nb)
}
static void
{
}
/*ARGSUSED1*/
int
{
bioinit(p);
return (0);
}
void
{
}
/*ARGSUSED1*/
void
trans_child_destructor(void *p, void *d)
{
biofini(p);
}
void
{
int ri = 0;
return;
if (domstr)
}
if (ri == 0)
return;
}
void
{
}
}
int
{
int err;
/*
* Do the open by device id if it is regular device
*/
}
if (err)
return (ENXIO);
if (err) {
return (ENXIO);
}
}
return (0);
}
int
{
/*
* initialize debug mode and always start with no shadowing.
*/
if (!snarfing)
return (0);
/*
* If snarfing the metatrans device,
* then remake the device number
*/
if (snarfing) {
}
/*
* db rec is partially deleted; finish the db delete later
*/
return (1);
}
/*
* With the current device id implementation there is possibility
* that we may have NODEV if the underlying can't be resolved at
* snarf time. If this is the case we want to be consistent with
* the normal behavior and continue to allow the snarf of unit
* and resolve the devt at the open time
*/
return (1);
}
/*
* retain the detach status; reset open status
*/
/*
* log device not set up yet; try again later
*/
return (1);
/*
* initialize incore fields
*/
un->un_logreset = 0;
/* necessary because capability didn't exist pre-4.1 */
/*
* attach the log
*/
trans_attach(un, 0);
/*
* check for master dev dynconcat
*/
struct mdc_unit *c;
}
/* place various information in the in-core data structures */
return (0);
}
int
{
int error = 0;
/*
* The caller is responsible for single-threading this routine.
*/
return (0);
/*
* already detached or the log isn't attached yet; do nothing
*/
return (0);
/*
* set state to detaching
*/
if (!MD_UPGRADE) {
trans_commit(un, 0);
}
}
/*
* device is busy
*/
if (md_unit_isopen(ui))
return (EBUSY);
/*
* detach the log
* if successful
* flags committed to TRANS_DETACHED in database
* un->un_l_unit set to NULL
* no error returned
*/
if (error)
return (error);
/*
* commit to database
*/
if (!MD_UPGRADE) {
trans_commit(un, 0);
}
return (0);
}
void
{
/*
* called from snarf, set, and attach. Hence, the attaching param
* The caller is responsible for single-threading this routine.
*/
/*
* not attaching; do nothing
*/
return;
/*
* find log unit struct
*/
return;
/*
* device is busy; do nothing
*/
return;
/*
*/
/*
* add metatrans device to the log's list of mt devices
*/
/*
* attached
*/
}
int
{
int error = 0;
/*
* reset log, maps, and ufs interface
*/
if (error)
return (error);
/*
* done with underyling devices
*/
if (!removing)
return (0);
/* Save the mstr key */
/* Remove the vtoc, if present */
if (vtoc_id)
return (0);
}
static void
{
drv_usecwait(10);
}
}
static void
{
char *str;
/*
* gather up params for cmn_err
*/
str = "read";
else
str = "write";
/*
* free up the resources for this request and done the errored buf
*/
md_biodone(pb);
/*
* print pretty error message
*/
}
int
{
/*
* device not in hard error state; report error
*/
if (panicstr)
else
return (1);
}
}
if (panicstr)
else
md_biodone(pb);
return (0);
}
static void
{
return;
}
/* check and map */
return;
}
/*
* Save essential information from the original buffhdr
* in the md_save structure.
*/
/*
* RELEASE DEBUG
* The following calls shadow debug for testing purposes if we are
* writing and if shadowing is turned on.
*/
/*
* panic in progress; process daemon queues
*/
if (panicstr) {
}
}
/* ARGSUSED */
static int
{
int error;
return (error);
}
/* ARGSUSED */
static int
{
int error;
return (error);
}
/* ARGSUSED */
static int
{
int error;
return (error);
}
/* ARGSUSED */
static int
{
int error;
return (error);
}
static void
{
trans_commit(un, 0);
/* Save the mstr key */
}
static int
{
int gotsomething;
int all_trans_gotten;
static int trans_found = 0;
if (cmd == MD_SNARF_CLEANUP) {
return (0);
/*
* clean up partially cleared trans devices
*/
}
}
/*
* clean up partially cleared log devices
*/
}
}
return (0);
}
/*
* must snarf up the log devices first
*/
gotsomething = 0;
all_trans_gotten = 1;
continue;
/*
* As trans records are always old records,
* we have to check if this record already has been converted.
* We don't want to do that work twice.
*/
newreqsize = sizeof (ml_unit_t);
/*
* Update userdata and incore userdata
* incores are at the end of ul
*/
} else {
/* already converted, just set the pointer */
}
all_trans_gotten = 0;
gotsomething = 1;
}
}
/*
* now snarf up metatrans devices
*/
gotsomething = 0;
continue;
if ((trans_found == 0) && (!MD_UPGRADE)) {
trans_found = 1;
}
/*
* As trans records are always old records,
* we have to check if this record already has been converted.
* We don't want to do that work twice.
*/
newreqsize = sizeof (mt_unit_t);
/*
* Update userdata and incore userdata
* incores are at the end of ul
*/
} else {
/* already converted, just set the pointer */
}
/*
* Create minor node for snarfed entry.
*/
continue;
}
all_trans_gotten = 0;
gotsomething = 1;
}
}
if (!all_trans_gotten)
return (gotsomething);
return (0);
}
static int
{
unit_t i;
if (cmd == MD_HALT_CLOSE) {
for (i = 0; i < md_nunits; i++) {
continue;
continue;
if (md_unit_isopen(ui)) {
return (1);
}
}
for (i = 0; i < md_nunits; i++) {
continue;
continue;
}
}
return (0);
}
if (cmd == MD_HALT_OPEN) {
for (i = 0; i < md_nunits; i++) {
continue;
continue;
}
return (0);
}
if (cmd == MD_HALT_CHECK) {
for (i = 0; i < md_nunits; i++) {
continue;
continue;
if (md_unit_isopen(ui)) {
return (1);
}
}
return (0);
}
if (cmd == MD_HALT_DOIT) {
for (i = 0; i < md_nunits; i++) {
continue;
continue;
0, 1);
}
return (0);
}
if (cmd == MD_HALT_UNLOAD)
return (0);
return (1);
}
/*ARGSUSED3*/
static int
int flag,
int otyp,
int md_oflags
)
{
int err;
/* disallow layered opens (e.g., PrestoServe) */
return (EINVAL);
/* single thread */
/* if already open, count open, return success */
if (md_unit_isopen(ui)) {
if (err != 0)
return (err);
return (0);
}
/*
* For some reason, not all of the metatrans devices attached to
* this log were openable at snarf; try again now. All of the
* underlying devices have to be openable for the roll thread to work.
*/
return (EINVAL);
}
/* count open */
if (err != 0)
return (err);
/* return success */
return (0);
}
/*ARGSUSED1*/
static int
int flag,
int otyp,
int md_oflags
)
{
int err = 0;
/* single thread */
/* count closed */
return (err);
}
/* if still open */
if (md_unit_isopen(ui)) {
return (0);
}
/*
* prevent new opens and try to detach the log
*/
(void) trans_detach(un, 0);
}
/*
* prevent new opens and try to attach the log
*/
}
return (0);
}
static int
)
{
int gotsomething = 0;
/*
* Do log first if there is any
* Note that trans record is always 32 bit
*/
continue;
/*
* Trans log record always is old format
* Go ahead update the record with the new set info
*/
/*
* Mark the record and update it
*/
goto out;
}
/*
* Now do the master
*/
continue;
/*
* Trans master record always is old format
*/
/*
* Mark the record and update it
*/
goto out;
gotsomething = 1;
}
out:
return (gotsomething);
}
{(intptr_t (*)()) trans_exchange_self_update_from_down,
{(intptr_t (*)()) trans_exchange_parent_update_to,
{NULL, 0 }
};
trans_open, /* open */
trans_close, /* close */
md_trans_strategy, /* strategy */
NULL, /* print */
NULL, /* dump */
md_trans_read, /* read */
md_trans_write, /* write */
md_trans_ioctl, /* trans ioctl */
trans_snarf, /* trans_snarf */
trans_halt, /* halt */
md_trans_aread, /* aread */
md_trans_awrite, /* awrite */
trans_imp_set, /* import set */
};
static void
init_init(void)
{
_init_ldl();
ASSERT(_init_debug());
}
static void
fini_uninit(void)
{
ASSERT(_fini_debug());
_fini_ldl();
}
/* define the module linkage */