HardenedBSD/sys/geom/union/g_union.h
Warner Losh 4d846d260e spdx: The BSD-2-Clause-FreeBSD identifier is obsolete, drop -FreeBSD
The SPDX folks have obsoleted the BSD-2-Clause-FreeBSD identifier. Catch
up to that fact and revert to their recommended match of BSD-2-Clause.

Discussed with:		pfg
MFC After:		3 days
Sponsored by:		Netflix
2023-05-12 10:44:03 -06:00

145 lines
5.6 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Marshall Kirk McKusick <mckusick@mckusick.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _G_UNION_H_
#define _G_UNION_H_
#define G_UNION_CLASS_NAME "UNION"
#define G_UNION_VERSION 1
#define G_UNION_SUFFIX ".union"
/*
* Special flag to instruct gunion to passthrough the underlying provider's
* physical path
*/
#define G_UNION_PHYSPATH_PASSTHROUGH "\255"
#ifdef _KERNEL
#define G_UNION_DEBUG(lvl, ...) \
_GEOM_DEBUG("GEOM_UNION", g_union_debug, (lvl), NULL, __VA_ARGS__)
#define G_UNION_LOGREQLVL(lvl, bp, ...) \
_GEOM_DEBUG("GEOM_UNION", g_union_debug, (lvl), (bp), __VA_ARGS__)
#define G_UNION_LOGREQ(bp, ...) G_UNION_LOGREQLVL(3, (bp), __VA_ARGS__)
TAILQ_HEAD(wiplist, g_union_wip);
/*
* State maintained by each instance of a UNION GEOM.
*/
struct g_union_softc {
struct rwlock sc_rwlock; /* writemap lock */
uint64_t **sc_writemap_root; /* root of write map */
uint64_t *sc_leafused; /* 1 => leaf has allocation */
uint64_t sc_map_size; /* size of write map */
long sc_root_size; /* entries in root node */
long sc_leaf_size; /* entries in leaf node */
long sc_bits_per_leaf; /* bits per leaf node entry */
long sc_writemap_memory; /* memory used by writemap */
off_t sc_offset; /* starting offset in lower */
off_t sc_size; /* size of union geom */
off_t sc_sectorsize; /* sector size of geom */
struct g_consumer *sc_uppercp; /* upper-level provider */
struct g_consumer *sc_lowercp; /* lower-level provider */
struct wiplist sc_wiplist; /* I/O work-in-progress list */
long sc_flags; /* see flags below */
long sc_reads; /* number of reads done */
long sc_wrotebytes; /* number of bytes written */
long sc_writes; /* number of writes done */
long sc_readbytes; /* number of bytes read */
long sc_deletes; /* number of deletes done */
long sc_getattrs; /* number of getattrs done */
long sc_flushes; /* number of flushes done */
long sc_cmd0s; /* number of cmd0's done */
long sc_cmd1s; /* number of cmd1's done */
long sc_cmd2s; /* number of cmd2's done */
long sc_speedups; /* number of speedups done */
long sc_readcurrentread; /* reads current with read */
long sc_readblockwrite; /* writes blocked by read */
long sc_writeblockread; /* reads blocked by write */
long sc_writeblockwrite; /* writes blocked by write */
};
/*
* Structure to track work-in-progress I/O operations.
*
* Used to prevent overlapping I/O operations from running concurrently.
* Created for each I/O operation.
*
* In usual case of no overlap it is linked to sc_wiplist and started.
* If found to overlap an I/O on sc_wiplist, it is not started and is
* linked to wip_waiting list of the I/O that it overlaps. When an I/O
* completes, it restarts all the I/O operations on its wip_waiting list.
*/
struct g_union_wip {
struct wiplist wip_waiting; /* list of I/Os waiting on me */
TAILQ_ENTRY(g_union_wip) wip_next; /* pending or active I/O list */
struct bio *wip_bp; /* bio for this I/O */
struct g_union_softc *wip_sc; /* g_union's softc */
off_t wip_start; /* starting offset of I/O */
off_t wip_end; /* ending offset of I/O */
long wip_numios; /* BIO_READs in progress */
long wip_error; /* merged I/O errors */
};
/*
* UNION flags
*/
#define DOING_COMMIT 0x00000001 /* a commit command is in progress */
#define DOING_COMMIT_BITNUM 0 /* a commit command is in progress */
#define BITS_PER_ENTRY (sizeof(uint64_t) * NBBY)
#define G_RLOCK(sc) rw_rlock(&(sc)->sc_rwlock)
#define G_RUNLOCK(sc) rw_runlock(&(sc)->sc_rwlock)
#define G_WLOCK(sc) rw_wlock(&(sc)->sc_rwlock)
#define G_WUNLOCK(sc) rw_wunlock(&(sc)->sc_rwlock)
#define G_WLOCKOWNED(sc) rw_assert(&(sc)->sc_rwlock, RA_WLOCKED)
/*
* The writelock is held while a commit operation is in progress.
* While held union device may not be used or in use.
* Returns == 0 if lock was successfully obtained.
*/
static inline int
g_union_get_writelock(struct g_union_softc *sc)
{
return (atomic_testandset_long(&sc->sc_flags, DOING_COMMIT_BITNUM));
}
static inline void
g_union_rel_writelock(struct g_union_softc *sc)
{
long ret __diagused;
ret = atomic_testandclear_long(&sc->sc_flags, DOING_COMMIT_BITNUM);
KASSERT(ret != 0, ("UNION GEOM releasing unheld lock"));
}
#endif /* _KERNEL */
#endif /* _G_UNION_H_ */