txg.c revision 495807d7dceb9c0357efb5f483dbf9f951dfeec6
/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/zfs_context.h>
#include <sys/txg_impl.h>
#include <sys/dmu_impl.h>
#include <sys/dsl_pool.h>
/*
* Pool-wide transaction groups.
*/
/*
* Prepare the txg subsystem.
*/
void
{
int c;
for (c = 0; c < max_ncpus; c++) {
int i;
for (i = 0; i < TXG_SIZE; i++) {
NULL);
sizeof (dmu_tx_callback_t),
}
}
}
/*
* Close down the txg subsystem.
*/
void
{
int c;
for (c = 0; c < max_ncpus; c++) {
int i;
for (i = 0; i < TXG_SIZE; i++) {
}
}
}
/*
* Start syncing transaction groups.
*/
void
{
/*
* The sync thread can need a larger-than-default stack size on
* 32-bit x86. This is due in part to nested pools and
* scrub_visitbp() recursion.
*/
}
static void
{
}
static void
{
tx->tx_threads--;
thread_exit();
}
static void
{
if (time)
ddi_get_lbolt() + time);
else
}
/*
* Stop syncing transaction groups.
*/
void
{
/*
* Finish off any work in progress.
*/
/*
* We need to ensure that we've vacated the deferred space_maps.
*/
/*
* Wake all sync threads and wait for them to die.
*/
while (tx->tx_threads != 0)
tx->tx_exiting = 0;
}
{
return (txg);
}
void
{
}
void
{
}
void
{
}
static void
{
int c;
/*
* Grab all tx_cpu locks so nobody else can get into this txg.
*/
for (c = 0; c < max_ncpus; c++)
tx->tx_open_txg++;
/*
* Now that we've incremented tx_open_txg, we can let threads
* enter the next transaction group.
*/
for (c = 0; c < max_ncpus; c++)
/*
* Quiesce the transaction group by waiting for everyone to txg_exit().
*/
for (c = 0; c < max_ncpus; c++) {
}
}
static void
{
}
/*
* Dispatch the commit callbacks registered on this txg to worker threads.
*/
static void
{
int c;
for (c = 0; c < max_ncpus; c++) {
/* No need to lock tx_cpu_t at this point */
continue;
/*
* Commit callback taskq hasn't been created yet.
*/
}
}
}
static void
{
for (;;) {
/*
* We sync when we're scrubbing, there's someone waiting
* on us, or the quiesce thread has handed off a txg to
* us, or we have reached our timeout.
*/
spa_shutting_down(spa)) &&
tx->tx_quiesced_txg == 0) {
dprintf("waiting; tx_synced=%llu waiting=%llu dp=%p\n",
}
/*
* Wait until the quiesce thread hands off a txg to us,
* prompting it to do so if necessary.
*/
}
if (tx->tx_exiting)
/*
* Consume the quiesced txg which has been handed off to
* us. This may cause the quiescing thread to now be
* able to quiesce another txg, so we must signal it.
*/
tx->tx_quiesced_txg = 0;
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
start = ddi_get_lbolt();
tx->tx_syncing_txg = 0;
/*
* Dispatch commit callbacks to worker threads.
*/
}
}
static void
{
for (;;) {
/*
* We quiesce when there's someone waiting on us.
* However, we can only have one txg in "quiescing" or
* "quiesced, waiting to sync" state. So we wait until
* the "quiesced, waiting to sync" txg has been consumed
* by the sync thread.
*/
while (!tx->tx_exiting &&
tx->tx_quiesced_txg != 0))
if (tx->tx_exiting)
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
/*
* Hand this txg off to the sync thread.
*/
}
}
/*
* Delay this thread by 'ticks' if we are still in the open transaction
* group and there is already a waiting txg quiesing or quiesced. Abort
* the delay if this txg stalls or enters the quiesing state.
*/
void
{
/* don't delay if this txg could transition to quiesing immediately */
return;
return;
}
while (ddi_get_lbolt() < timeout &&
timeout);
}
void
{
if (txg == 0)
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
dprintf("broadcasting sync more "
"tx_synced=%llu waiting=%llu dp=%p\n",
}
}
void
{
if (txg == 0)
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
}
}
{
}
{
tx->tx_quiesced_txg != 0);
}
/*
* Per-txg object lists.
*/
void
{
int t;
for (t = 0; t < TXG_SIZE; t++)
}
void
{
int t;
for (t = 0; t < TXG_SIZE; t++)
}
int
{
}
/*
* Add an entry to the list.
* Returns 0 if it's a new entry, 1 if it's already there.
*/
int
{
int already_on_list;
if (!already_on_list) {
}
return (already_on_list);
}
/*
* Add an entry to the end of the list (walks list to find end).
* Returns 0 if it's a new entry, 1 if it's already there.
*/
int
{
int already_on_list;
if (!already_on_list) {
txg_node_t **tp;
continue;
}
return (already_on_list);
}
/*
* Remove the head of the list and return it.
*/
void *
{
txg_node_t *tn;
void *p = NULL;
}
return (p);
}
/*
* Remove a specific item from the list and return it.
*/
void *
{
return (p);
}
}
return (NULL);
}
int
{
}
/*
* Walk a txg list -- only safe if you know it's not changing.
*/
void *
{
}
void *
{
}