1f03672ecSMatthew Dillon /* 268b321c1SMatthew Dillon * Copyright (c) 2006,2014-2018 The DragonFly Project. All rights reserved. 3f03672ecSMatthew Dillon * 4f03672ecSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5f03672ecSMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 6f03672ecSMatthew Dillon * 7f03672ecSMatthew Dillon * Redistribution and use in source and binary forms, with or without 8f03672ecSMatthew Dillon * modification, are permitted provided that the following conditions 9f03672ecSMatthew Dillon * are met: 10f03672ecSMatthew Dillon * 11f03672ecSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 12f03672ecSMatthew Dillon * notice, this list of conditions and the following disclaimer. 13f03672ecSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 14f03672ecSMatthew Dillon * notice, this list of conditions and the following disclaimer in 15f03672ecSMatthew Dillon * the documentation and/or other materials provided with the 16f03672ecSMatthew Dillon * distribution. 17f03672ecSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 18f03672ecSMatthew Dillon * contributors may be used to endorse or promote products derived 19f03672ecSMatthew Dillon * from this software without specific, prior written permission. 20f03672ecSMatthew Dillon * 21f03672ecSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22f03672ecSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23f03672ecSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24f03672ecSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25f03672ecSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26f03672ecSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27f03672ecSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28f03672ecSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29f03672ecSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30f03672ecSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31f03672ecSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32f03672ecSMatthew Dillon * SUCH DAMAGE. 33f03672ecSMatthew Dillon */ 3446558838SMatthew Dillon 35f03672ecSMatthew Dillon /* 3646558838SMatthew Dillon * CCMS - Cache Coherency Management System. 371ad77ed9SMatthew Dillon * 3846558838SMatthew Dillon * This subsystem can be tied into a VFS in order to supply persistent 3946558838SMatthew Dillon * cache management state for cluster or for remote cache-coherent operations. 40f03672ecSMatthew Dillon * 4146558838SMatthew Dillon * Local and cluster/remote cache state is maintained in a cache-coherent 4246558838SMatthew Dillon * fashion as well as integrated into the VFS's inode locking subsystem 4346558838SMatthew Dillon * (as a means of avoiding deadlocks). 44f03672ecSMatthew Dillon * 4546558838SMatthew Dillon * To operate properly the VFS must maintain a complete directory topology 4646558838SMatthew Dillon * leading to any given vnode/inode either open or cached by the system. 4746558838SMatthew Dillon * The vnode/namecache subsystem does not have to implement this but the 4846558838SMatthew Dillon * VFS (aka HAMMER2) does. 491ad77ed9SMatthew Dillon * 5046558838SMatthew Dillon * The filesystem embeds CCMS_CST structures in its internal inode 5146558838SMatthew Dillon * representatino as needed and implements callback to allow CCMS to 5246558838SMatthew Dillon * do topological recursions. 531ad77ed9SMatthew Dillon * 5446558838SMatthew Dillon * -- 551ad77ed9SMatthew Dillon * 5646558838SMatthew Dillon * The CCMS_CST structures represent granted cache and local locking states. 5746558838SMatthew Dillon * Grants can be recursively inherited, minimizing protocol overhead in 5846558838SMatthew Dillon * situations where there are no conflicts of interest. 591ad77ed9SMatthew Dillon * 6046558838SMatthew Dillon * -- 611ad77ed9SMatthew Dillon * 6246558838SMatthew Dillon * CCMS supports active front-end 'locks' on data objects utilizing the 6346558838SMatthew Dillon * ccms_inode, key, and desired cache state. It can grant the lock based 6446558838SMatthew Dillon * on inherited CST state and prevents downgrading of the CST by other 6546558838SMatthew Dillon * parties or threads while the lock is held. The CST's arranged 6646558838SMatthew Dillon * lock within the embedded CCMS_INODE and ref-counts the related CST. 67f03672ecSMatthew Dillon */ 68f03672ecSMatthew Dillon 69f03672ecSMatthew Dillon #ifndef _SYS_CCMS_H_ 70f03672ecSMatthew Dillon #define _SYS_CCMS_H_ 71f03672ecSMatthew Dillon 72f03672ecSMatthew Dillon #ifndef _SYS_TYPES_H_ 73f03672ecSMatthew Dillon #include <sys/types.h> 74f03672ecSMatthew Dillon #endif 75f03672ecSMatthew Dillon #ifndef _SYS_PARAM_H_ 76f03672ecSMatthew Dillon #include <sys/param.h> 77f03672ecSMatthew Dillon #endif 78f03672ecSMatthew Dillon #ifndef _SYS_SERIALIZE_H_ 79f03672ecSMatthew Dillon #include <sys/serialize.h> 80f03672ecSMatthew Dillon #endif 81f03672ecSMatthew Dillon #ifndef _SYS_SPINLOCK_H_ 82f03672ecSMatthew Dillon #include <sys/spinlock.h> 83f03672ecSMatthew Dillon #endif 84f03672ecSMatthew Dillon 8546558838SMatthew Dillon typedef uint64_t ccms_key_t; 8646558838SMatthew Dillon typedef uint64_t ccms_tid_t; 871ad77ed9SMatthew Dillon typedef uint8_t ccms_state_t; 8846558838SMatthew Dillon typedef uint8_t ccms_type_t; 891ad77ed9SMatthew Dillon 90f03672ecSMatthew Dillon struct ccms_cst; 91f03672ecSMatthew Dillon 92f03672ecSMatthew Dillon /* 9346558838SMatthew Dillon * CCMS_STATE_T - CCMS cache states. 94f03672ecSMatthew Dillon * 951ad77ed9SMatthew Dillon * INVALID - Cache state is unknown and must be acquired. 96f03672ecSMatthew Dillon * 9746558838SMatthew Dillon * ALLOWED - Cache state allows any recursive state to be acquired. 98f03672ecSMatthew Dillon * 9994491fa0SMatthew Dillon * SHARED - Cache state allows shared access. 1001ad77ed9SMatthew Dillon * 10194491fa0SMatthew Dillon * EXCLUSIVE - Cache state allows exclusive access. 1021ad77ed9SMatthew Dillon * 10346558838SMatthew Dillon * CCMS Implements an extended MESI model. The extensions are implemented 10446558838SMatthew Dillon * as CCMS_TYPE_T flags. 105f03672ecSMatthew Dillon */ 1061ad77ed9SMatthew Dillon #define CCMS_STATE_INVALID 0 /* unknown cache state */ 1071ad77ed9SMatthew Dillon #define CCMS_STATE_SHARED 2 /* clean, shared, read-only */ 10846558838SMatthew Dillon #define CCMS_STATE_EXCLUSIVE 3 /* clean, exclusive, read-only */ 109f03672ecSMatthew Dillon 110f03672ecSMatthew Dillon /* 11146558838SMatthew Dillon * CCMS_TYPE_T FLAGS 11246558838SMatthew Dillon * 11346558838SMatthew Dillon * INHERITED - Indicates the state field was inherited and was not directly 11446558838SMatthew Dillon * granted by the cluster controller. 11546558838SMatthew Dillon * 11646558838SMatthew Dillon * MODIFIED - This is a type-field flag associated with an EXCLUSIVE cache 11746558838SMatthew Dillon * state 11846558838SMatthew Dillon * 11946558838SMatthew Dillon * MASTER - This is a type-field flag associated with an EXCLUSIVE+MODIFIED 12046558838SMatthew Dillon * cache state which indicates that slaves might be present 12146558838SMatthew Dillon * which are caching our unsynchronized state. 12246558838SMatthew Dillon * 12346558838SMatthew Dillon * SLAVE - This is a type-field flag associated with the SHARED cache 12446558838SMatthew Dillon * state which indicates that the data present in our memory 12546558838SMatthew Dillon * caches is being mastered elsewhere and has not been 12646558838SMatthew Dillon * synchronized (meaning no quorum protocol has been run to 12746558838SMatthew Dillon * sync the data yet). Thus only the version of the data in 12846558838SMatthew Dillon * our memory and its originator is valid. 12946558838SMatthew Dillon * 13046558838SMatthew Dillon * QSLAVE - This indicates that the slaved data is also present in the 13146558838SMatthew Dillon * memory caches of a quorum of master nodes. 13246558838SMatthew Dillon */ 13346558838SMatthew Dillon #define CCMS_TYPE_INHERITED 0x01 13446558838SMatthew Dillon #define CCMS_TYPE_MODIFIED 0x02 13546558838SMatthew Dillon #define CCMS_TYPE_MASTER 0x04 13646558838SMatthew Dillon #define CCMS_TYPE_SLAVE 0x08 13746558838SMatthew Dillon #define CCMS_TYPE_QSALVE 0x10 13846558838SMatthew Dillon #define CCMS_TYPE_RECURSIVE 0x80 13946558838SMatthew Dillon 14046558838SMatthew Dillon /* 14146558838SMatthew Dillon * CCMS_CST - Low level locking state, persistent cache state 142f03672ecSMatthew Dillon * 14346558838SMatthew Dillon * Offset ranges are byte-inclusive, allowing the entire 64 bit data space 144f03672ecSMatthew Dillon * to be represented without overflowing the edge case. For example, a 1451ad77ed9SMatthew Dillon * 64 byte area might be represented as (0,63). The offsets are UNSIGNED 1461ad77ed9SMatthew Dillon * entities. 14746558838SMatthew Dillon * 148f3843dc2SMatthew Dillon * High level CST locks must be obtained top-down. 149f3843dc2SMatthew Dillon * 150f3843dc2SMatthew Dillon * count - Negative value indicates active exclusive lock, positive value 15146558838SMatthew Dillon * indicates active shared lock. 152f3843dc2SMatthew Dillon * 153f3843dc2SMatthew Dillon * spin - Structural spinlock, typically just one is held at a time. 154f3843dc2SMatthew Dillon * However, to complement the top-down nature of the higher level 155f3843dc2SMatthew Dillon * lock we allow the spin lock to be held recursively in a bottom-up 156f3843dc2SMatthew Dillon * fashion for race-to-root flags updates and lastdrop iterations. 157f03672ecSMatthew Dillon */ 158f03672ecSMatthew Dillon struct ccms_cst { 159*f3ee5e44STomohiro Kusumi hammer2_spin_t spin; /* thread spinlock */ 16046558838SMatthew Dillon ccms_state_t state; /* granted or inherited state */ 16146558838SMatthew Dillon ccms_type_t type; /* CST type and flags */ 16246558838SMatthew Dillon uint8_t unused02; 16346558838SMatthew Dillon uint8_t unused03; 1641ad77ed9SMatthew Dillon 165a0ed3c24SMatthew Dillon int32_t upgrade; /* upgrades pending */ 16646558838SMatthew Dillon int32_t count; /* active shared/exclusive count */ 16746558838SMatthew Dillon int32_t blocked; /* wakeup blocked on release */ 16846558838SMatthew Dillon thread_t td; /* if excl lock (count < 0) */ 169f03672ecSMatthew Dillon }; 170f03672ecSMatthew Dillon 1711ad77ed9SMatthew Dillon typedef struct ccms_cst ccms_cst_t; 172f03672ecSMatthew Dillon 173f03672ecSMatthew Dillon /* 174f03672ecSMatthew Dillon * Kernel API 175f03672ecSMatthew Dillon */ 176f03672ecSMatthew Dillon #ifdef _KERNEL 177f03672ecSMatthew Dillon 17894491fa0SMatthew Dillon void ccms_cst_init(ccms_cst_t *cst); 17946558838SMatthew Dillon void ccms_cst_uninit(ccms_cst_t *cst); 1801ad77ed9SMatthew Dillon 18146558838SMatthew Dillon void ccms_thread_lock(ccms_cst_t *cst, ccms_state_t state); 18246558838SMatthew Dillon int ccms_thread_lock_nonblock(ccms_cst_t *cst, ccms_state_t state); 183476d2aadSMatthew Dillon ccms_state_t ccms_thread_lock_temp_release(ccms_cst_t *cst); 1849797e933SMatthew Dillon void ccms_thread_lock_temp_restore(ccms_cst_t *cst, ccms_state_t ostate); 185a0ed3c24SMatthew Dillon ccms_state_t ccms_thread_lock_upgrade(ccms_cst_t *cst); 1869797e933SMatthew Dillon void ccms_thread_lock_downgrade(ccms_cst_t *cst, ccms_state_t ostate); 18746558838SMatthew Dillon void ccms_thread_unlock(ccms_cst_t *cst); 188731b2a84SMatthew Dillon void ccms_thread_unlock_upgraded(ccms_cst_t *cst, ccms_state_t ostate); 189a0ed3c24SMatthew Dillon int ccms_thread_lock_owned(ccms_cst_t *cst); 190a5913bdfSMatthew Dillon void ccms_thread_lock_setown(ccms_cst_t *cst); 19146558838SMatthew Dillon 192f03672ecSMatthew Dillon #endif 193f03672ecSMatthew Dillon 194f03672ecSMatthew Dillon #endif 195