From 24d1b29d4e89cc72eb3f644a7e5a573d1f09d99f Mon Sep 17 00:00:00 2001 From: OpenAI Date: Fri, 19 Jun 2026 08:44:01 +0000 Subject: [PATCH] nwnss: import NSS salvage purge runtime --- src/nwnss/CMakeLists.txt | 5 + src/nwnss/zlss/beastTree.h | 436 ++++ src/nwnss/zlss/dfsIO.h | 59 + src/nwnss/zlss/dir.h | 137 ++ src/nwnss/zlss/dirTree.h | 324 +++ src/nwnss/zlss/dlog.h | 529 +++++ src/nwnss/zlss/eflLog.h | 286 +++ src/nwnss/zlss/eflTree.h | 373 ++++ src/nwnss/zlss/mflBTree.h | 76 + src/nwnss/zlss/mfl_if.h | 106 + src/nwnss/zlss/mscIDE.h | 55 + src/nwnss/zlss/myBTree.h | 417 ++++ src/nwnss/zlss/nameTree.h | 247 +++ src/nwnss/zlss/node.h | 340 ++++ src/nwnss/zlss/purgeLog.c | 2951 ++++++++++++++++++++++++++++ src/nwnss/zlss/purgeLog.h | 277 +++ src/nwnss/zlss/purgeTree.c | 1904 ++++++++++++++++++ src/nwnss/zlss/purgeTree.h | 328 ++++ src/nwnss/zlss/purgeTree_if.h | 103 + src/nwnss/zlss/purgeTree_new.c | 828 ++++++++ src/nwnss/zlss/purgeTree_new.h | 122 ++ src/nwnss/zlss/repairBtree.h | 173 ++ src/nwnss/zlss/repairMain.h | 258 +++ src/nwnss/zlss/repairMap.h | 114 ++ src/nwnss/zlss/repairRAV.h | 262 +++ src/nwnss/zlss/repairRAVDebug.h | 43 + src/nwnss/zlss/repairZRP.h | 553 ++++++ src/nwnss/zlss/repairZVP.h | 388 ++++ src/nwnss/zlss/salvageLog.c | 146 ++ src/nwnss/zlss/sdZLSS.h | 656 +++++++ src/nwnss/zlss/userTree.h | 528 +++++ src/nwnss/zlss/xaction.h | 1668 ++++++++++++++++ src/nwnss/zlss/z_aes.h | 113 ++ src/nwnss/zlss/z_aes_locl.h | 85 + src/nwnss/zlss/zedExport.h | 60 + src/nwnss/zlss/zfs.h | 2770 ++++++++++++++++++++++++++ src/nwnss/zlss/zfsAsyncio.h | 71 + src/nwnss/zlss/zfsFileMap.h | 184 ++ src/nwnss/zlss/zfsSuperBlk.h | 893 +++++++++ src/nwnss/zlss/zfsXTree.h | 412 ++++ src/nwnss/zlss/zfsdefs.h | 284 +++ src/nwnss/zlss/zlog.h | 2148 ++++++++++++++++++++ src/nwnss/zlss/zlogFtest.h | 61 + src/nwnss/zlss/zlssConsumer.h | 251 +++ src/nwnss/zlss/zlssIOPerformance.h | 373 ++++ src/nwnss/zlss/zlssLogicalVolume.h | 1335 +++++++++++++ src/nwnss/zlss/zlssMSAP.h | 306 +++ src/nwnss/zlss/zlssManage.h | 151 ++ src/nwnss/zlss/zlssStartup.h | 203 ++ src/nwnss/zlss/zlssUpgrade.h | 277 +++ src/nwnss/zlss/zstoreConfig.h | 177 ++ 51 files changed, 24846 insertions(+) create mode 100644 src/nwnss/zlss/beastTree.h create mode 100644 src/nwnss/zlss/dfsIO.h create mode 100644 src/nwnss/zlss/dir.h create mode 100644 src/nwnss/zlss/dirTree.h create mode 100644 src/nwnss/zlss/dlog.h create mode 100644 src/nwnss/zlss/eflLog.h create mode 100644 src/nwnss/zlss/eflTree.h create mode 100644 src/nwnss/zlss/mflBTree.h create mode 100644 src/nwnss/zlss/mfl_if.h create mode 100644 src/nwnss/zlss/mscIDE.h create mode 100644 src/nwnss/zlss/myBTree.h create mode 100644 src/nwnss/zlss/nameTree.h create mode 100644 src/nwnss/zlss/node.h create mode 100644 src/nwnss/zlss/purgeLog.c create mode 100644 src/nwnss/zlss/purgeLog.h create mode 100644 src/nwnss/zlss/purgeTree.c create mode 100644 src/nwnss/zlss/purgeTree.h create mode 100644 src/nwnss/zlss/purgeTree_if.h create mode 100644 src/nwnss/zlss/purgeTree_new.c create mode 100644 src/nwnss/zlss/purgeTree_new.h create mode 100644 src/nwnss/zlss/repairBtree.h create mode 100644 src/nwnss/zlss/repairMain.h create mode 100644 src/nwnss/zlss/repairMap.h create mode 100644 src/nwnss/zlss/repairRAV.h create mode 100644 src/nwnss/zlss/repairRAVDebug.h create mode 100644 src/nwnss/zlss/repairZRP.h create mode 100644 src/nwnss/zlss/repairZVP.h create mode 100644 src/nwnss/zlss/salvageLog.c create mode 100644 src/nwnss/zlss/sdZLSS.h create mode 100644 src/nwnss/zlss/userTree.h create mode 100644 src/nwnss/zlss/xaction.h create mode 100644 src/nwnss/zlss/z_aes.h create mode 100644 src/nwnss/zlss/z_aes_locl.h create mode 100644 src/nwnss/zlss/zedExport.h create mode 100644 src/nwnss/zlss/zfs.h create mode 100644 src/nwnss/zlss/zfsAsyncio.h create mode 100644 src/nwnss/zlss/zfsFileMap.h create mode 100644 src/nwnss/zlss/zfsSuperBlk.h create mode 100644 src/nwnss/zlss/zfsXTree.h create mode 100644 src/nwnss/zlss/zfsdefs.h create mode 100644 src/nwnss/zlss/zlog.h create mode 100644 src/nwnss/zlss/zlogFtest.h create mode 100644 src/nwnss/zlss/zlssConsumer.h create mode 100644 src/nwnss/zlss/zlssIOPerformance.h create mode 100644 src/nwnss/zlss/zlssLogicalVolume.h create mode 100644 src/nwnss/zlss/zlssMSAP.h create mode 100644 src/nwnss/zlss/zlssManage.h create mode 100644 src/nwnss/zlss/zlssStartup.h create mode 100644 src/nwnss/zlss/zlssUpgrade.h create mode 100644 src/nwnss/zlss/zstoreConfig.h diff --git a/src/nwnss/CMakeLists.txt b/src/nwnss/CMakeLists.txt index 56f14bb..2f7b1e8 100644 --- a/src/nwnss/CMakeLists.txt +++ b/src/nwnss/CMakeLists.txt @@ -315,6 +315,10 @@ add_library(nwnss SHARED nssUserspaceProvider.c lsa/lsaXattrUserspace.c lsa/lsaXattr.c + zlss/purgeLog.c + zlss/salvageLog.c + zlss/purgeTree.c + zlss/purgeTree_new.c utcUserland.c) add_library(mars_nwe::nwnss ALIAS nwnss) @@ -399,6 +403,7 @@ target_include_directories(nwnss BEFORE "${CMAKE_SOURCE_DIR}/include/nwnss/comn/namespace" "${CMAKE_SOURCE_DIR}/include/nwnss/library/stdio" "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/zlss" "${CMAKE_CURRENT_SOURCE_DIR}/sharedsrc") target_link_libraries(nwnss diff --git a/src/nwnss/zlss/beastTree.h b/src/nwnss/zlss/beastTree.h new file mode 100644 index 0000000..203ae96 --- /dev/null +++ b/src/nwnss/zlss/beastTree.h @@ -0,0 +1,436 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2005-07-13 01:55:38 +0530 (Wed, 13 Jul 2005) $ + | + | $RCSfile$ + | $Revision: 1106 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and + +-------------------------------------------------------------------------*/ + +#ifndef _BEASTTREE_H_ +#define _BEASTTREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +/* + * Debug stuff + */ +#if NSS_DEBUG IS_ENABLED +#define VALIDATE_NODE(_node) (bbtValidateNode(_node)) +#else +#define VALIDATE_NODE(_node) ((void)0) +#endif + +#undef ZTREE_DEBUG +#define ZTREE_DEBUG ENABLE +#if NSS_DEBUG IS_ENABLED && ZTREE_DEBUG IS_ENABLED + +#define ZPRINT_NODE(_loc, _buf) zprintNode(# _loc, # _buf, _buf) +#define ZPRINT_ZID(_loc, _zid) zprintZid(# _loc, _zid) +#define ZPRINT_NINT(_loc, _nint) zprintNint(# _loc, _nint) + +void zprintNode(char *location, char *nameOfBuffer, Buffer_s *buffer); +void zprintZid(char *location, Zid_t zid); +void zprintNint(char *location, NINT value); +#else + +#define ZPRINT_NODE(_loc, _buf) ((void)0) +#define ZPRINT_ZID(_loc, _zid) ((void)0) +#define ZPRINT_NINT(_loc, _nint) ((void)0) + +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define CHECK_FOR_SPLIT 0x00000001 +#define CHECK_FOR_JOIN 0x00000002 + +/* + * State information about B-tree nodes. + * A node can be both a LEAF and a ROOT (for sufficiently small Btrees) + */ + +#define MIN_ZNODE_SIZE (sizeof(ZnodeHeader_s)) + +//#define FIND_RESERVE 2 /* Number of Bufmgrs to reserve for find */ +//#define UPDATE_RESERVE 3 /* Number of Bufmgrs to reserve for update */ +//#define INSERT_RESERVE 3 /* Number of Bufmgrs to reserve for insert */ +//#define DELETE_RESERVE 3 /* Number of Bufmgrs to reserve for delete */ + +/* state of a node */ +#define BBT_LEAF 0x1 /* Leaf node of a B-tree */ +#define BBT_ROOT 0x2 /* Root node of a B-tree */ +#define BBT_SYSTEM_BSTS_BLK 0x10 /* Special block for system beasts */ +//#define BTB_FREE 0x20 /* Node is free */ +#define BBT_GUID_HAS_BLOCK 0x40 /* The block's internal ID has the logical block location in it */ + +#define BBT_SMALL DISABLE +//#define BTT_SMALL ENABLE + +#if BBT_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define MAX_FREEBLKS 2 +#define MAX_BRANCHES 9 /*was 5*/ +#define MAX_LEAF_FREE 1024 +#else +#define MAX_FREEBLKS ((PAGE_SIZE - 32) / sizeof(Blknum_t)) +#define MAX_BRANCHES ((PAGE_SIZE - 32) / sizeof(BTBranch_s)) +#define MAX_LEAF_FREE (PAGE_SIZE - (32+8)) +#endif +#define MAX_BEAST_SIZE ((ZLOG_MAXIMUM_RECORD_SIZE / 2) - sizeof(NodeLen_t)) +#define MAX_LEAF_PTRS (MAX_LEAF_FREE/sizeof(NodeLen_t) - 1) /* is used as an array index -- must be zero based */ + +#define IS_SYSTEM_BEAST_ZID(_zid) \ + ((_zid < ZFSPOOL_MAX_RESERVED_SUPERBLK_ZID) && \ + (_zid > zINVALID_ZID)) + +#define SIZEOFFREESPACE(_node) \ + (MAX_LEAF_FREE - ((_node)->n.leaf.startOfFreeSpace + \ + (_node)->numRecs * sizeof(NodeLen_t))) + +#define LEAF n.leaf.space +#define MIN_BRANCHES (MAX_BRANCHES / 2) + +#define BBT_IS_LEAF(_n) ((_n)->state & BBT_LEAF) +#define BBT_IS_ROOT(_n) ((_n)->state & BBT_ROOT) +#define BBT_IS_SYSTEM_BSTS_BLK(_n) ((_n)->state & BBT_SYSTEM_BSTS_BLK) + +#define BBT_HAS_PARENT(_n) \ + ((!BBT_IS_ROOT(_n)) && (!BBT_IS_SYSTEM_BSTS_BLK(_n))) + +#define BBT_IS_MAX_ENTRIES(_node, _parms) \ + (BBT_IS_LEAF(_node) \ + ? (_node->n.leaf.freeSpace < (parms->beastLen + \ + sizeof(NodeLen_t))) \ + : ((_node)->numRecs >= MAX_BRANCHES)) + +#define BBT_IS_MIN_ENTRIES(_node) \ + (BBT_IS_LEAF(_node) \ + ? (_node->n.leaf.freeSpace > MAX_LEAF_FREE / 2) \ + : ((_node)->numRecs <= MIN_BRANCHES)) + +#define BBT_IS_LESSTHAN_MAX(_node, _sibling) \ + (BBT_IS_LEAF(_node) \ + ? (((_node)->n.leaf.freeSpace + (_sibling)->n.leaf.freeSpace) > MAX_LEAF_FREE) \ + : (((_node)->numRecs + (_sibling)->numRecs) < MAX_BRANCHES)) + + +/* Macros used for latching and unlatching the beastTree beast and checking + * to see if the beast we are inserting or updating is the beastTree beast */ +#define BBT_X_LATCH_BEASTTREE(_parms) \ + if ((_parms)->beast != &(_parms)->ztree->ZFSBEASTTREEroot) \ + { \ + X_LATCH(&(_parms)->ztree->ZFSBEASTTREEbeastLatch); \ + } + +#define BBT_UNX_LATCH_BEASTTREE(_parms) \ + if ((_parms)->beast != &(_parms)->ztree->ZFSBEASTTREEroot) \ + { \ + UNX_LATCH(&(_parms)->ztree->ZFSBEASTTREEbeastLatch); \ + } + +#define GET_LEFTMOST_LEAF(_ztree) \ + ((_ztree)->ZFSBEASTTREEroot.vol.zfsVol->pool->ZP_super-> \ + SB_Header.hdr.SBH_BeastTreeBlkNum) + +typedef WORD NodeLen_t; + + +/* + * structure to pass info and state between beast b-tree routines + */ +typedef struct BeastTreeParms_s +{ + RootBeast_s *beast; /* the beast to be used */ + NINT beastLen; /* the length of the beast */ + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + Znode_s *packArea; /* pointer to the area to put the packed record */ + struct ZfsXaction_s *xaction; /* Transaction being used */ + struct ZfsBeastTreeBeast_s *ztree; /* The pointer to the b-tree beast */ + BOOL physicalLogging; +} BeastTreeParms_s; + + /* The physicalLogging parameter specifies whether to log inserts and + * deletes physically or + * logically. For system beasts and the root dir zid we always do the + * logging to physically undo, for all others we do the logging to + * logically undo. We can do this because the location of the system + * beasts does not change from the special system beasts block. The root + * dir zid is always in the left most leaf of the beast tree and splits + * grows etc does not change its location. It is necessary to do the + * root dir physically because logical volume creation is one big + * xaction and root dir is inserted as part of the same transaction that + * allocates and initializes the left block. After physical undo is + * complete the system beasts have to be in a stable state since logical + * undo can modify them. Thus the system beasts inserts and deletes need + * to be done physically too. + */ + + +/* + * structures for defining what the tree nodes look like + */ +typedef struct BTBranch_s +{ + Zid_t zid; + Blknum_t child; +} NSS_MEDIA_STRUCTURE(BTBranch_s,child) BTBranch_s; + +typedef struct BTLeaf_s +{ + /* + * If the size of the header portion changes then change MAX_LEAF_FREE. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + WORD freeSpace; /* amount of free space left in leaf node */ + WORD startOfFreeSpace; /* pointer to the start of the free space */ + union + { + BYTE znode[MAX_LEAF_FREE]; /* space to store vnodes */ + NodeLen_t znodePtr[MAX_LEAF_FREE/sizeof(NodeLen_t)]; /* pointers to start of znodes */ + } NSS_MEDIA_UNION(NamelessUnion,znodePtr[MAX_LEAF_FREE/sizeof(NodeLen_t)]) space; +} NSS_MEDIA_STRUCTURE(BTLeaf_s,space.znodePtr[MAX_LEAF_FREE/sizeof(NodeLen_t)]) BTLeaf_s; + + +/* Modified GUID used in BT leafs and branches so that relink can + * detect blocks that are from a snapshot pool. GWB_Block is + * only valid if BBT_GUID_HAS_BLOCK is set. + */ +typedef struct GUIDWithBlock_t /* holds GUIDs*/ +{ + LONG timeLow; + WORD timeMid; + WORD timeHighAndVersion; + BYTE clockSeqHighAndReserved; + BYTE clockSeqLow; + Blknum_t GWB_Block; + BYTE GWB_Node[2]; +} NSS_MEDIA_STRUCTURE(GUIDWithBlock_t, GWB_Node[2]) GUIDWithBlock_t; + + +typedef struct BeastTreeNode_s +{ + /* + * If the size of the header portion changes then change MAX_FREEBLKS, + * MAX_BRANCHES and MAX_LEAF_FREE. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUIDWithBlock_t btn_internalIDWithBlock; /* Must be at OFFSET 16 - unique volume ID with possible + * block number (used by relink). Also used in debug + * write code to validate block. Also used in LV delete + * to ensure no BT jumping occurs. + */ + union + { + BTBranch_s branch[MAX_BRANCHES]; + BTLeaf_s leaf; +// Blknum_t freeBlks[MAX_FREEBLKS]; + } NSS_MEDIA_UNION(NamelessUnion,branch[MAX_BRANCHES]) n; +} NSS_MEDIA_STRUCTURE(BeastTreeNode_s,n.branch[MAX_BRANCHES]) BeastTreeNode_s; + +/* + * Structures and defines for log records for the beast b-tree. + */ + +typedef struct Split_s +{ + GUID_t s_internalID; + Zid_t zidForParent; /* zid to insert in the parent */ + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(Split_s,data[1]) Split_s; + +typedef struct Overflow_s +{ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(Overflow_s,data[1]) Overflow_s; + +typedef struct Grow_s +{ + GUID_t g_internalID; + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(Grow_s,blockForParent) Grow_s; + +typedef struct Balance_s +{ + Zid_t zidForParent; /* zid to insert in the parent */ + Zid_t oldZid; /* previous zid in the parent */ + LONG indexForParent; /* index where zid is changed in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(Balance_s,data[1]) Balance_s; + +typedef struct BeastTreeInit_s +{ + GUID_t bti_internalID; +} NSS_MEDIA_STRUCTURE(BeastTreeInit_s,bti_internalID) BeastTreeInit_s; + +/* defines for direction */ +#define LEFT_TO_RIGHT 0 +#define RIGHT_TO_LEFT 1 + +typedef struct BeastLog_s +{ + union + { + Znode_s znode; /* Volume ID for logical UNDO is packed in + * the log record after the variable len + * of the znode which is of size znode-> + * header.length + */ + Split_s split; + Overflow_s overflow; + Grow_s grow; + Balance_s balance; + BeastTreeInit_s bl_init; + } NSS_MEDIA_UNION(NamelessUnion,u) u; +} NSS_MEDIA_STRUCTURE(BeastLog_s,u.bl_init) BeastLog_s; + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +BOOL findZnodeByZid( + BeastTreeNode_s *node, + Zid_t zid, + NINT *i); + +void deleteZnodeFromChild( + BeastTreeNode_s *child, + NINT recNum); + +STATUS insertZnode ( + GeneralMsg_s *genMsg, + BeastTreeNode_s *child, + Zid_t zid, + NINT zlen, + Znode_s **packArea); + +STATUS getLeaf( + GeneralMsg_s *genMsg, + Zid_t zid, + ZfsVolume_s *volume, + BeastTreeParms_s *parms); + +STATUS ZFSVOL_VOL_InsertBeastIntoVolume( + struct GeneralMsg_s *genMsg, + struct RootBeast_s *beast, + NINT beastLen, + Xaction_s *xaction); + +STATUS ZFSVOL_VOL_RemoveBeastFromVolume( + struct GeneralMsg_s *genMsg, + struct RootBeast_s *beast, + Xaction_s *xaction); + +STATUS ZFSVOL_VOL_UpdateBeastToVolume( + struct GeneralMsg_s *genMsg, + struct RootBeast_s *beast, + NINT beastLen, + Xaction_s *xaction); + +void *ZFSVOL_VOL_GetBeastFromVolume( + struct GeneralMsg_s *genMsg, + Zid_t zid, + struct Volume_s *volume); + +void ZFSVOL_CheckZeroZid( + struct Volume_s *volume); + +void *ZFSVOL_GetBeastFromBuffer( + struct GeneralMsg_s *genMsg, + Zid_t zid, + struct Volume_s *volume, + struct Buffer_s *buffer); + +STATUS ZFSVOL_VOL_BrowseBeastsInVolume( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT selectionCriteria, + NINT numBeastsRequested, + Zid_t *lastZidReturned, /* inout */ + Zid_t *beastZids, /* out */ + NINT *numBeastsReturned); /* out */ + +Blknum_t findChildBlock( + BeastTreeNode_s *node, + Zid_t zid, + NINT *index); + +void initNode( + Buffer_s *buffer, + NINT state, + GUID_t *internalID); + +void insertZeroNode( + BeastTreeNode_s *node); + +STATUS copyZnode( + GeneralMsg_s *genMsg, + BeastTreeNode_s *src, + BeastTreeNode_s *dst, + Zid_t zid); + + +STATUS cleanZnode( + GeneralMsg_s *genMsg, + BeastTreeNode_s *src, + Zid_t zid); + +STATUS moveZnode( + GeneralMsg_s *genMsg, + BeastTreeNode_s *src, + BeastTreeNode_s *dst, + Zid_t zid); + +void garbageCollectNode(BeastTreeNode_s *node); + +#endif diff --git a/src/nwnss/zlss/dfsIO.h b/src/nwnss/zlss/dfsIO.h new file mode 100644 index 0000000..275d981 --- /dev/null +++ b/src/nwnss/zlss/dfsIO.h @@ -0,0 +1,59 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define the DFS routines. + +-------------------------------------------------------------------------*/ +#ifndef _DFSIO_H_ +#define _DFSIO_H_ + +#ifndef _MSGIO_H_ +#include +#endif + +#ifndef _FSMSG_H_ +#include +#endif + +STATUS ZFSVOL_VOL_dioReadUnits( + zNSSMsg_s *msg, + RootBeast_s *beast); + +STATUS ZFSVOL_VOL_dioWriteUnits( + zNSSMsg_s *msg, + RootBeast_s *beast); + +STATUS DIO_Startup(void); +void DIO_Shutdown(void); + +#endif diff --git a/src/nwnss/zlss/dir.h b/src/nwnss/zlss/dir.h new file mode 100644 index 0000000..ce1f6e5 --- /dev/null +++ b/src/nwnss/zlss/dir.h @@ -0,0 +1,137 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Defines structures used in the Naming B-Tree. + +-------------------------------------------------------------------------*/ +#ifndef _NSS_DIR_H_ +#define _NSS_DIR_H_ + +#define ADD_DELFILE_ZID_IN_NTREE_KEY 1 + +/* A null char is appended to all file names */ +typedef struct dir_key_s +{ + Zid_t pzid; /* Parent directory's ZID */ +#if ADD_DELFILE_ZID_IN_NTREE_KEY + Zid_t zid; /* File ZID (only used for deleted files) */ +#endif /* ADD_DELFILE_ZID_IN_NTREE_KEY */ + WORD nameType; /* Name Type */ + WORD namelen; /* Length of Name (#chars excluding null at end */ + fname_char_t name[1]; /* File name; inline */ +} NSS_MEDIA_STRUCTURE(dir_key_s,name[1]) dir_key_s; + +typedef struct dir_key_ool_s +{ + Zid_t pzid; /* Parent directory's ZID */ +#if ADD_DELFILE_ZID_IN_NTREE_KEY + Zid_t zid; /* File ZID (only used for deleted files) */ +#endif /* ADD_DELFILE_ZID_IN_NTREE_KEY */ + WORD nameType; /* Name Type */ + WORD namelen; /* Length of Name (#chars excluding null at end */ + fname_char_t *name; /* File name; out-of-line */ +} dir_key_ool_s; + +#if 0 +#define NAMEdup 0x2000 +#define NAMEovflow 0x4000 +#endif + +#define DIR_KEY_SIZE(_k) \ + (FIELD_OFFSET(dir_key_s, name) + \ + (((_k)->namelen & NAMEnameLenMask) + 1) * sizeof(fname_char_t)) + +extern void keycopy(dir_key_s *_dstkey, dir_key_s *_srckey); + +extern SNINT keycomp(dir_key_s *k1, dir_key_s *k2); +typedef SNINT (*fname_cmpfn_t)(CONST fname_char_t *n1, CONST fname_char_t *n2, + NINT flags); +typedef BOOL (*fpat_cmpfn_t)(fname_char_t *pattern, fname_char_t *name, + NINT flags); + +#define DIR_OP_LOOKUP 0 +#define DIR_OP_INSERT 1 +#define DIR_OP_DELETE 2 +#define DIR_OP_SETMASK 3 +#define DIR_OP_SETMATCHATTR 4 +#define DIR_OP_SETHLFLAGS 5 + +#define DIR_LOOKUP(_parms, _k, _mask, _zid, /* cnt _nunique,*/ _info, _ncmpfn) \ + dir_op_common(_parms, _k, _mask, DIR_OP_LOOKUP, _zid, /* cnt _nunique,*/ _info, 0, _ncmpfn) +#define DIR_INSERT(_parms, _k, _mask, _zid, /* cnt _nunique,*/ _mAttr) \ + dir_op_common(_parms, _k, _mask, DIR_OP_INSERT, &(_zid),/* cnt &(_nunique),*/ 0, _mAttr, 0) +#define DIR_DELETE(_parms, _k, _mask, _zid/* cnt , _nunique*/) \ + dir_op_common(_parms, _k, _mask, DIR_OP_DELETE, _zid, /* cnt _nunique,*/ 0, 0, 0) +#define DIR_MODIFY_NSMASK(_parms, _k, _zid, /* cnt _nunique,*/ _mask, _newmask) \ + dir_op_common(_parms, _k, _mask, DIR_OP_SETMASK, _zid, /* cnt _nunique,*/ 0, _newmask, 0) +#define DIR_MODIFY_MATCHATTR(_parms, _k, _zid, /* cnt _nunique,*/ _mask, _newmatch) \ + dir_op_common(_parms, _k, _mask, DIR_OP_SETMATCHATTR, _zid, /* cnt _nunique,*/ 0, _newmatch, 0) +#define DIR_MODIFY_HLFLAGS(_parms, _k, _zid, /* cnt _nunique,*/ _mask, _newhlflags) \ + dir_op_common(_parms, _k, _mask, DIR_OP_SETHLFLAGS, _zid, /* cnt _nunique,*/ 0, _newhlflags, 0) + + +extern STATUS +dir_op_common( + NameTreeParms_s *parms, + dir_key_s *key, + nsmask_t ns_mask, + SNINT op, + Zid_t *zid, +// cnt NINT *nameUniquifier, + FullDirectoryInfo_s *dirinfo, + nsmask_t newmask, + fname_cmpfn_t namecmp); + +extern STATUS +dir_pat_lookup( + NameTreeParms_s *parms, + Zid_t pzid, + NINT nameType, + nsmask_t ns_mask, + fname_char_t *pattern, + SearchMap_s *smap, + Zid_t *zid, +// cnt NINT *nameUniquifier, + FullDirectoryInfo_s *dirinfo, + fname_cmpfn_t ncmpfn, + fpat_cmpfn_t pcmpfn); + +#if ZFSNAMETREE_DEBUG +#define CHECK_DUPKEY_INSERT 1 +#endif /* ZFSNAMETREE_DEBUG */ + +#define DEFAULT_CURSOR_MEM 64 + +extern void ZFSNAMETREE_smap_cursor_cleanup(SearchMap_s *smap); + +#endif /* _NSS_DIR_H_ */ diff --git a/src/nwnss/zlss/dirTree.h b/src/nwnss/zlss/dirTree.h new file mode 100644 index 0000000..21e26b5 --- /dev/null +++ b/src/nwnss/zlss/dirTree.h @@ -0,0 +1,324 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | This defines all of the primitive BEASTS inside of PSS + | + | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! + | + | This header file should ONLY be used for NSS internal development. + | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). + | Any other use may cause conflicts which NSS will NOT fix. + +-------------------------------------------------------------------------*/ +#ifndef _DIRTREE_H_ +#define _DIRTREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +#if NSS_DEBUG IS_ENABLED +#define DBT_VALIDATE_NODE(_node) (DBT_validateNode(_node)) +#else +#define DBT_VALIDATE_NODE(_node) ((void)0) +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define DBT_CHECK_FOR_SPLIT 0x00000001 +#define DBT_CHECK_FOR_JOIN 0x00000002 + +/* state of a node */ +#define DBT_LEAF 0x1 /* Leaf node of a B-tree */ +#define DBT_ROOT 0x2 /* Root node of a B-tree */ +#define DBT_REZID_DONE 0x4 /* This node was ReZid + * This bit is only used while we are + * in the process of rezidding. + * When rezid is complete we clear this + * bit. + */ + +#define DBT_SMALL DISABLE +//#define DBT_SMALL ENABLE + + +#if DBT_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define DBT_MAX_BRANCH_ENTRIES 7 +#define DBT_MAX_LEAF_ENTRIES 5 +#else +#define DBT_MAX_BRANCH_ENTRIES ((PAGE_SIZE - 32) / sizeof(DirBranchEntry_s)) +#define DBT_MAX_LEAF_ENTRIES ((PAGE_SIZE - (32 + 4)) / sizeof(DirLeafEntry_s)) +#endif + +#define DBT_IS_LEAF(_n) ((_n)->state & DBT_LEAF) +#define DBT_IS_ROOT(_n) ((_n)->state & DBT_ROOT) + +#define DBT_MIN_BRANCH_ENTRIES (DBT_MAX_BRANCH_ENTRIES / 2) +#define DBT_MIN_LEAF_ENTRIES (DBT_MAX_LEAF_ENTRIES / 2) + +#define DBT_IS_MAX_ENTRIES(_node, _parms) \ + (DBT_IS_LEAF(_node) \ + ? ((_node)->numRecs >= DBT_MAX_LEAF_ENTRIES) \ + : ((_node)->numRecs >= DBT_MAX_BRANCH_ENTRIES)) + +#define DBT_IS_MIN_ENTRIES(_node) \ + (DBT_IS_LEAF(_node) \ + ? ((_node)->numRecs <= DBT_MIN_LEAF_ENTRIES) \ + : ((_node)->numRecs <= DBT_MIN_BRANCH_ENTRIES)) + +#define DBT_IS_LESSTHAN_MAX(_node, _sibling) \ + (DBT_IS_LEAF(_node) \ + ? (((_node)->numRecs + (_sibling)->numRecs) < DBT_MAX_LEAF_ENTRIES) \ + : (((_node)->numRecs + (_sibling)->numRecs) < DBT_MAX_BRANCH_ENTRIES)) + +#define DBRANCH(_entry) n.branch.entry[(_entry)] +#define DLEAF(_entry) n.leaf.entry[(_entry)] + +#define DBT_ZERO_ 0 + +/* + * structure to pass info and state between dir b-tree routines + */ +typedef struct DirTreeParms_s +{ + Zid_t dirZid; /* the directory ID to be used */ + Volume_s *volume; + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + SQUAD value; /* The value being set or adjusted */ + NINT type; /* The type of data contained in the value -- see defines below */ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + struct ZfsXaction_s *xaction; /* Transaction being used */ + struct ZfsDirTreeBeast_s *dirTreeBeast; /* The pointer to the b-tree beast */ +} DirTreeParms_s; + +/* + * Defines for "type" in DirTreeParms_s (not a bit mask) + */ + #define DBT_TYPE_USED_AMOUNT 1 + #define DBT_TYPE_QUOTA 2 + + +/* + * structures for defining what the tree nodes look like + */ + +typedef struct DirBranchEntry_s +{ + Zid_t dirZid; + Blknum_t child; +} NSS_MEDIA_STRUCTURE(DirBranchEntry_s,child) DirBranchEntry_s; + + +typedef struct DirBranch_s +{ + DirBranchEntry_s entry[DBT_MAX_BRANCH_ENTRIES]; +} NSS_MEDIA_STRUCTURE(DirBranch_s,entry[DBT_MAX_BRANCH_ENTRIES]) DirBranch_s; + +typedef struct DirLeafEntry_s +{ + Zid_t dirZid; + SQUAD usedAmount; + SQUAD quota; +} NSS_MEDIA_STRUCTURE(DirLeafEntry_s,quota) DirLeafEntry_s; + + +typedef struct DirLeaf_s +{ + /* + * If the size of the header portion changes then change + * DBT_MAX_LEAF_ENTRIES. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + DirLeafEntry_s entry[DBT_MAX_LEAF_ENTRIES]; +} NSS_MEDIA_STRUCTURE(DirLeaf_s,entry[DBT_MAX_LEAF_ENTRIES]) DirLeaf_s; + +typedef struct DirTreeNode_s +{ + /* + * If the size of the header portion changes then change + * DBT_MAX_BRANCH_ENTRIES and DBT_MAX_LEAF_ENTRIES. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t dtn_internalID; /* Must be at OFFSET 16 - unique volume ID (used + * by scanning repair). dtn -> directory Tree Node. + */ + union + { + DirBranch_s branch; + DirLeaf_s leaf; + } NSS_MEDIA_UNION(NamelessUnion,leaf) n; +} NSS_MEDIA_STRUCTURE(DirTreeNode_s,n.leaf) DirTreeNode_s; + +/* + * Structures and defines for log records for the directory b-tree. + */ + +typedef struct DBTEntry_s +{ + Zid_t dirZid; /* directory to be modified */ + SQUAD quota; /* Value for restriction amount */ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(DBTEntry_s,internalID) DBTEntry_s; + +typedef struct DBTModify_s +{ + Zid_t dirZid; /* directory to be modified */ + SQUAD oldValue; /* Value before change */ + SQUAD value; /* Value for change */ + LONG type; /* type of value ("used amount" or "restriction") */ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(DBTModify_s,internalID) DBTModify_s; + +typedef struct DBTSplit_s +{ + GUID_t internalID; + Zid_t dirZidForParent; /* zid to insert in the parent */ + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + WORD numToMove; /* number of entries logged */ + LONG totalLength; /* length of tree information being moved */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(DBTSplit_s,data) DBTSplit_s; + +typedef struct DBTOverflow_s +{ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(DBTOverflow_s,data) DBTOverflow_s; + +typedef struct DBTGrow_s +{ + GUID_t internalID; + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(DBTGrow_s,blockForParent) DBTGrow_s; + +typedef struct DBTBalance_s +{ + Zid_t dirZidForParent; /* zid to insert in the parent */ + Zid_t oldDirID; /* previous dir zid in the parent */ + LONG indexForParent; /* index where entry is changed in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(DBTBalance_s,data) DBTBalance_s; + +typedef struct DBTTreeInit_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(DBTTreeInit_s,internalID) DBTTreeInit_s; + +/* defines for direction */ + +#define DBT_LEFT_TO_RIGHT 0 +#define DBT_RIGHT_TO_LEFT 1 + +typedef struct DirLog_s +{ + union + { + DBTEntry_s entry; + DBTModify_s modify; + DBTSplit_s split; + DBTOverflow_s overflow; + DBTGrow_s grow; + DBTBalance_s balance; + DBTTreeInit_s initTree; + } NSS_MEDIA_UNION(NamelessUnion,initTree) u; +} NSS_MEDIA_STRUCTURE(DirLog_s,u.initTree) DirLog_s; + +typedef struct NTShrinkLogRecord_s { + LONG offsetOfPoke; + Blknum_t valueOfPoke; + /* The UNDO poke value is poolBlks[1] */ +} NSS_MEDIA_STRUCTURE(NTShrinkLogRecord_s,valueOfPoke) NTShrinkLogRecord_s; + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +STATUS ZFSVOL_VOL_GetDirQuotaInfo( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + Zid_t dirZid, + SQUAD *restrictionAmount, + SQUAD *usedAmount); + +STATUS ZFSVOL_VOL_SetDirQuota( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Xaction_s *xAction, + Zid_t dirZid, + SQUAD restrictionAmount); + +void ZFSVOL_VOL_AdjustUsedDirSpace( + struct Xaction_s *xAction, + struct Volume_s *volume, + Zid_t dirZid, + SQUAD amountToAdjust); + +STATUS ZFSVOL_VOL_RemoveDirectory( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Xaction_s *xAction, + Zid_t dirZid); + +STATUS ZFSVOL_VOL_ResetAllDirEntries( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume); + +STATUS ZFSVOL_VOL_BrowseDirsInVolume( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT numEntriesRequested, + Zid_t *lastDirReturned, /* inout */ + struct COMNDirQuota_s *dirEntries, /* out */ + NINT *numEntriesReturned); /* out */ + +STATUS DBT_CreateDirTreeBeast( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *volume); + +#endif diff --git a/src/nwnss/zlss/dlog.h b/src/nwnss/zlss/dlog.h new file mode 100644 index 0000000..9d3b325 --- /dev/null +++ b/src/nwnss/zlss/dlog.h @@ -0,0 +1,529 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Defines structures used in logging the Naming B-Tree operations. + +-------------------------------------------------------------------------*/ +#ifndef _DLOG_H_ +#define _DLOG_H_ + +#define DLOG_TEST ZLOG_TEST IS_ENABLED +typedef WORD dlog_op_t; +typedef SWORD dlog_ind_t; +typedef SWORD dlog_offset_t; + +#define DLOG_NBLKS(_dlbuf_) ((_dlbuf_)->ZXR_PoolBlockCount) + +typedef struct dlog_move +{ + dlog_op_t op; + dlog_ind_t srcblki; + dlog_ind_t srci; + dlog_ind_t dstblki; + dlog_ind_t dsti; + dlog_offset_t log; + dlog_ind_t nrecs; +} NSS_MEDIA_STRUCTURE(dlog_move_s,nrecs) dlog_move_s; + +#define DLOG_ADD_OP_MOVE_COMMON(_dl_ops_, _srcbi_, _si_, _dstbi_, \ + _di_, _log_, _nrecs_, _op) \ + do { \ + dlog_move_s *dlmove = &(_dl_ops_)->move; \ + dlmove->srcblki = (_srcbi_); \ + dlmove->srci = (_si_); \ + dlmove->dstblki = (_dstbi_); \ + dlmove->dsti = (_di_); \ + dlmove->log = (_log_); \ + dlmove->nrecs = (_nrecs_); \ + (_dl_ops_)->op = DLOG_OP_MOVE | (_op); \ + ++ (_dl_ops_); \ + } while (0) + +#define DLOG_ADD_OP_COPY(_dl_ops_, _srcbi_, _si_, _dstbi_, _di_, \ + _log_, _nrecs_) \ + DLOG_ADD_OP_MOVE_COMMON(_dl_ops_, _srcbi_, _si_, _dstbi_, \ + _di_, _log_, _nrecs_, DLOG_OP_COPY) + +#define DLOG_ADD_OP_MOVE(_dl_ops_, _srcbi_, _si_, _dstbi_, _di_, \ + _log_, _nrecs_) \ + DLOG_ADD_OP_MOVE_COMMON(_dl_ops_, _srcbi_, _si_, _dstbi_, \ + _di_, _log_, _nrecs_, 0) + +#define DLOG_ADD_OP_MOVE_DUP(_dl_ops_, _srcbi_, _si_, _dstbi_, _di_, \ + _log_, _nrecs_) \ + DLOG_ADD_OP_MOVE_COMMON(_dl_ops_, _srcbi_, _si_, _dstbi_, \ + _di_, _log_, _nrecs_, DLOG_OP_DUP) + +typedef struct dlog_replkey +{ + dlog_op_t op; + dlog_ind_t blki; + Blknum_t blk; + dlog_ind_t i; + dlog_offset_t oldlog; + dlog_offset_t newlog; + dlog_ind_t ovflow_data; +} NSS_MEDIA_STRUCTURE(dlog_replkey_s,ovflow_data) dlog_replkey_s; + +#define DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, _log_, \ + _b_, _op_, _oldl_, _ovflow_data_) \ + do { \ + dlog_replkey_s *replkey = &(_dl_ops_)->replkey; \ + replkey->blki = (_blki_); \ + replkey->i = (_i_); \ + replkey->newlog = (_log_); \ + (_dl_ops_)->op = DLOG_OP_REPLKEY | (_op_); \ + replkey->oldlog = (_oldl_); \ + replkey->blk = (_b_); \ + replkey->ovflow_data = (_ovflow_data_); \ + ++ (_dl_ops_); \ + } while (0) + +#define DLOG_ADD_OP_REPLKEY(_dl_ops_, _blki_, _i_, _log_, _b_, _oldl_) \ + DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, _log_, _b_, \ + 0, _oldl_, 0) + +#define DLOG_ADD_OP_INSKEY(_dl_ops_, _blki_, _i_, _log_, _b_) \ + DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, _log_, _b_, \ + DLOG_OP_INSERT, 0, 0) + +#define DLOG_ADD_OP_DELKEY(_dl_ops_, _blki_, _i_, _oldl_, _b_) \ + DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, 0, _b_, \ + DLOG_OP_DELETE, _oldl_, 0) + +#define DLOG_ADD_OP_REPLKEY_OVFLOW(_dl_ops_, _blki_, _i_, _log_, \ + _b_, _oldl_, _od_) \ + DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, _log_, _b_, \ + DLOG_OP_OVFLOW, _oldl_, _od_) + +#define DLOG_ADD_OP_INSKEY_OVFLOW(_dl_ops_, _blki_, _i_, _log_, _b_, _od_) \ + DLOG_ADD_OP_REPLKEY_COMMON(_dl_ops_, _blki_, _i_, _log_, _b_, \ + DLOG_OP_INSERT|DLOG_OP_OVFLOW, 0, _od_) + +typedef struct dlog_repl +{ + dlog_op_t op; + dlog_ind_t blki; + dlog_ind_t i; + dlog_ind_t dupi; + dlog_offset_t oldlog; + dlog_offset_t newlog; +} NSS_MEDIA_STRUCTURE(dlog_repl_s,newlog) dlog_repl_s; + +#define DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, _dupi, _log_, _op_, \ + _oldl_) \ + do { \ + dlog_repl_s *repl = &(_dl_ops_)->repl; \ + repl->blki = (_blki_); \ + repl->i = (_i_); \ + (_dl_ops_)->op = DLOG_OP_REPL | (_op_); \ + repl->dupi = (_dupi); \ + repl->newlog = (_log_); \ + repl->oldlog = (_oldl_); \ + ++ (_dl_ops_); \ + } while (0) + +#define DLOG_ADD_OP_INSERT(_dl_ops_, _blki_, _i_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, 0, _log_, \ + DLOG_OP_INSERT, 0) + +#define DLOG_ADD_OP_DELETE(_dl_ops_, _blki_, _i_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, 0, 0, \ + DLOG_OP_DELETE, _log_) + +#define DLOG_ADD_OP_INSERT_OVFLOW(_dl_ops_, _blki_, _i_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, 0, _log_, \ + DLOG_OP_INSERT|DLOG_OP_OVFLOW, 0) + +#define DLOG_ADD_OP_DELETE_OVFLOW(_dl_ops_, _blki_, _i_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, 0, 0, \ + DLOG_OP_DELETE|DLOG_OP_OVFLOW, _log_) + +#define DLOG_ADD_OP_INSERT_DUP(_dl_ops_, _blki_, _dupi_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, -1, _dupi_, _log_, \ + DLOG_OP_INSERT|DLOG_OP_DUP, 0) + +#define DLOG_ADD_OP_DELETE_DUP(_dl_ops_, _blki_, _i_, _dupi_, _log_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, _dupi_, 0, \ + DLOG_OP_DELETE|DLOG_OP_DUP, _log_) + +#define DLOG_ADD_OP_REPL_DUP(_dl_ops_, _blki_, _i_, _dupi_, _log_, _oldl_) \ + DLOG_ADD_OP_REPL_COMMON(_dl_ops_, _blki_, _i_, _dupi_, _log_, \ + DLOG_OP_DUP, _oldl_) + + +typedef struct dlog_expand +{ + dlog_op_t op; + dlog_ind_t blki; + dlog_ind_t i; + dlog_offset_t size; /* size > 0 => inskey present; < 0 => no inskey */ + dlog_offset_t log; /* log of the extra data added */ +} NSS_MEDIA_STRUCTURE(dlog_expand_s,log) dlog_expand_s; + +#define DLOG_ADD_OP_EXPAND(_dl_ops_, _blki_, _i_, _k_, _size_, _log_) \ + do { \ + dlog_expand_s *expand = &(_dl_ops_)->expand; \ + (_dl_ops_)->op = DLOG_OP_EXPAND; \ + expand->blki = (_blki_); \ + expand->i = (_i_); \ + expand->size = (_k_) ? (_size_) : - (_size_); \ + expand->log = (_log_); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_set_ovflow +{ + dlog_op_t op; + dlog_ind_t blki; + Blknum_t ovflow_blk; +} NSS_MEDIA_STRUCTURE(dlog_set_ovflow_s,ovflow_blk) dlog_set_ovflow_s; + +#define DLOG_ADD_OP_SET_OVFLOW_COMMON(_dl_ops_, _blki_, _ovblk_, _op_) \ + do { \ + dlog_set_ovflow_s *set_ovflow = \ + &(_dl_ops_)->set_ovflow; \ + (_dl_ops_)->op = DLOG_OP_SET_OVFLOW|(_op_); \ + set_ovflow->blki = (_blki_); \ + set_ovflow->ovflow_blk = (_ovblk_); \ + ++ (_dl_ops_); \ + } while (0) + +#define DLOG_ADD_OP_SET_OVFLOW(_dl_ops_, _blki_, _ovblk_) \ + DLOG_ADD_OP_SET_OVFLOW_COMMON(_dl_ops_, _blki_, _ovblk_, 0) + +#define DLOG_ADD_OP_RESET_OVFLOW(_dl_ops_, _blki_, _ovblk_) \ + DLOG_ADD_OP_SET_OVFLOW_COMMON(_dl_ops_, _blki_,_ovblk_,DLOG_OP_RESET_OVFLOW) + +typedef struct dlog_chmask +{ + dlog_op_t op; + dlog_ind_t blki; + dlog_ind_t i; + dlog_ind_t dupi; + nsmask_t oldmask; + nsmask_t newmask; +} NSS_MEDIA_STRUCTURE(dlog_chmask_s,newmask) dlog_chmask_s; + +#define DLOG_ADD_OP_CH_MASK(_dl_ops_, _blki_, _i_, _dupi_, _oldmask, _newmask) \ + do { \ + dlog_chmask_s *ch_mask = &(_dl_ops_)->chmask; \ + (_dl_ops_)->op = DLOG_OP_CH_MASK; \ + ch_mask->blki = (_blki_); \ + ch_mask->i = (_i_); \ + ch_mask->dupi = (_dupi_); \ + ch_mask->oldmask = (_oldmask); \ + ch_mask->newmask = (_newmask); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_chmatchAttr +{ + dlog_op_t op; + dlog_ind_t blki; + dlog_ind_t i; + dlog_ind_t dupi; + nsmask_t oldmatchAttr; + nsmask_t newmatchAttr; +} NSS_MEDIA_STRUCTURE(dlog_chmatchAttr_s,newmatchAttr) dlog_chmatchAttr_s; + +#define DLOG_ADD_OP_CH_MATCHATTR(_dl_ops_, _blki_, _i_, _dupi_, _oldmatch, \ + _newmatch) \ + do { \ + dlog_chmatchAttr_s *ch_matchAttr = &(_dl_ops_)->chmatchAttr; \ + (_dl_ops_)->op = DLOG_OP_CH_MATCHATTR; \ + ch_matchAttr->blki = (_blki_); \ + ch_matchAttr->i = (_i_); \ + ch_matchAttr->dupi = (_dupi_); \ + ch_matchAttr->oldmatchAttr = (_oldmatch); \ + ch_matchAttr->newmatchAttr = (_newmatch); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_chHlFlags +{ + dlog_op_t op; + dlog_ind_t blki; + dlog_ind_t i; + dlog_ind_t dupi; + nsmask_t oldHlFlags; + nsmask_t newHlFlags; +} dlog_chHlFlags_s; + +#define DLOG_ADD_OP_CH_HLFLAGS(_dl_ops_, _blki_, _i_, _dupi_, _oldHlFlags, \ + _newHlFlags) \ + do { \ + dlog_chHlFlags_s *ch_HlFlags = &(_dl_ops_)->chHlFlags; \ + (_dl_ops_)->op = DLOG_OP_CH_HLFLAGS; \ + ch_HlFlags->blki = (_blki_); \ + ch_HlFlags->i = (_i_); \ + ch_HlFlags->dupi = (_dupi_); \ + ch_HlFlags->oldHlFlags = (_oldHlFlags); \ + ch_HlFlags->newHlFlags = (_newHlFlags); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_chroot +{ + dlog_op_t op; + dlog_ind_t oldblki; + dlog_ind_t newblki; +} NSS_MEDIA_STRUCTURE(dlog_chroot_s,newblki) dlog_chroot_s; + +#define DLOG_ADD_OP_CH_ROOT(_dl_ops_, _oldroot_, _newroot_) \ + do { \ + dlog_chroot_s *ch_root = &(_dl_ops_)->chroot; \ + (_dl_ops_)->op = DLOG_OP_CH_ROOT; \ + ch_root->oldblki = (_oldroot_); \ + ch_root->newblki = (_newroot_); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_ch_lchild +{ + dlog_op_t op; + dlog_ind_t blki; + Blknum_t oldblk; + Blknum_t newblk; +} NSS_MEDIA_STRUCTURE(dlog_ch_lchild_s,newblk) dlog_ch_lchild_s; + +#define DLOG_ADD_OP_CH_LCHILD(_dl_ops_, _blki_, _oldblk_, _newblk_) \ + do { \ + dlog_ch_lchild_s *ch_lchild = &(_dl_ops_)->ch_lchild; \ + (_dl_ops_)->op = DLOG_OP_CH_LCHILD; \ + ch_lchild->blki = (_blki_); \ + ch_lchild->oldblk = (_oldblk_); \ + ch_lchild->newblk = (_newblk_); \ + ++ (_dl_ops_); \ + } while (0) + +typedef struct dlog_leaflist +{ + dlog_op_t op; + dlog_ind_t prevblki; + dlog_ind_t ind; + dlog_ind_t curblki; + Blknum_t nextblk; +} NSS_MEDIA_STRUCTURE(dlog_leaflist_s,nextblk) dlog_leaflist_s; + +#define DLOG_ADD_OP_LEAFLIST_COMMON(_dl_ops_, _prevbi, _i, _curbi, _nextb, \ + _op_) \ + do { \ + dlog_leaflist_s *leaflist = &(_dl_ops_)->leaflist; \ + (_dl_ops_)->op = DLOG_OP_LEAFLIST | (_op_); \ + leaflist->prevblki = (_prevbi); \ + leaflist->curblki = (_curbi); \ + leaflist->nextblk = (_nextb); \ + leaflist->ind = (_i); \ + ++ (_dl_ops_); \ + } while (0) + +#define DLOG_ADD_OP_LEAFLIST_INSERT(_dl_ops_, _prevblki, _curblki, _nextblk) \ + DLOG_ADD_OP_LEAFLIST_COMMON(_dl_ops_, _prevblki, -1, _curblki, _nextblk, \ + DLOG_OP_INSERT) + +#define DLOG_ADD_OP_LEAFLIST_DELETE(_dl_ops_, _prevblki, _curblki, _nextblk) \ + DLOG_ADD_OP_LEAFLIST_COMMON(_dl_ops_, _prevblki, -1, _curblki, _nextblk, \ + DLOG_OP_DELETE) + +#define DLOG_ADD_OP_LEAFLIST_DELETE_OVFLOW(_dl_ops_, _prevblki, _i, _curblki, \ + _nextblk) \ + DLOG_ADD_OP_LEAFLIST_COMMON(_dl_ops_, _prevblki, _i, _curblki, _nextblk, \ + DLOG_OP_DELETE|DLOG_OP_OVFLOW) + +#define DLOG_ADD_OP_LEAFLIST_INSERT_OVFLOW(_dl_ops_, _prevblki, _i, _curblki, \ + _nextblk) \ + DLOG_ADD_OP_LEAFLIST_COMMON(_dl_ops_, _prevblki, _i, _curblki, _nextblk, \ + DLOG_OP_INSERT|DLOG_OP_OVFLOW) + +#define DLOG_BASE_OP(_lop_) ((_lop_) & 0xf) +#define DLOG_OP_MOVE 0x0001 +#define DLOG_OP_COPY 0x1000 + +#define DLOG_OP_REPL 0x0002 +#define DLOG_OP_REPLKEY 0x0003 +#define DLOG_OP_INSERT 0x1000 +#define DLOG_OP_DELETE 0x2000 +#define DLOG_OP_OVFLOW 0x4000 +#define DLOG_OP_DUP 0x8000 +#define DLOG_OP_EXPAND 0x0004 + +#define DLOG_OP_CH_MASK 0x0005 +#define DLOG_OP_CH_ROOT 0x0006 +#define DLOG_OP_CH_LCHILD 0x0007 +#define DLOG_OP_SET_OVFLOW 0x0008 +#define DLOG_OP_RESET_OVFLOW 0x1000 +#define DLOG_OP_LEAFLIST 0x0009 +#define DLOG_OP_CH_MATCHATTR 0x000A +#define DLOG_OP_CH_HLFLAGS 0x000B + +typedef union +{ + dlog_move_s move; + dlog_replkey_s replkey; + dlog_repl_s repl; + dlog_expand_s expand; + dlog_set_ovflow_s set_ovflow; + dlog_chmask_s chmask; + dlog_chmatchAttr_s chmatchAttr; + dlog_chHlFlags_s chHlFlags; + dlog_chroot_s chroot; + dlog_ch_lchild_s ch_lchild; + dlog_leaflist_s leaflist; + dlog_op_t op; +} NSS_MEDIA_UNION(NamelessUnion,op) dlog_op_s; + +typedef struct dlog +{ + struct blk_alloc_s { /* Info about alloc'ed/dealloc'ed blocks */ + WORD is_leaf; /* type of block (leaf/branch): bitmap (0-15) */ + WORD is_ovflow; /* Is is an ovflow block?: bitmap (0-15) */ + } NSS_MEDIA_STRUCTURE(struct blk_alloc_s,is_ovflow) blk_alloc; + dlog_ind_t nOps; /* # of operations logged */ + WORD reserved; /* To make it QUAD aligned in size */ +} NSS_MEDIA_STRUCTURE(dlog_s,reserved) dlog_s; + +typedef struct dlog_newhdr_s +{ + GUID_t volumeInternalID; /* ZLSS ID of the volume affected by this record */ + dlog_s hdr; +} NSS_MEDIA_STRUCTURE(dlog_newhdr_s,hdr) dlog_newhdr_s; + +#define DLOG_ALLOC_BLK(_hdr_, _binfo_, _bi_, _isleaf_, _isovflow_) \ + do { \ + ZLOG_ALLOC_BLOCK((_binfo_)[_bi_]); \ + (_hdr_)->blk_alloc.is_leaf &= ~(((WORD)1) << (_bi_)); \ + (_hdr_)->blk_alloc.is_leaf |= (((WORD)(_isleaf_)) << (_bi_)); \ + (_hdr_)->blk_alloc.is_ovflow &= ~(((WORD)1) << (_bi_)); \ + (_hdr_)->blk_alloc.is_ovflow |= (((WORD)(_isovflow_)) << (_bi_)); \ + } while (0) + +#define DLOG_ALLOC_BRANCH(_hdr_, _binfo_, _bi_, _isovflow_) \ + DLOG_ALLOC_BLK(_hdr_, _binfo_, _bi_, 0, _isovflow_) + +#define DLOG_ALLOC_LEAF(_hdr_, _binfo_, _bi_, _isovflow_) \ + DLOG_ALLOC_BLK(_hdr_, _binfo_, _bi_, 1, _isovflow_) + +#define DLOG_DELETE_BLK(_xaction_, _hdr_, _binfo_, _bi_, _isleaf_, _isovfl_) \ + do { \ + (_hdr_)->blk_alloc.is_leaf &= ~(((WORD)1) << (_bi_)); \ + (_hdr_)->blk_alloc.is_leaf |= (((WORD)(_isleaf_)) << (_bi_)); \ + (_hdr_)->blk_alloc.is_ovflow &= ~(((WORD)1) << (_bi_)); \ + (_hdr_)->blk_alloc.is_ovflow |= (((WORD)(_isovfl_)) << (_bi_)); \ + ZLOG_DELETE_BLOCK(_xaction_, (_binfo_)[_bi_]); \ + } while (0) + +#define DLOG_DELETE_BRANCH(_xaction_, _hdr_, _binfo_, _bi_, _isovfl_) \ + DLOG_DELETE_BLK(_xaction_, _hdr_, _binfo_, _bi_, 0, _isovfl_) + +#define DLOG_DELETE_LEAF(_xaction_, _hdr_, _binfo_, _bi_, _isovfl_) \ + DLOG_DELETE_BLK(_xaction_, _hdr_, _binfo_, _bi_, 1, _isovfl_) + +/* In the new log record format, + * we prepend the volume's internal ID before the old record + * All macros below are relative to the old record. + * During recovery, we distinguish the record from the function index used */ +#define DLOG_NEWHDR_SIZE sizeof(dlog_newhdr_s) +#define DLOG_NEWHDR(_dlrec_) ((dlog_newhdr_s *)(_dlrec_)) +#define DLOG_VOLUMEID(_dlrec_) (&DLOG_NEWHDR(_dlrec_)->volumeInternalID) +#define DLOG_OLD_RECORD(_dlrec_) (&DLOG_NEWHDR(_dlrec_)->hdr) + +#define DLOG_HDR(_old_dlrec_) ((dlog_s *)(_old_dlrec_)) +#define DLOG_HDR_SIZE sizeof(dlog_s) +#define DLOG_OPS(_old_dlrec_) \ + ((dlog_op_s *) (((BYTE *)(_old_dlrec_)) + DLOG_HDR_SIZE)) + +#define DLOG_ENTRIES(_old_dlrec_) \ + (((BYTE *)DLOG_OPS(_old_dlrec_)) \ + + DLOG_HDR(_old_dlrec_)->nOps * sizeof(dlog_op_s)) + +#define DLOG_DATA_SIZE(_lhdr_, _entrysz_) \ + ((_lhdr_)->nOps * sizeof(dlog_op_s) + (_entrysz_)) + +#define DLOG_SIZE(_nblks_, _datasz_) \ + (ZLOG_BLOCK_INFO_SIZE(_nblks_) + DLOG_NEWHDR_SIZE + (_datasz_)) + +#define DLOG_INIT_LOG_RECORD(_ntree, _xaction, _buffer, _numblks, \ + _poolblks, _logrecord) \ +do { \ + ZLOG_INIT_LOG_RECORD(XFUNC_NTREE_INTERNAL_OP, _xaction, _buffer, \ + _numblks, _poolblks, _logrecord); \ + DLOG_NEWHDR(_logrecord)->volumeInternalID = \ + (_ntree)->ZFSNAMETREEinternalID; \ + (_logrecord) = DLOG_OLD_RECORD(_logrecord); \ +} while (0) + +#define DLOG_INIT_LOGICAL_LOG_RECORD(_ntree, _xaction, _buffer, _numblks, \ + _poolblks, _logrecord) \ +do { \ + ZLOG_INIT_LOG_RECORD(XFUNC_NTREE_LOGICAL_OP, _xaction, _buffer, \ + _numblks, _poolblks, _logrecord); \ + DLOG_NEWHDR(_logrecord)->volumeInternalID = \ + (_ntree)->ZFSNAMETREEinternalID; \ + (_logrecord) = DLOG_OLD_RECORD(_logrecord); \ +} while (0) + +#define DLOG_SET_BLKINFO(_bi_, _blki_, _buf_, _lsn_, _xact_) \ + ZLOG_ASSIGN_BLOCK_INFO2((_bi_)[_blki_], (_buf_)->BUFblknum, _lsn_, \ + _buf_, _xact_, _blki_, (LogTestCompareFunc_t)node_compare) + +#define DLOG_ADD_ENTRY_COMMON(_dlentry_, _off_, _entry_, _isleaf, _isovflow) \ + do { \ + SNINT _size_ = ENTRYBYTES(_entry_); \ + SNINT _mask_ = ((_isleaf) ? FREE_ENTRY_MASK : 0) | \ + ((_isovflow) ? FREE_PREVENTRY_MASK : 0); \ + memmove(_dlentry_, _entry_, _size_); \ + (*(node_offset_t *)(_dlentry_)) = NWORDS(_size_) | _mask_; \ + (_dlentry_) += (_size_); \ + (_off_) += (_size_); \ + } while (0) + +#define DLOG_ADD_OVFLOW_ENTRY(_dlentry_, _off_, _entry_) \ + DLOG_ADD_ENTRY_COMMON(_dlentry_, _off_, _entry_, 0, 1) + +#define DLOG_ADD_ENTRY(_dlentry_, _off_, _entry_, _isleaf) \ + DLOG_ADD_ENTRY_COMMON(_dlentry_, _off_, _entry_, _isleaf, 0) + +extern STATUS dlog_recovery_common( + GeneralMsg_s *gm, + ZfsPool_s *pool, + struct ZfsXasRecovery_s *dlbuf, + NINT action); + +extern STATUS dlog_logical_recovery_common( + GeneralMsg_s *gm, + ZfsPool_s *pool, + struct ZfsXasRecovery_s *dlbuf, + NINT action); + +#endif /* _DLOG_H_ */ diff --git a/src/nwnss/zlss/eflLog.h b/src/nwnss/zlss/eflLog.h new file mode 100644 index 0000000..2e8f8f4 --- /dev/null +++ b/src/nwnss/zlss/eflLog.h @@ -0,0 +1,286 @@ +/**************************************************************************** + | + | (C) Copyright 2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $ + | + | $RCSfile$ + | $Revision: 1177 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and externs for EFL log + +-------------------------------------------------------------------------*/ + +#ifndef _EFLLOG_H_ +#define _EFLLOG_H_ + +/* Pre-declare the following structure(s) */ +struct ZfsXaction_s; +struct EFLLeafEntry_s; + +#define ELOG_ENTRY_MAGIC 0x5858 /* "XX" */ +#define ELOG_MAX_FREE (PAGE_SIZE - sizeof(ELogNode_s)) +#define ELOG_HEADER_RECORD 0 +#define ELOG_LOG_RECORD 1 + +/* Bit mask for clearing operations from the log */ +#define ELOG_CLEAR_ALL -1 +#define ELOG_CLEAR_CREATE 0x0001 +#define ELOG_CLEAR_DELETE 0x0002 +#define ELOG_CLEAR_MODIFY 0x0004 +#define ELOG_CLEAR_RENAME 0x0008 + +typedef struct ELogLink_s +{ + Blknum_t blockNum; /* block number of the entry */ + LONG resBlk; /* reserved for 64 bit block */ + LONG offset; /* offset into the block of the start of the entry */ +} NSS_MEDIA_STRUCTURE(ELogLink_s,offset) ELogLink_s; + +typedef struct ELogEntry_s +{ + WORD magic; + WORD len; + WORD entryNum; /* zero based */ + WORD action; + Zid_t zid; + EFLEpochMask_t epochs; + ELogLink_s nextLogEntry; + WORD state; + WORD oldNameIndex; + unicode_t names[1]; /* variable length section with old and new names */ +} NSS_MEDIA_STRUCTURE(ELogEntry_s,names[1]) ELogEntry_s; + +/* Values for action */ +#define ELOG_CREATE EFL_FILE_STATE_CREATE_FILE +#define ELOG_DELETE EFL_FILE_STATE_DELETE_FILE +#define ELOG_MODIFY EFL_FILE_STATE_MODIFY_DATA +#define ELOG_MODIFY_META_DATA EFL_FILE_STATE_MODIFY_METADATA +#define ELOG_RENAME EFL_FILE_STATE_RENAME + +/* Values for state */ +#define ELOG_ENTRY_STATE_DELETED 0x0001 /* set if this is a deleted entry */ +#define ELOG_ENTRY_STATE_DIRECTORY 0x0002 /* set if this entry is for a directory*/ +#define ELOG_ENTRY_STATE_DATASTREAM 0x0004 /* set if this entry is for a datastream*/ +#define ELOG_ENTRY_STATE_EXTENDED_ATTRIBUTE 0x0008 /* set if this entry is for an extended attribute*/ + +typedef struct ELogHeader_s +{ + Blknum_t lastBlock; /* The last block in the list */ + LONG resBlk; /* reserved for 64 bit block */ +} NSS_MEDIA_STRUCTURE(ELogHeader_s,resBlk) ELogHeader_s; + +typedef struct ELogLog_s +{ + WORD numGoodEntries; /* The number of entries still in use */ + WORD numFirstEntries; /* The number of entries pointed to by the EFL tree */ + LONG insertOffset; /* The point in the block to start inserting */ + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(ELogLog_s,data[1]) ELogLog_s; + +typedef struct ELogNode_s +{ + /* + * If the size of the header portion changes then change EFL_MAX_FREEBLKS, + * EFL_MAX_BRANCHES and EFL_MAX_LEAF_FREE. + */ + LONG magic; + WORD numEntries; + WORD state; + Lsn_t lsn; + GUID_t elog_internalID; /* Must be at OFFSET 16 - unique volume ID (used + * by scanning repair). + */ + Blknum_t nextBlock; + LONG resBlk; /* reserved for 64 bit blocks */ + union + { + ELogHeader_s header; + ELogLog_s log; + } NSS_MEDIA_UNION(NamelessUnion,log) u; +} NSS_MEDIA_STRUCTURE(ELogNode_s,u.log) ELogNode_s; + +#define ELOG_STATE_HEADER 0x0001 /* set if this is the header block */ +#define ELOG_STATE_REZID_DONE 0x0002 /* This node was ReZid + * This bit is only used while we are + * in the process of rezidding. + * When rezid is complete we clear this + * bit. + */ + +typedef struct ELogParms_s +{ + NINT originalNameLen; + unicode_t *originalName; + NINT newNameLen; + unicode_t *newName; +} ELogParms_s; + +typedef struct ELogAddNode_s +{ + GUID_t internalID; + Blknum_t newBlock; + Blknum_t oldNextLink; + Blknum_t oldLastLink; +} NSS_MEDIA_STRUCTURE(ELogAddNode_s,oldLastLink) ELogAddNode_s; + +typedef struct ELogAddEntry_s +{ + GUID_t internalID; + ELogEntry_s entry; + LONG lastEntryOffset; + LONG offset; + LONG firstEntry; + ELogLink_s firstLogEntry; + LONG numGoodLogEntries; +} NSS_MEDIA_STRUCTURE(ELogAddEntry_s,numGoodLogEntries) ELogAddEntry_s; + +typedef struct ELogAddEntryName_s +{ + LONG entryLen; + LONG nameIndex; + unicode_t name[1]; +} NSS_MEDIA_STRUCTURE(ELogAddEntryName_s,name[1]) ELogAddEntryName_s; + +typedef struct ELogRemoveNode_s +{ + Blknum_t currentBlock; + Blknum_t nextBlock; +} NSS_MEDIA_STRUCTURE(ELogRemoveNode_s,nextBlock) ELogRemoveNode_s; + +typedef struct ELogModifyEpochs_s +{ + LONG offset; + EFLEpochMask_t epochsToChange; + LONG firstEntryAdjustment; +} NSS_MEDIA_STRUCTURE(ELogModifyEpochs_s,firstEntryAdjustment) ELogModifyEpochs_s; + +typedef struct EFLRecoveryLog_s +{ + union + { + ELogAddNode_s addNode; + ELogAddEntry_s addEntry; + ELogAddEntryName_s addEntryName; + ELogRemoveNode_s removeNode; + ELogModifyEpochs_s modifyEpochs; + } NSS_MEDIA_UNION(NamelessUnion,modifyEpochs) u; +} NSS_MEDIA_STRUCTURE(EFLRecoveryLog_s,u.modifyEpochs[1]) EFLRecoveryLog_s; + +/* Prototypes */ + +void EFL_DisplayLogEntry ( + ELogEntry_s *entry, + NINT offset); + +Buffer_s *ELOG_ReadPoolBlk ( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *iomsg); + +void ELOG_InitNode( + Buffer_s *buffer, + GUID_t *internalID, + NINT type); + +Buffer_s *ELOG_AllocateHeaderNode( + struct GeneralMsg_s *genMsg, + Volume_s *volume, + struct ZfsXaction_s *localXaction); + +STATUS ELOG_AddLogEntry( + struct GeneralMsg_s *genMsg, + struct ZfsXaction_s *xaction, + struct EFLLeafEntry_s *leafEntry, + NINT action, + EFLEpochMask_t epochs, + struct Volume_s *volume, + Zid_t zid, + unicode_t *oldName); + +STATUS ELOG_RemoveNode( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Buffer_s *prevBuffer, + struct Buffer_s *buffer); + +STATUS ELOG_FindModifyForEpochs( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct EFLLeafEntry_s *leafEntry, + EFLEpochMask_t activeEpochs, + EFLEpochMask_t *notFoundEpochs, + BOOL includeMetaData); + +STATUS ELOG_ClearALogEntry( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct EFLLeafEntry_s *leafEntry, + Blknum_t block, + NINT offset, + EFLEpochMask_t epoch, + struct ZfsXaction_s *xaction, + NINT *operation); + +STATUS ELOG_ClearLogEntries( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct EFLLeafEntry_s *leafEntry, + EFLEpochMask_t activeEpochs, + struct ZfsXaction_s *xaction, + BOOL justModifies); + +STATUS ELOG_ClearSameNameCreate( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct EFLLeafEntry_s *leafEntry, + EFLEpochMask_t epochs, + struct ZfsXaction_s *xaction, + unicode_t *name, + EFLEpochMask_t *changedEpochs); + +Buffer_s *ELOG_GetFirstGoodEntry( + struct GeneralMsg_s *genMsg, + struct ZfsEFLTreeBeast_s *eTree, + Blknum_t block, + NINT offset, + Blknum_t *retBlock, + NINT *retOffset); + +Buffer_s *ELOG_GetNextGoodEntry( + struct GeneralMsg_s *genMsg, + struct ZfsEFLTreeBeast_s *eTree, + struct Buffer_s *buffer, + NINT offset, + Blknum_t *retBlock, + NINT *retOffset); + +STATUS ELOG_CleanupBlocks( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + BOOL unusedOnly); + +#endif diff --git a/src/nwnss/zlss/eflTree.h b/src/nwnss/zlss/eflTree.h new file mode 100644 index 0000000..96a660f --- /dev/null +++ b/src/nwnss/zlss/eflTree.h @@ -0,0 +1,373 @@ +/**************************************************************************** + | + | (C) Copyright 2002, 2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and externs for EFL + +-------------------------------------------------------------------------*/ + +#ifndef _EFLTREE_H_ +#define _EFLTREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +#ifndef _EFLLOG_H_ +#include "eflLog.h" +#endif + +/* + * Debug stuff + */ +#if NSS_DEBUG IS_ENABLED +#define EFL_VALIDATE_NODE(_node) (EFL_ValidateNode(_node)) +#else +#define EFL_VALIDATE_NODE(_node) ((void)0) +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define EFL_CHECK_FOR_SPLIT 0x00000001 +#define EFL_CHECK_FOR_JOIN 0x00000002 + +/* state of a node */ +#define EFL_LEAF 0x1 /* Leaf node of a B-tree */ +#define EFL_ROOT 0x2 /* Root node of a B-tree */ +#define EFL_REZID_DONE 0x4 /* This node was ReZid + * This bit is only used while we are + * in the process of rezidding. + * When rezid is complete we clear this + * bit. + */ + +#define EFL_SMALL DISABLE +//#define EFL_SMALL ENABLE + +#if EFL_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define EFL_MAX_BRANCH_ENTRIES 7 +#define EFL_MAX_LEAF_ENTRIES 5 +#else +#define EFL_MAX_BRANCH_ENTRIES ((PAGE_SIZE - 32) / sizeof(EFLBranchEntry_s)) +#define EFL_MAX_LEAF_ENTRIES ((PAGE_SIZE - 32 + 4) / sizeof(EFLLeafEntry_s)) +#endif + +#define EFL_MIN_BRANCH_ENTRIES (EFL_MAX_BRANCH_ENTRIES / 2) +#define EFL_MIN_LEAF_ENTRIES (EFL_MAX_LEAF_ENTRIES / 2) + +#define EFL_IS_LEAF(_n) ((_n)->state & EFL_LEAF) +#define EFL_IS_ROOT(_n) ((_n)->state & EFL_ROOT) + +#define EFL_IS_MAX_ENTRIES(_node, _parms) \ + (EFL_IS_LEAF(_node) \ + ? ((_node)->numRecs >= EFL_MAX_LEAF_ENTRIES) \ + : ((_node)->numRecs >= EFL_MAX_BRANCH_ENTRIES)) + +#define EFL_IS_MIN_ENTRIES(_node) \ + (EFL_IS_LEAF(_node) \ + ? ((_node)->numRecs <= EFL_MIN_LEAF_ENTRIES) \ + : ((_node)->numRecs <= EFL_MIN_BRANCH_ENTRIES)) + +#define EFL_IS_LESSTHAN_MAX(_node, _sibling) \ + (EFL_IS_LEAF(_node) \ + ? (((_node)->numRecs + (_sibling)->numRecs) < EFL_MAX_LEAF_ENTRIES) \ + : (((_node)->numRecs + (_sibling)->numRecs) < EFL_MAX_BRANCH_ENTRIES)) + +#define EFL_GET_NAME_SPACE_ID(_volume) ((ZfsVolume_s *)(_volume))->eflTree->p.nameSpace + +#define EFL_GET_INACTIVE_EPOCH_INTERVAL(_volume) \ + ((ZfsVolume_s *)(_volume))->eflTree->p.inactiveInterval + +#define EBRANCH(_entry) n.branch.entry[(_entry)] +#define ELEAF(_entry) n.leaf.entry[(_entry)] + +/* Macros used for latching and unlatching the eflTree beast and checking + * to see if the beast we are inserting or updating is the eflTree beast */ +#define EFL_X_LATCH_TREE(_parms) \ + X_LATCH(&(_parms)->eTree->ZFSEFLTREEbeastLatch); + +#define EFL_UNX_LATCH_TREE(_parms) \ + UNX_LATCH(&(_parms)->eTree->ZFSEFLTREEbeastLatch); + +#define EFL_TREE_X_LATCHED(_parms) \ + IS_XLATCHED(&(_parms)->eTree->ZFSEFLTREEbeastLatch) + +#define EFL_ANY_EPOCH_ACTIONS(_entry) \ + ((_entry).createEpochs || (_entry).modifyEpochs || \ + (_entry).metaDataEpochs || (_entry).deleteEpochs) + +#define EFL_GET_EPOCH_MASK(_eTree, _epoch) getEFLEpochMask(_eTree, _epoch) + +#define EFL_DEFAULT_NAMESPACE zNSPACE_LONG +/* + * structures for defining what the tree nodes look like + */ +typedef struct EFLBranchEntry_s +{ + Zid_t zid; + Blknum_t child; + LONG resBlk; /* reserved for 64 bit blocks */ +} NSS_MEDIA_STRUCTURE(EFLBranchEntry_s,resBlk) EFLBranchEntry_s; + +typedef struct EFLBranch_s +{ + EFLBranchEntry_s entry[EFL_MAX_BRANCH_ENTRIES]; +} NSS_MEDIA_STRUCTURE(EFLBranch_s,entry[EFL_MAX_BRANCH_ENTRIES]) EFLBranch_s; + +typedef struct EFLLeafEntry_s +{ + Zid_t zid; + EFLEpochMask_t createEpochs; + EFLEpochMask_t modifyEpochs; /* data modified */ + EFLEpochMask_t metaDataEpochs; /* metadata modified */ + EFLEpochMask_t deleteEpochs; + LONG objectType; + ELogLink_s firstLogEntry; + ELogLink_s lastLogEntry; + LONG numGoodLogEntries; + LONG extra[4]; /* extra space for future use */ +} NSS_MEDIA_STRUCTURE(EFLLeafEntry_s,extra[4]) EFLLeafEntry_s; + +/* Values for objectType */ +#define ELF_TYPE_FILE 0 +#define ELF_TYPE_DIRECTORY 1 +#define ELF_TYPE_DATASTREAM 2 +#define ELF_TYPE_EXTENDED_ATTRIBUTE 3 + +typedef struct EFLLeaf_s +{ + /* + * If the size of the header portion changes then change + * EFL_MAX_LEAF_ENTRIES. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + LONG resBlk; /* reserved for 64 bit blocks */ + EFLLeafEntry_s entry[EFL_MAX_LEAF_ENTRIES]; +} NSS_MEDIA_STRUCTURE(EFLLeaf_s,entry[EFL_MAX_LEAF_ENTRIES]) EFLLeaf_s; + +typedef struct EFLTreeNode_s +{ + /* + * If the size of the header portion changes then change EFL_MAX_FREEBLKS, + * EFL_MAX_BRANCHES and EFL_MAX_LEAF_FREE. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t efl_internalID; /* Must be at OFFSET 16 - unique volume ID (used + * by scanning repair). btn -> Beast Tree Node. + */ + union + { + EFLBranch_s branch; + EFLLeaf_s leaf; + } NSS_MEDIA_UNION(NamelessUnion,leaf) n; +} NSS_MEDIA_STRUCTURE(EFLTreeNode_s,n.leaf) EFLTreeNode_s; + +/* + * structure to pass info and state between EFL b-tree routines + */ +typedef struct EFLTreeParms_s +{ + Volume_s *volume; /* the volume we are working on */ + Zid_t zid; + NINT action; + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + EFLEpochMask_t epochMask; + struct ZfsXaction_s *xaction; /* Transaction being used */ + struct ZfsEFLTreeBeast_s *eTree; /* The pointer to the b-tree beast */ +} EFLTreeParms_s; + +/* + * Structures and defines for log records for the EFL b-tree. + */ + +typedef struct EFLSplit_s +{ + GUID_t internalID; + Zid_t zidForParent; /* zid to insert in the parent */ + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(EFLSplit_s,data[1]) EFLSplit_s; + +typedef struct EFLGrow_s +{ + GUID_t internalID; + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(EFLGrow_s,blockForParent) EFLGrow_s; + +typedef struct EFLBalance_s +{ + Zid_t zidForParent; /* zid to insert in the parent */ + Zid_t oldZid; /* previous zid in the parent */ + LONG indexForParent; /* index where zid is changed in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(EFLBalance_s,data[1]) EFLBalance_s; + +typedef struct EFLTreeInit_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(EFLTreeInit_s,internalID) EFLTreeInit_s; + +typedef struct EFLModify_s +{ + GUID_t internalID; + EFLLeafEntry_s oldEntry; + EFLLeafEntry_s newEntry; +} NSS_MEDIA_STRUCTURE(EFLModify_s,newEntry) EFLModify_s; + +typedef struct EFLInsert_s +{ + GUID_t internalID; + EFLLeafEntry_s newEntry; +} NSS_MEDIA_STRUCTURE(EFLInsert_s,newEntry) EFLInsert_s; + +typedef struct EFLDelete_s +{ + GUID_t internalID; + EFLLeafEntry_s entry; +} NSS_MEDIA_STRUCTURE(EFLDelete_s,entry) EFLDelete_s; + +typedef struct EFLRemoveLog_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(EFLRemoveLog_s,internalID) EFLRemoveLog_s; + +/* defines for direction */ +#define EFL_LEFT_TO_RIGHT 0 +#define EFL_RIGHT_TO_LEFT 1 + +typedef struct EFLLog_s +{ + union + { + EFLSplit_s split; + EFLGrow_s grow; + EFLBalance_s balance; + EFLTreeInit_s init; + EFLModify_s modify; + EFLInsert_s insert; + EFLDelete_s delete; + EFLRemoveLog_s removeLog; + } NSS_MEDIA_UNION(NamelessUnion,removeLog) u; +} NSS_MEDIA_STRUCTURE(EFLLog_s,u.removeLog) EFLLog_s; + + + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +STATUS ZFSVOL_VOL_insertEFLEntry( + struct GeneralMsg_s *genMsg, + struct File_s *file, + NINT action, + unicode_t *name, + struct Xaction_s *xaction); + +STATUS ZFSVOL_VOL_deleteEFLEntry( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + Zid_t zid, + QUAD id1, + QUAD id2, + EFLEpoch_t *epoch, + struct Xaction_s *xaction); + +STATUS ZFSVOL_VOL_lookupEFLEntry( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + Zid_t zid, + EFLEpoch_t *epoch, + EFLEntry_s *entry); + +STATUS ZFSVOL_VOL_enumerateEFL( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + EFLEpoch_t *targetEpoch, + NINT maxEntries, + struct EFLEntryIndex_s *nextEntry, /* inout */ + struct EFLEntry_s *retEntries, /* out */ + NINT *numEntriesReturned); /* out */ + +STATUS ZFSVOL_VOL_administerEFL( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT opCode, + EFLAdminIn_s *data, + EFLAdminOut_s *retData); + +STATUS ZFSVOL_VOL_resetEFL( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume); + +void EFL_RemoveEpochThread( + EFLRemoveEpochData_s *fsm, + void *unused); + +void EFL_checkerStart(OneShot_s *alarm); + +STATUS eflRemoveEpoch( + GeneralMsg_s *genMsg, + Volume_s *volume, + EFLEpoch_t *epoch); + + +BOOL EFL_ValidateNode( + EFLTreeNode_s *node); + + +Buffer_s *EFL_ReadPoolBlk ( + GeneralMsg_s *genMsg, + IoMsg_s *iomsg); + +/* efl startup/shutdown routine */ +void eflInit(); + +void eflUninit(); + +#endif diff --git a/src/nwnss/zlss/mflBTree.h b/src/nwnss/zlss/mflBTree.h new file mode 100644 index 0000000..34d50c4 --- /dev/null +++ b/src/nwnss/zlss/mflBTree.h @@ -0,0 +1,76 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | MFL internal header file. + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define internal structures and functions for MFL BTree + | This file should not be used outside MFL Btree code. + +-------------------------------------------------------------------------*/ + +#ifndef _MFL_H_ +#define _MFL_H_ + +#ifndef _MYBTREE_H_ +#include "myBTree.h" +#endif + +#define MFL_MAGIC 0x204c464d /* "MFL " */ + +typedef MYBTreeNode_s MFLTreeNode_s; + + +extern MYBTreeInstanceInfo_s MFLTreeInfo; + +#define MFL_IS_LEAF(_n) MYBT_IS_LEAF(_n) +#define MFL_LEAF_ENTRY(_n, _i) MYBT_LEAFENTRY(&MFLTreeInfo, _n, _i) +#define MFL_BRANCH_ENTRY(_n, _i) MYBT_BRANCHENTRY(&MFLTreeInfo, _n, _i) + +/* Doesn't assert */ +#define MFL_IS_NODE_VALID(_node) MYBT_IS_NODE_VALID(&MFLTreeInfo, _node) + +/* + * Debug stuff + */ +/* Asserts on invalid nodes */ +#define MFL_VALIDATE_NODE(_node) MYBT_VALIDATE_NODE(&MFLTreeInfo, _node) + +#if NSS_DEBUG IS_ENABLED +void ZfsDisplayMFL( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +#define zfsDisplayMFLNode(_location, _nameOfBuffer, _buffer) \ + MYBT_displayNode(&MFLTreeInfo, _location, _nameOfBuffer, _buffer) +#endif + +#endif /* _MFL_H_ */ diff --git a/src/nwnss/zlss/mfl_if.h b/src/nwnss/zlss/mfl_if.h new file mode 100644 index 0000000..e89d453 --- /dev/null +++ b/src/nwnss/zlss/mfl_if.h @@ -0,0 +1,106 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996-2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | MFL data structure interface. + +-------------------------------------------------------------------------*/ + +#ifndef _MFL_IF_H_ +#define _MFL_IF_H_ + +#define MFL_ENABLED(_volume) \ + (((_volume)->VOLenabledAttributes & zATTR_MFL) != 0) + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +extern STATUS +ZFSVOL_VOL_createMFL( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol); + +extern STATUS +ZFSVOL_VOL_destroyMFL( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol); + +extern STATUS +ZFSVOL_VOL_insertMFLEntry( + GeneralMsg_s *genMsg, + Volume_s *volume, + Zid_t zid, + Epoch_t epoch, + Xaction_s *xaction); + +extern STATUS +ZFSVOL_VOL_deleteMFLEntry( + GeneralMsg_s *genMsg, + Volume_s *volume, + Zid_t zid, + Epoch_t *epoch, /* out */ + Xaction_s *xaction); + +extern STATUS +ZFSVOL_VOL_lookupMFLEntry( + GeneralMsg_s *genMsg, + Volume_s *volume, + Zid_t zid, + Epoch_t *epoch); /* out */ + +STATUS ZFSVOL_VOL_enumerateMFL( + GeneralMsg_s *genMsg, + Volume_s *volume, + Epoch_t targetEpoch, + NINT numEntriesRequested, + Zid_t *lastZidReturned, /* inout */ + MFLEntry_s *mflEntries, /* out */ + NINT *numEntriesReturned, /* out */ + BOOL *isMFLincomplete); /* out */ + +extern STATUS +ZFSVOL_VOL_administerMFL( + GeneralMsg_s *genMsg, + Volume_s *volume, + NINT opCode, + MFLAdminParms_s *parms); /* inout */ + +extern void +MFL_verify( + Volume_s *volume, + MFLVerifyStats_s *verifyStats, /* out */ + BOOL doFix); + +#endif /* _MFL_IF_H_ */ diff --git a/src/nwnss/zlss/mscIDE.h b/src/nwnss/zlss/mscIDE.h new file mode 100644 index 0000000..ba12fda --- /dev/null +++ b/src/nwnss/zlss/mscIDE.h @@ -0,0 +1,55 @@ +/**************************************************************************** + | + | (C) Copyright 2002 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | mscIDE - Defines only needed while compiling in MSC IDE. + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + +-------------------------------------------------------------------------*/ + + + +#ifdef AT_HOME +#define bzero( a, b ) memset( a, 0, b ) +#endif + + +#ifdef AT_HOME +#define ZBLDN 100 +//#define ULONG_MAX 0x7ffffffful +#endif + + +#ifdef AT_HOME +#define ULONGLONG_MAX _UI64_MAX +#define LONGLONG_MAX _I64_MAX +#define LONGLONG_MIN _I64_MIN +#endif diff --git a/src/nwnss/zlss/myBTree.h b/src/nwnss/zlss/myBTree.h new file mode 100644 index 0000000..1bcf28d --- /dev/null +++ b/src/nwnss/zlss/myBTree.h @@ -0,0 +1,417 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $ + | + | $RCSfile$ + | $Revision: 1177 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define a generic fixed-key, fixed-value B-tree index interface + | Multiple instances of this tree can be initiated. + | Keys and Values should be multiples of 64-bit words in length + | and must be aligned to 64-bit boundary. They are maintained that way + | inside the tree too. + | + | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! + | + | This header file should ONLY be used for NSS internal development. + | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). + | Any other use may cause conflicts which NSS will NOT fix. + +-------------------------------------------------------------------------*/ +#ifndef _MYBTREE_H_ +#define _MYBTREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +/* Pre-declare the following structure(s) */ +struct ZfsXasRecovery_s; + +#define MYBT_getOwnerID(_beast) ((_beast)->ROOTownerID) + +#define MYBT_LEAF_MAGIC(_treeInfo) (_treeInfo)->leafMagic +#define MYBT_BRANCH_MAGIC(_treeInfo) (_treeInfo)->branchMagic + +#define MYBT_IS_NODE_VALID(_treeInfo, _node) \ + MYBT_validateNode(_treeInfo, (MYBTreeNode_s *)(_node), TRUE) + +#if NSS_DEBUG IS_ENABLED +#define MYBT_VALIDATE_NODE(_treeInfo, _node) \ + ((void)MYBT_validateNode(_treeInfo, (MYBTreeNode_s *)(_node), FALSE)) +#else +#define MYBT_VALIDATE_NODE(_treeInfo, _node) ((void)0) +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define MYBT_CHECK_FOR_SPLIT 0x00000001 +#define MYBT_CHECK_FOR_JOIN 0x00000002 + +/* state of a node */ +#define MYBT_LEAF 0x1 /* Leaf node of a B-tree */ +#define MYBT_ROOT 0x2 /* Root node of a B-tree */ + +#define MYBT_IS_LEAF(_n) ((_n)->state & MYBT_LEAF) +#define MYBT_IS_ROOT(_n) ((_n)->state & MYBT_ROOT) + +typedef BYTE *MYBTKey_t; +typedef BYTE *MYBTValue_t; + +/* + * Definitions of B-tree customization parameters + */ + +typedef struct MYBTreeInstanceInfo_s { + NINT keySize; + NINT valueSize; + NINT leafEntrySize; + LONG leafMagic; + LONG branchMagic; + NINT internalRecoveryStartOpCode; + NINT logicalRecoveryStartOpCode; + SNINT (* keyComp)(void *key1, void *key2); + void (* setZeroKey)(void *key); + STATUS (* upgradeNode)( + GeneralMsg_s *genMsg, + Buffer_s *buf, + BYTE mode, + BOOL *modified); /* out Was the node modified? */ +#if NSS_DEBUG IS_ENABLED + void (* displayKey)(NINT color, void *key); + void (* displayValue)(NINT color, void *value); +#endif +} MYBTreeInstanceInfo_s; + +#define MYBT_KEY_SIZE(_treeInfo) (_treeInfo)->keySize +#define MYBT_VALUE_SIZE(_treeInfo) (_treeInfo)->valueSize +#define MYBT_ENTRY_SIZE(_treeInfo) \ + (MYBT_KEY_SIZE(_treeInfo) + MYBT_VALUE_SIZE(_treeInfo)) + +/* + * structure to pass info and state between beast b-tree routines + */ +typedef struct MYBTreeParms_s +{ + MYBTreeInstanceInfo_s *treeInfo; /* B-Tree instance-specific information */ + MYBTKey_t key; /* the key to be used */ + Volume_s *volume; + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + MYBTValue_t value; /* The value being set */ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + struct ZfsXaction_s *xaction; /* Transaction being used */ + struct ZfsMYBTreeBeast_s *btreeBeast; /* The pointer to the b-tree beast */ + STATUS (*updateCallback)( + GeneralMsg_s *genMsg, + MYBTValue_t oldValue, + MYBTValue_t newValue); + /* Set to NULL for insert * and no update. + * Otherwise to update the value + * define the callback routine. This + * routine will be called with the existing + * value and the value asked to be inserted + * The newValue will be changed to reflect + * the updated value to be inserted back + * in the tree + */ +} MYBTreeParms_s; + +/* + * structures for defining what the tree nodes look like + */ +typedef struct MYBTBranchEntry_s +{ + Blknum_t child; + LONG reserved; /* to align key to 64-bit boundary */ + BYTE key[1]; +} NSS_MEDIA_STRUCTURE(MYBTBranchEntry_s,key[1]) MYBTBranchEntry_s; + +#define MYBT_BRANCHENTRY_SIZE(_treeInfo) \ + (offsetof(MYBTBranchEntry_s, key) + MYBT_KEY_SIZE(_treeInfo)) +#define MYBT_BRANCHENTRY_KEY(_treeInfo, _entry) (&(_entry)->key) + +#define MYBT_BRANCHENTRY(_treeInfo, _node, _index) \ + ((MYBTBranchEntry_s *)((BYTE *)&(_node)->n.branch.v_entry + \ + (_index) * MYBT_BRANCHENTRY_SIZE(_treeInfo))) + +#define MYBT_BRANCH_IND_KEY(_treeInfo, _node, _ind) \ + MYBT_BRANCHENTRY_KEY(_treeInfo, \ + MYBT_BRANCHENTRY(_treeInfo, _node, _ind)) + +#define MYBT_LEAFENTRY(_treeInfo, _node, _index) \ + ((BYTE *)&(_node)->n.leaf.vv_entry + (_index) * MYBT_LEAFENTRY_SIZE(_treeInfo)) + +#define MYBT_LEAFENTRY_KEY(_treeInfo, _entry) (_entry) +#define MYBT_LEAFENTRY_VALUE(_treeInfo, _entry) \ + ((_entry) + MYBT_KEY_SIZE(_treeInfo)) +#define MYBT_LEAF_IND_KEY(_treeInfo, _node, _ind) \ + MYBT_LEAFENTRY(_treeInfo, _node, _ind) +#define MYBT_LEAF_IND_VALUE(_treeInfo, _node, _ind) \ + (MYBT_LEAFENTRY(_treeInfo, _node, _ind) + MYBT_KEY_SIZE(_treeInfo)) +#define MYBT_LEAFENTRY_SIZE(_treeInfo) (_treeInfo)->leafEntrySize + +typedef struct MYBTreeNode_s +{ + /* + * If the size of the header portion changes then change + * MYBT_MAX_BRANCH_ENTRIES and MYBT_MAX_LEAF_ENTRIES. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t utn_internalID; /* Must be at OFFSET 16 - unique volume ID (used + * by scanning repair). utn -> User Tree Node. + */ + union + { + struct NSSFakeNameRJ4 { + LONG v_entry; + } NSS_MEDIA_STRUCTURE(NSSFakeNameRJ4,entry) branch; + struct NSSFakeNameHU8{ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + LONG reserved; /* To align entries to 64-bit boundary */ + LONG vv_entry; + } NSS_MEDIA_STRUCTURE(NSSFakeNameHU8,entry) leaf; + } NSS_MEDIA_UNION(NamelessUnion,leaf.entry) n; +} NSS_MEDIA_STRUCTURE(MYBTreeNode_s,n.leaf.entry) MYBTreeNode_s; + +#define MYBT_MAX_BRANCH_ENTRIES(_treeInfo) \ + ((PAGE_SIZE - offsetof(MYBTreeNode_s, n.branch.v_entry)) \ + / MYBT_BRANCHENTRY_SIZE(_treeInfo)) + +#define MYBT_MAX_LEAF_ENTRIES(_treeInfo) \ + ((PAGE_SIZE - offsetof(MYBTreeNode_s, n.leaf.vv_entry)) \ + / MYBT_LEAFENTRY_SIZE(_treeInfo)) + +#define MYBT_MIN_BRANCH_ENTRIES(_treeInfo) (MYBT_MAX_BRANCH_ENTRIES(_treeInfo) / 2) +#define MYBT_MIN_LEAF_ENTRIES(_treeInfo) (MYBT_MAX_LEAF_ENTRIES(_treeInfo) / 2) + +#define MYBT_IS_MAX_ENTRIES(_treeInfo, _node) \ + (MYBT_IS_LEAF(_node) \ + ? ((_node)->numRecs >= MYBT_MAX_LEAF_ENTRIES(_treeInfo)) \ + : ((_node)->numRecs >= MYBT_MAX_BRANCH_ENTRIES(_treeInfo))) + +#define MYBT_IS_MIN_ENTRIES(_treeInfo, _node) \ + (MYBT_IS_LEAF(_node) \ + ? ((_node)->numRecs <= MYBT_MIN_LEAF_ENTRIES(_treeInfo)) \ + : ((_node)->numRecs <= MYBT_MIN_BRANCH_ENTRIES(_treeInfo))) + +#define MYBT_IS_LESSTHAN_MAX(_treeInfo, _node, _sibling) \ + (MYBT_IS_LEAF(_node) \ + ? (((_node)->numRecs + (_sibling)->numRecs) < MYBT_MAX_LEAF_ENTRIES(_treeInfo)) \ + : (((_node)->numRecs + (_sibling)->numRecs) < MYBT_MAX_BRANCH_ENTRIES(_treeInfo))) + +/* + * Structures and defines for log records for the user b-tree. + */ + +typedef struct MYBTEntry_s +{ + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(MYBTEntry_s,data[1]) MYBTEntry_s; + +typedef struct MYBTSplit_s +{ + GUID_t internalID; + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + LONG dataLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + LONG reserved; /* to align data to 64-bit boundary */ + BYTE data[1]; /* data to move */ +#if 0 + MYBTKey_s keyForParent; /* Key to insert in the parent */ +#endif /* 0 */ +} NSS_MEDIA_STRUCTURE(MYBTSplit_s,data[1]) MYBTSplit_s; + +typedef struct MYBTGrow_s +{ + GUID_t internalID; + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(MYBTGrow_s,blockForParent) MYBTGrow_s; + +typedef struct MYBTBalance_s +{ + LONG indexForParent; /* index where entry is changed in the parent */ + LONG dataLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + WORD reserved1; /* to align data to 64-bit boundary */ + LONG reserved2; /* to align data to 64-bit boundary */ + BYTE data[1]; /* data to move */ +#if 0 + MYBTKey_s oldKey; /* previous key in the parent */ + MYBTKey_s keyForParent; /* key to insert in the parent */ +#endif /* 0 */ +} NSS_MEDIA_STRUCTURE(MYBTBalance_s,data[1]) MYBTBalance_s; + +typedef struct MYBTTreeInit_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(MYBTTreeInit_s,internalID) MYBTTreeInit_s; +/* defines for direction */ + +#define MYBT_LEFT_TO_RIGHT 0 +#define MYBT_RIGHT_TO_LEFT 1 + +/* + * Structure of log records for BTree-internal operations. + */ +typedef struct MybtInternalLog_s +{ + union + { + MYBTSplit_s split; + MYBTGrow_s grow; + MYBTBalance_s balance; + MYBTTreeInit_s initTree; + } NSS_MEDIA_UNION(NamelessUnion,balance.data[1]) u; +} NSS_MEDIA_STRUCTURE(MybtInternalLog_s,u.balance.data[1]) MybtInternalLog_s; + +/* Tree-internal operations */ +#define MYBT_RECOVERY_OP_SPLIT 0 +#define MYBT_RECOVERY_OP_JOIN 1 +#define MYBT_RECOVERY_OP_BALANCE 2 +#define MYBT_RECOVERY_OP_GROW 3 +#define MYBT_RECOVERY_OP_SHRINK 4 +#define MYBT_RECOVERY_OP_INIT 5 +#define MYBT_RECOVERY_OP_REMOVE_NODE 6 +#define MYBT_RECOVERY_MAX_INTERNAL_OPS 7 + +typedef STATUS (* MYBTInternalRecovery_f)( + struct GeneralMsg_s *genMsg, + MYBTreeInstanceInfo_s *treeInfo, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* redo routine stored at even index, undo routine at odd index */ +extern MYBTInternalRecovery_f MYBTreeInternalRecoveryFuncTable[ + 2 * MYBT_RECOVERY_MAX_INTERNAL_OPS]; +#define MYBT_CALL_INTERNAL_RECOVERY_FUNC(_genMsg, _treeInfo, _pool, _logBuf, \ + _action) \ + MYBTreeInternalRecoveryFuncTable[ \ + 2 * ((_logBuf)->ZXR_FunctionIndex - \ + (_treeInfo)->internalRecoveryStartOpCode) + \ + (((_action) == X_REDO) ? 0 : 1)] \ + (_genMsg, _treeInfo, _pool, _logBuf, _action) + +/* + * Structure of log records for BTree-interface operations. + * Tree instances can use this structure to obtain the volume ID and + * btree beast ZID during recovery. + */ +typedef struct MybtLogicalLog_s +{ + GUID_t internalVolumeID; + Zid_t btreeBeastZid; + union + { + BYTE entry[1]; + } NSS_MEDIA_UNION(NamelessUnion,entry[1]) u; +} NSS_MEDIA_STRUCTURE(MybtLogicalLog_s,u.entry[1]) MybtLogicalLog_s; + +/* Tree-interface (logical) operations */ +#define MYBT_RECOVERY_L_OP_INSERT_ENTRY 0 +#define MYBT_RECOVERY_L_OP_DELETE_ENTRY 1 +#define MYBT_RECOVERY_L_OP_MODIFY_ENTRY 2 /* reserved for future use */ +#define MYBT_RECOVERY_MAX_LOGICAL_OPS 3 + +typedef STATUS (* MYBTLogicalRecovery_f)( + struct GeneralMsg_s *genMsg, + MYBTreeInstanceInfo_s *treeInfo, + struct ZfsPool_s *pool, + struct ZfsMYBTreeBeast_s *btreeBeast, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* redo routine stored at even index, undo routine at odd index */ +extern MYBTLogicalRecovery_f MYBTreeLogicalRecoveryFuncTable[ + 2 * MYBT_RECOVERY_MAX_LOGICAL_OPS]; +#define MYBT_CALL_LOGICAL_RECOVERY_FUNC(_genMsg, _treeInfo, _pool, _beast, \ + _logBuf, _action) \ + MYBTreeLogicalRecoveryFuncTable[ \ + 2 * ((_logBuf)->ZXR_FunctionIndex - \ + (_treeInfo)->logicalRecoveryStartOpCode) + \ + (((_action) == X_REDO) ? 0 : 1)] \ + (_genMsg, _treeInfo, _pool, _beast, _logBuf, _action) + +/* + * MYBTree Interface operations. + */ +STATUS MYBT_insertEntry( + GeneralMsg_s *genMsg, + MYBTreeParms_s *parms); + +STATUS MYBT_deleteEntry ( + GeneralMsg_s *genMsg, + MYBTreeParms_s *parms); + +STATUS MYBT_lookupEntry( + GeneralMsg_s *genMsg, + MYBTreeParms_s *parms); + +STATUS MYBT_browseEntries( + GeneralMsg_s *genMsg, + MYBTreeParms_s *parms, + NINT numEntriesRequested, + BYTE *userEntries, /* out */ + NINT *numEntriesReturned); /* out */ + +STATUS MYBT_resetTree( + GeneralMsg_s *genMsg, + MYBTreeInstanceInfo_s *treeInfo, + ZfsMYBTreeBeast_s *btreeBeast, + Volume_s *volume); + +BOOL MYBT_validateNode( + MYBTreeInstanceInfo_s *treeInfo, + MYBTreeNode_s *node, + BOOL dontAssert); + +#if NSS_DEBUG IS_ENABLED +void MYBT_displayTree( + MYBTreeInstanceInfo_s *treeInfo, + ZfsMYBTreeBeast_s *ztree); + +void MYBT_displayNode( + MYBTreeInstanceInfo_s *treeInfo, + char *location, + char *nameOfBuffer, + Buffer_s *buffer); + +#endif /* NSS_DEBUG */ + +#endif /* _MYBTREE_H_ */ diff --git a/src/nwnss/zlss/nameTree.h b/src/nwnss/zlss/nameTree.h new file mode 100644 index 0000000..e02abbc --- /dev/null +++ b/src/nwnss/zlss/nameTree.h @@ -0,0 +1,247 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2007-04-18 23:26:20 +0530 (Wed, 18 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1954 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Defines the Naming B-tree's SNINTerface. + +-------------------------------------------------------------------------*/ +#ifndef _NAMETREE_H_ +#define _NAMETREE_H_ + +#define FIELD_OFFSET(_struct_, _field_) \ + ((NINT)&((_struct_ *)0)->_field_) + +#define NAMETREE_MAGIC 0x48726944 + +#ifndef _ZFSDEFS_H_ +#include +#endif /* _ZFSDEFS_H_ */ + +#ifndef _NSS_DIR_H_ +#include +#endif /* _NSS_DIR_H_ */ + +#ifndef _DLOG_H_ +#include +#endif /* _DLOG_H_ */ + +#ifndef _NSS_NODE_H_ +#include +#endif /* _NSS_NODE_H_ */ + +#define BRANCH_OVFLOW(_parms, _b_, _pb_, _pi_, _k_, _kpar_) \ + node_ovflow_insert(_parms, _b_, 0, _pb_, _pi_, _k_,0,0, _kpar_) +#define BRANCH_UFLOW(_parms, _b_, _pb_, _pi_, _kpar_) \ + node_underflow(_parms, _b_, _pb_, _pi_, _kpar_) +#define LEAF_UFLOW(_parms, _b_, _pb_, _pi_) \ + node_underflow(_parms, _b_, _pb_, _pi_, 0) + +#define OVFLOW_INSERT(_b_, _i_, _k, _blk, _ob, _dlops, _blki, _oblki, _oldl, \ + _newl) \ + ovflow_insert_common(_b_, _i_, _k, _blk, _ob, 1, _dlops, _blki, \ + _oblki_, _oldl_, _newl_) + +#define OVFLOW_REPLACE(_b_, _i_, _k, _ob, _dlops, _blki, _oblki, _oldl, _newl) \ + ovflow_insert_common(_b_, _i_, _k, 0, _ob, 1, _dlops, _blki, \ + _oblki, _oldl, _newl) +extern STATUS +ovflow_insert_common(Buffer_s *buf, node_ind_t ind, dir_key_s *newkey, + Blknum_t blk, Buffer_s *ovflow_buf, SNINT replace, + dlog_op_s **dlops, dlog_ind_t blki, dlog_ind_t ovflow_blki, + SNINT oldoff, SNINT newoff); + +extern STATUS +node_ovflow_insert(NameTreeParms_s *parms, Buffer_s **buf, + node_ind_t ind, Buffer_s **parbuf, node_ind_t *parind, dir_key_s *inskey, + BYTE *data, SNINT datasz, SNINT *key_in_par); + +extern STATUS +node_underflow( + NameTreeParms_s *parms, + Buffer_s **buf, /* inout */ + Buffer_s **parbuf, /* inout */ + node_ind_t *pind, /* inout */ + SNINT *key_in_par); /* inout */ + +STATUS +leaf_ovflow_delete( + NameTreeParms_s *parms, + Buffer_s *buf, + node_ind_t ind, + node_ind_t dupind, + Buffer_s *firstbuf, + Buffer_s *keybuf); /* Buf in which delentry was found */ + +extern STATUS +node_delete_entry( + NameTreeParms_s *parms, + Buffer_s *buf, + dir_key_s *delkey, + Zid_t *zid); /* out */ + +extern STATUS +get_sibnode(NameTreeParms_s *parms, Buffer_s *parbuf, Buffer_s *buf, + SNINT ovflow_right, node_ind_t ind, Buffer_s **sib_buf); +extern STATUS alloc_ntree_blks(NameTreeParms_s *parms, + ZfsXaction_s *xaction, NINT nblks, Buffer_s **buf); + +/* Special nearBlock values that take advantage that the + first ZLSS superblock uses blocks 0 to 15. */ +#define NT_ALLOC_GLOBAL_SEED 0 +#define NT_ALLOC_NEW_AREA 1 +extern STATUS alloc_ntree_blks2( + NameTreeParms_s *_parms, + ZfsXaction_s *_xact, + NINT nblks, + Blknum_t *nearBlocks, + Buffer_s **_buf); +extern STATUS ntree_ch_root_node(NameTreeParms_s *parms, + ZfsXaction_s *xaction, Buffer_s *oldbuf, Buffer_s *newbuf); + +/* + * The following are some wrapper functions for use by the naming B-tree + * implementation. + */ +#if NSS_DEBUG IS_ENABLED +#define FETCH_NTREE_BLK_EXCL(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_UPDATE, TRUE, _debug_id) +#define FETCH_NTREE_BLK_SHARED(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_READ, TRUE, _debug_id) +#define FETCH_NTREE_BLK_EXCL_NO_MAGIC_CHECK(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_UPDATE, FALSE, _debug_id) +#define FETCH_NTREE_BLK_SHARED_NO_MAGIC_CHECK(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_READ, FALSE, _debug_id) +#define FETCH_NTREE_BLK_DEBUG(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_NONE, TRUE, _debug_id) +#else +#define FETCH_NTREE_BLK_EXCL(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_UPDATE, TRUE) +#define FETCH_NTREE_BLK_SHARED(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_READ, TRUE) +#define FETCH_NTREE_BLK_EXCL_NO_MAGIC_CHECK(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_UPDATE, FALSE) +#define FETCH_NTREE_BLK_SHARED_NO_MAGIC_CHECK(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_READ, FALSE) +#define FETCH_NTREE_BLK_DEBUG(_parms, _b, _buf, _debug_id) \ + fetch_ntree_blk(_parms, _b, _buf, MODE_NONE, TRUE) +#endif + +#define RELEASE_NTREE_BLK_EXCL(_parms, _buf) \ + RELEASE_NTREE_BLK(_parms, _buf) +#define RELEASE_NTREE_BLK_SHARED(_parms, _buf) \ + RELEASE_NTREE_BLK(_parms, _buf) +#define RELEASE_NTREE_BLK_DIRTY(_parms, _buf_) \ + do { \ + SET_NTREE_BLK_DIRTY(_buf_); \ + RELEASE_NTREE_BLK(_parms, _buf_); \ + } while(0) + +#define NTREE_GET_ROOT_BLK(_ntree) DIR_ROOT(_ntree) + +#define NTREE_SET_ROOT_BLK(_ntree, _blknum) DIR_ROOT(_ntree) = (_blknum) + +#define MYABS(_i) (((_i) < 0) ? -(_i) : (_i)) + +/* + * Declarations for the Global Hash table data structure + * used to invalidate searchmap entries in response to Name tree operations. + */ +#define SMAP_TABLE_SIZE 31 /* The number of entries in the SMAP table */ +typedef struct valid_smap_tab_s +{ + NINT size; /* # of hash table buckets in hash array */ + DQhead_t *vst_hash; /* hash array */ +#ifdef USE_LATCH_FOR_HASH_TABLE + Latch_s latch; /* latch to control changes in this structure */ +#endif +} valid_smap_tab_s; + +extern valid_smap_tab_s valid_smap_tab; /* control head for valid SMAP hash */ + +#ifdef USE_LATCH_FOR_HASH_TABLE +#define LOCK_VALID_SMAP_TAB() X_LATCH(&valid_smap_tab.latch) +#define UNLOCK_VALID_SMAP_TAB() UNX_LATCH(&valid_smap_tab.latch) +#else +#define LOCK_VALID_SMAP_TAB() +#define UNLOCK_VALID_SMAP_TAB() +#endif + +#define ISVALID_SMAP(_smap) (SMAP_CURSOR(_smap)->leafhint != INVALID_BLK) + +extern STATUS valid_smap_tab_init(void); +extern void valid_smap_tab_uninit(void); + +extern void revalidate_smap(SearchMap_s *smap, Blknum_t leafhint, + Blknum_t ovflow_hint); +extern void invalidate_smaps(Blknum_t leafhint, Blknum_t ovflow_hint); + +/* + * Some debug routines + */ +#if ZFSNAMETREE_DEBUG /* { */ +extern void dir_dumpnode(NameTreeParms_s *parms, Buffer_s *buf); +extern STATUS dir_dump(NameTreeParms_s *parms, Blknum_t nextchild, + SNINT idx); /* Indent index */ +extern STATUS dir_ls(NameTreeParms_s *parms, Blknum_t nextchild); + +#define PRINT_FNAME(_name) \ + do { \ + char c; \ + fname_char_t *_myname = (_name); \ + while ((c = (char)(*_myname++)) != 0) { \ + DB_PRINTF((CYAN, MSGNot("%c"), c)); \ + } \ + } while (0) + +#define PRINT_SINGLE_LENTRY(_l) \ + do { \ + DB_PRINTF((CYAN, MSGNot("<[0x%Lx, "), (_l)->k.pzid)); \ + DB_PRINTF((CYAN, MSGNot("%hd, \""), (_l)->k.nameType)); \ + PRINT_FNAME((_l)->k.name); \ + DB_PRINTF((CYAN, MSGNot("\", 0x%x, ], 0x%Lx>\n"), (_l)->ns_mask, \ + (_l)->zid)); \ + zASSERT(((_l)->k.namelen & NAMEnameLenMask) == unilen((_l)->k.name)); \ + } while (0) + +#define PRINT_BENTRY(_b) \ + do { \ + DB_PRINTF((CYAN, MSGNot("[0x%Lx, "), (_b)->k.pzid)); \ + DB_PRINTF((CYAN, MSGNot("%hd, \""), (_b)->k.nameType)); \ + PRINT_FNAME((_b)->k.name); \ + DB_PRINTF((CYAN, MSGNot("\"] -> blk# %d\n"), (_b)->child_blk)); \ + zASSERT(((_b)->k.namelen & NAMEnameLenMask) == unilen((_b)->k.name)); \ + } while(0); + +#endif /* ZFSNAMETREE_DEBUG */ /* } */ + + +#endif /* _NAMETREE_H_ */ diff --git a/src/nwnss/zlss/node.h b/src/nwnss/zlss/node.h new file mode 100644 index 0000000..8cb33d2 --- /dev/null +++ b/src/nwnss/zlss/node.h @@ -0,0 +1,340 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Declares structures, macros and functions for manipulating + | Naming B-Tree nodes. + +-------------------------------------------------------------------------*/ +#ifndef _NSS_NODE_H_ +#define _NSS_NODE_H_ + +#ifndef _REPAIRMAIN_H_ +# include "repairMain.h" +#endif + +#define ISVALID_BLKNUM(_blknum) 1 +#define ISVALID_LSN(_lsn) 1 +#define ISVALID_NSMASK(_nsmask) 1 +#define ISVALID_ZID(_zid) 1 +#define ISVALID_NAME_TYPE(_nameType) 1 + + +/* + * State information about B-tree nodes. + * A node can be both a LEAF and a ROOT (for sufficiently small Btrees) + */ +#define NT_LEAF 0x1 /* Leaf node of a B-tree */ +#define NT_BRANCH 0x2 /* Branch node of a B-tree */ +#define NT_ROOT 0x4 /* Root node of a B-tree */ +#define NT_OVERFLOW 0x8 /* Overflow node (could be branch or leaf) */ +#define NT_FREE 0x10 /* Node is free */ + +#define NT_LEAF_OVFLOW (NT_LEAF|NT_OVERFLOW) /* to hold duplicate keys */ +#define NT_BRANCH_OVFLOW (NT_BRANCH|NT_OVERFLOW) + +#define IS_LEAF(_n) ((_n)->state & NT_LEAF) +#define IS_BRANCH(_n) ((_n)->state & NT_BRANCH) +#define IS_LEAF_OVFLOW(_n) \ + (((_n)->state & NT_LEAF_OVFLOW) == NT_LEAF_OVFLOW) +#define IS_BRANCH_OVFLOW(_n) \ + (((_n)->state & NT_BRANCH_OVFLOW) == NT_BRANCH_OVFLOW) +#define IS_FREE(_n) ((_n)->state & NT_FREE) +#define NT_IS_ROOT(_n) ((_n)->state & NT_ROOT) + +typedef Lsn_t blk_version_t; +typedef LONG magic_t; +typedef SLONG node_offset_t; + +/* 2005April + * Instead of a BRANCH_DATASIZE define, Sai uses sizeof(Blknum_t) directly within the code. + * LEAF_DATASIZE/BRANCH_DATASIZE must not include the node_offset_t 'size' or dir_key_s 'k' + * fields. The 'k' is variable sized so sizeof is not used on it. See ENTRYSIZE_FROM_KEY. + * Note that it is this macro that adds in the 'size' field size. Also note that + * ENTRY_ALIGN_MASK is used to align the final 'size' value to a QUADs boundary. And finally, + * NWORDS is used to make size a count of 'LONGs' and not bytes! + */ + +typedef struct Branch_s +{ + node_offset_t size; + Blknum_t child_blk; + dir_key_s k; +} NSS_MEDIA_STRUCTURE(Branch_s,k) Branch_s; + + +typedef struct Ldata_s +{ + Zid_t zid; + nsmask_t ns_mask; + BYTE matchAttributes; + BYTE miscFlags; +} Ldata_s; +//} NSS_MEDIA_STRUCTURE(Ldata_s,matchAttributes) Ldata_s; + +/* This must match the data fields in Leaf_s (see above comment dated 2005April) */ +#define LEAF_DATASIZE (sizeof(nsmask_t) + sizeof(Zid_t) + sizeof(WORD) + \ + sizeof(BYTE) + sizeof(BYTE) + sizeof(LONG)) + +typedef struct Leaf_s +{ + node_offset_t size; + nsmask_t ns_mask; + Zid_t zid; + WORD oldNameUniquifier; + BYTE matchAttributes; + BYTE miscFlags; + LONG reserved2; + dir_key_s k; +} NSS_MEDIA_STRUCTURE(Leaf_s,k) Leaf_s; + +typedef union +{ + QUAD data; + Blknum_t ovflow_blk; + LONG nduplicates; +} NSS_MEDIA_UNION(Dupinfo_s,nduplicates) Dupinfo_s; + +#define LEAF_MAX_DUPENTRY_INLINE_SIZE \ + (NODE_MAX_FREEBYTES/2 + sizeof(Dupinfo_s)) + +typedef struct Node_s +{ + magic_t magic; /* Implementation version */ + WORD state; /* Type of node */ + SWORD numRecs; /* Number of directory entries in this node */ + blk_version_t vers; /* Must be at OFFSET 8 - Generation # of this blk */ + GUID_t n_internalID; /* Must be at OFFSET 16 */ + union + { + Blknum_t ovflow_blk; /* location of overflow block */ + Blknum_t nextleaf; /* Singly linked list of Leaf nodes */ + } NSS_MEDIA_UNION(NamelessUnion,nextleaf) u; + Blknum_t child_blk; /* Leftmost child blk of a branch node */ + node_offset_t nfreebytes; /* #bytes of free space on this node */ + node_offset_t nextfree; /* Offset of next free chunk */ + BYTE padbytes[1]; +} NSS_MEDIA_STRUCTURE(Node_s,padbytes[1]) Node_s; + +#define DIR_PADSIZE (DIRBLKSIZE - FIELD_OFFSET(Node_s, padbytes)) + + +#define NODE_MAX_FREEBYTES DIR_PADSIZE + +#define OFFSETSZ sizeof(node_offset_t) +#define NWORDS(_nbytes_) ((_nbytes_) / OFFSETSZ) + +#ifndef NBITS +#define NBITS(_obj_) (sizeof(_obj_) * 8) +#endif + +#define NODE_OVFLOW(_n_) ((_n_)->u.ovflow_blk != INVALID_BLK) +#define NODE_UFLOW(_n_) ((_n_)->nfreebytes > NODE_UNDERFLOW) +#define NODE_UNDERFLOW (NODE_MAX_FREEBYTES/2) +#define NODE_FIRST(_n_) 0 +#define NODE_LEFTMOST(_n_) (NODE_FIRST(_n_) - 1) +#define NODE_LAST(_n_) ((_n_)->numRecs - 1) +#define NODE_NEXT(_n_, _ind_) ((_ind_) + 1) +#define NODE_PREV(_n_, _ind_) ((_ind_) - 1) + +#define NODE_INDARR(_n_) \ + (((node_offset_t *)(_n_)) + NWORDS(DIRBLKSIZE) - (_n_)->numRecs) +#define NODE_ENTRY(_n_, _ind_) \ + ((node_offset_t *)(&(_n_)->padbytes[NODE_INDARR(_n_)[_ind_]])) +#define BRANCH_ENTRY(_n_, _ind_) ((Branch_s *) NODE_ENTRY(_n_, _ind_)) +#define LEAF_ENTRY(_n_, _ind_) ((Leaf_s *) NODE_ENTRY(_n_, _ind_)) + +#define FREE_ENTRY_MASK ((node_offset_t) (1<<(NBITS(node_offset_t)- 1))) +#define FREE_PREVENTRY_MASK ((node_offset_t) (1<<(NBITS(node_offset_t)- 2))) +#define ENTRYSIZE_MASK ((node_offset_t) (FREE_PREVENTRY_MASK - 1)) +#define ISFREE(_e_) ((*(node_offset_t *)(_e_)) & FREE_ENTRY_MASK) +#define FREE_ENTRY_SIZE(_size_) ((_size_) | FREE_ENTRY_MASK) +#define ISFREE_PREVENTRY(_e_) \ + ((*(node_offset_t *)(_e_)) & FREE_PREVENTRY_MASK) +#define ENTRYSIZE(_e_) (ENTRYSIZE_MASK & (*(node_offset_t *)(_e_))) +#define ENTRYBYTES(_e_) (ENTRYSIZE(_e_) * OFFSETSZ) +#define BRANCH_ENTRY_SIZE(_e_) ENTRYBYTES(_e_) +#define LEAF_ENTRY_SIZE(_e_) ENTRYBYTES(_e_) + + +extern void init_node(Node_s *node, GUID_t *internalID); +extern BOOL node_findkey(Node_s *node, dir_key_s *k, node_ind_t *ind); +extern void node_ndelete(Node_s *node, node_ind_t ind, SNINT nentries); +extern void node_ncopy(Node_s *destnode, node_ind_t destind, Node_s *srcnode, + node_ind_t srcind, SNINT nentries, SNINT move); +extern void node_insert_common(Node_s *node, node_ind_t ind, dir_key_s *inskey, + BYTE *data, SNINT datasize, SNINT replace); + +extern void node_shrink_entry(Node_s *node, node_offset_t *entry, SNINT newsize); +extern void node_delete_dup(Node_s *node, Leaf_s *head, SNINT dupind); +extern void node_expand_entry(Node_s *node, node_ind_t ind, dir_key_s *inskey, + BYTE *data, SNINT datasize); + + +#if ZFSNAMETREE_DEBUG +extern STATUS node_compare(Node_s *n1, Node_s *n2, SNINT length); +extern STATUS node_validate(Node_s *node); +#define PRE_VALIDATE_NTREE_NODE(_parms, _node) \ + ((_parms)->validate_ntree_nodes ? node_validate(_node) : zOK) +#define POST_VALIDATE_NTREE_NODE(_parms, _node) \ + ((_parms)->validate_ntree_nodes ? node_validate(_node) : zOK) +#else +#define PRE_VALIDATE_NTREE_NODE(_parms, _node) ((void)0) +#define POST_VALIDATE_NTREE_NODE(_parms, _node) ((void)0) +#endif /* ZFSNAMETREE_DEBUG */ + +extern void node_blk_copy(Node_s *node, node_ind_t ind, SNINT nentries, + node_offset_t *entries, SNINT replace, SNINT isovflow); + +#define INIT_LEAF_NODE(_n_, _is_ovflow_, _internalID_) \ + do { \ + init_node(_n_,_internalID_); \ + (_n_)->u.nextleaf = INVALID_BLK; \ + (_n_)->state = NT_LEAF | ((_is_ovflow_) ? NT_OVERFLOW : 0); \ + } while(0) + +#define INIT_BRANCH_NODE(_n_, _is_ovflow_, _internalID_) \ + do { \ + init_node(_n_,_internalID_); \ + (_n_)->u.ovflow_blk = INVALID_BLK; \ + (_n_)->state = NT_BRANCH | ((_is_ovflow_) ? NT_OVERFLOW : 0); \ + } while (0) + +#define SPACE_NEEDED_ENTRY(_e_) (ENTRYBYTES(_e_) + OFFSETSZ) +#define SPACE_NEEDED_BRANCH(_e_) SPACE_NEEDED_ENTRY(_e_) +#define SPACE_NEEDED_LEAF(_e_) SPACE_NEEDED_ENTRY(_e_) + +#define ENTRY_ALIGN_MASK (sizeof(QUAD) - 1) +#define ENTRYSIZE_FROM_KEY(_k_, _datasz_) \ + ((DIR_KEY_SIZE(_k_) \ + + (_datasz_) \ + + OFFSETSZ + ENTRY_ALIGN_MASK) & ~ ENTRY_ALIGN_MASK) +#define SPACE_NEEDED_ENTRY_FROM_KEY(_k_, _datasz_) \ + (ENTRYSIZE_FROM_KEY(_k_, _datasz_) + OFFSETSZ) + +#define SPACE_NEEDED_BRANCH_FROM_KEY(_k_) \ + SPACE_NEEDED_ENTRY_FROM_KEY(_k_, sizeof(Blknum_t)) +#define SPACE_NEEDED_LEAF_FROM_KEY(_k_, _datasz_) \ + SPACE_NEEDED_ENTRY_FROM_KEY(_k_, _datasz_) + +typedef struct Ovflow_op_data_t +{ + SLONG ind; + SLONG replace; +} NSS_MEDIA_STRUCTURE(Ovflow_op_data_t,replace) Ovflow_op_data_t; + +#define OVFLOW_NRECS(_n_) ((_n_)->numRecs) +#define OVFLOW_OP_DATA_SZ \ + ((sizeof(Ovflow_op_data_t) + ENTRY_ALIGN_MASK) & ~ ENTRY_ALIGN_MASK) + +#define OVFLOW_OP_DATA(_ovflow_e_) \ + (Ovflow_op_data_t *)((BYTE *)(_ovflow_e_) + \ + BRANCH_ENTRY_SIZE(_ovflow_e_) - OVFLOW_OP_DATA_SZ) + +#define OVFLOW_ENTRY(_n_, _ovflow_i_, _ind_, _e_repl_, _entry_) \ + do { \ + Ovflow_op_data_t *_op_data_; \ + *(_entry_) = BRANCH_ENTRY(_n_, _ovflow_i_); \ + _op_data_ = OVFLOW_OP_DATA(*(_entry_)); \ + *(_ind_) = _op_data_->ind; \ + *(_e_repl_) = _op_data_->replace; \ + } while(0) + +#define OVFLOW_SET_ENTRY(_n_, _ovflow_i_, _ind_, _e_repl_) \ + do { \ + Ovflow_op_data_t *_op_data_; \ + _op_data_ = OVFLOW_OP_DATA(BRANCH_ENTRY(_n_, _ovflow_i_)); \ + _op_data_->ind = (_ind_); \ + _op_data_->replace = (_e_repl_); \ + } while(0) + +#define NODE_REPLACE(_n_, _ind_, _k_, _d_, _datasz_) \ + node_insert_common(_n_, _ind_, _k_, _d_, _datasz_, 1) +#define NODE_INSERT(_n_, _ind_, _k_, _d_, _datasz_) \ + node_insert_common(_n_, _ind_, _k_, _d_, _datasz_, 0) +#define NODE_INSERT_FIRST(_n_, _k_, _d_, _datasz_) \ + NODE_INSERT(_n_, NODE_LEFTMOST(_n_), _k_, (char *)_d_, _datasz_) +#define NODE_INSERT_LAST(_n_, _k_, _d_, _datasz_) \ + NODE_INSERT(_n_, NODE_LAST(_n_), _k_, (char *)_d_, _datasz_) +#define NODE_DELETE(_n_, _ind_) node_ndelete(_n_, _ind_, 1) + +#define MIN_KEY_SIZE \ + (FIELD_OFFSET(dir_key_s, name) + (1 + 1) * sizeof(fname_char_t)) +#define MIN_ENTRY_SIZE(_datasz) \ + (((_datasz) + MIN_KEY_SIZE + OFFSETSZ + ENTRY_ALIGN_MASK) \ + & ~ENTRY_ALIGN_MASK) + +/* node validate routines uset by verify */ +extern NINT ZV_NTkey_validate(dir_key_s *k); +extern NINT ZV_NTleafentry_validate(Leaf_s *e); +extern STATUS ZV_nameNode_validate(Node_s *node, Blknum_t blknum, VerifyStats_s *vStats, NTStats_s *NTStats, ZVP_NTData_s *ntData); + +#define ISVALID_ENTRY(_e) ((! ISFREE(_e)) && (ENTRYSIZE(_e) > 0)) +#if ZFSNAMETREE_DEBUG +#define ISVALID_LEAF_ENTRY(_l) \ + (ISVALID_ENTRY(_l) && \ + ISVALID_NSMASK((_l)->ns_mask) && \ + ISVALID_ZID((_l)->zid) && \ + key_validate(&(_l)->k) && \ + leafentry_validate(_l)) + +#define ISVALID_BRANCH_ENTRY(_b) \ + (ISVALID_ENTRY(_b) && \ + ISVALID_BLKNUM((_b)->child_blk) && \ + ((_b)->child_blk != INVALID_BLK) && \ + key_validate(&(_b)->k)) +#endif /* ZFSNAMETREE_DEBUG*/ + + + +#define ZV_ISVALID_LEAF_ENTRY(_l) \ + (ISVALID_ENTRY(_l) && \ + ISVALID_NSMASK((_l)->ns_mask) && \ + ISVALID_ZID((_l)->zid) && \ + ZV_NTkey_validate(&(_l)->k) && \ + ZV_NTleafentry_validate(_l)) + +#define ZV_ISVALID_BRANCH_ENTRY(_b) \ + (ISVALID_ENTRY(_b) && \ + ISVALID_BLKNUM((_b)->child_blk) && \ + ((_b)->child_blk != INVALID_BLK) && \ + ZV_NTkey_validate(&(_b)->k)) + + /* A Branch that may have had the LV delete code run on + * it can have the child_blk set to INVALID_BLK. + */ +#define ZV_ISVALID_DELETED_BRANCH_ENTRY(_b) \ + (ISVALID_ENTRY(_b) && \ + ISVALID_BLKNUM((_b)->child_blk) && \ + ZV_NTkey_validate(&(_b)->k)) + +#endif /* _NSS_NODE_H_ */ diff --git a/src/nwnss/zlss/purgeLog.c b/src/nwnss/zlss/purgeLog.c new file mode 100644 index 0000000..b2dde2d --- /dev/null +++ b/src/nwnss/zlss/purgeLog.c @@ -0,0 +1,2951 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) module. + | + |--------------------------------------------------------------------------- + | + | $Author: cteerlink $ + | $Date: 2007-04-25 03:45:26 +0530 (Wed, 25 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1960 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Maintain the beast purge log in the zfs storage system. + +-------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#include "guid.h" +#include "purgeLog.h" +#include "zParams.h" +#include "comnBeasts.h" +#include "comnBeastClass.h" +#include "zfs.h" +#include "xaction.h" +#include "msgIO.h" +#include "zlog.h" +#include "comnPublics.h" +#include "parse.h" +#include "zlssStartup.h" +#include "zfsXTree.h" +#include "cmNSS.h" +#include "zlssLogicalVolume.h" +#include "comnAuthorize.h" +#include "volume.h" +#include "dirQuotas.h" +#include "objectIDStore.h" +#include "eflTree.h" + +#ifdef NSS_USERSPACE +extern void abort(void); +static void +nssZlssUserspaceAbend(const char *message) +{ + (void)message; + abort(); +} +#define Abend nssZlssUserspaceAbend +#endif + +#if NSS_DEBUG IS_ENABLED + +typedef struct PurgeRec_s +{ + Blknum_t block; + NINT slot; +} PurgeRec_s; + +#define MAX_PURGE_RECS (1<<12) +PurgeRec_s PurgeRec[MAX_PURGE_RECS]; +NINT PurgeRecIndex = 0; +#define BUG_PURGE_REC(_blk, _slot) \ +{ \ + PurgeRec[PurgeRecIndex & (MAX_PURGE_RECS - 1)].block = (_blk); \ + PurgeRec[PurgeRecIndex++ & (MAX_PURGE_RECS - 1)].slot = (_slot); \ +} + +#define MAX_PURGE_BLOCKS (1<<7) +Blknum_t PurgeBlocks[MAX_PURGE_BLOCKS] = { 0 }; +NINT PurgeBlockIndex = 0; +#define BUG_PURGE_BLOCK(_blk) \ + (PurgeBlocks[PurgeBlockIndex++ & (MAX_PURGE_BLOCKS - 1)] = _blk) + + +void DisplayPurgeLogInfo2 ( + GeneralMsg_s *genMsg, + ZfsVolume_s *volume, + ZfsPurgeLogBeast_s *purgeLog ) +{ + + IoMsg_s iomsg; + Buffer_s *buffer; + Blknum_t block; + Blknum_t newBlock; + NINT slot; + NINT blockCount = 0; + NINT availCount = 0; + NINT beastDeleteCount = 0; + NINT beastCompCount = 0; + NINT truncCount = 0; + NINT blockFreeCount = 0; + NINT fixVisibCount = 0; + NINT userScanCount = 0; + NINT userFreeCount = 0; + NINT userClearCount = 0; + NINT dirFreeCount = 0; + NINT dirUsedCount = 0; + NINT epochRemoveCount = 0; + NINT resetEFLCount = 0; + PurgeLogBlock_s *pLogBlock; + PurgeBeastEntry_s *beastEntry; + TruncateEntry_s *truncEntry; + PurgeBlockEntry_s *blockEntry; + FreeEntry_s *freeEntry; + FixVisEntry_s *visibEntry; + UserClearEntry_s *userClearEntry; + UserScanEntry_s *userScanEntry; + UserEntry_s *userEntry; + DirEntry_s *dirEntry; + DirUsed_s *dirUsed; + EFLEpochRemove_s *epochRemove; + EFLTreeReset_s *resetEFL; + + if (purgeLog == NULL) + { + printf(MSGNot("Error getting the purge log beast")); + return; + } + + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* Latch the log */ + DBG_DebugPrintf(LBLUE, MSGNot("First Record = %d\n"), purgeLog->p.firstBlock); + DBG_DebugPrintf(LBLUE, MSGNot("Next Block = %d\n"), purgeLog->nextUnused.block); + DBG_DebugPrintf(LBLUE, MSGNot("Next Slot = %d\n"), purgeLog->nextUnused.slot); + + /* count the number of blocks in the purge log */ + block = purgeLog->p.firstBlock; + while(block != 0) + { + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + printf(MSGNot("Error reading block %d\n"),block); + goto errorExit; + } + + blockCount++; + newBlock = ((PurgeLogBlock_s *)buffer->pBuf.data)->nextBlock; + CACHE_RELEASE(buffer); + if (block == purgeLog->nextUnused.block) + { + break; + } + else + { + block = newBlock; + } + } + DBG_DebugPrintf(LBLUE, MSGNot("Number of blocks in log = %d\n"), blockCount); + DBG_DebugPrintf(LBLUE, MSGNot("Number of entries in log = %d\n"), + (blockCount-1) * MAX_PURGE_LOG_ENTRIES + purgeLog->nextUnused.slot); + + /* follow avail list */ + block = purgeLog->freeList.block; + slot = purgeLog->freeList.slot; + while(block != 0) + { + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + printf(MSGNot("Error reading block %d\n"),block); + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + availCount++; + block = ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->block; + slot = ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->slot; + if (pLogBlock->logEntry[slot].type != PLOG_UNUSED) + { + DBG_DebugPrintf(RED,MSGNot("Free list has an entry not marked free\n")); + } + CACHE_RELEASE(buffer); + } + DBG_DebugPrintf(LBLUE, MSGNot("Number of avail entries in log = %d\n"), availCount); + + /* + * Scan all entries in the log and report usage + */ + DBG_DebugPrintf(LBLUE, MSGNot("******* Purge Log Entries *******\n")); + availCount = 0; + block = purgeLog->p.firstBlock; + + /* process each entry in the log */ + while (block != 0) + { /* process each block until we are past the last block */ + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + printf(MSGNot("Error reading block %d\n"),block); + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + if ((block == purgeLog->nextUnused.block) && + (slot >= purgeLog->nextUnused.slot)) + { /* if past the last purge log entry - end*/ + CACHE_RELEASE(buffer); + goto done; /* done */ + } + + switch (pLogBlock->logEntry[slot].type) + { + case PLOG_UNUSED: + { + availCount++; + freeEntry = &pLogBlock->logEntry[slot].info.free; + DBG_DebugPrintf(LRED, + MSGNot("FREE Block=%d Slot=%d nextBlock=%d nextSlot=%d\n"), + block, slot, freeEntry->link.block, + freeEntry->link.slot); + break; + } + case PLOG_BEAST_DELETE: + { + beastDeleteCount++; + beastEntry = &pLogBlock->logEntry[slot].info.beast; + DBG_DebugPrintf(LBLUE, + MSGNot("BEAST Block=%d Slot=%d volumeID=%d zid=%d\n"), + block, slot, (LONG)beastEntry->volumeID.timeLow, (LONG)beastEntry->zid); + break; + } + case PLOG_TRUNCATE: + { + truncCount++; + truncEntry = &pLogBlock->logEntry[slot].info.trunc; + DBG_DebugPrintf(BLUE, + MSGNot("TRUNCATE Block=%d Slot=%d volumeID=%d zid=%d startBlock=%d len=%d\n"), + block, slot, (LONG)truncEntry->volumeID.timeLow, (LONG)truncEntry->zid, + truncEntry->startBlock, truncEntry->len); + break; + } + case PLOG_BLOCK_FREE: + { + blockFreeCount++; + blockEntry = &pLogBlock->logEntry[slot].info.block; + DBG_DebugPrintf(MAGENTA, + MSGNot("BLOCK Block=%d Slot=%d Freed block=%d\n"), + block, slot, blockEntry->blockNumber); + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + beastCompCount++; + beastEntry = &pLogBlock->logEntry[slot].info.beast; + DBG_DebugPrintf(LBLUE, + MSGNot("BEAST COMP CLEANUP Block=%d Slot=%d volumeID=%d zid=%d\n"), + block, slot, (LONG)beastEntry->volumeID.timeLow, (LONG)beastEntry->zid); + break; + } + case PLOG_FIX_VISIBILITY: + { + fixVisibCount++; + visibEntry = &pLogBlock->logEntry[slot].info.visib; + DBG_DebugPrintf(GREEN, + MSGNot("BEAST FIX VISIBILITY Block=%d Slot=%d parent zid=%d trusteeID=%d Action=%d\n"), block, slot, (LONG)visibEntry->parentZID, (LONG)visibEntry->trusteeID.timeLow, visibEntry->action); + break; + } + case PLOG_SCAN_USER_NAMES: + { + userScanCount++; + userScanEntry = &pLogBlock->logEntry[slot].info.userScan; + DBG_DebugPrintf(MAGENTA, + MSGNot("USER Block=%d Slot=%d volumeID=%Lx\n"), + block, slot, userScanEntry->volumeID); + break; + } + case PLOG_REMOVE_USER_TREE: + { + userFreeCount++; + userEntry = &pLogBlock->logEntry[slot].info.user; + DBG_DebugPrintf(MAGENTA, + MSGNot("USER Block=%d Slot=%d volumeID=%Lx\n"), + block, slot, userEntry->volumeID); + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + userClearCount++; + userClearEntry = &pLogBlock->logEntry[slot].info.userClear; + DBG_DebugPrintf(MAGENTA, + MSGNot("USER Clear Block=%d Slot=%d volumeID=%Lx\n"), + block, slot, userClearEntry->volumeID); + break; + } + case PLOG_REMOVE_DIR_TREE: + { + dirFreeCount++; + dirEntry = &pLogBlock->logEntry[slot].info.directory; + DBG_DebugPrintf(MAGENTA, + MSGNot("DIR Block=%d Slot=%d volumeID=%Lx\n"), + block, slot, dirEntry->volumeID); + break; + } + case PLOG_DIR_QUOTA_USED: + { + dirUsedCount++; + dirUsed = &pLogBlock->logEntry[slot].info.dirUsed; + DBG_DebugPrintf(MAGENTA, + MSGNot("DIR Used Block=%d Slot=%d volumeID=%Lx dirZid=%d\n"), + block, slot, dirUsed->volumeID, dirUsed->dirZid); + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + epochRemoveCount++; + epochRemove = &pLogBlock->logEntry[slot].info.epochRemove; + DBG_DebugPrintf(MAGENTA, + MSGNot("DIR Used Block=%d Slot=%d epoch=%d volumeID=%Lx\n"), + block, slot, epochRemove->epoch.clockSeqHighAndReserved & 0x1F, + epochRemove->volumeID); + break; + } + case PLOG_EFL_RESET_TREE: + { + resetEFLCount++; + resetEFL = &pLogBlock->logEntry[slot].info.resetEFL; + DBG_DebugPrintf(MAGENTA, + MSGNot("USER Block=%d Slot=%d volumeID=%Lx\n"), + block, slot, resetEFL->volumeID); + break; + } + default: + { + DBG_DebugPrintf(RED, MSGNot("Unknown record type Block=%d Slot=%d\n"), + block, slot); + } + } + } + /* catch the case where nextUnused.slot is one greater than MAX_PURGE_LOG_ENTRIES */ + if (block == purgeLog->nextUnused.block) + { + CACHE_RELEASE(buffer); + goto done; /* done */ + } + block = pLogBlock->nextBlock; + CACHE_RELEASE(buffer); + } +done: + DBG_DebugPrintf(LBLUE, MSGNot("Total free=%d Bstdels=%d Trun=%d BlkFree=%d Comp=%d TotVis=%d UsrScan=%d UsrFree=%d UsrClr=%d removeEpoch=%d resetEFL=%d Total=%d\n"), + availCount, beastDeleteCount, truncCount, blockFreeCount, + beastCompCount, fixVisibCount, userScanCount, userFreeCount, userClearCount, + epochRemoveCount, resetEFLCount, + availCount+beastDeleteCount+truncCount+blockFreeCount+beastCompCount+ + fixVisibCount+userScanCount+userFreeCount+userClearCount+epochRemoveCount+resetEFLCount); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + return; + +errorExit: + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + return; + +} + + +/**************************************************************************** + * + ****************************************************************************/ +void DisplayPurgeLogInfo ( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm) +{ + GeneralMsg_s genMsg; + ZfsVolume_s *volume; + ZfsPurgeLogBeast_s *purgeLog; + + + MPKNSS_LOCK(); + DBG_DebugPrintf(LBLUE, MSGNot("***** Purge Log Display Volume %U *****\n"), + (unicode_t *)switchDef->ret_value ); + COMN_SETUP_GENERAL_MSG_NOSA( &genMsg ); + COMN_INCLUDE_INTERNAL_VOLUMES( &genMsg ); + volume = (ZfsVolume_s *)COMN_VolumeNameLookup(&genMsg, + (unicode_t *)switchDef->ret_value,TRUE,NULL); + if (volume == NULL) + { + printf(MSGNot("Volume not found.\n")); + MPKNSS_UNLOCK(); + return; + } + + purgeLog = volume->ZFSVOLvolumePurgeLog; + DisplayPurgeLogInfo2( &genMsg, volume, purgeLog ); + + purgeLog = volume->pool->purgeLogBeast; + DBG_DebugPrintf(LBLUE, MSGNot("***** Volume's Pool Purge Log Display *****\n") ); + + DisplayPurgeLogInfo2( &genMsg, volume, purgeLog ); + + COMN_Release( &volume ); + MPKNSS_UNLOCK(); + return; + +} + + +/**************************************************************************** + * + ****************************************************************************/ +void plogValidate ( + ZfsPurgeLogBeast_s *purgeLog, + BOOL shouldBeEmpty ) /* TRUE when PLOG should be empty */ +{ + GeneralMsg_s genMsg; + IoMsg_s iomsg; + Buffer_s *buffer; + Blknum_t block; + Blknum_t newBlock; + Blknum_t prvBlock; /* Debug only */ + NINT slot; + NINT prvSlot; /* Debug only */ + NINT blockCount = 0; + NINT availCount = 0; + NINT freeCount = 0; + NINT usedCount = 0; + BOOL end = FALSE; + BOOL freeCountError = FALSE; + PurgeLogBlock_s *pLogBlock; + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + + /* count the number of blocks in the purge log */ + block = purgeLog->p.firstBlock; + while(block != 0) + { + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(&genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + + blockCount++; + newBlock = ((PurgeLogBlock_s *)buffer->pBuf.data)->nextBlock; + CACHE_RELEASE(buffer); + if (block == purgeLog->nextUnused.block) + { + break; + } + else + { + block = newBlock; + } + } + + /* follow avail list */ + block = ((ZfsPurgeLogLoc_s *)&purgeLog->freeList)->block; + slot = ((ZfsPurgeLogLoc_s *)&purgeLog->freeList)->slot; + zASSERT(slot < MAX_PURGE_LOG_ENTRIES); +// zASSERT(slot <= MAX_PURGE_LOG_ENTRIES); + while(block != 0) + { + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(&genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + freeCountError = TRUE; + CACHE_RELEASE(buffer); + break; + } + zASSERT(pLogBlock->logEntry[slot].type == PLOG_UNUSED); + if ( pLogBlock->logEntry[slot].type != PLOG_UNUSED ) + { /* If not a free block then we MUST not follow + * block list. + */ + freeCountError = TRUE; + CACHE_RELEASE(buffer); + break; + } + freeCount++; + prvBlock = block; + prvSlot = slot; + block = ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->block; + slot = ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->slot; + CACHE_RELEASE(buffer); + } + + /* + * Scan all entries in the log and report usage + */ + availCount = 0; + usedCount = 0; + block = purgeLog->p.firstBlock; + + /* process each entry in the log */ + while (block != 0) + { /* process each block until we are past the last block */ + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(&genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + if ((block == purgeLog->nextUnused.block) && + (slot >= purgeLog->nextUnused.slot)) + { /* if past the last purge log entry - end*/ + end = TRUE; + } + if (end) + { + zASSERT(pLogBlock->logEntry[slot].type == PLOG_UNUSED); + break; + } + + if (pLogBlock->logEntry[slot].type != PLOG_UNUSED) + { /* if it is not an open entry */ + usedCount++; + if ( shouldBeEmpty ) + { + zASSERT("Found an non-empty PL entry"==NULL); + } + } + else + { + availCount++; + } + } + /* catch the case where nextUnused.slot is one greater than MAX_PURGE_LOG_ENTRIES */ + if (block == purgeLog->nextUnused.block) + { + end = TRUE; + } + block = pLogBlock->nextBlock; + CACHE_RELEASE(buffer); + } + if (blockCount != 0) + { + zASSERT((availCount + usedCount) == ((blockCount - 1) * + MAX_PURGE_LOG_ENTRIES + purgeLog->nextUnused.slot)); + if ( !freeCountError ) + { + zASSERT(freeCount <= availCount); + } + } + return; + +errorExit: + zASSERT(0); + return; +} + + /* + * Validate that a particular block is in the purge log. + */ +#define PLOG_VALIDATE_BLOCK(_pLog, _blk) plogValidateBlock((_pLog), (_blk)) + +void plogValidateBlock ( + ZfsPurgeLogBeast_s *purgeLog, + Blknum_t blockToFind) +{ + GeneralMsg_s genMsg; + IoMsg_s iomsg; + Buffer_s *buffer; + Blknum_t block; + Blknum_t newBlock; + NINT blockCount = 0; + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + + block = purgeLog->p.firstBlock; + while (block != 0) + { + if (block == blockToFind) + { + return; + } + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(iomsg, 0); + buffer = ZFS_ReadPoolBlk(&genMsg, &iomsg); + if (buffer == NULL) + { + zASSERT(0); + break; + } + + blockCount++; + newBlock = ((PurgeLogBlock_s *)buffer->pBuf.data)->nextBlock; + CACHE_RELEASE(buffer); + if (block == purgeLog->nextUnused.block) + { + break; + } + else + { + block = newBlock; + } + } + zASSERT(!blockToFind); +} + +#else + +#define BUG_PURGE_REC(_blk, _slot) ((void) 0) +#define BUG_PURGE_BLOCK(_blk) ((void) 0) +#define PLOG_VALIDATE_BLOCK(_pLog, _blk) ((void) 0) + +#endif + +/**************************************************************************** + * + * This routine front ends the pool read routines and checks to make sure + * block that is read in has a valid magic number. + * + ****************************************************************************/ +Buffer_s *PLOG_ReadPoolBlk ( + GeneralMsg_s *genMsg, + IoMsg_s *iomsg) +{ + Buffer_s *buffer; + NINT magic; + + buffer = ZFS_ReadPoolBlk(genMsg, iomsg); + if ((buffer != NULL) && (iomsg->mode != CACHE_WRITE)) + { + magic = ((PurgeLogBlock_s *)buffer->pBuf.data)->magic; + if (magic != PURGE_LOG_MAGIC) + { + SetErrno(genMsg, zERR_MEDIA_CORRUPTED); + ZLSSPOOL_MediaIsCorrupt(genMsg, buffer, iomsg ); + CACHE_RELEASE(buffer); + return NULL; + } + } + return buffer; +} + + +/**************************************************************************** + * This routines sets up everything so the log can be used. This must be + * done early so that additions can be made to the log before it is played. + ****************************************************************************/ +STATUS ZFSPURGELOG_Setup ( + GeneralMsg_s *genMsg, + ZfsPurgeLogBeast_s *purgeLog) +{ + IoMsg_s iomsg; + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + NINT slot; + Blknum_t block = 0; + + if (purgeLog->p.firstBlock == 0) + { /* if the log has never been created */ + zASSERT("Purge log not found" == 0); + return zOK; + } + + /* setup the purgeLog beast */ + purgeLog->freeList.block = 0; + purgeLog->freeList.slot = 0; + + /* initialize the avail list */ + purgeLog->nextUnused.block = purgeLog->p.firstBlock; + zASSERT( purgeLog->nextUnused.block != 0 ); + while (purgeLog->nextUnused.block != 0) + { /* process each entry until we are past the last block */ + READBLK_IO_MSG(iomsg, purgeLog, purgeLog->nextUnused.block, + CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 9); + buffer = PLOG_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + return zFAILURE; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + return zFAILURE; + } + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + if (pLogBlock->logEntry[slot].type == PLOG_UNUSED) + { + pLogBlock->logEntry[slot].info.free.link.block + = purgeLog->freeList.block; + pLogBlock->logEntry[slot].info.free.link.slot + = purgeLog->freeList.slot; + purgeLog->freeList.block = purgeLog->nextUnused.block; + purgeLog->freeList.slot = slot; + } + } + block = purgeLog->nextUnused.block; /* save the old block number */ + purgeLog->nextUnused.block = pLogBlock->nextBlock; + CACHE_DIRTY_RELEASE(buffer); + } + + zASSERT(block != 0); + purgeLog->nextUnused.block = block; + purgeLog->nextUnused.slot = MAX_PURGE_LOG_ENTRIES; + return zOK; +} + +/**************************************************************************** + * Play the purge log. Called during system recovery. It assumes the + * system structures have been restored. + ****************************************************************************/ +STATUS ZFSVOL_PlayPurgeLog ( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + ZfsPurgeLogBeast_s *purgeLog, + NINT mode ) +{ + STATUS status; + ZfsPool_s *zfsPool; + ZlssPool_s *zlssPool; + + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(CYAN,MSGNot("CVS@ZFSVOL_PlayPurgeLog\n"))); + zlssPool = (ZlssPool_s *)(zfsVol->ZFSVOLvol.v_pool); + zASSERT( zlssPool != NULL ); + zASSERT( zlssPool->ZLSSPOOLzfsPool != NULL ); + zfsPool = zlssPool->ZLSSPOOLzfsPool; + /** + * Now for more gross LV AIPU code. In the first few steps + * of upgrading to LVs the volume purge log does not exist. + * Therefore it is wise to check for this condition and skip + * playing the log. Note that STEP 2A of LV ZIPU creates + * the volume purge log for the pool. + */ + if ( purgeLog == NULL ) + { + LONG version; + + version = zfsPool->ZP_super->SB_Header.hdr.SBH_VersionMediaMajor * 0x100L + + zfsPool->ZP_super->SB_Header.hdr.SBH_VersionMediaMinor; + + if ( version < (AIPU_LV_MEDIA_MAJOR*0x100L+AIPU_LV_STEP_PVPL_DONE) ) + { /* Media still may not have Volume Purge Log */ + return( zOK ); + } + else + { +// return( zOK ); + SetErrno(genMsg, zERR_MEDIA_CORRUPTED ); + return( zFAILURE ); + } + } + /** + * Back to normal code. Just call the standard play back code + * suppling the Volume Purge Log as the log to play. We also must + * supply the Volume that the purge log is on. + */ + status = ZFSPOOL_PlayPurgeLog( genMsg, zfsPool, zfsVol, purgeLog, mode ); + return( status ); +} + +/**************************************************************************** + * Play the purge log. Called during system recovery. It assumes the + * system structures have been restored. + ****************************************************************************/ +STATUS ZFSPOOL_PlayPurgeLog ( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsVolume_s *zfsVol, /* LV */ + ZfsPurgeLogBeast_s *purgeLog, /* Can be Pool purge log OR Volume + * purge log. The ZID is used to + * indicate which purge we are playing. + */ + NINT mode ) +{ + Volume_s *volume = &zfsVol->ZFSVOLvol; + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + PurgeBeastEntry_s *beastEntry; + TruncateEntry_s *truncEntry; + FixVisEntry_s *visibEntry; + NINT slot; + Blknum_t block; + Blknum_t nextBlock; + RootBeast_s *beast = NULL; + ZfsXaction_s *xaction; + ZfsXasRecovery_s *logBuffer; + BlockInfo_s *poolBlks; + LogPurgeLog_s *logRecord; + Extent_s extent; + BOOL beastIsLatched; + NINT savedRestartCount; + typedef struct PLStats_s { + NINT PLS_numBeastDeletes; + NINT PLS_numBeastCompCleanups; + NINT PLS_numBlockDeletes; + NINT PLS_numTruncates; + NINT PLS_numFixVisib; + NINT PLS_numScanUser; + NINT PLS_numRemoveUser; + NINT PLS_numClearUser; + NINT PLS_numRemoveDirTree; + NINT PLS_numDirQuotaUsed; + NINT PLS_numEpochRemove; + NINT PLS_numResetEFL; + } PLStats_s; + SQUAD usedAmount; + SQUAD amountUsed; + SQUAD quota; + ZfsPurgeLogLoc_s location; + STATUS status; + BOOL allowedInactive; /* State of genMsg ALLOW_INACTIVE_VOLUME + * bit used to be able to reset bit + * back to orginal state. + */ +#if LOG_TEST IS_ENABLED + Lsn_t holdLsn; +#endif + typedef struct Stack_s { + IoMsg_s iomsg; + PLStats_s stats; + } Stack_s; + STACK_ALLOC(); + bzero( &aStack->stats, sizeof(aStack->stats) ); + + ENTER(TPLOG, ZFSPOOL_PlayPurgeLog); + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(CYAN,MSGNot("CVS@ZFSPOOL_PlayPurgeLog\n") )); + allowedInactive = genMsg->flags & ALLOW_INACTIVE_VOLUME; + genMsg->flags |= ALLOW_INACTIVE_VOLUME; + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* Latch the log */ + /* We now use the Volume's activation count instead of the global + * RestartCount. We do this because we stopped doing restart + * count setting when in MAINTENANCE mode. + */ +// savedRestartCount = pool->zfsLogBeast->ZLB_P.ZLBP_RecoveryActivationCount; + savedRestartCount = zfsVol->ZFSVOLactivationCount; + + block = purgeLog->p.firstBlock; + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(NSS_POOL_COLOR, MSGNot(" ** ")); + } + /* process each entry in the log */ + while (block != 0) + { /* process each entry until we are past the last block */ + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(NSS_POOL_COLOR, MSGNot(".")); + } + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + /* + * This read must be done inside the loop because the buffer cannot + * be kept locked. It causes the purge log transactions to not + * home. This causes the truncate log entries to build up and + * fill the log. + */ + beastIsLatched = FALSE; + READBLK_IO_MSG(aStack->iomsg, purgeLog, block, CACHE_READ); + SET_DEBUG_ID(aStack->iomsg, 10); + buffer = PLOG_ReadPoolBlk(genMsg, &aStack->iomsg); + if (buffer == NULL) + { + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(NSS_POOL_COLOR, MSGNot("\n")); + } + if ( !allowedInactive ) + { + genMsg->flags &= ~ALLOW_INACTIVE_VOLUME; + } + STACK_FREE(); + RTN_STATUS(zFAILURE); + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + nextBlock = pLogBlock->nextBlock; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(NSS_POOL_COLOR, MSGNot("\n")); + } + if ( !allowedInactive ) + { + genMsg->flags &= ~ALLOW_INACTIVE_VOLUME; + } + STACK_FREE(); + RTN_STATUS(zFAILURE); + } + if (pLogBlock->logEntry[slot].generation >= savedRestartCount) + { /* the log record was inserted during the playing of the log -- ignore it*/ +#if NSS_DEBUG IS_ENABLED + if (pLogBlock->logEntry[slot].type != PLOG_UNUSED) + { /* We do not display UNUSED info as it is bogus anyway */ + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot("PL generation %d while volume is %d so skipping Purge Log Blk:%d Slot:%d type:%d\n"), + pLogBlock->logEntry[slot].generation, + savedRestartCount, + block, slot, pLogBlock->logEntry[slot].type)); + } +#endif + CACHE_RELEASE(buffer); + goto next; + } + +#if NSS_DEBUG IS_ENABLED + if (pLogBlock->logEntry[slot].type != PLOG_UNUSED) + { + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot("Processing Purge Log Blk:%d Slot:%d type:%d\n"), + block, slot, pLogBlock->logEntry[slot].type)); + } +#endif + /* release the lock, but keep the buffer around */ + CACHE_PIN(buffer); + CACHE_RELEASE(buffer); + + /* Check the record type and take the appropriate action */ + switch (pLogBlock->logEntry[slot].type) + { + case PLOG_UNUSED: + { /* entry is unused -- skip it */ + buffer = PLOG_ReadPoolBlk(genMsg, &aStack->iomsg); /* latch the buffer again */ + if(buffer == NULL) + { + Abend("PLOG_ReadPoolBlk returned null pointer to a previously pinned buffer.\n"); + } + CACHE_UNPIN(buffer); + CACHE_RELEASE(buffer); + goto next; + break; + } + + case PLOG_BEAST_DELETE: + { /* a beast is being deleted */ + aStack->stats.PLS_numBeastDeletes++; + beastEntry = &pLogBlock->logEntry[slot].info.beast; + DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, + MSGNot("BEAST DELETE - Zid=%d\n"), + (LONG)beastEntry->zid)); + + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + /* get the beast to remove */ + beast = BEASTHASH_LookupByZid(genMsg, volume, beastEntry->zid, + NOTLATCHED); + if (beast != NULL) + { + /* beast has not been deleted -- delete it */ + /* remove data streams and extended attributes, + * and do any necessary salvage system maintenance */ + if (COMN_IsDerivedFrom(beast,zFTYPE_FILE)) + { + genMsg->flags |= ALLOW_INACTIVE_VOLUME; + if (BST_cleanupDeletedFile(genMsg,beast,TRUE,FALSE) != zOK) + { + /* Ignore errors, but do an assert if debug */ + zASSERT(0); + ClearErrno(genMsg); + } + } + + X_LATCH(&beast->ROOTbeastLatch); + beastIsLatched = TRUE; + + if (CM_COMPRESSION_ENABLED(beast->ROOTvolume)) + { + if (CM_prepareToTruncateFile(genMsg, beast, TRUE) != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + } + + /* + * The state is set to purging so that the directory + * quota routine will know not to adjust for these + * blocks. They have already been done during + * the original beast delete. + */ + beast->bstState |= BST_STATE_PURGING; + + /* remove all blocks from the beast*/ + if (beast->ROOTcomnOps.BST_truncateFile(genMsg, beast, 0, -1) + != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + +/*------------------------------------------------------------------------- + * Ensure that any mycache items are written and then TOSS the mycache. + * Most LSS will already have a clean mycache. ZLSS does not because + * it can not TOSS indirect blocks because they have to be written to handle + * 'dirty read' problem as it relates to REDO/UNDO and letting home + * move to soon. + *-------------------------------------------------------------------------*/ + beast->bstState |= BST_STATE_FLUSHING; + cacheFlushMyCacheBufs(&beast->ROOTmycache); + UNX_LATCH(&beast->ROOTbeastLatch); + defaultFlushWait(&beast->ROOTmycache.agent); + cacheTossAll(&beast->ROOTmycache); + X_LATCH(&beast->ROOTbeastLatch); + zASSERT(beast->useCount == 1); + + + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + + if (beast->ROOTcomnVolOps.VOL_removeBeastFromVolume(genMsg, + beast, &xaction->xaction) != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + + status = VOL_insertEFLEntry (genMsg, beast, + EFL_FILE_STATE_DELETE_FILE, NULL, + &xaction->xaction); + + zASSERT(status == zOK); + ClearErrno(genMsg); + + /* Remove any directory quota entries */ + status = beast->ROOTcomnVolOps.VOL_removeDirectory( + genMsg, beast->ROOTvolume, &xaction->xaction, + beast->zid); + if (status != zOK) + { + status = GetErrno(genMsg); + if (status != zERR_DIR_QUOTAS_NOT_ENABLED && + status != zERR_NO_SUCH_DIR) + { + zASSERT("Problem removing directory quota in purge log" == 0); + } + ClearErrno(genMsg); + } + } + else + { + ClearErrno(genMsg); + beastIsLatched = FALSE; + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + } + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_TRUNCATE: + { + aStack->stats.PLS_numTruncates++; + truncEntry = &pLogBlock->logEntry[slot].info.trunc; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("Zid=%d startBlock=%d len=%d/n"), + (LONG)truncEntry->zid, truncEntry->startBlock, truncEntry->len)); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + /* get the beast to remove */ + beast = BEASTHASH_LookupByZid(genMsg, volume, + truncEntry->zid, XLATCHED); + if (beast != NULL) + { + beastIsLatched = TRUE; + + if ((truncEntry->startBlock == 0) && + (truncEntry->len == -1) && + CM_COMPRESSION_ENABLED(beast->ROOTvolume)) + { + if (CM_prepareToTruncateFile(genMsg, beast, TRUE) + != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + } + if (beast->ROOTcomnOps.BST_truncateFile(genMsg, beast, + truncEntry->startBlock, truncEntry->len) != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + +/*------------------------------------------------------------------------- + * Ensure that any mycache items are written and then TOSS the mycache. + * Most LSS will already have a clean mycache. ZLSS does not because + * it can not TOSS indirect blocks because they have to be written to handle + * 'dirty read' problem as it relates to REDO/UNDO and letting home + * move to soon. + *-------------------------------------------------------------------------*/ + beast->bstState |= BST_STATE_FLUSHING; + cacheFlushMyCacheBufs(&beast->ROOTmycache); + UNX_LATCH(&beast->ROOTbeastLatch); + defaultFlushWait(&beast->ROOTmycache.agent); + cacheTossAll(&beast->ROOTmycache); + X_LATCH(&beast->ROOTbeastLatch); + zASSERT(beast->useCount == 1); + + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + } + else + { + ClearErrno(genMsg); + beastIsLatched = FALSE; + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + } + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_BLOCK_FREE: + { + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot(" PLOG_BLOCK_FREE block %ld(0x%lx)\n"), + pLogBlock->logEntry[slot].info.block.blockNumber, + pLogBlock->logEntry[slot].info.block.blockNumber)); + aStack->stats.PLS_numBlockDeletes++; + beastIsLatched = FALSE; + xaction = BeginXLocal(/*ZLSS_POOL_TO_VOLUME(pool)*/&zfsVol->ZFSVOLvol, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + extent.lengthOfExtent = 1; + extent.poolBlkNum = + pLogBlock->logEntry[slot].info.block.blockNumber; + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + zfsFreeExtent(genMsg, /*&pool->ZFSPOOLzfsVol*/zfsVol, &extent, xaction); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { /* a beast's compression state is being cleaned up */ + ++aStack->stats.PLS_numBeastCompCleanups; + beastEntry = &pLogBlock->logEntry[slot].info.beast; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("BEAST COMP CLEANUP - Zid=%d\n"), (LONG)beastEntry->zid)); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + /* get the beast to remove */ + beast = BEASTHASH_LookupByZid(genMsg, volume, beastEntry->zid, + NOTLATCHED); + if (beast != NULL) + { + zASSERT(beast->useCount == 1); + + X_LATCH(&beast->ROOTbeastLatch); + if (CM_cleanupBeast(genMsg, beast, 0) != zOK) + { + zASSERT(0); + ClearErrno(genMsg); + } + + beast->bstState |= BST_STATE_FLUSHING; + cacheFlushMyCacheBufs(&beast->ROOTmycache); + UNX_LATCH(&beast->ROOTbeastLatch); + defaultFlushWait(&beast->ROOTmycache.agent); + cacheTossAll(&beast->ROOTmycache); + X_LATCH(&beast->ROOTbeastLatch); + + beastIsLatched = TRUE; + } + else + { + ClearErrno(genMsg); + beastIsLatched = FALSE; + } + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_FIX_VISIBILITY: + { + aStack->stats.PLS_numFixVisib++; + beastIsLatched = FALSE; + zASSERT( volume == &zfsVol->ZFSVOLvol ); + + visibEntry = &pLogBlock->logEntry[slot].info.visib; + +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("BEAST FIX VISIB - Parent Zid=%d Trustee ID=%d Action=%d\n"),(LONG)visibEntry->parentZID, (LONG)visibEntry->trusteeID.timeLow, visibEntry->action)); + + /* unlatch the log so new records can be logged */ + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); + + location.block = block; + location.slot = slot; + if (ZAS_FixVisibility( genMsg, visibEntry->action, + volume, visibEntry->parentZID, + &visibEntry->trusteeID, + &location) != zOK ) + { +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf(LRED,MSGNot("%s Error setter is %s and error code is %ld\n"), WHERE, GetErrnoSetter(genMsg), GetErrno(genMsg) ); +#endif + aprintf(LRED, MSG("Error fixing visibility of trustees that were being added or removed when the system crashed\n", 883)); + if (GetErrno(genMsg) == zERR_UNABLE_TO_OPEN_BEAST) + { + ClearErrno(genMsg); + goto needToRemoveEntry; + } + ClearErrno(genMsg); + } + /* This entry in the purgelog was removed by + * Fix_visibility, so do not start a transaction + */ + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch log*/ + buffer = PLOG_ReadPoolBlk(genMsg, &aStack->iomsg); + if(buffer == NULL) + { + Abend("PLOG_ReadPoolBlk returned null pointer to a previously pinned buffer.\n"); + } + CACHE_UNPIN(buffer); + CACHE_RELEASE(buffer); + goto next; +needToRemoveEntry: + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_SCAN_USER_NAMES: + { + aStack->stats.PLS_numScanUser++; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("SCAN USER NAMES - VolID=%Lx\n"), + pLogBlock->logEntry[slot].info.userScan.volumeID)); + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + OID_InitObjectInfo(genMsg, volume); + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_REMOVE_USER_TREE: + { + aStack->stats.PLS_numRemoveUser++; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("REMOVE USER TREE - VolID=%Lx\n"), + pLogBlock->logEntry[slot].info.user.volumeID)); + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + VOL_ChangeUserSpaceAttribute(genMsg, volume, FALSE); + volume->VOLcomnVolOps.VOL_resetAllObjects(genMsg, volume); + OID_InvalidateObjectIDCache(volume); + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + aStack->stats.PLS_numClearUser++; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("CLEAR USER TREE USED AMOUNT- VolID=%Lx\n"), + pLogBlock->logEntry[slot].info.userClear.volumeID)); + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + VOL_ChangeUserSpaceAttribute(genMsg, volume, FALSE); + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_REMOVE_DIR_TREE: + { +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("REMOVE DIR TREE - VolID=%Lx\n"), + pLogBlock->logEntry[slot].info.directory.volumeID)); + aStack->stats.PLS_numRemoveDirTree++; + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + DIRQ_ChangeDirQuotaAttribute(genMsg, volume, FALSE); + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + case PLOG_DIR_QUOTA_USED: + { +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("DIR USED AMOUNT - VolID=%Lx zid=%Ld\n"), + pLogBlock->logEntry[slot].info.dirUsed.volumeID, + pLogBlock->logEntry[slot].info.dirUsed.dirZid)); + aStack->stats.PLS_numDirQuotaUsed++; + zASSERT(volume == (Volume_s *)zfsVol); + + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + DIRQ_ComputeUsedAmount(volume, + pLogBlock->logEntry[slot].info.dirUsed.dirZid, + &amountUsed, FALSE); + + if (amountUsed >= 0) + { + /* If the amount is good then make any needed adjustment */ + + if (volume->VOLcomnVolOps.VOL_getDirQuotaInfo(genMsg, + volume, + pLogBlock->logEntry[slot].info.dirUsed.dirZid, + "a, &usedAmount) != zOK) + { + zASSERT("Problem getting dir quota used amount" == 0); + errPrintf(WHERE, Module, 1469, + MSG("Unable to get used amount in dir quota, status=%d.\n", + 113), GetErrno(genMsg)); + usedAmount = 0; + } + + amountUsed -= usedAmount; + + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + volume->VOLcomnVolOps.VOL_adjustUsedDirSpace( + &xaction->xaction, volume, + pLogBlock->logEntry[slot].info.dirUsed.dirZid, + amountUsed); + } + else + { + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + } + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + aStack->stats.PLS_numEpochRemove++; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("REMOVE EFL EPOCH- VolID=%Lx epoch = %d\n"), + pLogBlock->logEntry[slot].info.epochRemove.volumeID, pLogBlock->logEntry[slot].info.epochRemove.epoch)); + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + + if (eflRemoveEpoch(genMsg, volume, + &pLogBlock->logEntry[slot].info.epochRemove.epoch) != zOK) + { +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf(LRED,MSGNot("%s Error setter is %s and error code is %ld\n"), WHERE, GetErrnoSetter(genMsg), GetErrno(genMsg) ); +#endif + aprintf(LRED, MSG("Error removing epoch that is being processed when the system crashed\n", 582)); + ClearErrno(genMsg); + } + + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* latch the log so new records can be logged */ + + break; + } + case PLOG_EFL_RESET_TREE: + { + aStack->stats.PLS_numResetEFL++; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (CYAN, MSGNot("REMOVE EFL TREE - VolID=%Lx\n"), + pLogBlock->logEntry[slot].info.resetEFL.volumeID)); + zASSERT(volume == (Volume_s *)zfsVol); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log so new records can be logged */ + volume->VOLcomnVolOps.VOL_resetEFL(genMsg, volume); + xaction = BeginXLocal(volume, BXL_DEFAULT|X_CF_OK_TO_THROTTLE); + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* relatch the log */ + break; + } + default: + { + zASSERT("Unknown purge log record type" == 0); + buffer = PLOG_ReadPoolBlk(genMsg, &aStack->iomsg); /* latch the buffer again */ + if(buffer == NULL) + { + Abend("PLOG_ReadPoolBlk returned null pointer to a previously pinned buffer.\n"); + } + CACHE_UNPIN(buffer); + CACHE_RELEASE(buffer); + goto next; + break; + } + } + + aStack->iomsg.mode = CACHE_UPDATE; + buffer = PLOG_ReadPoolBlk(genMsg, &aStack->iomsg); /* latch the buffer again - exclusive*/ + if(buffer == NULL) + { + Abend("PLOG_ReadPoolBlk returned null pointer to a previously pinned buffer.\n"); + } + CACHE_UNPIN(buffer); + + /* log the deletion */ + ZLOG_ObtainRecord(xaction, ZLOG_BLOCK_INFO_SIZE(1) + + sizeof(LogPurgeLog_s)); + ZLOG_INIT_LOG_RECORD(XFUNC_PLOG_DELETE, xaction, logBuffer, 1, + poolBlks, logRecord); + ZLOG_ASSIGN_BLOCK_INFO(poolBlks[0], block, pLogBlock->lsn, buffer, + xaction, 0); /* old block number */ +#if LOG_TEST IS_ENABLED + holdLsn = logBuffer->ZXR_Lsn; +#else + pLogBlock->lsn = logBuffer->ZXR_Lsn; +#endif + + logRecord->slot = slot; + logRecord->entry = pLogBlock->logEntry[slot]; + + ZLOG_BIND(xaction, buffer); + ZLOG_TEST_REDO(xaction); + ZLOG_ReleaseRecordAndLogEnd(xaction); +#if LOG_TEST IS_ENABLED + pLogBlock->lsn = holdLsn; +#endif + EndXlocal(xaction); + + /* fill in the purged record and put it on the avail list*/ + pLogBlock->logEntry[slot].type = PLOG_UNUSED; + ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->block + = purgeLog->freeList.block; + ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->slot + = purgeLog->freeList.slot; + purgeLog->freeList.block = block; + purgeLog->freeList.slot = slot; + +// /* +// * uplatch the buffer to make changes -- it is shared while +// * doing the truncates so the transactions can be homed. +// */ +// UP_LATCH(&buffer->agent.latch); + pLogBlock->logEntry[slot].type = PLOG_UNUSED; + + /* release the beast beasts */ + if (beastIsLatched) + { + UNX_LATCH(&beast->ROOTbeastLatch); + BST_releaseAndFree(beast); + } + /* + * Release the cache block from the purge log. It cannot be kept + * locked because it causes the purge log transactions not to + * home. This causes the trucate transactions to pile up. + */ + CACHE_DIRTY_RELEASE(buffer); +next: + continue; + } + block = nextBlock; + } + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(NSS_POOL_COLOR, MSGNot("\n")); + } + +// This code does not modify Purgelog, so it is not necessary to mark +// it dirty. Flushing it on a timer can cause a situation that we have +// 30 threads waiting for the purgelog Latch while the purgelog flush +// is waiting for a thread. +// COMN_MARK_BEAST_DIRTY(&purgeLog->ZFSPURGELOGroot); +#if NSS_DEBUG IS_ENABLED + /* March 29, 2000 - The purge log needs to be empty for + * Logical Volume(LV) Auto-in-place-upgrade(AIPU) to be + * able run successfully. LV AIPU counts blocks and move + * system beast so it can not have these beasts being used. + * We will properly be forced to ensure this BEFORE six-pack + * zlss runs. Either with a media 34 NSS or ZLSS. + * + * WARNING - currently we do not ensure this. For example, + * if a beast delete causes a b-tree join or shrink then there + * will be a purge log entry for the system block free. + */ +// plogValidate( purgeLog, TRUE ); /* Validate that PL is EMPTY */ + VALIDATE_PLOG(purgeLog); +#endif + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ +#if NSS_DEBUG IS_ENABLED + if ( mode & VOLMODE_VERBOSE ) + { + aprintf(CYAN, + MSGNot(" Beast deletes: %d Beast truncates: %d Block frees: %d\n" + " Compress clean: %d Visiblity fix: %d Remove user tree: %d\n" + " Clear user tree: %d Remove dir tree: %d Compute used amount: %d\n" + " Scan user tree: %d Epoch Remove: %d Reset EFL tree: %d\n"), + aStack->stats.PLS_numBeastDeletes, + aStack->stats.PLS_numTruncates, + aStack->stats.PLS_numBlockDeletes, + aStack->stats.PLS_numBeastCompCleanups, + aStack->stats.PLS_numFixVisib, + aStack->stats.PLS_numRemoveUser, + aStack->stats.PLS_numClearUser, + aStack->stats.PLS_numRemoveDirTree, + aStack->stats.PLS_numDirQuotaUsed, + aStack->stats.PLS_numScanUser, + aStack->stats.PLS_numEpochRemove, + aStack->stats.PLS_numResetEFL); + } +#endif + if ( !allowedInactive ) + { + genMsg->flags &= ~ALLOW_INACTIVE_VOLUME; + } + STACK_FREE(); + RTN_STATUS(zOK); + +} + +/**************************************************************************** + * Init a new purge log block + * + ****************************************************************************/ +void ZFSVOL_InitPurgeLogBlock ( + Buffer_s *buffer, + GUID_t *internalID) +{ + PurgeLogBlock_s *pLogBlock; + NINT slot; + + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + + pLogBlock->magic = PURGE_LOG_MAGIC; + pLogBlock->nextBlock = 0; + pLogBlock->lsn = 0; + zASSERT( LB_GUIDValidate( internalID ) ); + pLogBlock->plb_internalID = *internalID; + for(slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { + pLogBlock->logEntry[slot].type = PLOG_UNUSED; + } +} + + +/**************************************************************************** + * + * Add an entry to to the purge log + * + ****************************************************************************/ +STATUS ZFSVOL_VOL_AddPurgeLogEntry ( + GeneralMsg_s *genMsg, + Volume_s *volume, + NINT type, /* input: the type of entry being added */ + PurgeLogMsg_s *purgeMsg, /* input: the actual information to be logged */ + Xaction_s *xAction) +{ + NINT slot; + Buffer_s *buffer; + Blknum_t newBlock; + IoMsg_s iomsg; + ZfsXasRecovery_s *logBuffer; + BlockInfo_s *poolBlks; + LogPurgeLog_s *logRecord; + PurgeLogBlock_s *pLogBlock; + ZfsPurgeLogBeast_s *purgeLog; + ZfsXaction_s *xaction; + ZfsPurgeLogLoc_s *location = NULL; + NINT retryCount; + + ENTER(TPLOG, ZFSVOL_AddPurgeLogEntry); + + zASSERT(!(volume->VOLenabledAttributes & zATTR_READONLY)); + + retryCount = 0; + xaction = (ZfsXaction_s *)xAction; + + switch (type) + { + /* These are the purge log records that are handled by + * the VOLUME Purge Log. + */ + case PLOG_BLOCK_FREE: + case PLOG_BEAST_COMP_CLEANUP: + case PLOG_BEAST_DELETE: + case PLOG_TRUNCATE: + case PLOG_FIX_VISIBILITY: + case PLOG_SCAN_USER_NAMES: + case PLOG_REMOVE_USER_TREE: + case PLOG_CLEAR_USED_AMOUNT: + case PLOG_REMOVE_DIR_TREE: + case PLOG_DIR_QUOTA_USED: + case PLOG_EFL_REMOVE_EPOCH: + case PLOG_EFL_RESET_TREE: + { + purgeLog = ((ZfsVolume_s *)volume)->ZFSVOLvolumePurgeLog; + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot("*** *** Add Purge Log (VOLUME) operation %d ***\n"), + type)); +// zASSERT( purgeLog != NULL ); + if ( purgeLog == NULL ) + { /** + * This code is here just in case someone calls this + * routine during LV AIPU before the volume purge logs + * are created. + */ + purgeLog = ((ZfsVolume_s *)volume)->pool->ZFSPOOLpurgeLogBeast; + zASSERT( purgeLog != NULL ); + if ( purgeLog == NULL ) + { + SetErrno( genMsg, zERR_MISSING_BEAST ); + return( zFAILURE ); + } + } + break; + } +#if 0 + /* These are the purge log records that are handled by + * the POOL Purge Log. + */ + case PLOG_BLOCK_FREE: + { + purgeLog = ((ZfsVolume_s *)volume)->pool->ZFSPOOLpurgeLogBeast; + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot("*** *** Add Purge Log (POOL) operation %d *****\n") + ,type)); + zASSERT( purgeLog != NULL ); + break; + } +#endif + default: + { + zASSERT("Bad purge log record type" == 0); + SetErrno( genMsg, zERR_NOT_SUPPORTED ); + return( zFAILURE ); + } + } + + +tryAgain: + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* Latch the log */ + + if (purgeLog->p.firstBlock == 0) + { /* if the log has never been created */ + zASSERT("Purge log not found" == 0); + goto errorExit; + } + /* log is already there */ + VALIDATE_PLOG(purgeLog); + if (purgeLog->freeList.block == 0) + { /* if the free list is empty */ + READBLK_IO_MSG(iomsg, purgeLog, purgeLog->nextUnused.block, CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 11); + buffer = PLOG_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + goto errorExit; + } + slot = purgeLog->nextUnused.slot++; + + if (slot >= MAX_PURGE_LOG_ENTRIES) + { /* if the block is full then get a new block */ + if (pLogBlock->nextBlock != 0) + { /* if there is another block allocated read it */ + newBlock = pLogBlock->nextBlock; + CACHE_RELEASE(buffer); + READBLK_IO_MSG(iomsg, purgeLog, newBlock, CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 12); + buffer = PLOG_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + goto errorExit; + } + purgeLog->nextUnused.block = buffer->volBlk; /* point to new block */ + purgeLog->nextUnused.slot = 1; /* init pointer to next free slot */ + slot = 0; + } + else + { /* need to add a block to the file */ + /* Start a new transaction */ + LogPurgeLogGrow_s *growLogRecord; + PurgeLogBlock_s *newLogBlock; + Buffer_s *newBuffer; + ZfsXaction_s *localXaction; + Buffer_s *spBuf; + + localXaction = BeginXLocal(volume, BXL_DEFAULT); + XALLOCBLK_IO_MSG( iomsg, purgeLog, localXaction, CACHE_UPDATE); + newBuffer = ZFS_AllocPoolBlkSpecial(genMsg, &iomsg, &spBuf); + if (newBuffer == NULL) + { + EndXlocal(localXaction); + if (++retryCount >= 10) + { + goto errorBufferRelease; + } + ClearErrno(genMsg); + purgeLog->nextUnused.slot--; + CACHE_RELEASE(buffer); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + LB_delay(100); + goto tryAgain; + } + + newBlock = newBuffer->volBlk; /* block number for the new block */ + pLogBlock->nextBlock = newBlock; /* link the new block to the old one */ + BUG_PURGE_BLOCK(newBlock); + + newLogBlock = (PurgeLogBlock_s *)newBuffer->pBuf.data; + zASSERT( LB_GUIDValidate( &purgeLog->ZFSPURGELOGroot.ROOTvolumeID ) ); + ZFSVOL_InitPurgeLogBlock(newBuffer, + &purgeLog->ZFSPURGELOGroot.ROOTinternalID); + purgeLog->nextUnused.block = newBlock; /* point to new block */ + purgeLog->nextUnused.slot = 1; /* init pointer to next free slot */ + + /* log the grow record */ + ZLOG_ObtainRecord(localXaction, + ZLOG_BLOCK_INFO_SIZE(2) + sizeof(LogPurgeLogGrow_s)); + ZLOG_INIT_LOG_RECORD(XFUNC_PLOG_GROW, localXaction, logBuffer, 2, + poolBlks, growLogRecord); + ZLOG_ASSIGN_BLOCK_INFO(poolBlks[0], buffer->volBlk, + pLogBlock->lsn, buffer, localXaction, 0); /* old block number */ + ZLOG_ASSIGN_BLOCK_INFO(poolBlks[1], newBlock, + newLogBlock->lsn, newBuffer, localXaction, 1); + pLogBlock->lsn = logBuffer->ZXR_Lsn; + newLogBlock->lsn = logBuffer->ZXR_Lsn; + growLogRecord->lplg_internalID = + purgeLog->ZFSPURGELOGroot.ROOTinternalID; + + ZLOG_BIND(localXaction, buffer); + ZLOG_BIND(localXaction, newBuffer); + + ZLOG_ReleaseRecord(localXaction); + EndXlocal(localXaction); + CACHE_DIRTY_RELEASE(spBuf); + CACHE_DIRTY_RELEASE(buffer); + /* Switch over to new block */ + buffer = newBuffer; + pLogBlock = newLogBlock; + slot = 0; +DEBUG_PRINTF(TPLOG, DBG_NOINDENT, (GREEN, MSGNot("PLOG -- added a new block (%d) to the log\n"), buffer->volBlk)); + } + } + } + else + { /* get the entry from the free list */ + READBLK_IO_MSG(iomsg, purgeLog, purgeLog->freeList.block, CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 13); + buffer = PLOG_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + goto errorExit; + } + slot = purgeLog->freeList.slot; + purgeLog->freeList.block = + pLogBlock->logEntry[slot].info.free.link.block; + purgeLog->freeList.slot = + pLogBlock->logEntry[slot].info.free.link.slot; + } + + /* add the entry to the log */ + pLogBlock->logEntry[slot].type = type; +// pLogBlock->logEntry[slot].generation = RestartCount; +// pLogBlock->logEntry[slot].generation = +// xaction->ZX_zlogBeast->ZLB_P.ZLBP_RecoveryActivationCount; + pLogBlock->logEntry[slot].generation = ((ZfsVolume_s *)volume)->ZFSVOLactivationCount; + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot(" Activation count is %d\n"), + ((ZfsVolume_s *)volume)->ZFSVOLactivationCount)); + switch (type) + { + case PLOG_BEAST_DELETE: + { + pLogBlock->logEntry[slot].info.beast.volumeID = + purgeMsg->beast.beast->vol.volume->VOLvolumeID; + zASSERT(purgeMsg->beast.beast->zid != 0); + pLogBlock->logEntry[slot].info.beast.zid = + purgeMsg->beast.beast->zid; + if (purgeMsg->beast.dirBeast != NULL) + { + zASSERT(purgeMsg->beast.dirBeast->zid != 0); + pLogBlock->logEntry[slot].info.beast.dirZid = + purgeMsg->beast.dirBeast->zid; + } + else + { + pLogBlock->logEntry[slot].info.beast.dirZid = zINVALID_ZID; + } + location = &purgeMsg->beast.beast->storage.zfsInfo->deletePurgeLogLoc; + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + pLogBlock->logEntry[slot].info.beast.volumeID = + purgeMsg->beast.beast->vol.volume->VOLvolumeID; + zASSERT(purgeMsg->beast.beast->zid != 0); + zASSERT(purgeMsg->beast.dirBeast == NULL); + pLogBlock->logEntry[slot].info.beast.zid = + purgeMsg->beast.beast->zid; + pLogBlock->logEntry[slot].info.beast.dirZid = zINVALID_ZID; + location = &purgeMsg->beast.beast->storage.zfsInfo->compCleanupPurgeLogLoc; + break; + } + case PLOG_TRUNCATE: + { + pLogBlock->logEntry[slot].info.trunc.volumeID = + purgeMsg->trunc.beast->vol.volume->VOLvolumeID; + pLogBlock->logEntry[slot].info.trunc.zid = + purgeMsg->trunc.beast->zid; + pLogBlock->logEntry[slot].info.trunc.startBlock = + purgeMsg->trunc.startBlock; + pLogBlock->logEntry[slot].info.trunc.len = purgeMsg->trunc.len; + location = &purgeMsg->trunc.beast->storage.zfsInfo->purgeLogLoc; + break; + } + case PLOG_BLOCK_FREE: + { + pLogBlock->logEntry[slot].info.block.blockNumber = + purgeMsg->block.blockNumber; + location = purgeMsg->block.purgeLogLoc; + break; + } + case PLOG_FIX_VISIBILITY: + { + pLogBlock->logEntry[slot].info.visib.action = + purgeMsg->visib.action; + pLogBlock->logEntry[slot].info.visib.trusteeID = + *(purgeMsg->visib.trusteeID); + pLogBlock->logEntry[slot].info.visib.parentZID = + purgeMsg->visib.parentZID; + location = purgeMsg->visib.purgeLogLoc; + break; + } + case PLOG_SCAN_USER_NAMES: + { + pLogBlock->logEntry[slot].info.userScan.volumeID = + purgeMsg->userScan.volume->VOLvolumeID; + location = purgeMsg->userScan.purgeLogLoc; + break; + } + case PLOG_REMOVE_USER_TREE: + { + pLogBlock->logEntry[slot].info.user.volumeID = + purgeMsg->user.volume->VOLvolumeID; + location = purgeMsg->user.purgeLogLoc; + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + pLogBlock->logEntry[slot].info.userClear.volumeID = + purgeMsg->userClear.volume->VOLvolumeID; + location = purgeMsg->userClear.purgeLogLoc; + break; + } + case PLOG_REMOVE_DIR_TREE: + { + pLogBlock->logEntry[slot].info.directory.volumeID = + purgeMsg->directory.volume->VOLvolumeID; + location = purgeMsg->directory.purgeLogLoc; + break; + } + case PLOG_DIR_QUOTA_USED: + { + pLogBlock->logEntry[slot].info.dirUsed.volumeID = + purgeMsg->dirUsed.volume->VOLvolumeID; + pLogBlock->logEntry[slot].info.dirUsed.dirZid = + purgeMsg->dirUsed.dirZid; + location = purgeMsg->dirUsed.purgeLogLoc; + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + pLogBlock->logEntry[slot].info.epochRemove.volumeID = + purgeMsg->epochRemove.volume->VOLvolumeID; + pLogBlock->logEntry[slot].info.epochRemove.epoch = + *(purgeMsg->epochRemove.epoch); + location = purgeMsg->epochRemove.purgeLogLoc; + break; + } + case PLOG_EFL_RESET_TREE: + { + pLogBlock->logEntry[slot].info.resetEFL.volumeID = + purgeMsg->resetEFL.volume->VOLvolumeID; + location = purgeMsg->resetEFL.purgeLogLoc; + break; + } + } + /* log the insertion */ + ZLOG_ObtainRecord(xaction, ZLOG_BLOCK_INFO_SIZE(1) + sizeof(LogPurgeLog_s)); + ZLOG_INIT_LOG_RECORD(XFUNC_PLOG_INSERT, xaction, logBuffer, 1, + poolBlks, logRecord); + ZLOG_ASSIGN_BLOCK_INFO(poolBlks[0], buffer->volBlk, pLogBlock->lsn, buffer, + xaction, 0); /* block number */ + pLogBlock->lsn = logBuffer->ZXR_Lsn; + + logRecord->slot = slot; + logRecord->entry = pLogBlock->logEntry[slot]; + + ZLOG_BIND(xaction, buffer); + ZLOG_ReleaseRecord(xaction); + + BUG_PURGE_REC(buffer->volBlk, slot); + + /* make sure it's empty */ + zASSERT( (location->block == 0) || (location->block == INVALID_BLK) ); + location->block = buffer->volBlk; + location->slot = slot; + +#if NSS_DEBUG IS_ENABLED + switch (type) + { + case PLOG_BEAST_DELETE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Beast Delete) -- inserted zid %d in %d:%d\n"), + (LONG)purgeMsg->beast.beast->zid, location->block, location->slot)); + break; + } + case PLOG_TRUNCATE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Beast Truncate) -- inserted zid %d in %d:%d\n"), + (LONG)purgeMsg->trunc.beast->zid, location->block, location->slot)); + break; + } + case PLOG_BLOCK_FREE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Block Free) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Beast Comp Cleanup) -- inserted zid %d in %d:%d\n"), + (LONG)purgeMsg->beast.beast->zid, location->block, location->slot)); + break; + } + case PLOG_FIX_VISIBILITY: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Fix Visibility) -- inserted parent zid %d in %d:%d\n"), + (LONG)purgeMsg->visib.parentZID, location->block, location->slot)); + break; + } + case PLOG_SCAN_USER_NAMES: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Scan User Names) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_REMOVE_USER_TREE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Remove User Tree) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Clear User Tree) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_REMOVE_DIR_TREE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Remove Directory Tree) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_DIR_QUOTA_USED: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Directory Tree Used Amount) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Remove EFL epoch) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + case PLOG_EFL_RESET_TREE: + { + DEBUG_PRINTF(TPLOG, DBG_INDENT, (LGREEN, MSGNot("PLOG (Reset EFL Tree) -- inserted block %d in %d:%d\n"), + (LONG)purgeMsg->block.blockNumber, location->block, location->slot)); + break; + } + } +#endif + + CACHE_DIRTY_RELEASE(buffer); + VALIDATE_PLOG(purgeLog); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + +//DEBUG_PRINTF(TPLOG, DBG_INDENT,(GREEN, MSGNot(" next unused = %d:%d\n"), +// purgeLog->nextUnused.block, purgeLog->nextUnused.slot)); + RTN_STATUS(zOK); + +errorBufferRelease: + CACHE_RELEASE(buffer); +errorExit: +// zASSERT(0); + switch (type) + { + case PLOG_BEAST_DELETE: + { + location = + &purgeMsg->beast.beast->storage.zfsInfo->deletePurgeLogLoc; + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + location = + &purgeMsg->beast.beast->storage.zfsInfo->compCleanupPurgeLogLoc; + break; + } + case PLOG_TRUNCATE: + { + location = &purgeMsg->trunc.beast->storage.zfsInfo->purgeLogLoc; + break; + } + case PLOG_BLOCK_FREE: + { + location = purgeMsg->block.purgeLogLoc; + break; + } + case PLOG_FIX_VISIBILITY: + { + location = purgeMsg->visib.purgeLogLoc; + break; + } + case PLOG_SCAN_USER_NAMES: + { + location = purgeMsg->userScan.purgeLogLoc; + break; + } + case PLOG_REMOVE_USER_TREE: + { + location = purgeMsg->user.purgeLogLoc; + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + location = purgeMsg->userClear.purgeLogLoc; + break; + } + case PLOG_REMOVE_DIR_TREE: + { + location = purgeMsg->directory.purgeLogLoc; + break; + } + case PLOG_DIR_QUOTA_USED: + { + location = purgeMsg->dirUsed.purgeLogLoc; + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + location = purgeMsg->epochRemove.purgeLogLoc; + break; + } + case PLOG_EFL_RESET_TREE: + { + location = purgeMsg->resetEFL.purgeLogLoc; + break; + } + } + location->block = 0; + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + RTN_STATUS(zFAILURE); +} + +/**************************************************************************** + * + * Remove an entry from the purge log + * + ****************************************************************************/ +STATUS ZFSVOL_VOL_RemovePurgeLogEntry ( + GeneralMsg_s *genMsg, + Volume_s *volume, + NINT type, /* input: the type of entry being removed */ + PurgeLogMsg_s *purgeMsg, /* input: the information to find the log entry */ + Xaction_s *xAction) +{ + NINT slot; + Buffer_s *buffer; + IoMsg_s iomsg; + ZfsXasRecovery_s *logBuffer; + BlockInfo_s *poolBlks; + LogPurgeLog_s *logRecord; + PurgeLogBlock_s *pLogBlock; + ZfsPurgeLogBeast_s *purgeLog; + ZfsXaction_s *xaction; + ZfsPurgeLogLoc_s *location; +#if LOG_TEST IS_ENABLED + Lsn_t holdLsn; +#endif + FreePurgeLogEntries_s *pLogEntry; + + ENTER(TPLOG, ZFSVOL_RemovePurgeLogEntry); + zASSERT(!(volume->VOLenabledAttributes & zATTR_READONLY)); + + switch (type) + { + /* These are the purge log records that are handled by + * the VOLUME Purge Log. + */ + case PLOG_BEAST_COMP_CLEANUP: + case PLOG_BEAST_DELETE: + case PLOG_TRUNCATE: + case PLOG_BLOCK_FREE: + case PLOG_FIX_VISIBILITY: + case PLOG_SCAN_USER_NAMES: + case PLOG_REMOVE_USER_TREE: + case PLOG_CLEAR_USED_AMOUNT: + case PLOG_REMOVE_DIR_TREE: + case PLOG_DIR_QUOTA_USED: + case PLOG_EFL_REMOVE_EPOCH: + case PLOG_EFL_RESET_TREE: + { + purgeLog = ((ZfsVolume_s *)volume)->ZFSVOLvolumePurgeLog; + DEBUG_PRINTF(TPLOG,DBG_NOINDENT,(CYAN, + MSGNot("*** *** Remove Purge Log (VOLUME) operation %d ***\n"), + type)); + zASSERT( purgeLog != NULL ); + if ( purgeLog == NULL ) + { /** + * This code is here just in case someone calls this + * routine during LV AIPU before the volume purge logs + * are created. + */ + purgeLog = ((ZfsVolume_s *)volume)->pool->ZFSPOOLpurgeLogBeast; + zASSERT( purgeLog != NULL ); + if ( purgeLog == NULL ) + { + SetErrno( genMsg, zERR_MISSING_BEAST ); + return( zFAILURE ); + } + } + break; + } + /* These are the purge log records that are handled by + * the POOL Purge Log. + */ +#if 0 + case PLOG_BLOCK_FREE: + { + purgeLog = ((ZfsVolume_s *)volume)->pool->ZFSPOOLpurgeLogBeast; +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf( CYAN, "*** *** Remove Purge Log (POOL) operation %d *****\n",type); +#endif + zASSERT( purgeLog != NULL ); + break; + } +#endif + default: + { + zASSERT("Bad purge log record type" == 0); + SetErrno( genMsg, zERR_NOT_SUPPORTED ); + return( zFAILURE ); + } + } + + xaction = (ZfsXaction_s *)xAction; + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* Latch the log */ + VALIDATE_PLOG(purgeLog); + + /* get the location of the purge log record to be deleted */ + switch (type) + { + case PLOG_BEAST_DELETE: + { + location = &purgeMsg->beast.beast->storage.zfsInfo->deletePurgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + location = &purgeMsg->beast.beast->storage.zfsInfo->compCleanupPurgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_FIX_VISIBILITY: + { + location = purgeMsg->visib.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_TRUNCATE: + { + location = &purgeMsg->trunc.beast->storage.zfsInfo->purgeLogLoc; + break; + } + case PLOG_BLOCK_FREE: + { + location = purgeMsg->block.purgeLogLoc; + break; + } + case PLOG_SCAN_USER_NAMES: + { + location = purgeMsg->userScan.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_REMOVE_USER_TREE: + { + location = purgeMsg->user.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + location = purgeMsg->userClear.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_REMOVE_DIR_TREE: + { + location = purgeMsg->directory.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_DIR_QUOTA_USED: + { + location = purgeMsg->dirUsed.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + location = purgeMsg->epochRemove.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + case PLOG_EFL_RESET_TREE: + { + location = purgeMsg->resetEFL.purgeLogLoc; + PLOG_VALIDATE_BLOCK(purgeLog, location->block); + break; + } + default: + { + zASSERT("Bad purge log record type in delete" == 0); + SetErrno( genMsg, zERR_BAD_PARAMETER_VALUE ); + goto errorExitNoLocation; + } + } + + if (location->block == 0) + { + SetErrno( genMsg, zERR_INVALID_STATE ); + goto errorExit; + } + + READBLK_IO_MSG(iomsg, purgeLog, location->block, CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 14); + buffer = PLOG_ReadPoolBlk(genMsg, &iomsg); + if (buffer == NULL) + { + goto errorExit; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_MEDIA_CORRUPTED ); + goto errorExit; + } + slot = location->slot; + +#if NSS_DEBUG IS_ENABLED + switch (type) + { + case PLOG_BEAST_DELETE: + { + zASSERT(purgeMsg->beast.beast->zid == pLogBlock->logEntry[slot].info.beast.zid); + break; + } + case PLOG_BEAST_COMP_CLEANUP: + { + zASSERT(purgeMsg->beast.beast->zid == pLogBlock->logEntry[slot].info.beast.zid); + break; + } + case PLOG_TRUNCATE: + { + zASSERT(purgeMsg->trunc.beast->zid == pLogBlock->logEntry[slot].info.trunc.zid); + break; + } + case PLOG_FIX_VISIBILITY: + { + zASSERT(purgeMsg->visib.parentZID == pLogBlock->logEntry[slot].info.visib.parentZID); + break; + } + case PLOG_BLOCK_FREE: + { + break; + } + case PLOG_SCAN_USER_NAMES: + { + break; + } + case PLOG_REMOVE_USER_TREE: + { + break; + } + case PLOG_CLEAR_USED_AMOUNT: + { + break; + } + case PLOG_REMOVE_DIR_TREE: + { + break; + } + case PLOG_DIR_QUOTA_USED: + { + break; + } + case PLOG_EFL_REMOVE_EPOCH: + { + break; + } + case PLOG_EFL_RESET_TREE: + { + break; + } + default: + { + zASSERT("Bad purge log record type in delete check" == 0); + } + } + +// zASSERT(beast->zid == pLogBlock->logEntry[slot].u.entry.zid); +#endif + + /* log the deletion */ + ZLOG_ObtainRecord(xaction, ZLOG_BLOCK_INFO_SIZE(1) + sizeof(LogPurgeLog_s)); + ZLOG_INIT_LOG_RECORD(XFUNC_PLOG_DELETE, xaction, logBuffer, 1, + poolBlks, logRecord); + ZLOG_ASSIGN_BLOCK_INFO(poolBlks[0], buffer->volBlk, pLogBlock->lsn, buffer, + xaction, 0); /* old block number */ +#if LOG_TEST IS_ENABLED + holdLsn = logBuffer->ZXR_Lsn; /* this is done so the lsn is ok for testing */ +#else + pLogBlock->lsn = logBuffer->ZXR_Lsn; +#endif + + logRecord->slot = slot; + logRecord->entry = pLogBlock->logEntry[slot]; + + ZLOG_BIND(xaction, buffer); + ZLOG_TEST_REDO(xaction); + ZLOG_ReleaseRecord(xaction); +#if LOG_TEST IS_ENABLED + pLogBlock->lsn = holdLsn; +#endif + + /* fill in the purged record and put it on the avail list*/ + pLogBlock->logEntry[slot].type = PLOG_UNUSED; + + pLogEntry = objCacheAlloc(&PLogFreeEntry); + + COMN_USE_BEAST(&purgeLog->ZFSPURGELOGroot); + pLogEntry->purgeLog = purgeLog; + pLogEntry->location.block = location->block; + pLogEntry->location.slot = location->slot; + DQ_ENQ(&xaction->freePurgeLogEntries, pLogEntry, xactionLink); + +DEBUG_PRINTF(TPLOG, DBG_INDENT, (GREEN, MSGNot("PLOG -- removed entry from %d:%d\n"), + location->block, location->slot)); + location->block = 0; /* indicate this field is no longer in use */ + + CACHE_DIRTY_RELEASE(buffer); + VALIDATE_PLOG(purgeLog); + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + RTN_STATUS(zOK); + +errorExit: + +#if NSS_DEBUG IS_ENABLED + location->block = INVALID_BLK; +#endif + +errorExitNoLocation: + UNX_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* unlatch the log */ + RTN_STATUS(zFAILURE); +} + +void PLOG_PutEntryOnFreeList( + FreePurgeLogEntries_s *pLogEntry) +{ + ZfsPurgeLogBeast_s *purgeLog = pLogEntry->purgeLog; + NINT slot = pLogEntry->location.slot; + Blknum_t block = pLogEntry->location.block; + Buffer_s *buffer; + IoMsg_s iomsg; + PurgeLogBlock_s *pLogBlock; + GeneralMsg_s genMsg; + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + + X_LATCH(&purgeLog->ZFSPURGELOGbeastLatch); /* latch the log */ + + READBLK_IO_MSG(iomsg, purgeLog, block, CACHE_UPDATE); + SET_DEBUG_ID(iomsg, 14); + buffer = PLOG_ReadPoolBlk(&genMsg, &iomsg); + if (buffer == NULL) + { + goto cleanupAndReturn; + } + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + zASSERT( pLogBlock->magic == PURGE_LOG_MAGIC ); + if ( pLogBlock->magic != PURGE_LOG_MAGIC ) + { + CACHE_RELEASE(buffer); + goto cleanupAndReturn; + } + + ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->block = + purgeLog->freeList.block; + ((ZfsPurgeLogLoc_s *)&pLogBlock->logEntry[slot].info.free.link)->slot = + purgeLog->freeList.slot; + purgeLog->freeList.block = block; + purgeLog->freeList.slot = slot; + + CACHE_DIRTY_RELEASE(buffer); + +cleanupAndReturn: + /* An extra use count was put on the purgelog beast when this entry was + * linked on the xaction. + */ + objCacheFree(pLogEntry); + COMN_UnlatchAndRelease(&purgeLog, XLATCHED); + return; +} + + +/*---------------------------------------------------------------------------*/ +/**************************************************************************** + * + * Recovery routines + * + ****************************************************************************/ + +/**************************************************************************** + * Recovery routine for initing the purge log + ****************************************************************************/ +//STATUS recoveryPurgeLogInit( +// GeneralMsg_s *genMsg, +// ZfsPool_s *pool, +// ZfsXasRecovery_s *logBuffer, +// NINT action) +//{ +// Buffer_s *buffer; +// PurgeLogBlock_s *pLogBlock; +// IoMsg_s iomsg; +// BlockInfo_s *poolBlks; +// +// poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); +// +// if (ZLOG_VALID_BLOCK(poolBlks[0])) +// { +// READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) +// if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) +// { +// zASSERT(0); +// return zFAILURE; +// } +// +// /* init the block */ +// pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; +// pLogBlock->nextBlock = 0; +// +// ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); +// CACHE_DIRTY_RELEASE(buffer); +// } +// return zOK; +//} +// +///**************************************************************************** +// * Recovery routine for uniniting the purge log (undo for init) +// ****************************************************************************/ +//STATUS recoveryPurgeLogUninit( +// GeneralMsg_s *genMsg, +// ZfsPool_s *pool, +// ZfsXasRecovery_s *logBuffer, +// NINT action) +//{ +// Buffer_s *buffer; +// IoMsg_s iomsg; +// BlockInfo_s *poolBlks; +// +// poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); +// +// if (ZLOG_VALID_BLOCK(poolBlks[0])) +// { +// /* make sure the cache block for the deleted block is gone */ +// READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) +// if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) != NULL) +// { +// cacheReleaseToss(buffer); +// } +// } +// return zOK; +//} + +/**************************************************************************** + * Recovery routine for growing the purge log + ****************************************************************************/ +STATUS recoveryPurgeLogGrow( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + LogPurgeLogGrow_s *logRecord; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* restore the previous end record of the log */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + zASSERT(0); + return zFAILURE; + } + + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + if (ZLOG_ALREADY_DONE(pool, logBuffer, pLogBlock->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { + pLogBlock->nextBlock = poolBlks[1].blkNum; /* link the new block to the old one */ + BUG_PURGE_BLOCK(poolBlks[1].blkNum); + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* restore the new end record of the log */ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_WRITE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + zASSERT(0); + return zFAILURE; + } + + zASSERT( LB_GUIDValidate( &logRecord->lplg_internalID ) ); + ZFSVOL_InitPurgeLogBlock(buffer, &logRecord->lplg_internalID); + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[1], action); + CACHE_DIRTY_RELEASE(buffer); + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for shrinking the purge log (undo for grow) + ****************************************************************************/ +STATUS recoveryPurgeLogShrink( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + /* restore the previous end record of the log */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + zASSERT(0); + return zFAILURE; + } + + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + if (ZLOG_ALREADY_DONE(pool, logBuffer, pLogBlock->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { + pLogBlock->nextBlock = 0; /* mark as the end of the list */ + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); + CACHE_DIRTY_RELEASE(buffer); + } + } + + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + /* make sure the cache block for the deleted block is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_WRITE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { + cacheReleaseToss(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for inserting into the purge log (undo for remove) + ****************************************************************************/ +STATUS recoveryPurgeLogInsert( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + LogPurgeLog_s *logRecord; +// NINT slot; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + zASSERT(0); + return zFAILURE; + } + +//DBG_DebugPrintf(RED, MSGNot("REDO - Purge Log Insert. block:%d\n"),poolBlks[0].blkNum); + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + if (ZLOG_ALREADY_DONE(pool, logBuffer, pLogBlock->lsn, action)) + { +//DBG_DebugPrintf(LRED, MSGNot(" Already done.\n")); + CACHE_RELEASE(buffer); + } + else + { + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + if (pLogBlock->logEntry[logRecord->slot].type == PLOG_UNUSED) + { /* if the original entry is open then use it */ +//DBG_DebugPrintf(LRED, MSGNot(" Inserting in the same slot:%d type=%d\n"), +// logRecord->slot, logRecord->entry.type); + pLogBlock->logEntry[logRecord->slot] = logRecord->entry; + } + else + { /* find an open entry */ + zASSERT("PurgeLog Recovery - Bad slot" == NULL); /* This should no longer happen */ +#if 1 + /* Dec 2002 - Vandana wanted to return an error + * verses just using the slot. Greg wanted to + * just use the slot, but he owned Vandana a + * favor. This code can be tested with the ZSB + * files from incident 2835342 (you must also + * apply the new.zsb so that all of the journal is + * played. Greg has all related information on a CD. + */ + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_RECOVERY_SLOT_IN_USE ); + return( zFAILURE ); +// pLogBlock->logEntry[logRecord->slot] = logRecord->entry; +#else + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + if (pLogBlock->logEntry[slot].type == PLOG_UNUSED) + { /* if it is an open entry */ +//DBG_DebugPrintf(LRED, MSGNot(" Inserting in a new slot:%d type=%d\n"), slot, +// logRecord->entry.type); + pLogBlock->logEntry[slot] = + logRecord->entry; + break; + } + } + zASSERT(slot < MAX_PURGE_LOG_ENTRIES); /* we better find an entry */ +#endif + } + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); + CACHE_DIRTY_RELEASE(buffer); + } + } +//DBG_DebugPrintf(RED, MSGNot("End purge log insert redo\n")); + return zOK; +} + +/**************************************************************************** + * Recovery routine for deleting from the purge log (undo for insert) + ****************************************************************************/ +STATUS recoveryPurgeLogRemove( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + LogPurgeLog_s *logRecord; +// NINT slot; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + SET_DEBUG_ID(iomsg, 0); + if ((buffer = PLOG_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + zASSERT(0); + return zFAILURE; + } + + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + if (ZLOG_ALREADY_DONE(pool, logBuffer, pLogBlock->lsn, action)) + { +//DBG_DebugPrintf(RED, MSGNot(" Already done.\n")); + CACHE_RELEASE(buffer); + } + else + { + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + if (memcmp(&logRecord->entry, &pLogBlock->logEntry[logRecord->slot], + sizeof(PurgeLogEntry_s)) == 0) + { /* if the slot is still the correct record then delete it */ +//DBG_DebugPrintf(RED, MSGNot(" Removing from the same slot:%d\n"),logRecord->slot); + pLogBlock->logEntry[logRecord->slot].type = PLOG_UNUSED; + } + else + { /* find the entry to be deleted */ + zASSERT("PurgeLog Recovery - Bad slot" == NULL); /* This should no longer happen */ +#if 1 + CACHE_RELEASE(buffer); + SetErrno( genMsg, zERR_RECOVERY_SLOT_MISMATCH ); + return( zFAILURE ); +// pLogBlock->logEntry[logRecord->slot].type = PLOG_UNUSED; +#else + for (slot = 0; slot < MAX_PURGE_LOG_ENTRIES; slot++) + { /* process each entry in the block */ + if (memcmp(&logRecord->entry, &pLogBlock->logEntry[slot], + sizeof(PurgeLogInfo_s)) == 0) + { /* if the slot is the correct record then delete it */ +//DBG_DebugPrintf(RED, MSGNot(" Removing from a new slot:%d\n"),slot); + pLogBlock->logEntry[slot].type = PLOG_UNUSED; + break; + } + } + zASSERT(slot < MAX_PURGE_LOG_ENTRIES); /* we better find an entry */ +#endif + } + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); + CACHE_DIRTY_RELEASE(buffer); + } + } + return zOK; +} + + +/*=========================================================================== + *=========================================================================== + *=========================================================================== + * + * ZFSPURGELOG BEAST + * + *=========================================================================== + *=========================================================================== + *===========================================================================*/ + +/**************************************************************************** + * ZFSPURGELOG COMMON BEAST OPERATIONS definition + *****************************************************************************/ + +/*--------------------------------------------------------------------------- + * Defines all of the ZFS purge log beast operations + *---------------------------------------------------------------------------*/ +CommonBeastOps_s ZFSPURGELOG_ComnBeastOps = +{ + NULL, /* construct */ + NULL, /* destruct */ + +// cnt NULL, /* BST_getNameUniquifier */ + NULL, /* BST_setupNameTypeSpecificInfo */ + NULL, /* BST_lookupByNameInDirectory*/ + NULL, /* BST_isDirectoryEmpty*/ + NULL, /* BST_addNameToDirectory*/ + NULL, /* BST_removeNameFromDirectory*/ + NULL, /* BST_modifyNameSpaceMaskInDirectory*/ + NULL, /* BST_setMatchAttributesInDirectory*/ + NULL, /* BST_wildcardLookup*/ + + NULL, /* BST_truncateFile*/ + NULL, /* BST_getStorageInfo*/ + NULL, /* BST_getExtentList*/ + NULL, /* BST_getPhysicalExtent*/ + NULL, /* BST_isBlockInBeast*/ + + NULL, /* BST_asyncReadFileBlk*/ + NULL, /* BST_getFileBlk*/ + NULL, /* BST_dfsReadUnits*/ + NULL, /* BST_dfsWriteUnits*/ + + NULL, /* BST_getZID*/ + NULL, /* BST_beastNotify*/ + NULL, /* BST_getInfo*/ + NULL /* BST_modifyInfo*/ +}; + + +/**************************************************************************** + * EXTENT BASED storage pack routine + *****************************************************************************/ +STATIC NINT ZFSPURGELOG_PackedSize( + void *beast_LX) +{ + return sizeof(PersistentZfsPurgeLog_s); +} + +/**************************************************************************** + * EXTENT BASED storage pack routine + *****************************************************************************/ +STATIC BYTE *ZFSPURGELOG_Pack( + void *beast_LX, + BYTE *storeBuffer) +{ + ZfsPurgeLogBeast_s *beast = (ZfsPurgeLogBeast_s *)beast_LX; + + memcpy(storeBuffer,&beast->p,sizeof(PersistentZfsPurgeLog_s)); + return (storeBuffer + sizeof(PersistentZfsPurgeLog_s)); +} + +/**************************************************************************** + * EXTENT BASED storage pack routines + *****************************************************************************/ +STATIC BYTE *ZFSPURGELOG_Unpack( + GeneralMsg_s *genMsg, + void *beast_LX, + BYTE *storeBuffer) +{ + ZfsPurgeLogBeast_s *beast = (ZfsPurgeLogBeast_s *)beast_LX; + + memcpy(&beast->p,storeBuffer,sizeof(PersistentZfsPurgeLog_s)); + return (storeBuffer + sizeof(PersistentZfsPurgeLog_s)); +} + +/*--------------------------------------------------------------------------- + * file beast STORAGE ops definition + *---------------------------------------------------------------------------*/ +LSSSpecificPackUnpackOps_s ZFSPURGELOG_lssOps[] = +{ + {zLSS_ID_ZLSS,ZFSPURGELOG_PackedSize,ZFSPURGELOG_Pack,NULL,ZFSPURGELOG_Unpack}, + {zLSS_ID_INVALID} +}; + + +/**************************************************************************** + * Recovery routine for initing the purge log first block + ****************************************************************************/ +STATUS recoveryPurgeLogInit( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeLogBlock_s *pLogBlock; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + LogPurgeLogGrow_s *logRecord; + + zASSERT( logBuffer->ZXR_FunctionIndex == XFUNC_LV_PL_INIT ); + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + buffer = ZFS_ReadPoolBlk(genMsg, &iomsg); + zASSERT( buffer != NULL ); + + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + zASSERT( LB_GUIDValidate( &logRecord->lplg_internalID ) ); + ZFSVOL_InitPurgeLogBlock(buffer, &logRecord->lplg_internalID); + pLogBlock = (PurgeLogBlock_s *)buffer->pBuf.data; + + ZLOG_SET_LSN(logBuffer, pLogBlock->lsn, poolBlks[0], action); + CACHE_DIRTY_RELEASE(buffer); + + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for uniniting the purge log first block (undo for init) + ****************************************************************************/ +STATUS recoveryPurgeLogUninit( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + zASSERT( logBuffer->ZXR_FunctionIndex == XFUNC_LV_PL_INIT ); + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + /* make sure the cache block for the deleted block is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + if ((buffer = ZFS_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { + cacheReleaseToss(buffer); + } + } + return zOK; +} diff --git a/src/nwnss/zlss/purgeLog.h b/src/nwnss/zlss/purgeLog.h new file mode 100644 index 0000000..d2119f6 --- /dev/null +++ b/src/nwnss/zlss/purgeLog.h @@ -0,0 +1,277 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) module. + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $ + | + | $RCSfile$ + | $Revision: 1177 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and defines for the purge log + +-------------------------------------------------------------------------*/ + +#ifndef _PURGELOG_H_ +#define _PURGELOG_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +#ifndef _NSS_SLAB_H_ +#include "slab.h" +#endif + +/************************************************************************** + * + * Definitions + * + **************************************************************************/ +#define PLOG_SMALL DISABLE +//#define PLOG_SMALL ENABLE + +#if PLOG_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define MAX_PURGE_LOG_ENTRIES 5 +#else +#define MAX_PURGE_LOG_ENTRIES \ + ( (PAGE_SIZE - \ + (sizeof(LONG) + sizeof (Lsn_t) + sizeof(Blknum_t) + sizeof(VolumeID_t) \ + ) \ + ) \ + / sizeof(PurgeLogEntry_s) \ + ) +#endif + +#define PURGE_LOG_MAGIC 0x474f4c50 + +#if NSS_DEBUG IS_ENABLED +//#define VALIDATE_PLOG(_plog) ((void)0) +#define VALIDATE_PLOG(_plog) (plogValidate(_plog, FALSE)) +#else +#define VALIDATE_PLOG(_plog) ((void)0) +#endif + +/************************************************************************** + * + * Structures for the purge log + * + **************************************************************************/ + +/* + * Layout for an entry in a block for the purge log + */ + +typedef struct FreeEntry_s +{ + ZfsPurgeLogLoc_s link; /* link to the next entry on the free list */ +} NSS_MEDIA_STRUCTURE(FreeEntry_s,link) FreeEntry_s; + +typedef struct PurgeBlockEntry_s +{ + Blknum_t blockNumber; +} NSS_MEDIA_STRUCTURE(PurgeBlockEntry_s,blockNumber) PurgeBlockEntry_s; + +typedef struct PurgeBeastEntry_s +{ + VolumeID_t volumeID; /* guid of the volume the beast is on */ + Zid_t zid; /* zid of the beast */ + Zid_t dirZid; /* zid of the beast's parent container */ +} NSS_MEDIA_STRUCTURE(PurgeBeastEntry_s,dirZid) PurgeBeastEntry_s; + +typedef struct TruncateEntry_s +{ + VolumeID_t volumeID; /* guid of the volume the beast is on */ + Zid_t zid; /* zid of the beast */ + Blknum_t startBlock; /* block num to start the truncate */ + Blkcnt_t len; /* length of the extent to be truncated */ +} NSS_MEDIA_STRUCTURE(TruncateEntry_s,len) TruncateEntry_s; + + +typedef struct FixVisEntry_s +{ + UserID_t trusteeID; + Zid_t parentZID; + LONG action; +} NSS_MEDIA_STRUCTURE(FixVisEntry_s,action) FixVisEntry_s; + +typedef struct UserEntry_s +{ + VolumeID_t volumeID; +} NSS_MEDIA_STRUCTURE(UserEntry_s,volumeID) UserEntry_s; + +typedef struct UserScanEntry_s +{ + VolumeID_t volumeID; +} NSS_MEDIA_STRUCTURE(UserScanEntry_s,volumeID) UserScanEntry_s; + +typedef struct UserClearEntry_s +{ + VolumeID_t volumeID; +} NSS_MEDIA_STRUCTURE(UserClearEntry_s,volumeID) UserClearEntry_s; + +typedef struct DirEntry_s +{ + VolumeID_t volumeID; +} NSS_MEDIA_STRUCTURE(DirEntry_s,volumeID) DirEntry_s; + +typedef struct DirUsed_s +{ + VolumeID_t volumeID; + Zid_t dirZid; /* zid of directory where we are computing used amount */ +} NSS_MEDIA_STRUCTURE(DirUsed_s,dirZid) DirUsed_s; + +typedef struct EFLEpochRemove_s +{ + VolumeID_t volumeID; + EFLEpoch_t epoch; +} NSS_MEDIA_STRUCTURE(EFLEpochRemove_s,epoch) EFLEpochRemove_s; + +typedef struct EFLTreeReset_s +{ + VolumeID_t volumeID; +} NSS_MEDIA_STRUCTURE(EFLTreeReset_s,volumeID) EFLTreeReset_s; + +typedef union PurgeLogInfo_s +{ + FreeEntry_s free; /* link to the next entry on the free list */ + PurgeBeastEntry_s beast; /* normal purge log entry */ + TruncateEntry_s trunc; /* trucate and entry */ + PurgeBlockEntry_s block; /* remove a block (add it to the free tree) */ + FixVisEntry_s visib; /* add/remove visibility going up the tree */ + UserEntry_s user; /* remove the user tree for a volume */ + UserScanEntry_s userScan; /* scan the user names for a volume */ + UserClearEntry_s userClear; /* clear all used space for users */ + DirEntry_s directory; /* remove the directory tree for a volume */ + DirUsed_s dirUsed; /* compute used amount for dir quota */ + EFLEpochRemove_s epochRemove; /* remove a certain epoch in volume's EFL tree */ + EFLTreeReset_s resetEFL; /* reset volume's EFL tree */ +} NSS_MEDIA_UNION(PurgeLogInfo_s,trunc.len) PurgeLogInfo_s; + +typedef struct PurgeLogEntry_s +{ + LONG type; /* the type of entry */ + LONG generation; /* this is the system restart count */ + PurgeLogInfo_s info; /* the information to be logged */ +} NSS_MEDIA_STRUCTURE(PurgeLogEntry_s,info.trunc.len) PurgeLogEntry_s; + +/* + * Layout of a block in the purge log + */ +typedef struct PurgeLogBlock_s +{ + /* + * If fields are added or deleted from this structure make sure to + * update MAX_PURGE_LOG_ENTRIES. + */ + LONG magic; + Blknum_t nextBlock; /* link to the next block with purge log entries */ + Lsn_t lsn; /* Must be at offset 8 - the log sequence number */ + GUID_t plb_internalID; /* Must be at OFFSET 16 - unique volume ID (used + * by scanning repair). xnh is x Node Header. + */ + PurgeLogEntry_s logEntry[MAX_PURGE_LOG_ENTRIES]; /* maximum entries in a block */ +} NSS_MEDIA_STRUCTURE(PurgeLogBlock_s,logEntry[MAX_PURGE_LOG_ENTRIES]) PurgeLogBlock_s; + +/************************************************************************** + * + * Structures for transaction logging of the purge log + * + **************************************************************************/ + +typedef struct LogPurgeLog_s +{ + LONG slot; + PurgeLogEntry_s entry; +} NSS_MEDIA_STRUCTURE(LogPurgeLog_s,entry.info.trunc.len) LogPurgeLog_s; + + // For GROW and INIT +typedef struct LogPurgeLogGrow_s +{ + VolumeID_t lplg_internalID; +} NSS_MEDIA_STRUCTURE(LogPurgeLogGrow_s,lplg_internalID) LogPurgeLogGrow_s; + +/************************************************************************* + * + ************************************************************************/ +typedef struct FreePurgeLogEntries_s +{ + DQlink_t xactionLink; + ZfsPurgeLogLoc_s location; + ZfsPurgeLogBeast_s *purgeLog; +} FreePurgeLogEntries_s; + +extern void PLOG_PutEntryOnFreeList( + FreePurgeLogEntries_s *pLogEntry); + +extern ObjCache_s PLogFreeEntry; + + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ +void plogValidate ( + ZfsPurgeLogBeast_s *purgeLog, + BOOL shouldBeEmpty); + +STATUS ZFSPURGELOG_Setup ( + struct GeneralMsg_s *genMsg, + struct ZfsPurgeLogBeast_s *purgeLog); + +STATUS ZFSPOOL_PlayPurgeLog ( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsVolume_s *zfsVol, + struct ZfsPurgeLogBeast_s *purgeLog, + NINT mode ); + +STATUS ZFSVOL_PlayPurgeLog ( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + struct ZfsPurgeLogBeast_s *purgeLog, + NINT mode ); + +STATUS ZFSVOL_VOL_AddPurgeLogEntry ( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT type, + PurgeLogMsg_s *purgeMsg, + struct Xaction_s *xAction); + +STATUS ZFSVOL_VOL_RemovePurgeLogEntry ( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT type, + PurgeLogMsg_s *purgeMsg, + struct Xaction_s *xAction); + +void ZFSVOL_InitPurgeLogBlock ( + struct Buffer_s *buffer, + VolumeID_t *volumeID); + +#endif /* _PURGELOG_H_ */ diff --git a/src/nwnss/zlss/purgeTree.c b/src/nwnss/zlss/purgeTree.c new file mode 100644 index 0000000..fc94154 --- /dev/null +++ b/src/nwnss/zlss/purgeTree.c @@ -0,0 +1,1904 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Implement the purgetree data structure (used by ZLSS' salvage system). + +-------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#include "zParams.h" +#include "comnPublics.h" +#include "inst.h" +#include "fsm.h" +#include "pssDebug.h" +#include "comnIO.h" +#include "msgIO.h" +#include "purgeTree.h" +#include "purgeTree_if.h" +#include "comnBeastClass.h" +#include "comnBeasts.h" +#include "comnPublics.h" +#include "parse.h" +#include "pssDebug.h" +#include "zlssStartup.h" +#include "zfsAsyncio.h" +#include "zfsSuperBlk.h" +#include "zlog.h" +#include "zlssLogicalVolume.h" +#include + +/* + * Ztree is an implementation of a B-tree algorithm for storing + * lentrys. The algorithm does splits and joins as it decends + * the tree. This makes it so we can get buy with just locking the + * nodes and not the whole tree. + */ + +#define VERIFY_CONDITION(_cond, _dontAssert) \ +while (! _cond) \ +{ \ + if (! (_dontAssert)) \ + { \ + zASSERT(_cond); \ + } \ + goto invalidNode; \ +} + +SNINT purgekey_comp(PurgeKey_s *k1, PurgeKey_s *k2) +{ + SNINT diff; + + diff = KEY_COMP(k1->deltime, k2->deltime); + if (diff != 0) return diff; + diff = LB_GUIDCompare(&k1->internalID, &k2->internalID); + if (diff != 0) return diff; + diff = KEY_COMP(k1->zid, k2->zid); +/* cnt if (diff != 0) return diff; + diff = KEY_COMP(k1->nameUniquifier, k2->nameUniquifier); */ + + return diff; +} + +BOOL pbtValidateNode(PurgeTreeNode_s *node, BOOL dontAssert) +{ + NINT i; + NINT currentPosition; + NINT total; + NINT totalFree; + Zid_t zid; + PurgeInfo_s *pinfo, *prev_pinfo; + + if (PBT_IS_LEAF(node)) + { + VERIFY_CONDITION((node->magic == PURGETREE_MAGIC), dontAssert); + prev_pinfo = 0; + for (i = 0; i < node->numRecs; ++i) + { + VERIFY_CONDITION((PT_LEAF_ENTRY_OFF(node, i) <= PBT_MAX_LEAF_FREE), dontAssert); + pinfo = PT_LEAF_ENTRY(node, i); + zid = pinfo->key.zid; + VERIFY_CONDITION((*(LONG *)&zid != -1), dontAssert); + VERIFY_CONDITION(((zid != zOPEN_ENTRY_ZID) && ((zid != zINVALID_ZID) || (i == 0))), dontAssert); + VERIFY_CONDITION(((i == 0) || + (purgekey_comp(&prev_pinfo->key, &pinfo->key) < 0)), dontAssert); + prev_pinfo = pinfo; + } + total = PBT_MAX_LEAF_FREE - node->n.leaf.startOfFreeSpace; + totalFree = total - (node->numRecs * sizeof(pbtNodeLen_t)); + for(currentPosition = 0; currentPosition < node->n.leaf.startOfFreeSpace; + currentPosition += pinfo->length) + { + pinfo = (PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[currentPosition]; + VERIFY_CONDITION((pinfo->length == MIN_PT_LEAF_ENTRY_SIZE), dontAssert); + total += pinfo->length; + if ((pinfo->length < MIN_PT_LEAF_ENTRY_SIZE) || (pinfo->key.zid == zOPEN_ENTRY_ZID)) + { + totalFree += pinfo->length; + } + if (pinfo->length == 0) + break; + } + VERIFY_CONDITION((total == PBT_MAX_LEAF_FREE), dontAssert); + VERIFY_CONDITION((totalFree == node->n.leaf.freeSpace), dontAssert); + } + else + { + + PbtBranch_s *b_curr; + PbtBranch_s *b_prev; + int cnt; + + VERIFY_CONDITION((node->magic == PURGETREE_MAGIC), dontAssert); + + /*- set up extent pointers -*/ + b_prev = &node->n.branch[0]; + + VERIFY_CONDITION(( PBT_MAX_BRANCHES >= node->numRecs ), dontAssert); + for(cnt = 1; cnt < node->numRecs; cnt++) + { + /*- set the current record -*/ + b_curr = &node->n.branch[cnt]; + + /*- check if keys ascend -*/ + VERIFY_CONDITION((purgekey_comp(&b_prev->key, &b_curr->key) < 0), dontAssert); + + /*- set previous record and try next -*/ + b_prev = b_curr; + } + + } + return TRUE; +invalidNode: ; + return FALSE; +} + +///* +// * Debugging support +// */ + + +#if NSS_DEBUG IS_ENABLED + +/**************************************************************************** + * + ****************************************************************************/ +void zfsDisplayPurgeTreeNode (char *location, char *nameOfBuffer, + Buffer_s *buffer) +{ + PurgeTreeNode_s *node = (PurgeTreeNode_s *)buffer->pBuf.data; + NINT i; + NINT currentPosition; + NINT total; + NINT totalFree; + Zid_t zid; + PurgeInfo_s *pinfo; + + DBG_DebugPrintf( LBLUE, "\n%s=%s<%lx(%ld.)>", location, nameOfBuffer, + (unsigned long)buffer->volBlk, (unsigned long)buffer->volBlk ); + + if (PBT_IS_ROOT(node)) + { + DBG_DebugPrintf( LBLUE, "ROOT:"); + } + if (PBT_IS_LEAF(node)) + { + DBG_DebugPrintf( LBLUE, "LEAF"); + if (node->magic != PURGETREE_MAGIC) + { + DBG_DebugPrintf( LRED, "\n:ERROR(Node does not have correct MAGIC (value is %lx))\n",node->magic); + zASSERT(node->magic == PURGETREE_MAGIC); + return; + } + DBG_DebugPrintf( LBLUE, "(free=%d, start=%d, numRecs=%d)", + node->n.leaf.freeSpace, node->n.leaf.startOfFreeSpace, node->numRecs); + for (i = 0; i < node->numRecs; ++i) + { + zASSERT(PT_LEAF_ENTRY_OFF(node, i) <= PBT_MAX_LEAF_FREE); + zid = PT_LEAF_ENTRY(node, i)->key.zid; + zASSERT(*(LONG *)&zid != -1); + zASSERT((zid != zOPEN_ENTRY_ZID) && ((zid != zINVALID_ZID) || (i == 0))); + zASSERT((i == 0) || (zid > PT_LEAF_ENTRY(node, i-1)->key.zid)); + if ( i != 0 && (zid <= PT_LEAF_ENTRY(node, i-1)->key.zid) ) + { /* Out Of ORDER */ + DBG_DebugPrintf( LRED, ":ERROR(out-of-order)"); + } + DBG_DebugPrintf( LBLUE, ":%lx", (LONG)zid); + } + DBG_DebugPrintf( LBLUE, "\n"); + total = PBT_MAX_LEAF_FREE - node->n.leaf.startOfFreeSpace; + totalFree = total - (node->numRecs * sizeof(pbtNodeLen_t)); + for(currentPosition = 0; currentPosition < node->n.leaf.startOfFreeSpace; + currentPosition += pinfo->length) + { + pinfo = (PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[currentPosition]; + total += pinfo->length; + if ((pinfo->length < MIN_PT_LEAF_ENTRY_SIZE) || (pinfo->key.zid == zOPEN_ENTRY_ZID)) + { + totalFree += pinfo->length; + } + DBG_DebugPrintf( YELLOW, " %d(%d)",(LONG)pinfo->key.zid, pinfo->length); + if (pinfo->length == 0) + break; + } + if (total != PBT_MAX_LEAF_FREE) + { + DBG_DebugPrintf( RED, "\nTotal space not equal to node length. Total=%d, Node Length=%d", + total, PBT_MAX_LEAF_FREE); + } + zASSERT(total == PBT_MAX_LEAF_FREE); + zASSERT(totalFree == node->n.leaf.freeSpace); + } + else + { + DBG_DebugPrintf( LGREEN, "BRANCH"); + if (node->magic != PURGETREE_MAGIC) + { + DBG_DebugPrintf( LRED, "\n:ERROR(Node does not have correct MAGIC (value is %lx))\n",node->magic); + zASSERT(node->magic == PURGETREE_MAGIC); + return; + } + DBG_DebugPrintf( LBLUE, "(numRecs=%d)", node->numRecs); + for (i = 0; i < node->numRecs; ++i) + { + DBG_DebugPrintf( LBLUE, "<%d, %d>", + (LONG)node->n.branch[i].key.zid, +// cnt (LONG)node->n.branch[i].key.nameUniquifier, + (LONG)node->n.branch[i].child); + } + } + DBG_DebugPrintf( LBLUE, "\n"); +} + +/**************************************************************************** + * + ****************************************************************************/ +void zfsDisplayPurgeSubtree( + ZfsPurgeTreeBeast_s *treeBeast, + Buffer_s *buffer) +{ + GeneralMsg_s genMsg; + PurgeTreeNode_s *node = (PurgeTreeNode_s *)buffer->pBuf.data; + Buffer_s *newBuf; + NINT i; + IoMsg_s iomsg; + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + if (PBT_IS_LEAF(node)) + { + zfsDisplayPurgeTreeNode("Full Tree", "LEAF", buffer); + } + else + { + zfsDisplayPurgeTreeNode("Full Tree", "BRANCH", buffer); + if ( node->magic == PURGETREE_MAGIC ) + { + for (i = 0; i < node->numRecs; i++) + { + READBLK_IO_MSG(iomsg, treeBeast, + node->n.branch[i].child, CACHE_READ); + newBuf = ZFS_ReadPoolBlk( &genMsg, &iomsg); + zfsDisplayPurgeSubtree(treeBeast, newBuf); + CACHE_RELEASE(newBuf); + } + } + } +} + +/**************************************************************************** + * Given a volume, display the tree + ****************************************************************************/ +void ZfsDoDisplayPurgeTree( + ZfsPurgeTreeBeast_s *ztree) +{ + GeneralMsg_s genMsg; + Buffer_s *buffer; + IoMsg_s iomsg; + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + + S_LATCH(&ztree->ZFSPURGETREEbeastLatch); /* Latch the tree */ + wPause(stdout, -1); + +// RootDisplayMyCache(ztree); + + DBG_DebugPrintf( LBLUE, "***** Purge B-TREE *****\n"); + DBG_DebugPrintf( LBLUE, "ptRoot=%d\n", + ztree->ZFSPURGETREEzbtree.p.btRoot); + if (ztree->zfsBtree.p.btRoot != INVALID_BLK) + { + READBLK_IO_MSG(iomsg, ztree, ztree->zfsBtree.p.btRoot, CACHE_READ); + buffer = ZFS_ReadPoolBlk( &genMsg, &iomsg); + zASSERT(buffer != NULL); + zfsDisplayPurgeSubtree(ztree, buffer); + CACHE_RELEASE(buffer); + } + else + { + DBG_DebugPrintf( LBLUE, "Empty Purge B-Tree\n"); + } + wPause(stdout, 0); + UNS_LATCH(&ztree->ZFSPURGETREEbeastLatch); +} + + +/**************************************************************************** + * Called from command line parser to display the given tree + ****************************************************************************/ +void ZfsDisplayPurgeTree( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm) +{ + GeneralMsg_s genMsg; + ZfsVolume_s *volume; + + MPKNSS_LOCK(); + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + volume = (ZfsVolume_s *)COMN_VolumeNameLookup(&genMsg, + (unicode_t *)switchDef->ret_value,TRUE,NULL); + + if (volume != NULL) + { + ZfsDoDisplayPurgeTree(volume->ZFSVOLpurgeTree); + } + else + { + printf(MSG("Volume not found.\n", 462)); + } + COMN_Release(&volume); + MPKNSS_UNLOCK(); +} + +/**************************************************************************** + * + ****************************************************************************/ +void pbtCompare ( + PurgeTreeNode_s *node1, + PurgeTreeNode_s *node2, + NINT len) +{ + PurgeInfo_s *lentry1; + PurgeInfo_s *lentry2; + NINT i; + + PBT_VALIDATE_NODE(node1); + PBT_VALIDATE_NODE(node2); + if (!PBT_IS_LEAF(node1)) + { + zASSERT(memcmp(node1, node2, len) == 0); + return; + } + + /* leaf testing */ + zASSERT(node1->state == node2->state); + zASSERT(node1->lsn == node2->lsn); + zASSERT(node1->numRecs == node2->numRecs); + for (i = 0; i < node1->numRecs; i++) + { + lentry1 = PT_LEAF_ENTRY(node1, i); + lentry2 = PT_LEAF_ENTRY(node2, i); + zASSERT(lentry1->length == lentry2->length); + zASSERT(memcmp(lentry1, lentry2, lentry1->length) == 0); + } +} + +/**************************************************************************** + * + ****************************************************************************/ +void pbtNoCompare ( + PurgeTreeNode_s *node1, + PurgeTreeNode_s *node2, + NINT len) +{ +} + +#endif + +#if NSS_DEBUG IS_ENABLED && ZTREE_DEBUG IS_ENABLED +/**************************************************************************** + * + ****************************************************************************/ +void zprintPurgeTreeNode (char *location, char *nameOfBuffer, Buffer_s *buffer) +{ + if(zfsDebugBtree) + { + zfsDisplayPurgeTreeNode(location, nameOfBuffer, buffer); + } +} +#endif + +/**************************************************************************** + * + * This routine front ends the pool read routines and checks to make sure + * block that is read in has a valid magic number. + * + ****************************************************************************/ +Buffer_s *PBT_ReadPoolBlk ( + GeneralMsg_s *genMsg, + IoMsg_s *iomsg) +{ + Buffer_s *buffer; + NINT magic; + + buffer = ZFS_ReadPoolBlk(genMsg, iomsg); + if ((buffer != NULL) && (iomsg->mode != CACHE_WRITE)) + { + magic = ((PurgeTreeNode_s *)buffer->pBuf.data)->magic; + if (magic != PURGETREE_MAGIC) + { + SetErrno(genMsg, zERR_MEDIA_CORRUPTED); + ZLSSPOOL_MediaIsCorrupt(genMsg, buffer, iomsg); + CACHE_RELEASE(buffer); + return NULL; + } + } + return buffer; +} + +/***************************************************************** + * pbt_findLentryByKey + * I: buffer - the buffer to be searched + * I: zid - ZID to find + * O: index into the ptr array (0 to numrecs) + * index of the item before which the given key can be inserted. + * R: True if the ZID is found + */ +BOOL pbt_findLentryByKey( + PurgeTreeNode_s *node, + PurgeKey_s *key, + NINT *ind) +{ + PurgeInfo_s *pinfo; + SNINT i = 0, low = 0, high = node->numRecs-1; + SNINT res = -1; + + ENTER(TZTREE, pbt_findLentryByKey); + PBT_VALIDATE_NODE(node); + + while (low <= high) + { + i = (low + high)/2; + pinfo = PT_LEAF_ENTRY(node, i); + res = purgekey_comp(key, &pinfo->key); + if (res == 0) + { + if (low == high) + { + *ind = i; + RTN_BOOL(TRUE); + } + high = i; + } + else if (res > 0) + low = i+1; + else high = i-1; + } + + if (res < 0) + --i; + *ind = i+1; + RTN_BOOL(FALSE); +} + +/**************************************************************************** + * + ****************************************************************************/ +void pbt_initNode (Buffer_s *buffer, NINT state, GUID_t *internalID) +{ + PurgeTreeNode_s *node = (PurgeTreeNode_s *)buffer->pBuf.data; + + ENTER(TZTREE, pbt_initNode); + + node->magic = PURGETREE_MAGIC; + zASSERT(LB_GUIDValidate(internalID)); + if (state & PBT_LEAF) + { + node->n.leaf.nextLeaf = INVALID_BLK; /* init the leaf link field */ + node->n.leaf.freeSpace = PBT_MAX_LEAF_FREE; /* put length in free block */ + node->n.leaf.startOfFreeSpace = 0; /* starts at the end of the node */ + } + node->state = state; + node->ptn_internalID = *internalID; + node->numRecs = 0; + node->lsn = 0; + + buffer->state |= CACHE_DIRTY; + + PBT_VALIDATE_NODE(node); + RTN_VOID(); +} + +/**************************************************************************** + * + ****************************************************************************/ +void pbt_insertZeroNode (PurgeTreeNode_s *node) +{ + ENTER(TZTREE, insertZeroNode); + + PBT_VALIDATE_NODE(node); + /* + * We always want a zero in the first location to establish a lower bound + * so we do not need a lot of special case code. + */ + node->numRecs = 1; + node->PBTLEAFSPACE.pinfoPtr[PBT_MAX_LEAF_PTRS] = node->n.leaf.startOfFreeSpace; + node->n.leaf.startOfFreeSpace += MIN_PT_LEAF_ENTRY_SIZE; + node->n.leaf.freeSpace -= MIN_PT_LEAF_ENTRY_SIZE + sizeof(pbtNodeLen_t); + ((PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[0])->length = MIN_PT_LEAF_ENTRY_SIZE; /* very small pinfo */ + ((PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[0])->key.deltime = 0; + ((PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[0])->key.internalID = zINVALID_GUID; + ((PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[0])->key.zid = zINVALID_ZID; + ((PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[0])->key.reserved = 0; + PBT_VALIDATE_NODE(node); + RTN_VOID(); +} + +/**************************************************************************** + * + ****************************************************************************/ +void pbt_garbageCollectNode (PurgeTreeNode_s *node) +{ + NINT newStart; + NINT currentPosition; + PurgeInfo_s *curLentry; + NINT len; + NINT i; + + /* + * This routine garbage collects the internal area of a leaf node + */ + currentPosition = 0; + newStart = node->n.leaf.startOfFreeSpace; + while (currentPosition < node->n.leaf.startOfFreeSpace) + { /* garbage collect the free space */ + curLentry = (PurgeInfo_s *)&node->PBTLEAFSPACE.pinfo[currentPosition]; + zASSERT((node->n.leaf.startOfFreeSpace - currentPosition) + >= MIN_PT_LEAF_ENTRY_SIZE); + len = curLentry->length; + zASSERT(len >= MIN_PT_LEAF_ENTRY_SIZE); + if (curLentry->key.zid == zOPEN_ENTRY_ZID) + { /* if this is a free block then remember where it starts */ + if (currentPosition < newStart) + { /* first block of new space */ + newStart = currentPosition; + } + } + else + { /* found some used space -- does it need to be moved? */ + if (currentPosition > newStart) + { /* if there is open free space to collapse then collapse it*/ + memmove(&node->PBTLEAFSPACE.pinfo[newStart], + &node->PBTLEAFSPACE.pinfo[currentPosition], len); + /* update pinfo pointer array */ + for (i = PBT_MAX_LEAF_PTRS; i > (PBT_MAX_LEAF_PTRS - node->numRecs);i--) + { /* check each pointer in the array */ + if (node->PBTLEAFSPACE.pinfoPtr[i] == currentPosition) + { + node->PBTLEAFSPACE.pinfoPtr[i] = newStart; + break; + } + } + newStart += len; + } + } + currentPosition += len; + } + zASSERT(node->n.leaf.startOfFreeSpace == currentPosition); + node->n.leaf.startOfFreeSpace = newStart; + return; +} + +/************************************************************************** + * + * Insert a pinfo + * + **************************************************************************/ + +/**************************************************************************** + * Make room in the current buffer for a new beast pinfo + * + * Input: Child has the node to be inserted into. The child is latched. + * + ****************************************************************************/ +STATUS pbt_insertEntry( + GeneralMsg_s *genMsg, + PurgeTreeNode_s *child, + PurgeInfo_s *purgeInfo, + NINT entrylen) +{ + NINT i; + NINT len; + PurgeInfo_s *pinfo; + + /* + * This routine assumes a check has ready been done to make sure there + * there is enough free space in the buffer to hold the new pinfo. + */ + + ENTER(TZTREE, pbt_insertEntry); + + /* + * Add the pinfo to the leaf node + */ + if (pbt_findLentryByKey(child, &purgeInfo->key, &i)) + { + SetErrno(genMsg, zERR_FILE_ALREADY_EXISTS); + RTN_STATUS(zERR_FILE_ALREADY_EXISTS); + } + if (entrylen + sizeof(pbtNodeLen_t) > PBT_SIZEOFFREESPACE(child)) + { + pbt_garbageCollectNode(child); + } + /* make room for the pinfo pointer */ + memmove(&PT_LEAF_ENTRY_OFF(child, child->numRecs), /* Destination */ + &PT_LEAF_ENTRY_OFF(child, child->numRecs-1), /* Source */ + (child->numRecs - i) * sizeof(pbtNodeLen_t)); + + zASSERT(entrylen + sizeof(pbtNodeLen_t) <= PBT_SIZEOFFREESPACE(child)); + /* + * The pinfo will fit in the remaining free space . + */ + pinfo = (PurgeInfo_s *)&child->PBTLEAFSPACE.pinfo[child->n.leaf.startOfFreeSpace]; + memmove((BYTE *)pinfo, (BYTE *)purgeInfo, entrylen); + pinfo->length = entrylen; + + /* update all of the various counts for the new pinfo */ + PT_LEAF_ENTRY_OFF(child, i) = child->n.leaf.startOfFreeSpace; + child->n.leaf.startOfFreeSpace += entrylen; + child->n.leaf.freeSpace -= (entrylen + sizeof(pbtNodeLen_t)); /* include the + length of the + pointer */ + ++(child->numRecs); + + /* update the free space pointers */ + len = PBT_SIZEOFFREESPACE(child); + if (len >= MIN_PT_LEAF_ENTRY_SIZE) + { + pinfo=(PurgeInfo_s *)&child->PBTLEAFSPACE.pinfo[child->n.leaf.startOfFreeSpace]; + pinfo->length = len; + pinfo->key.zid = zOPEN_ENTRY_ZID; /* mark as free space */ + } + + ++Inst.ztree.insert; + + RTN_STATUS(zOK); +} + +/*************************************************************************** + * + * Delete a Beast + * + ***************************************************************************/ +/**************************************************************************** + * Remove the pinfo from the child record. This is used by delete and by + * modify. + ****************************************************************************/ +void pbt_deleteEntryFromChild( + PurgeTreeNode_s *child, + NINT recNum) +{ + PurgeInfo_s *pinfo; + + ENTER(TZTREE, pbt_deleteEntryFromChild); + PBT_VALIDATE_NODE(child); + pinfo = PT_LEAF_ENTRY(child, recNum); + child->n.leaf.freeSpace += pinfo->length + sizeof(pbtNodeLen_t); + pinfo->key.zid = zOPEN_ENTRY_ZID; + --(child->numRecs); + memmove(&PT_LEAF_ENTRY_OFF(child, (child->numRecs - 1)), + &PT_LEAF_ENTRY_OFF(child, child->numRecs), + (child->numRecs - recNum) * sizeof(pbtNodeLen_t)); + PBT_VALIDATE_NODE(child); + RTN_VOID(); +} + +/*---------------------------------------------------------------------------*/ +/**************************************************************************** + * + * Recovery routines + * + ****************************************************************************/ + +/**************************************************************************** + * Recovery routine for initing a tree + ****************************************************************************/ +STATUS pbt_recoveryInit( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + /* update the new root */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + /* init the node */ + node = (PurgeTreeNode_s *)buffer->pBuf.data; + pbt_initNode(buffer, PBT_ROOT|PBT_LEAF, &pool->ZFSPOOLinternalID); + pbt_insertZeroNode(node); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + ZPRINT_PTREE_NODE(restoreShrink, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for uniniting a tree (undo for init) + ****************************************************************************/ +STATUS pbt_recoveryUninit( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + Buffer_s *buffer; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + /* make sure the cache block for the deleted node is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { +#if LOG_TEST IS_ENABLED + if (LogTest) + ZLOG_SET_LSN(logBuffer, ((PurgeTreeNode_s *)buffer->pBuf.data)->lsn, + poolBlks[0], action); +#endif +// PBT_VALIDATE_NODE((PurgeTreeNode_s *)buffer->pBuf.data); + cacheReleaseToss(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for shrinking a tree + ****************************************************************************/ +STATUS pbt_recoveryShrink( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + /* make sure the cache block for the deleted node is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { +#if LOG_TEST IS_ENABLED + if (LogTest) + ZLOG_SET_LSN(logBuffer, ((PurgeTreeNode_s *)buffer->pBuf.data)->lsn, + poolBlks[0], action); +#endif +// PBT_VALIDATE_NODE((PurgeTreeNode_s *)buffer->pBuf.data); + cacheReleaseToss(buffer); + } + } + + /* update the new root */ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the root */ + node->state |= PBT_ROOT; /* set the root state */ + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[1], action); + ZPRINT_PTREE_NODE(restoreShrink, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for growing a tree + ****************************************************************************/ +STATUS pbt_recoveryGrow( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* update the new root */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + + /* fix up the root */ + pbt_initNode(buffer, PBT_ROOT, &pool->ZFSPOOLinternalID); + node->numRecs = 1; + node->n.branch[0].key.deltime = 0; + node->n.branch[0].key.zid = 0; + node->n.branch[0].key.reserved = 0; + node->n.branch[0].child = logRecord->u.grow.blockForParent; + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + ZPRINT_PTREE_NODE(restoreGrowRoot, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + + /* update the child */ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the child */ + node->state &= ~(PBT_ROOT); /* reset the root state */ + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[1], action); + ZPRINT_PTREE_NODE(restoreGrowChild, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for joining leafs + ****************************************************************************/ +STATUS pbt_recoveryBalance( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + NINT i; + PurgeInfo_s *currentLentry; + NINT lentryLength; + NINT lenMoved; + NINT numToMove; + NINT block; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* update the parent */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + zASSERT(node->magic == PURGETREE_MAGIC); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the parent */ + ZPRINT_PTREE_NODE(restoreBalanceParent1, buffer); + if (action == X_REDO) + { + node->n.branch[logRecord->u.balance.indexForParent].key = + logRecord->u.balance.keyForParent; + } + else + { + node->n.branch[logRecord->u.balance.indexForParent].key = + logRecord->u.balance.oldKey; + } + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + ZPRINT_PTREE_NODE(restoreBalanceParent2, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* update the source */ + block = (action == X_REDO) ? 1 : 2; + if (ZLOG_VALID_BLOCK(poolBlks[block])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[block].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the source node */ + ZPRINT_PTREE_NODE(restoreBalanceSource1, buffer); + ZPRINT_NINT(restoreBalanceChild_NumRecs, logRecord->u.balance.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.balance.data[0], + lenMoved = 0; + lenMoved < logRecord->u.balance.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_findLentryByKey(node, ¤tLentry->key, &i)) + { + pbt_deleteEntryFromChild(node, i); + } + else + { /* zid not found in the buffer */ + CACHE_RELEASE(buffer); + SetErrno(genMsg, zERR_ZID_NOT_FOUND); + return zFAILURE; + } + } + } + else + { /* branch */ + numToMove = logRecord->u.balance.numToMove; + if ((numToMove > 0) && + (purgekey_comp(&((PbtBranch_s *)&logRecord->u.balance.data[0])->key, + &node->n.branch[0].key) == 0)) + { /* if we are removing from the start of the branch record.. */ + memmove(&node->n.branch[0], /* Destination */ + &node->n.branch[numToMove], + (node->numRecs - numToMove) * sizeof(PbtBranch_s) ); +// logRecord->u.balance.totalLength); + } + node->numRecs -= numToMove; + } + + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[block], action); + ZPRINT_PTREE_NODE(restoreBalanceSource2, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* update the destination */ + block = (action == X_REDO) ? 2 : 1; + if (ZLOG_VALID_BLOCK(poolBlks[block])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[block].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the destination node */ + ZPRINT_PTREE_NODE(restoreBalanceDest1, buffer); + ZPRINT_NINT(restoreBalanceChild_NumRecs, logRecord->u.balance.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.balance.data[0], + lenMoved = 0; + lenMoved < logRecord->u.balance.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_insertEntry(genMsg, node, currentLentry, lentryLength) + != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + } + } + else + { /* branch */ + numToMove = logRecord->u.balance.numToMove; + lenMoved = logRecord->u.balance.totalLength; + if ( numToMove > 0 ) + { + if ( purgekey_comp(&((PbtBranch_s *)&logRecord->u.balance.data[0])->key, + &node->n.branch[0].key) < 0) + { /* if we are inserting at the start of the branch record ... */ + + /* make room for the insert */ + memmove(&node->n.branch[numToMove], /* Destination */ + &node->n.branch[0], /* Source */ + node->numRecs * sizeof(PbtBranch_s) ); + // lenMoved); + + /* insert the info from the log record */ + memcpy(&node->n.branch[0], + &logRecord->u.balance.data[0], + lenMoved); + } + else + { + /* insert the info from the log record */ + // memcpy(&node->n.branch[numToMove], + memcpy(&node->n.branch[node->numRecs], + &logRecord->u.balance.data[0], + lenMoved); + } + node->numRecs += numToMove; + } + } + + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[block], action); + ZPRINT_PTREE_NODE(restoreBalanceDest2, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for joining leafs + ****************************************************************************/ +STATUS pbt_recoveryJoin( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + NINT i; + PurgeInfo_s *currentLentry; + NINT lentryLength; + NINT lenMoved; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* update the parent */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + zASSERT(node->magic == PURGETREE_MAGIC); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the parent */ + ZPRINT_PTREE_NODE(restoreJoinParent1, buffer); + --(node->numRecs); + i = logRecord->u.split.indexForParent; + memmove( &node->n.branch[i], /* Destination */ + &node->n.branch[i + 1], /* Source */ + (node->numRecs - i) * sizeof(PbtBranch_s)); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + ZPRINT_PTREE_NODE(restoreJoinParent2, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* update the child */ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the child */ + ZPRINT_PTREE_NODE(restoreJoinChild1, buffer); + ZPRINT_NINT(restoreJoinChild_NumRecs, logRecord->u.split.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.split.data[0], + lenMoved = 0; + lenMoved < logRecord->u.split.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_insertEntry(genMsg, node, currentLentry, lentryLength) + != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + } + node->n.leaf.nextLeaf = logRecord->u.split.leafLink; + } + else + { /* branch */ + memcpy(&node->n.branch[node->numRecs], + &logRecord->u.split.data[0], + logRecord->u.split.totalLength); + node->numRecs += logRecord->u.split.numToMove; + } + ZPRINT_PTREE_NODE(restoreJoinChild2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[1], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + if (ZLOG_VALID_BLOCK(poolBlks[2])) + { + /* make sure the cache block for the deleted node is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[2].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { +#if LOG_TEST IS_ENABLED + if (LogTest) + ZLOG_SET_LSN(logBuffer, ((PurgeTreeNode_s *)buffer->pBuf.data)->lsn, + poolBlks[2], action); +#endif +// PBT_VALIDATE_NODE((PurgeTreeNode_s *)buffer->pBuf.data); + cacheReleaseToss(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for splitting leafs + ****************************************************************************/ +STATUS pbt_recoverySplit( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + NINT i; + PurgeInfo_s *currentLentry; + NINT lentryLength; + NINT lenMoved; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* update the parent */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + zASSERT(node->magic == PURGETREE_MAGIC); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the parent */ + ZPRINT_PTREE_NODE(restoreSplitParent1, buffer); + i = logRecord->u.split.indexForParent; + memmove(&node->n.branch[i + 1], /* Destination */ + &node->n.branch[i], /* Source */ + (node->numRecs - i) * sizeof(PbtBranch_s)); + ++(node->numRecs); + node->n.branch[i].key = logRecord->u.split.keyForParent; + node->n.branch[i].child = logRecord->u.split.blockForParent; + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + ZPRINT_PTREE_NODE(restoreSplitParent2, buffer); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* remove from the old node (on the left)*/ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { + ZPRINT_PTREE_NODE(restoreSplitChild1, buffer); + ZPRINT_NINT(restoreSplitChild_NumRecs, logRecord->u.split.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.split.data[0], + lenMoved = 0; + lenMoved < logRecord->u.split.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_findLentryByKey(node, ¤tLentry->key, &i)) + { + pbt_deleteEntryFromChild(node, i); + } + else + { /* zid not found in the buffer */ + CACHE_RELEASE(buffer); + SetErrno(genMsg, zERR_ZID_NOT_FOUND); + return zFAILURE; + } + } + node->n.leaf.nextLeaf = logRecord->u.split.blockForParent; + } + else + { /* branch */ + node->numRecs -= logRecord->u.split.numToMove; + } + ZPRINT_PTREE_NODE(restoreSplitChild2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[1], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* add to the new node */ + if (ZLOG_VALID_BLOCK(poolBlks[2])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[2].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + + /* fix up the child */ + ZPRINT_PTREE_NODE(restoreSplitNewChild1, buffer); + ZPRINT_NINT(restoreSplitNewChild_NumRecs, logRecord->u.split.numToMove); + pbt_initNode(buffer, logRecord->u.split.nodeType, + &pool->ZFSPOOLinternalID); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.split.data[0], + lenMoved = 0; + lenMoved < logRecord->u.split.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_insertEntry(genMsg, node, currentLentry, lentryLength) + != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + } + node->n.leaf.nextLeaf = logRecord->u.split.leafLink; + } + else + { /* branch */ + memcpy(&node->n.branch[0], + &logRecord->u.split.data[0], + logRecord->u.split.totalLength); + node->numRecs = logRecord->u.split.numToMove; + } + ZPRINT_PTREE_NODE(restoreSplitNewChild2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[2], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for the overflow log record used in joining leafs + ****************************************************************************/ +STATUS pbt_recoveryInsertOverflow( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + PurgeInfo_s *currentLentry; + NINT lentryLength; + NINT lenMoved; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* update the child */ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { /* fix up the child */ + ZPRINT_PTREE_NODE(restoreJoinOverflow1, buffer); + ZPRINT_NINT(restoreJoinOverflow_NumRecs, logRecord->u.overflow.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.overflow.data[0], + lenMoved = 0; + lenMoved < logRecord->u.overflow.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_insertEntry(genMsg, node, currentLentry, lentryLength) + != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + } + } + else + { /* branch */ + memcpy(&node->n.branch[node->numRecs], + &logRecord->u.overflow.data[0], + logRecord->u.overflow.totalLength); + node->numRecs += logRecord->u.overflow.numToMove; + } + ZPRINT_PTREE_NODE(restoreJoinOverflow2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + /* make sure the cache block for the deleted node is gone */ + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_WRITE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) != NULL) + { +#if LOG_TEST IS_ENABLED + if (LogTest) + ZLOG_SET_LSN(logBuffer, ((PurgeTreeNode_s *)buffer->pBuf.data)->lsn, + poolBlks[1], action); +#endif +// PBT_VALIDATE_NODE((PurgeTreeNode_s *)buffer->pBuf.data); + cacheReleaseToss(buffer); + } + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for removing beasts found in the overflow log record + ****************************************************************************/ +STATUS pbt_recoveryRemoveOverflow( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + NINT i; + PurgeInfo_s *currentLentry; + NINT lentryLength; + NINT lenMoved; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + /* remove from the old node (on the left)*/ + if (ZLOG_VALID_BLOCK(poolBlks[0])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + } + else + { + ZPRINT_PTREE_NODE(restoreOverflow1, buffer); + ZPRINT_NINT(restoreOverflow_NumRecs, logRecord->u.overflow.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.overflow.data[0], + lenMoved = 0; + lenMoved < logRecord->u.overflow.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_findLentryByKey(node, ¤tLentry->key, &i)) + { + pbt_deleteEntryFromChild(node, i); + } + else + { /* zid not found in the buffer */ + CACHE_RELEASE(buffer); + SetErrno(genMsg, zERR_ZID_NOT_FOUND); + return zFAILURE; + } + } + } + else + { /* branch */ + node->numRecs -= logRecord->u.overflow.numToMove; + } + ZPRINT_PTREE_NODE(restoreOverflow2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + } + + /* add to the new node */ + if (ZLOG_VALID_BLOCK(poolBlks[1])) + { + READBLK_IO_MSG(iomsg, pool, poolBlks[1].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + + /* fix up the child */ + ZPRINT_PTREE_NODE(restoreOverflowChild1, buffer); + ZPRINT_NINT(restoreOverflowChild_NumRecs, logRecord->u.overflow.numToMove); + if (PBT_IS_LEAF(node)) + { /* leaf */ + for (currentLentry = (PurgeInfo_s *)&logRecord->u.overflow.data[0], + lenMoved = 0; + lenMoved < logRecord->u.overflow.totalLength; + lenMoved += lentryLength, + currentLentry = (PurgeInfo_s *)(((ADDR)currentLentry) + lentryLength)) + { + lentryLength = currentLentry->length; + if (pbt_insertEntry(genMsg, node, currentLentry, lentryLength) + != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + } + } + else + { /* branch */ + memcpy(&node->n.branch[0], + &logRecord->u.overflow.data[0], + logRecord->u.overflow.totalLength); + node->numRecs = logRecord->u.overflow.numToMove; + } + ZPRINT_PTREE_NODE(restoreOverflowChild2, buffer); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[1], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + } + return zOK; +} + +/**************************************************************************** + * Recovery routine for inserting a pinfo into a beast + ****************************************************************************/ +STATUS pbt_recoveryInsertEntry( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (!ZLOG_VALID_BLOCK(poolBlks[0])) + { + return zOK; + } + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + zASSERT(node->magic == PURGETREE_MAGIC); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + return zOK; + } + + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + if (pbt_insertEntry(genMsg, node, &logRecord->u.pinfo, + logRecord->u.pinfo.length) != zOK) + { + CACHE_RELEASE(buffer); + return zFAILURE; + } + else + { + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); \ + return zOK; + } + +} + +/**************************************************************************** + * Recovery routine for deleting a pinfo from a beast + ****************************************************************************/ +STATUS pbt_recoveryDeleteEntry( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + PbtLog_s *logRecord; + NINT i; + Buffer_s *buffer; + PurgeTreeNode_s *node; + IoMsg_s iomsg; + BlockInfo_s *poolBlks; + + poolBlks = ZLOG_START_OF_POOL_BLOCKS(logBuffer); + + if (!ZLOG_VALID_BLOCK(poolBlks[0])) + { + return zOK; + } + READBLK_IO_MSG(iomsg, pool, poolBlks[0].blkNum, CACHE_UPDATE) + if ((buffer = PBT_ReadPoolBlk(genMsg, &iomsg)) == NULL) + { + //zASSERT(0); + return zFAILURE; + } + + node = (PurgeTreeNode_s *)buffer->pBuf.data; + PBT_VALIDATE_NODE(node); + zASSERT(node->magic == PURGETREE_MAGIC); + + if (ZLOG_ALREADY_DONE(pool, logBuffer, node->lsn, action)) + { + CACHE_RELEASE(buffer); + return zOK; + } + + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + if (pbt_findLentryByKey(node, &logRecord->u.pinfo.key, &i)) + { + pbt_deleteEntryFromChild(node, i); + ZLOG_SET_LSN(logBuffer, node->lsn, poolBlks[0], action); + PBT_VALIDATE_NODE(node); + CACHE_DIRTY_RELEASE(buffer); + return zOK; + } + else + { /* zid not found in the buffer */ + CACHE_RELEASE(buffer); + SetErrno(genMsg, zERR_ZID_NOT_FOUND); + return zFAILURE; + } +} + + +/**************************************************************************** + * Recovery routine for inserting a pinfo into a beast + ****************************************************************************/ +STATUS pbt_recoveryInsertEntryLogical( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + STATUS status; + PbtLog_s *logRecord; + ZfsXaction_s *xaction; + PurgeInfo_s *pInfo; + + ASSERT_MPKNSS_LOCK(); + + if (action == X_UNDO) + { + return zX_LOGICAL; + } + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + pInfo = &logRecord->u.pinfo; + + xaction = BeginXLocal(&pool->ZFSPOOLvol, BXL_LOGICAL_UNDO); + + status = purgeq_insert_name(genMsg, + pool->purgeTree, + pInfo->key.deltime, &pInfo->key.internalID, + pInfo->key.zid, /* cnt pInfo->key.nameUniquifier, */ + pInfo->pzid, &xaction->xaction); + + SET_LUNDO_LSN(xaction, logBuffer, status); + EndXlocal(xaction); + return status; +} + +/**************************************************************************** + * Recovery routine for deleting a pinfo from a beast + ****************************************************************************/ +STATUS pbt_recoveryDeleteEntryLogical( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZfsXasRecovery_s *logBuffer, + NINT action) +{ + STATUS status; + PbtLog_s *logRecord; + ZfsXaction_s *xaction; + PurgeInfo_s *pInfo; + + ASSERT_MPKNSS_LOCK(); + + if (action == X_UNDO) + { + return zX_LOGICAL; + } + logRecord = ZLOG_START_OF_LOG_RECORD(logBuffer); + + pInfo = &logRecord->u.pinfo; + + xaction = BeginXLocal(&pool->ZFSPOOLvol, BXL_LOGICAL_UNDO); + + status = purgeq_delete_name(genMsg, + pool->purgeTree, + pInfo->key.deltime, &pInfo->key.internalID, + pInfo->key.zid, /* cnt pInfo->key.nameUniquifier, */ + pInfo->pzid, &xaction->xaction); + + SET_LUNDO_LSN(xaction, logBuffer, status); + EndXlocal(xaction); + return status; +} + + +/*=========================================================================== + *=========================================================================== + *=========================================================================== + * + * ZFSPURGETREE BEAST + * + *=========================================================================== + *=========================================================================== + *===========================================================================*/ +/*--------------------------------------------------------------------------- + * Defines all of the ZFS B-Tree beast operations + *---------------------------------------------------------------------------*/ +CommonBeastOps_s ZFSPURGETREE_ComnBeastOps = +{ + NULL, /* construct */ + NULL, /* destruct */ + +// cnt NULL, /* BST_getNameUniquifier */ + NULL, /* BST_setupNameTypeSpecificInfo */ + NULL, /* BST_lookupByNameInDirectory*/ + NULL, /* BST_isDirectoryEmpty*/ + NULL, /* BST_addNameToDirectory*/ + NULL, /* BST_removeNameFromDirectory*/ + NULL, /* BST_modifyNameSpaceMaskInDirectory*/ + NULL, /* BST_setMatchAttributesInDirectory*/ + NULL, /* BST_wildcardLookup*/ + + NULL, /* BST_truncateFile*/ + NULL, /* BST_getStorageInfo*/ + NULL, /* BST_getExtentList*/ + NULL, /* BST_getPhysicalExtent*/ + NULL, /* BST_isBlockInBeast*/ + + NULL, /* BST_asyncReadFileBlk*/ + NULL, /* BST_getFileBlk*/ + NULL, /* BST_dfsReadUnits*/ + NULL, /* BST_dfsWriteUnits*/ + + NULL, /* BST_getZID*/ + NULL, /* BST_beastNotify*/ + NULL, /* BST_getInfo*/ + NULL, /* BST_modifyInfo*/ + NULL, /* BST_getInfoXML */ + NULL /* BST_modifyInfoXML*/ +}; + +/**************************************************************************** + * EXTENT BASED storage pack routine + *****************************************************************************/ +STATIC NINT ZFSPURGETREE_PackedSize( + void *beast_LX) +{ + return(0); +} + +/**************************************************************************** + * EXTENT BASED storage pack routine + *****************************************************************************/ +STATIC BYTE *ZFSPURGETREE_Pack( + void *beast_LX, + BYTE *storeBuffer) +{ + return(storeBuffer); +} + +/**************************************************************************** + * EXTENT BASED storage pack routines + *****************************************************************************/ +STATIC BYTE *ZFSPURGETREE_Unpack( + GeneralMsg_s *genMsg, + void *beast_LX, + BYTE *storeBuffer) +{ + return(storeBuffer); +} + +/*--------------------------------------------------------------------------- + * file beast STORAGE ops definition + *---------------------------------------------------------------------------*/ +LSSSpecificPackUnpackOps_s ZFSPURGETREE_lssOps[] = +{ + {zLSS_ID_ZLSS, ZFSPURGETREE_PackedSize, ZFSPURGETREE_Pack, NULL, ZFSPURGETREE_Unpack}, + {zLSS_ID_INVALID} +}; diff --git a/src/nwnss/zlss/purgeTree.h b/src/nwnss/zlss/purgeTree.h new file mode 100644 index 0000000..3e0fe36 --- /dev/null +++ b/src/nwnss/zlss/purgeTree.h @@ -0,0 +1,328 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define internal structures and functions for Purge Tree + | This file should not be used outside purge tree code. + +-------------------------------------------------------------------------*/ + +#ifndef _PURGETREE_H_ +#define _PURGETREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(_struct_, _field_) \ + ((NINT)&((_struct_ *)0)->_field_) +#endif + +#undef ZTREE_DEBUG +#define ZTREE_DEBUG ENABLE +#if NSS_DEBUG IS_ENABLED && ZTREE_DEBUG IS_ENABLED + +#define ZPRINT_PTREE_NODE(_loc, _buf) zprintPurgeTreeNode(# _loc, # _buf, _buf) +#define ZPRINT_ZID(_loc, _zid) zprintZid(# _loc, _zid) +#define ZPRINT_NINT(_loc, _nint) zprintNint(# _loc, _nint) + +void zprintPurgeTreeNode(char *location, char *nameOfBuffer, Buffer_s *buffer); + +/* The following two functions are defined in beastTree.c */ +extern void zprintZid(char *location, Zid_t zid); +extern void zprintNint(char *location, NINT value); +#else + +#define ZPRINT_PTREE_NODE(_loc, _buf) ((void)0) +#define ZPRINT_ZID(_loc, _zid) ((void)0) +#define ZPRINT_NINT(_loc, _nint) ((void)0) + +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define PBT_CHECK_FOR_SPLIT 0x00000001 +#define PBT_CHECK_FOR_JOIN 0x00000002 + +/* + * State information about B-tree nodes. + * A node can be both a LEAF and a ROOT (for sufficiently small Btrees) + */ + +#define MIN_PT_LEAF_ENTRY_SIZE (sizeof(PurgeInfo_s)) + +//#define FIND_RESERVE 2 /* Number of Bufmgrs to reserve for find */ +//#define UPDATE_RESERVE 3 /* Number of Bufmgrs to reserve for update */ +//#define INSERT_RESERVE 3 /* Number of Bufmgrs to reserve for insert */ +//#define DELETE_RESERVE 3 /* Number of Bufmgrs to reserve for delete */ + +#define PURGETREE_MAGIC 0x51475250 /* "PRGQ" */ +/* state of a node */ +#define PBT_LEAF 0x1 /* Leaf node of a B-tree */ +#define PBT_ROOT 0x2 /* Root node of a B-tree */ +//#define BTB_FREE 0x10 /* Node is free */ + +#define PBT_SMALL DISABLE +//#define BTT_SMALL ENABLE + +#define PBTLEAFSPACE n.leaf.space +#if PBT_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define PBT_MAX_FREEBLKS 2 +#define PBT_MAX_BRANCHES 9 /*was 5*/ +#define PBT_MAX_LEAF_FREE 1024 +#else +#define PBT_MAX_FREEBLKS ((PAGE_SIZE - 16) / sizeof(Blknum_t)) +#define PBT_MAX_BRANCHES \ + ((PAGE_SIZE - FIELD_OFFSET(PurgeTreeNode_s, n.branch)) / sizeof(PbtBranch_s)) +#define PBT_MAX_LEAF_FREE (PAGE_SIZE - FIELD_OFFSET(PurgeTreeNode_s, PBTLEAFSPACE)) +#endif +#define PBT_MAX_BEAST_SIZE ((ZLOG_MAXIMUM_RECORD_SIZE / 2) - sizeof(pbtNodeLen_t)) +#define PBT_MAX_LEAF_PTRS (PBT_MAX_LEAF_FREE/sizeof(pbtNodeLen_t) - 1) + /* is used as an array index -- must be zero based */ + +#define PBT_SIZEOFFREESPACE(_node) \ + (PBT_MAX_LEAF_FREE - ((_node)->n.leaf.startOfFreeSpace + \ + (_node)->numRecs * sizeof(pbtNodeLen_t))) + +#define PBT_MIN_BRANCHES (PBT_MAX_BRANCHES / 2) + +#define PBT_IS_LEAF(_n) ((_n)->state & PBT_LEAF) +#define PBT_IS_ROOT(_n) ((_n)->state & PBT_ROOT) + +#define PBT_IS_MAX_ENTRIES(_node, _parms) \ + (PBT_IS_LEAF(_node) \ + ? (_node->n.leaf.freeSpace < (parms->purgeInfo.length + \ + sizeof(pbtNodeLen_t))) \ + : ((_node)->numRecs >= PBT_MAX_BRANCHES)) + +#define PBT_IS_MIN_ENTRIES(_node) \ + (PBT_IS_LEAF(_node) \ + ? (_node->n.leaf.freeSpace > PBT_MAX_LEAF_FREE / 2) \ + : ((_node)->numRecs <= PBT_MIN_BRANCHES)) + +#define PBT_IS_LESSTHAN_MAX(_node, _sibling) \ + (PBT_IS_LEAF(_node) \ + ? (((_node)->n.leaf.freeSpace + (_sibling)->n.leaf.freeSpace) > PBT_MAX_LEAF_FREE) \ + : (((_node)->numRecs + (_sibling)->numRecs) < PBT_MAX_BRANCHES)) + + +/* Macros used for latching and unlatching the purgeTree beast and checking + * to see if the beast we are inserting or updating is the purgeTree beast */ +#define PBT_X_LATCH_PURGETREE(_parms) \ + X_LATCH(&(_parms)->ztree->ZFSPURGETREEbeastLatch) \ + +#define PBT_UNX_LATCH_PURGETREE(_parms) \ + UNX_LATCH(&(_parms)->ztree->ZFSPURGETREEbeastLatch) \ + + +typedef WORD pbtNodeLen_t; + +/* + * The Auto Purge-Queue is a collection of tuples, + * <[Effective deletion time, VolumeID, ZID, ], PZID> + * implemented as a heterogeneous B-Tree (all data at leaf nodes only) + * with the set of fields in "[]" comprising its primary key. + * + * The following operations need to be supported on the purge-queue. + * STATUS purgeq_insert_name(deltime, volume, zid, nameUniquifier, pzid); + * STATUS purgeq_delete_name(deltime, volume, zid, nameUniquifier, pzid); + * STATUS purgeq_serial_lookup(curtime, out deltime, out volumeID, out zid, + * out nameUniquifier, out pzid); + * Optionally, + * STATUS purgeq_delete_next_name(curtime, out deltime, out zid, + * out nameUniquifier, out pzid); + * (This operation can be implemented using the above operations). + */ +typedef struct PurgeKey_s +{ + GUID_t internalID; /* Beast's volume ID */ + Zid_t zid; /* ZID of the purgeable file. */ + Time_t deltime; /* Effective deletion time */ + WORD reserved; /* cnt Name Uniquifier for the above file's name */ +} NSS_MEDIA_STRUCTURE(PurgeKey_s,nameUniquifier) PurgeKey_s; + +typedef struct PurgeInfo_s +{ + Zid_t pzid; /* parent directory's ZID */ + PurgeKey_s key; + WORD length; /* length of the record */ +} NSS_MEDIA_STRUCTURE(PurgeInfo_s,length) PurgeInfo_s; + +/* + * structure to pass info and state between beast b-tree routines + */ +typedef struct PurgeTreeParms_s +{ + PurgeInfo_s purgeInfo; /* The purge info to be used */ +// NINT beastLen; /* the length of the beast */ + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + PurgeInfo_s *packArea; /* pointer to the area to put the packed record */ + struct ZfsXaction_s *xaction; /* Transaction being used */ + ZfsPurgeTreeBeast_s *ztree; /* The pointer to the b-tree beast */ +} PurgeTreeParms_s; + +/* + * structures for defining what the tree nodes look like + */ +typedef struct PbtBranch_s +{ +// Zid_t zid; + PurgeKey_s key; + WORD reserved1; + Blknum_t child; + LONG reserved2; +} NSS_MEDIA_STRUCTURE(PbtBranch_s,reserved2) PbtBranch_s; + +typedef struct PbtLeaf_s +{ + /* + * If the size of the header portion changes then change PBT_MAX_LEAF_FREE. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + WORD freeSpace; /* amount of free space left in leaf node */ + WORD startOfFreeSpace; /* pointer to the start of the free space */ + union + { + BYTE pinfo[1]; /* space to store vnodes */ + pbtNodeLen_t pinfoPtr[1]; /* pointers to start of pinfos */ + } NSS_MEDIA_UNION(NamelessUnion,pinfoPtr[1]) space; +} NSS_MEDIA_STRUCTURE(PbtLeaf_s,space.pinfoPtr[1]) PbtLeaf_s; + +typedef struct PurgeTreeNode_s +{ + /* + * If the size of the header portion changes then change PBT_MAX_FREEBLKS, + * PBT_MAX_BRANCHES and PBT_MAX_LEAF_FREE. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t ptn_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). ptn -> Purge Tree Node. + */ + union + { + PbtBranch_s branch[1]; + PbtLeaf_s leaf; +// Blknum_t freeBlks[PBT_MAX_FREEBLKS]; + } NSS_MEDIA_UNION(NamelessUnion,branch[1]) n; +} NSS_MEDIA_STRUCTURE(PurgeTreeNode_s,n.branch[1]) PurgeTreeNode_s; + +#define PT_LEAF_ENTRY_OFF(_n_, _ind_) \ + ((_n_)->PBTLEAFSPACE.pinfoPtr[PBT_MAX_LEAF_PTRS - (_ind_)]) +#define PT_LEAF_ENTRY(_n_, _ind_) \ + ((PurgeInfo_s *)&(_n_)->PBTLEAFSPACE.pinfo[PT_LEAF_ENTRY_OFF(_n_, _ind_)]) + +/* + * Structures and defines for log records for the beast b-tree. + */ + +typedef struct PbtSplit_s +{ + PurgeKey_s keyForParent; /* key to insert in the parent */ +// Zid_t zidForParent; /* zid to insert in the parent */ + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(PbtSplit_s,data[1]) PbtSplit_s; + +typedef struct PbtOverflow_s +{ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(PbtOverflow_s,data[1]) PbtOverflow_s; + +typedef struct PbtGrow_s +{ + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(PbtGrow_s,blockForParent) PbtGrow_s; + +typedef struct PbtBalance_s +{ + PurgeKey_s keyForParent; /* Key to insert in the parent */ + PurgeKey_s oldKey; /* previous key in the parent */ + LONG indexForParent; /* index where zid is changed in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(PbtBalance_s,data[1]) PbtBalance_s; + +/* defines for direction */ +#define LEFT_TO_RIGHT 0 +#define RIGHT_TO_LEFT 1 + +typedef struct PbtLog_s +{ + union + { + PurgeInfo_s pinfo; + PbtSplit_s split; + PbtOverflow_s overflow; + PbtGrow_s grow; + PbtBalance_s balance; + } NSS_MEDIA_UNION(NamelessUnion,balance.data[1]) u; +} NSS_MEDIA_STRUCTURE(PbtLog_s,u.balance.data[1]) PbtLog_s; + +BOOL pbtValidateNode(PurgeTreeNode_s *node, BOOL dontAssert); +#define PBT_IS_NODE_VALID(_node) \ + pbtValidateNode((PurgeTreeNode_s *)(_node), TRUE) + +/* + * Debug stuff + */ +#if NSS_DEBUG IS_ENABLED +#define PBT_VALIDATE_NODE(_node) \ + ((void)pbtValidateNode((PurgeTreeNode_s *)(_node), FALSE)) +void zfsDisplayPurgeTreeNode (char *location, char *nameOfBuffer, + Buffer_s *buffer); +void ZfsDisplayPurgeTree( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); +#else +#define PBT_VALIDATE_NODE(_node) ((void)0) +#endif + +#endif /* _PURGETREE_H_ */ diff --git a/src/nwnss/zlss/purgeTree_if.h b/src/nwnss/zlss/purgeTree_if.h new file mode 100644 index 0000000..ecef6a9 --- /dev/null +++ b/src/nwnss/zlss/purgeTree_if.h @@ -0,0 +1,103 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and + +-------------------------------------------------------------------------*/ + +#ifndef _PURGETREE_IF_H_ +#define _PURGETREE_IF_H_ + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +extern STATUS +purgeq_insert_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ptree, + Time_t deltime, + GUID_t *internalID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid, + Xaction_s *xaction); + +extern STATUS +purgeq_delete_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ptree, + Time_t deltime, + GUID_t *internalID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid, + Xaction_s *xaction); + +STATUS purgeq_lookup_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ztree, + Time_t deltime, + VolumeID_t *volumeID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid); + +typedef QUAD storage_size_t; + /* Should match the type of ZlssPool_s.ZP_BlksToSalvage */ + +#define PBT_FREESPACE_LOW_WATERMARK(_zlssPool_) \ + ((((_zlssPool_)->ZLSSPOOLtotalBlocks * (_zlssPool_)->ZLSSPOOLlowWaterMark))/100) + +#define PBT_FREESPACE_HIGH_WATERMARK(_zlssPool_) \ + ((((_zlssPool_)->ZLSSPOOLtotalBlocks * (_zlssPool_)->ZLSSPOOLhighWaterMark))/100) + +#define PBT_NUM_FREEBLKS(_zlssPool_) \ + (((_zlssPool_)->ZLSSPOOLtotalBlocks > (_zlssPool_)->ZLSSPOOLinUseBlocks) ? \ + ((_zlssPool_)->ZLSSPOOLtotalBlocks - (_zlssPool_)->ZLSSPOOLinUseBlocks) : 0) + +extern STATUS ZLSSPOOL_VOL_MakeVolumeFreeSpace( + GeneralMsg_s *genMsg, + void *zlssPool_LX, + BOOL purgeAllDeletedFiles, + BOOL asyncPurge, + storage_size_t nblocks_needed); + +extern Time_t getOldestDeletedTime( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol); + + +#endif /* _PURGETREE_IF_H_ */ diff --git a/src/nwnss/zlss/purgeTree_new.c b/src/nwnss/zlss/purgeTree_new.c new file mode 100644 index 0000000..cce4ccf --- /dev/null +++ b/src/nwnss/zlss/purgeTree_new.c @@ -0,0 +1,828 @@ +/**************************************************************************** + | + | (C) Copyright 1995-2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Implement the purgetree data structure (used by ZLSS' salvage system). + +-------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#include "zParams.h" +#include "comnPublics.h" +#include "inst.h" +#include "fsm.h" +#include "pssDebug.h" +#include "comnIO.h" +#include "msgIO.h" +#include "purgeTree_new.h" +#include "purgeTree_if.h" +#include "comnBeastClass.h" +#include "comnBeasts.h" +#include "comnPublics.h" +#include "parse.h" +#include "pssDebug.h" +#include "zlssStartup.h" +#include "zfsAsyncio.h" +#include "zfsSuperBlk.h" +#include "zlog.h" +#include "zlssLogicalVolume.h" +#include + +/* Backwards compatibility stuff */ +/* + * Upgrade a purgeTree node from old format to new format. + */ +STATUS pbtUpgradeNode( + GeneralMsg_s *genMsg, + Buffer_s *buf, + BYTE mode, + BOOL *modified) /* out Was node modified? */ +{ + PurgeTreeNewNode_s *newnode = ((PurgeTreeNewNode_s *)buf->pBuf.data); + PurgeTreeNode_s *oldnode = ((PurgeTreeNode_s *)buf->pBuf.data); + PurgeTreeNewNode_s *tempnode; + SNINT i; + + *modified = FALSE; + if (oldnode->magic == PURGETREE_MAGIC) + { +#if NSS_DEBUG IS_ENABLED + PBT_VALIDATE_NODE(oldnode); +#endif /* NSS_DEBUG ENABLED */ + /* Needs upgrade */ + if (PBT_IS_LEAF(oldnode)) + { + PurgeInfo_s *oldPinfo; + PurgeNewInfo_s *newPinfo; + + /* Create a temporary node in new format and copy back to oldnode */ + tempnode = (PurgeTreeNewNode_s *)malloc(PAGE_SIZE); + if (! tempnode) + { + SetErrno(genMsg, zERR_NO_MEMORY); + return zFAILURE; + } + + /* Copy the header */ + memmove(tempnode, oldnode, offsetof(PurgeTreeNewNode_s, n.leaf.vv_entry)); + tempnode->n.leaf.reserved = 0; + tempnode->magic = PURGETREE_NEW_MAGIC; + + /* Copy each entry to temporary node in its new format */ + for (i = 0; i < oldnode->numRecs; ++ i) + { + oldPinfo = PT_LEAF_ENTRY(oldnode, i); + newPinfo = PBT_NEW_LEAF_ENTRY(tempnode, i); + bzero((BYTE *)newPinfo, sizeof(*newPinfo)); + newPinfo->key.internalID = oldPinfo->key.internalID; + newPinfo->key.zid = oldPinfo->key.zid; + newPinfo->key.deltime = oldPinfo->key.deltime; +// cnt newPinfo->key.nameUniquifier = oldPinfo->key.nameUniquifier; + newPinfo->value.pzid = oldPinfo->pzid; + } + + /* Overwrite original node with new contents */ + memmove(oldnode, tempnode, PAGE_SIZE); + free(tempnode); + } + else /* Branch node */ + { + BYTE newentrySpace[offsetof(MYBTBranchEntry_s, key) + sizeof(PurgeQNewKey_s)]; + MYBTBranchEntry_s *newentry = (MYBTBranchEntry_s *)&newentrySpace; + PbtBranch_s *oldentry; + + zASSERT(sizeof(PbtBranch_s) == sizeof(newentrySpace)); + for (i = 0; i < oldnode->numRecs; ++ i) + { + oldentry = &oldnode->n.branch[i]; + bzero(newentry, sizeof(newentrySpace)); + newentry->child = oldentry->child; + ((PurgeQNewKey_s *)&newentry->key)->internalID = oldentry->key.internalID; + ((PurgeQNewKey_s *)&newentry->key)->zid = oldentry->key.zid; + ((PurgeQNewKey_s *)&newentry->key)->deltime = oldentry->key.deltime; +// cnt ((PurgeQNewKey_s *)&newentry->key)->nameUniquifier = oldentry->key.nameUniquifier; + + memmove(oldentry, newentry, sizeof(newentrySpace)); + } + newnode->magic = PURGETREE_NEW_MAGIC; + } + *modified = TRUE; + } + return zOK; +} + + +STATIC SNINT pbtNewKeyComp( + void *k1_LX, + void *k2_LX) +{ + PurgeQNewKey_s *k1 = (PurgeQNewKey_s *)k1_LX; + PurgeQNewKey_s *k2 = (PurgeQNewKey_s *)k2_LX; + SNINT diff; + + diff = KEY_COMP(k1->deltime, k2->deltime); + if (diff != 0) return diff; + diff = LB_GUIDCompare(&k1->internalID, &k2->internalID); + if (diff != 0) return diff; + diff = KEY_COMP(k1->zid, k2->zid); +// cnt if (diff != 0) return diff; +// cnt diff = KEY_COMP(k1->nameUniquifier, k2->nameUniquifier); + + return diff; +} + +#if NSS_DEBUG IS_ENABLED +STATIC void pbtDisplayKey( + NINT color, + void *key_LX ) +{ + PurgeQNewKey_s *key = (PurgeQNewKey_s *)key_LX; + + DBG_DebugPrintf(color, MSGNot("0x%8x, 0x%Lx"), + key->deltime, + key->zid/* cnt, + key->nameUniquifier*/); +} + +STATIC void pbtDisplayValue( + NINT color, + void *value_LX) +{ + PurgeQNewValue_s *value = (PurgeQNewValue_s *)value_LX; + DBG_DebugPrintf(color, MSGNot("0x%Lx"), value->pzid); +} +#endif + +void pbtSetZeroKey( + void *key_LX) +{ + PurgeQNewKey_s *key = (PurgeQNewKey_s *)key_LX; + + bzero((BYTE *)key, sizeof(PurgeQNewKey_s)); + key->internalID = zINVALID_GUID; + key->zid = zINVALID_ZID; + key->deltime = 0; + key->reserved = 0; +} + +MYBTreeInstanceInfo_s PurgeTreeInfo = +{ + sizeof(PurgeQNewKey_s), + sizeof(PurgeQNewValue_s), + sizeof(PurgeQNewKey_s) + sizeof(PurgeQNewValue_s), + PURGETREE_NEW_MAGIC, + PURGETREE_NEW_MAGIC, + XFUNC_PTREE_INTERNAL_OP_START, + XFUNC_PTREE_LOGICAL_OP_START, + pbtNewKeyComp, + pbtSetZeroKey, + pbtUpgradeNode, +#if NSS_DEBUG IS_ENABLED + pbtDisplayKey, + pbtDisplayValue, +#endif +}; + +/**************************************************************************** + * + ****************************************************************************/ +STATUS purgeq_insert_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ztree, + Time_t deltime, + GUID_t *internalID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid, + Xaction_s *xAction) +{ + MYBTreeParms_s parms; + PurgeQNewKey_s key; + PurgeQNewValue_s value; + + bzero((BYTE *)&key, sizeof(key)); + bzero((BYTE *)&value, sizeof(value)); + key.deltime = deltime; + key.internalID = *internalID; + key.zid = zid; + key.reserved = 0; + value.pzid = pzid; + + parms.treeInfo = &PurgeTreeInfo; + parms.xaction = (ZfsXaction_s *)xAction; + parms.volume = ztree->ZFSPURGETREEvolume; + parms.btreeBeast = ztree; + parms.key = (MYBTKey_t)&key; + parms.value = (MYBTValue_t)&value; + parms.updateCallback = NULL; + + return MYBT_insertEntry(genMsg, &parms); +} + +STATUS purgeq_delete_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ztree, + Time_t deltime, + GUID_t *internalID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid, + Xaction_s *xAction) +{ + MYBTreeParms_s parms; + PurgeQNewKey_s key; + PurgeQNewValue_s value; + + key.deltime = deltime; + key.internalID = *internalID; + key.zid = zid; + key.reserved = 0; + value.pzid = pzid; + + parms.treeInfo = &PurgeTreeInfo; + parms.xaction = (ZfsXaction_s *)xAction; + parms.volume = ztree->ZFSPURGETREEvolume; + parms.btreeBeast = ztree; + parms.key = (MYBTKey_t)&key; + parms.value = (MYBTValue_t)&value; + parms.updateCallback = NULL; + + return MYBT_deleteEntry(genMsg, &parms); +} + +STATUS purgeq_lookup_name( + GeneralMsg_s *genMsg, + ZfsPurgeTreeBeast_s *ztree, + Time_t deltime, + GUID_t *internalID, + Zid_t zid, +// cnt NINT nameUniquifier, + Zid_t pzid) +{ + MYBTreeParms_s parms; + PurgeQNewKey_s key; + PurgeQNewValue_s value; + + key.deltime = deltime; + key.internalID = *internalID; + key.zid = zid; + key.reserved = 0; + value.pzid = pzid; + + parms.treeInfo = &PurgeTreeInfo; + parms.xaction = 0; + parms.volume = ztree->ZFSPURGETREEvolume; + parms.btreeBeast = ztree; + parms.key = (MYBTKey_t)&key; + parms.value = (MYBTValue_t)&value; + parms.updateCallback = NULL; + + return MYBT_lookupEntry(genMsg, &parms); +} + +/* + * Invoke common layer to purge the beast specified by given pinfo. + * If couldn't find the beast, just throw it away from the purge queue. + */ +STATIC STATUS +doPurgeBeast( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool, + PurgeNewInfo_s *pinfo) +{ + STATUS rc; + ZfsVolume_s *zfsVol; + BOOL weSet = FALSE; + + /* Since we allow zAPI into internal volumes they + * can have purgeable space. We therefore must + * include in our search. + */ + if ( !(genMsg->flags & GM_FLAGS_INTERNAL_VOLUME) ) + { + COMN_INCLUDE_INTERNAL_VOLUMES( genMsg ); + weSet = TRUE; + } + zfsVol = ZLSS_VolumeIDLookup(genMsg, &pinfo->key.internalID, + TRUE, zlssPool->ZLSSPOOLzfsPool); + if ( weSet ) + { /* Reset only if we did the set */ + COMN_EXCLUDE_INTERNAL_VOLUMES( genMsg ); + } + if (zfsVol == NULL) + { + return zFAILURE; + } + + /* + * Invoke common layer to purge the beast name identified by + * tuple. + */ + rc = BST_PurgeFileName(genMsg, &zfsVol->vol, pinfo->value.pzid, + pinfo->key.zid/* cnt, pinfo->key.nameUniquifier*/); + COMN_Release(&zfsVol); + + if ((rc != zOK) && (GetErrno(genMsg) == zERR_ZID_NOT_FOUND)) + { + ZfsXaction_s *localXaction = + BeginXLocal(zlssPool->ZLSSPOOLpurgeTree->ZFSPURGETREEvolume, + BXL_DEFAULT); + /* No Beast found so deleting PT entry */ + ClearErrno(genMsg); + rc = purgeq_delete_name(genMsg, zlssPool->ZLSSPOOLpurgeTree, + pinfo->key.deltime, &pinfo->key.internalID, pinfo->key.zid, + /* cnt pinfo->key.nameUniquifier,*/ pinfo->value.pzid, + (Xaction_s *)localXaction); + /* Ignore the result of delete_name */ + if (rc != zOK) + { + ClearErrno(genMsg); + rc = zOK; + } + EndXlocal(localXaction); + } + return rc; +} + +/**************************************************************************** + * Find the next file to purge, whose deletion time has elapsed. + * + * return: If found, + * returns the file's deletion time, zid, nameUniquifier, + * pzid and zOK. + * Note: We use the ZfsPurgeTreeBeast_s.zfsBtree.p.btFree field to hold the + * Blknum of the leftmost leaf node of the Purge Tree. + * As long as the root node remains non-null, the leftmost leaf node's blknum + * remains the same. + * + ****************************************************************************/ + +STATIC STATUS +make_freeSpace_common( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool, +// ZfsPool_s *pool, + BOOL delete_by_time, /* Based on this flag, either */ + Time_t delete_keep_time, /* Purge all files deleted at least + * this many seconds ago */ + storage_size_t target_freeblks) /* OR, Free this many blks of storage */ +{ + STATUS rc; + ZfsPurgeTreeBeast_s *ztree = zlssPool->ZLSSPOOLpurgeTree; + MYBTreeParms_s parms; + PurgeNewInfo_s purgeInfo; + BOOL success = FALSE; + + ENTER(TZTREE, make_freeSpace_common); + + if (ztree == NULL) + { + goto done; + } + + if (! delete_by_time) + { +#if 0 + if (target_freeblks < PBT_FREESPACE_HIGH_WATERMARK(zlssPool)) + target_freeblks = PBT_FREESPACE_HIGH_WATERMARK(zlssPool); +#endif + } + + /* + * We keep trying to purge beasts whose deletion time has elapsed (in + * deltime order) until we can get the freespace to >= target_freeblks. + * purging attempt fails for a beast, we skip it and move on to purge + * others. + * If delete_by_time flag is TRUE, we purge all deleted beasts whose + * PBT_MAX_keep_time has elapsed. + */ + + /* Start from leftmost leaf's first entry */ + parms.treeInfo = &PurgeTreeInfo; + parms.xaction = 0; + purgeInfo.key.deltime = INVALID_UTC_TIME; + purgeInfo.key.internalID = zINVALID_GUID; + purgeInfo.key.zid = zINVALID_ZID; + purgeInfo.key.reserved = 0; + parms.btreeBeast = ztree; + parms.key = (MYBTKey_t)&purgeInfo.key; + parms.updateCallback = NULL; + + /* + * Sequentially scan the linked list of leaf nodes for beasts to purge + * (starting at the beast at (parms.child, nextind+1)). + */ + for (;;) + { + Time_t curtime; + NINT numEntriesReturned; + + /* Quit the loop if leaving active state or not in active state. */ + if ((zlssPool->ZLSSPOOLstate != zVOLSTATE_ACTIVE) || + (zlssPool->ZLSSPOOLstatusFlag & VOL_SF_LEAVING_ACTIVE_STATE_CLEANUP)) + { + /* success == FALSE, so this will return an error */ + goto done; + } + + curtime = GetUTCTime() - + (delete_by_time ? delete_keep_time + : zlssPool->ZLSSPOOLminKeepSeconds); + if (! delete_by_time) + { + /* Check if we met our freeSpace target */ + if (PBT_NUM_FREEBLKS(zlssPool) >= target_freeblks) + { + success = TRUE; + goto done; + } + } + + rc = MYBT_browseEntries(genMsg, &parms, 1, (BYTE *)&purgeInfo, + &numEntriesReturned); + switch (rc) + { + case zOK: + break; + case zERR_ZID_NOT_FOUND: + success = delete_by_time; + goto done; + default: + goto error_ret; + } + if (numEntriesReturned < 1) + { + success = delete_by_time; + goto done; + } + + /* Examine the entry to see if the beast can be purged */ + if (KEY_COMP(curtime, purgeInfo.key.deltime) < 0) /* Are we done? */ + { + success = delete_by_time; + goto done; + } + + /* Purge the beast just found */ + rc = doPurgeBeast(genMsg, zlssPool, &purgeInfo); + /* Ignore the result */ + if (rc != zOK) + { + ClearErrno(genMsg); + rc = zOK; + } + } + +done: ; + if (! success) + { + SetErrno(genMsg, zERR_ZID_NOT_FOUND); + rc = zFAILURE; + } + else rc = zOK; +error_ret: ; + RTN_STATUS(rc); +} + +STATIC void +make_freeSpace_worker_thread( + FsmLite_s *fsm, + void *unused) +{ + GeneralMsg_s genMsg; + STATUS rc; +// ZfsPool_s *pool = STRUCT(fsm, ZfsPool_s, ZP_makeFreeSpaceFsm); + ZlssPool_s *zlssPool = STRUCT(fsm, ZlssPool_s, ZP_MakeFreeSpaceFsm); + storage_size_t target_freeblks; + storage_size_t min_freeblks = zlssPool->ZP_BlocksToSalvage + + ZFS_RESERVED_BLOCKS_FOR_INTERNAL_ALLOCATION; + + + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + /* Convert into target freeSpace */ + target_freeblks = zlssPool->ZP_BlocksToSalvage + PBT_NUM_FREEBLKS(zlssPool); + if (target_freeblks < min_freeblks) + { + target_freeblks = min_freeblks; + } + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(MAGENTA, + MSGNot("make_freeSpace_worker_thread freeing %Ld blocks\n"), + target_freeblks)); + rc = make_freeSpace_common(&genMsg, zlssPool, FALSE, 0, target_freeblks); + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(MAGENTA, + MSGNot("make_freeSpace_worker_thread DONE\n"))); + zlssPool->ZP_BlocksToSalvage = 0; + --(zlssPool->ZLSSPOOLkeepActiveUseCount); +} + +/* + * STATIC BOOL make_freeSpace_async - + * Starts a worker thread that will attempt to generate 'nblks_needed' + * blocks of free space via purging files. This routine is not concerned + * about which Logical Volume(s) the space comes from. + * + * Returns - + * TRUE if the thread was just started. + * FALSE if it's already running or we have enough blocks + * to satisfy request without hitting our low water + * mark that would require us to start purging. + */ +STATIC BOOL +make_freeSpace_async( + ZlssPool_s *zlssPool, + storage_size_t nblks_needed) +{ + storage_size_t freespace_high, freespace_low, new_freeSpace; + + if (zlssPool->ZP_BlocksToSalvage > 0) + { /* Thread is already running */ + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(MAGENTA, + MSGNot("make_freespace_async thread already running\n"))); + return FALSE; + } + + freespace_low = PBT_FREESPACE_LOW_WATERMARK(zlssPool); + new_freeSpace = PBT_NUM_FREEBLKS(zlssPool) - nblks_needed; + + if (new_freeSpace >= freespace_low) + { /* Request does not cause us to meet our 'minimum + * number of blocks that must be free at any given + * moment' requirement. I.E. we do not need to + * start our purge thread to free purgable blocks + * because we are ABOVE our low water mark of free blocks. + */ +// DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(MAGENTA, +// MSGNot("HAPPY space = %Ld lowmark = %Ld\n"), +// new_freeSpace,freespace_low)); + return FALSE; + } + + /* Calculate the number of blocks needed to be + * freed to enable us to be at our high water mark. + */ + freespace_high = PBT_FREESPACE_HIGH_WATERMARK(zlssPool); + zlssPool->ZP_BlocksToSalvage = freespace_high - new_freeSpace; + if (nblks_needed > zlssPool->ZP_BlocksToSalvage) + { + zlssPool->ZP_BlocksToSalvage = nblks_needed; + } + DEBUG_PRINTF(TLVOLUMES,DBG_NOINDENT,(MAGENTA, + MSGNot("make_freespace_async thread starting\n"))); + ++(zlssPool->ZLSSPOOLkeepActiveUseCount); + WORK_Schedule(&zlssPool->ZP_MakeFreeSpaceFsm, + make_freeSpace_worker_thread, 0); + return TRUE; +} + +/* + * ZLSSPOOL_VOL_MakeVolumeFreeSpace - + * Pool common operation that is used to free space in the salvage + * (purge) system. This function can free space on any Logical Volume. + * The space is freed based on oldest purgeable file(s) on all LVs. + * + * Parameters - + * delete_by_time - TRUE means to purge all files on the LV/POOL + * that have been deleted for at least 'delete_keep_time' seconds. + * target_freeblks - The number of blocks that should be free when + * this function returns. I.E. as long as this function can + * purge files it will do so until 'target_freeblks' blocks are + * free. This paramter is ONLY used if 'delete_by_time' is FALSE + * + * Note - + * Currently, the common layer does not call this function. It is + * used by the ZfsVol_s volume common op to ask the pool to salvage space + * on any volume. + * + */ + +STATUS +ZLSSPOOL_VOL_MakeVolumeFreeSpace( + GeneralMsg_s *genMsg, + void *zlssPool_LX, + BOOL purgeAllDeletedFiles, + BOOL asyncPurge, + storage_size_t nblks_needed) +{ + ZlssPool_s *zlssPool = (ZlssPool_s *)zlssPool_LX; + storage_size_t target_freeblks; + storage_size_t min_freeblks; + +// zASSERT(!(volume->VOLenabledAttributes & zATTR_READONLY)); + zASSERT(COMN_IsDerivedFrom(zlssPool, zFTYPE_ZLSS_LOGICAL_POOL)); + + if (asyncPurge) + { + if ( zlssPool->ZP_Version >= + (AIPU_LV_MEDIA_MAJOR*0x100L+AIPU_LV_STEP_4_DONE) ) + { /* Caller wanted ASYNC and we are NOT doing AIPU */ + (void) make_freeSpace_async(zlssPool, nblks_needed); + return zOK; + } + else + { /* LV AIPU does not like purge thread to go ASYNC as + * LV AIPU may be counting blocks in some of the system trees. + * If these trees are changing then some of our counts + * will be off. + * July 25, 2001. Changed so to skip purging if we have + * enough free blocks. This is different than check in + * make_freeSpace_async as it will purge if we are below + * salvage low water mark. + */ + storage_size_t freeBlocks; + +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf( MAGENTA, + MSGNot("ZLSSPOOL_VOL_MakeVolumeFreeSpace called ASYNC during LV AIPU converting to SYNC call\n")); +#endif + freeBlocks = PBT_NUM_FREEBLKS(zlssPool); + if ( freeBlocks >= (nblks_needed + 1024) ) + { /* Have enough free blocks so no purge. During LV AIPU + * we try to avoid purge because we can deadlock. E.G. + * if LV AIPU is creating a file which causes a split + * in the BT which ask purge to purge a file in the + * same BT Leaf that the split has lock we deadlock. + * I saw this on a volume with 12 files of which 8 are + * deleted. + * + * The 1024 is so that we reduce the chance that we + * MUST have the purge succeed for a block to be allocated. + * If we get to this point then we could deadlock as + * above. + */ +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf( MAGENTA, + MSGNot("ZLSSPOOL_VOL_MakeVolumeFreeSpace LV AIPU ASYNC not needed as have enough free blocks\n")); +#endif + return zOK; + } + /* July 25, 2001. We must go ASYNC or we may deadlock + * see above. Since we NEED blocks we must purge. + */ +#if NSS_DEBUG IS_ENABLED + DBG_DebugPrintf( MAGENTA, + MSGNot("ZLSSPOOL_VOL_MakeVolumeFreeSpace LV AIPU going ASYNC.\n")); +#endif + (void) make_freeSpace_async(zlssPool, nblks_needed); + LB_delay( 2000 ); /* Give purge some time to run. This will + * make call look sync to LV AIPU if sleeping + * thread does not own resources that purge + * needs. + */ + return zOK; + } + } + /* Convert into target freeSpace */ + min_freeblks = nblks_needed + ZFS_RESERVED_BLOCKS_FOR_INTERNAL_ALLOCATION; + target_freeblks = nblks_needed + PBT_NUM_FREEBLKS(zlssPool); + if (target_freeblks < min_freeblks) + { + target_freeblks = min_freeblks; + } + return make_freeSpace_common(genMsg, zlssPool, purgeAllDeletedFiles, (Time_t)0, + target_freeblks); +} /* End of ZLSSPOOL_VOL_MakeVolumeFreeSpace */ + +/* + * This function returns the oldest delete time in the pool. It was decided + * that this would be O.K. for Logical Volumes. Brenda and Oly said that no one + * really looks at this value. + */ +Time_t +getOldestDeletedTime( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol) +{ + STATUS rc; + ZfsPurgeTreeBeast_s *ztree = zfsVol->ZFSVOLpurgeTree; + MYBTreeParms_s parms; + PurgeNewInfo_s purgeInfo; + NINT numEntriesReturned; + + ENTER(TZTREE, getOldestDeletedTime); + + if (ztree == NULL) + { + rc = zERR_ZID_NOT_FOUND; + goto error_ret; + } + + /* Get the leftmost leaf's first entry */ + parms.treeInfo = &PurgeTreeInfo; + parms.xaction = 0; + purgeInfo.key.deltime = INVALID_UTC_TIME; + purgeInfo.key.internalID = zINVALID_GUID; + purgeInfo.key.zid = zINVALID_ZID; + purgeInfo.key.reserved = 0; + parms.btreeBeast = ztree; + parms.key = (MYBTKey_t)&purgeInfo.key; + parms.updateCallback = NULL; + + rc = MYBT_browseEntries(genMsg, &parms, 1, (BYTE *)&purgeInfo, + &numEntriesReturned); +error_ret: ; + if (rc != zOK || (numEntriesReturned < 1)) + { + ClearErrno(genMsg); + RTN_NINT(INVALID_UTC_TIME); + } + else RTN_NINT(purgeInfo.key.deltime); +} + +#if NSS_DEBUG IS_ENABLED +/**************************************************************************** + * Called from command line parser to display the given tree + ****************************************************************************/ +void ZfsDisplayPurgeTreeNew( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm) +{ + GeneralMsg_s genMsg; + ZfsVolume_s *volume; + + MPKNSS_LOCK(); + COMN_SETUP_GENERAL_MSG_NOSA(&genMsg); + volume = (ZfsVolume_s *)COMN_VolumeNameLookup(&genMsg, + (unicode_t *)switchDef->ret_value,TRUE,NULL); + + if (volume != NULL) + { + MYBT_displayTree(&PurgeTreeInfo, volume->ZFSVOLpurgeTree); + } + else + { + printf(MSG("Volume not found.\n", 427)); + } + COMN_Release(&volume); + MPKNSS_UNLOCK(); +} +#endif /* NSS_DEBUG */ + +STATUS pbt_internalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action) +{ + return MYBT_CALL_INTERNAL_RECOVERY_FUNC(genMsg, &PurgeTreeInfo, pool, + logBuffer, action); +} + +STATUS pbt_logicalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action) +{ + if (action == X_UNDO) + { + return zX_LOGICAL; + } + else if (action == X_L_UNDO) + { + return MYBT_CALL_LOGICAL_RECOVERY_FUNC(genMsg, &PurgeTreeInfo, + pool, pool->purgeTree, logBuffer, action); + } + else + { + /* During REDO we do not have a purgeTree in memory yet */ + zASSERT(action == X_REDO); + return MYBT_CALL_LOGICAL_RECOVERY_FUNC(genMsg, &PurgeTreeInfo, + pool, NULL, logBuffer, action); + } +} diff --git a/src/nwnss/zlss/purgeTree_new.h b/src/nwnss/zlss/purgeTree_new.h new file mode 100644 index 0000000..c6bccc4 --- /dev/null +++ b/src/nwnss/zlss/purgeTree_new.h @@ -0,0 +1,122 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define internal structures and functions for Purge Tree + | This file should not be used outside purge tree code. + +-------------------------------------------------------------------------*/ + +#ifndef _PURGETREE_NEW_H_ +#define _PURGETREE_NEW_H_ + +#define PURGETREE_NEW_MAGIC 0x32475250 /* "PRG2" */ + +#ifndef _MYBTREE_H_ +#include "myBTree.h" +#endif + +#ifndef _PURGETREE_H_ +#include "purgeTree.h" +#endif + +typedef MYBTreeNode_s PurgeTreeNewNode_s; + +typedef struct PurgeQNewKey_s +{ + GUID_t internalID; /* Beast's volume ID */ + Zid_t zid; /* ZID of the purgeable file. */ + Time_t deltime; /* Effective deletion time */ +// cnt WORD nameUniquifier; /* Name Uniquifier for the above file's name */ + LONG reserved; /* To make the key size a multiple of 64-bits */ +} NSS_MEDIA_STRUCTURE(PurgeQNewKey_s,reserved) PurgeQNewKey_s; + +typedef struct PurgeQNewValue_s +{ + Zid_t pzid; /* ZID of File's parent directory */ +} NSS_MEDIA_STRUCTURE(PurgeQNewValue_s,pzid) PurgeQNewValue_s; + +typedef struct PurgeNewInfo_s +{ + PurgeQNewKey_s key; + PurgeQNewValue_s value; +} NSS_MEDIA_STRUCTURE(PurgeNewInfo_s,value.reserved) PurgeNewInfo_s; + +extern MYBTreeInstanceInfo_s PurgeTreeInfo; + +#define PBT_NEW_IS_LEAF(_n) MYBT_IS_LEAF(_n) +#define PBT_NEW_LEAF_ENTRY(_n, _i) \ + ((PurgeNewInfo_s *)MYBT_LEAFENTRY(&PurgeTreeInfo, _n, _i)) +#define PBT_NEW_BRANCH_ENTRY(_n, _i) MYBT_BRANCHENTRY(&PurgeTreeInfo, _n, _i) + +/* Doesn't assert */ +#define PBT_NEW_IS_NODE_VALID(_node) \ + ((((PurgeTreeNewNode_s *)_node)->magic == PURGETREE_MAGIC) \ + ? PBT_IS_NODE_VALID(_node) \ + : MYBT_IS_NODE_VALID(&PurgeTreeInfo, _node)) + +/* + * Debug stuff + */ + +#if NSS_DEBUG IS_ENABLED +void ZfsDisplayPurgeTreeNew( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +#define zfsDisplayPurgeTreeNewNode(_location, _nameOfBuffer, _buffer) \ + MYBT_displayNode(&PurgeTreeInfo, _location, _nameOfBuffer, _buffer) + +/* Asserts on invalid nodes */ +#define PBT_NEW_VALIDATE_NODE(_node) \ + if (((PurgeTreeNewNode_s *)_node)->magic == PURGETREE_MAGIC) \ + { \ + PBT_VALIDATE_NODE(_node); \ + } \ + else { \ + MYBT_VALIDATE_NODE(&PurgeTreeInfo, _node); \ + } +#else +#define PBT_NEW_VALIDATE_NODE(_node) ((void)0) +#endif + +/* + * Upgrade a purgeTree node from old format to new format. + */ +STATUS pbtUpgradeNode( + GeneralMsg_s *genMsg, + Buffer_s *buf, + BYTE mode, + BOOL *modified); /* out Was node modified? */ + +#endif /* _PURGETREE_NEW_H_ */ diff --git a/src/nwnss/zlss/repairBtree.h b/src/nwnss/zlss/repairBtree.h new file mode 100644 index 0000000..447afd0 --- /dev/null +++ b/src/nwnss/zlss/repairBtree.h @@ -0,0 +1,173 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Storage Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Work with the free extent tree + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRBTREE_H_ +#define _REPAIRBTREE_H_ + + +#ifndef _NSS_DIR_H_ +#include "dir.h" +#endif + +#ifndef _REPAIRRAV_H_ +#include "repairRAV.h" +#endif + +#ifndef _REPAIRMAIN_H_ +#include "repairMain.h" +#endif + + +#ifndef _EFLTREE_H_ +#include "eflTree.h" +#endif + +/* Pre-declare the following structure(s) */ +struct PurgeKey_s; +struct BeastTreeNode_s; + +/* the froolowing defines are for controlling the two passes in verify */ +/* BMP_TST_EXTENT is the first pass to account for all blocks in system */ +/* FIND_BLOCK is the second pass iff needed to find corss linked blocks */ +#define BMP_TST_EXTENT 1 +#define FIND_BLOCK 2 + +#define BTREE_BLOCKS 0 +#define ZLOG_BLOCKS 1 +#define SUPER_BLOCKS 2 +#define PURGELOG_BLOCKS 3 +#define FILE_BLOCKS 4 +#define DIR_BLOCKS 5 +#define FREE_BLOCKS 6 +#define SALVAGE_BLOCKS 7 +#define NAME_BLOCKS 8 +#define DATA_BLOCKS 9 + +#define ZIDTABLEENTRY_FLAG_NAMED 0x01 + + +////FixFixFix6 +////WARNING-THERE IS A DUPLICATE DEFINITION OF THIS STRUCTURE IN ZLSSLSSOPS.C +////CALLED ZFSPackedroot_s. If you change this, it must be changed there too!!!! +//typedef struct PackedRoot_s +//{ +// ZnodeHeader_s header; +// BYTE beastLayout; +// BYTE blkSizeShift; +// WORD sizeFmap; +// LONG metaDataSeqNum; +// QUAD eof; +// Blknum_t nextBlk; +// Blknum_t fmapDataBlks; +// Blknum_t fmapTreeBlks; +// BYTE reserved[10]; +// WORD variableSize; /* Size of variable packed root data */ +// BYTE fmap; +//} PackedRoot_s; + +typedef struct ZidTableEntry_s +{ + Zid_t zid; + BYTE flag; +} ZidTableEntry_s; + + +typedef struct ZidTableHeader_s +{ + Zid_t minZid; + Zid_t maxZid; + LONG numEntries; +} ZidTableHeader_s; + + +typedef struct ZidTable_s +{ + ZidTableHeader_s header; + ZidTableEntry_s zidEntry[(4096-sizeof(ZidTableHeader_s)) / sizeof(ZidTableEntry_s)]; +} ZidTable_s; + + +typedef struct indirectFmapBlock_s +{ + Blknum_t nextBlk[1000]; +} indirectFmapBlock_s; + +ZVP_ERROR ZVP_FMTreeWalk(VerifyStats_s *vStats, BTStats_s *BTStats, Blknum_t rootBlk, Blknum_t *cntNextBlk, Zid_t volZid); +STATUS VerifyFMTreeWalk(GeneralMsg_s *genMsg, RepairStats_s *stats, RBTStats_s *RBTStats, Fmap_s *fMap, Blknum_t *cntFmapDataBlks, Blknum_t *cntFmapTreeBlks, Blknum_t *cntNextBlk, Zid_t fileZid); +LONG ZVP_EFLTreeAndLogWalkPool(VerifyStats_s *vStats); +LONG ZVP_EFLTreeAndLogWalk(VerifyStats_s *vStats, EFLStats_s *EFLStats, Blknum_t rootBlock, Zid_t volZid); +LONG ZVP_MFLTreeWalkPool(VerifyStats_s *vStats); +LONG ZVP_MFLTreeWalk(VerifyStats_s *vStats, MFLStats_s *MFLStats, Blknum_t rootBlock, Zid_t volZid); +LONG ZVP_DBTTreeWalkPool(VerifyStats_s *vStats); +LONG ZVP_UBTTreeWalkPool(VerifyStats_s *vStats); +STATUS ZVP_UBTTreeWalk(VerifyStats_s *vStats, UBTStats_s *UBTStats, Blknum_t rootBlock, Blknum_t ubtFree, Zid_t volZid); +STATUS ZVP_DBTTreeWalk(VerifyStats_s *vStats, DBTStats_s *DBTStats, Blknum_t rootBlock, Zid_t volZid); +ZVP_ERROR ZVP_FreeTreeWalk(VerifyStats_s *vStats, FTStats_s *FTStats); +LONG ZVP_BeastTreeWalkPool(VerifyStats_s *stats); +//LONG BeastTreeWalk(VerifyStats_s *vStats, BTStats_s *BTStats, Blknum_t rootBlock, Blknum_t specialBlock, Zid_t volZid); +LONG ZVP_NameTreeWalkPool(VerifyStats_s *stats); +LONG ZVP_NameTreeWalk(VerifyStats_s *vStats, NTStats_s *NTStats, Blknum_t rootBlock, Zid_t volZid, ZVP_NTData_s *ntData); +ZVP_ERROR ZVP_SalvageTreeWalkPool(VerifyStats_s *vStats); +ZVP_ERROR ZVP_SalvageTreeWalk(VerifyStats_s *vStats, STStats_s *STStats, Zid_t volZid); +void ZVP_mapTestSetBit(VerifyStats_s *stats, Blknum_t blockNum, Zid_t volZid); +STATUS repairTestSetBit(RepairStats_s *stats, Blknum_t blockNum); +void setSysBlockBit(RepairStats_s *stats, Blknum_t blockNum); +void clrSysBlockBit(RepairStats_s *stats, Blknum_t blockNum); +void ZRB_SetFmapBlockBit(RepairStats_s *stats, Blknum_t blockNum); +void ZVP_checkBlockForConflicts(VerifyStats_s *stats, Blknum_t blockNum, Zid_t volZid); +void checkBlockForConflicts(VerifyStats_s *stats, Blknum_t blockNum, Zid_t volZid); +STATUS testForConflictFMTreeWalk(RepairStats_s *stats, Fmap_s *fmap); +STATUS freeConflictFMTreeWalk(GeneralMsg_s *genMsg, RepairStats_s *stats, Fmap_s *fmap, RBTStats_s *RBTStats); + +STATUS VerifyAndLoadLVSystemBeasts(GeneralMsg_s *genMsg, ZfsVolume_s *vol); +STATUS UnloadlvSystemBeasts(GeneralMsg_s *genMsg, ZfsVolume_s *vol); +//g void verifylog_WriteDeletedFilenameToLog (GeneralMsg_s *genMsg,VerifyStats_s *vStats,Zid_t parentZid, NINT nameType,NINT nameSpaceID,unicode_t *name,VolumeID_t volID); +SNINT purgekey_compare(struct PurgeKey_s *k1, struct PurgeKey_s *k2); + +STATUS ZRB_PackSystemBeastInSpecialBlock( + GeneralMsg_s *genMsg, + RBTStats_s *rbtStats, + struct RootBeast_s *systemBeast, + Zid_t beastZid, + struct BeastTreeNode_s *specialNode); + +STATUS ZRB_PackBeastInBlock( + GeneralMsg_s *genMsg, + RBTStats_s *rbtStats, + struct RootBeast_s *systemBeast, + struct BeastTreeNode_s *specialNode); + +#endif diff --git a/src/nwnss/zlss/repairMain.h b/src/nwnss/zlss/repairMain.h new file mode 100644 index 0000000..22dc8bc --- /dev/null +++ b/src/nwnss/zlss/repairMain.h @@ -0,0 +1,258 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Service (NSS) Debug Menu module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Manage display/edit templates. + | + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRMAIN_H_ +#define _REPAIRMAIN_H_ + +#include + +#ifndef _QUE_H_ +#include "que.h" +#endif + +#ifndef _VOLUME_H_ +# include "volume.h" +#endif + +#ifndef _ZFS_H_ +# include "zfs.h" +#endif + +#ifndef _USERTREE_H_ +# include "userTree.h" +#endif + +#ifndef _DIRTREE_H_ +# include "dirTree.h" +#endif + +#ifndef _DIR_H_ +# include "dir.h" +#endif + +#ifndef _ZLSSLOGICALVOLUME_H_ +# include "zlssLogicalVolume.h" +#endif + +#include "repairRAV.h" +#include "repairZVP.h" +#include "repairZRP.h" + +/* defines for rebuild orphanage sub directories */ +#define ZRB_ORPHAN_DIR 0 +#define ZRB_ORPHAN_EA_DIR 1 +#define ZRB_ORPHAN_NDS_DIR 2 +#define ZRB_ORPAHN_DELETED_DIR 3 +#define ZRB_ORPHAN_UNKNOWN_DIR 4 +#define ZRB_ORPHAN_DUP 5 +#define ZRB_ORPHAN_EA_DUP 6 +#define ZRB_ORPHAN_NDS_DUP 7 +#define ZRB_ORPHAN_DELETED_DUP 8 +#define ZRB_ORPHAN_UNKNOWN_DUP 9 +#define ZRB_ORPHAN_DIR_COUNT 10 + +////////////////////////////////////////////////////////////// + + +//gtypedef struct RollUpStats_s /* User Interface sum total of data from LVs etc */ +//g{ +//g NINT MainStatsPage; // UI control +//g SNINT ConflictsPage; // UI control +//g} RollUpStats_s; + + + +////////////////////////////////////////////////////////////////////// + + +//gvoid repairlog_WriteRealRepairLogFileToVolume( GeneralMsg_s *genMsg, RepairStats_s *stats, char *repairString ); +//gvoid repairlog_CloseRepairLogFileToVolume( GeneralMsg_s *genMsg, void *stats, NINT flag ); +//gextern void repairlog_CreateRepairLogFileToVolume( GeneralMsg_s *genMsg, void *stats, char *volumeName, NINT flag ); + + + +/* Prototypes */ +LONG GetCharSem(LONG handle, LONG *value, LONG *semphore); // temporary prototype +//STATUS UBT_verifyNode(UserTreeNode_s *node); +STATUS ZRB_UBTTreeWalk(RepairStats_s *stats, RUBTStats_s *RUBTStats ,Blknum_t rootBlock); +STATUS ZRB_VisitUBTNode(UserTreeNode_s *node, RepairStats_s *stats, RUBTStats_s *RUBTStats); +STATUS UsrNode_validateNode(UserTreeNode_s *node); +STATUS DsrNode_validateNode(DirTreeNode_s *node); +STATUS OldUsrNode_validateNode(OldUserTreeNode_s *node); + +extern void ZRB_ValidateAndMapSRTrees( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + RepairStats_s *stats, + RBTStats_s *RBTStats, + RUBTStats_s *RUBTStats, + RDBTStats_s *RDBTStats, + unicode_t *lvName); + +void ZRB_LoadUserAndDsrBeasts( + GeneralMsg_s *genMsg, + RepairStats_s *stats, + RBTStats_s *RBTStats); + +extern STATUS ZUP_CheckForLeftBlockCleanup( + GeneralMsg_s *genMsg, + RepairStats_s *stats, + BOOL *needToCreateSpecialBlk); + +extern STATUS ZUP_CreateSpecialBeastsBlock( + GeneralMsg_s *genMsg, + RepairStats_s *stats); + +extern STATUS ZUP_CheckToMapSRTrees( + GeneralMsg_s *genMsg, + RepairStats_s *stats); + +extern STATUS ZUP_CheckAndSetVolumeBeastVersion( + GeneralMsg_s *genMsg, + RepairStats_s *stats); + +extern STATUS ZUP_CheckAndCreateLV( + GeneralMsg_s *genMsg, + RepairStats_s *stats ); + +extern STATUS ZUP_LogicalVolumeUpgradeCleanup ( + GeneralMsg_s *genMsg, + RepairStats_s *rStats, + ZfsPool_s *pool, + RBTStats_s *rbtStats, + ZfsVolume_s *zVolume); + + +/************************************************************************** + * + * REZID related defines and prototypes + * + **************************************************************************/ + + +#define REZID_IN_PROCESS(_zfsvol) \ + ((_zfsvol)->ZFSVOLvol.p.stateAttributes & VOLSTATEATTR_REZID) + +STATUS REZID_DoRezid( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + RBTStats_s *rbtStats, + RepairStats_s *stats); + + +void SaveLeafInfoEnd( + RBTStats_s *RBTStats); + +STATUS SaveLeafInfo( + Blknum_t blockNum, + Zid_t lowestZid, + RepairStats_s *stats, + RBTStats_s *RBTStats, + GeneralMsg_s *genMsg); + +STATUS BuildNewBeastTree( + ZfsPool_s *pool, + Blknum_t leftLeaf, + Blknum_t specialLeaf, + GeneralMsg_s *genMsg, +//g NINT *volumeBitMap, + LONG leafCount, + RepairStats_s *stats, + RBTStats_s *RBTStats); + +STATUS ZRB_AllocationMapPass(GeneralMsg_s *genMsg, + RepairStats_s *stats, + RBTStats_s *RBTStats, + LONG *leafCount, + BOOL specialBlockExists); + +NamedBeast_s *ZRB_GetDestinationDirectory(GeneralMsg_s *genMsg, + NamedBeast_s *beast, + ParentEntry_s *parent, + RepairStats_s *stats, + RBTStats_s *RBTStats, + ZfsXaction_s *xaction, + BOOL *fileMoved ); + +STATUS ZRB_CreateDot1Dir(GeneralMsg_s *genMsg, + RepairStats_s *stats, + RBTStats_s *RBTStats, + Volume_s *volume); + + +STATUS COMPFIX_VerifyAndLoadLVSystemBeasts( + GeneralMsg_s *genMsg, + Volume_s *vol); + +STATUS COMPFIX_UnloadlvSystemBeasts( + GeneralMsg_s *genMsg, + Volume_s *vol); + +void COMPFIX_verify_FlushVolVolumeBuffers( + Volume_s *vol); + + +BOOL RAV_BlockIsEndBlock( Blknum_t blockNum ); +STATUS ZRB_ReadInPoolDataBlock( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + ZlssPool_s *zlssPool, + ZLSSCheckIOProcess_s *ZCProcessPtr ); + +STATUS ZRB_BuildVolDataBlocks(GeneralMsg_s *genMsg, + RepairStats_s *stats, + RBTStats_s *RBTStats, + NINT zv_repairFlags); +STATUS ZRB_CreateNewVolSystemBeasts(GeneralMsg_s *genMsg, RepairStats_s *stats, ZRP_LVData_s *RLVStatsPtr); +void ZRB_InitVolumeData(ZfsVolume_s *zfsVol,NINT repairFlags,BOOL virtualFileFlag,RBTStats_s *RBTStats); +void ZRB_ModifyVolDataBlock(GeneralMsg_s *genMsg, RBTStats_s *RBTStats); +STATUS ZRB_WriteNameTreeBeastToDisk(GeneralMsg_s *genMsg, RepairStats_s *rStats, RBTStats_s *RBTStats, RVDBStats_s *RVDBStats, ZfsNameTree_s *nameTreeBeast); +STATUS ZRB_BuildPoolDataBlocks(GeneralMsg_s *genMsg, RepairStats_s *stats, RBTStats_s *RBTStats); +STATUS ZRB_ReBuildNameTree(GeneralMsg_s *genMsg,RepairStats_s *stats,RBTStats_s *RBTStats, ZfsBeastTreeBeast_s *beastTree); +void ZRB_ModifyPoolDataBlock(GeneralMsg_s *genMsg, RepairStats_s *stats); +STATUS ZRB_CreateOrphanageDir(GeneralMsg_s *genMsg, RepairStats_s *stats, RBTStats_s *RBTStats, Volume_s *volume ); +STATUS ZRB_WriteSalvageTreeBeastToDisk(GeneralMsg_s *genMsg, RepairStats_s *rStats, RBTStats_s *RBTStats, RVDBStats_s *RVDBStats, ZfsPurgeTreeBeast_s *salvageBeast); +STATUS ZRB_CreateNewPoolSystemBeasts(GeneralMsg_s *genMsg,RepairStats_s *stats); +void ZRB_InitPoolData(RepairStats_s *stats); +STATUS ZRB_UnloadSystemBeasts(GeneralMsg_s *genMsg, ZfsPool_s *pool, ZLSSCheckIOProcess_s *ZCProcessPtr); +void GetLeafInfoEnd(RepairStats_s *stats, RBTStats_s *RBTStats); +STATUS BuildNewFreeTree(GeneralMsg_s *genMsg,ZfsPool_s *pool,Blknum_t specialLeaf,ZfsFreeExtent_s *freeTreeBeast, RepairStats_s *stats); +STATUS updateFreeTree(GeneralMsg_s *genMsg,ZfsPool_s *pool,Blknum_t specialLeaf,ZfsFreeExtent_s *freeTreeBeast, RepairStats_s *stats); +STATUS beastTreeBranchPass(GeneralMsg_s *genMsg,ZfsPool_s *pool, RepairStats_s *stats, RBTStats_s *RBTStats); + +#endif diff --git a/src/nwnss/zlss/repairMap.h b/src/nwnss/zlss/repairMap.h new file mode 100644 index 0000000..2e9130a --- /dev/null +++ b/src/nwnss/zlss/repairMap.h @@ -0,0 +1,114 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Service (NSS) Debug Menu module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Manage display/edit templates. + | + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRMAP_H_ +#define _REPAIRMAP_H_ + +#ifndef _OMNI_H_ +# include +#endif + + +#ifndef _VOLUME_H_ +# include +#endif + +#ifndef _ZLSSLOGICALVOLUME_H_ +# include +#endif + +#ifndef _REPAIRBTREE_H_ +# include "repairBtree.h" +#endif + +#ifndef _REPAIRMAIN_H_ +# include "repairMain.h" +#endif + + +#ifndef _BEASTTREE_H_ +# include "beastTree.h" +#endif + +/* Misc definitions */ + + + +/* defines */ +#define MAX_CONFLICTS 1000 + +/* global vars */ + + +/* Function prototypes */ + +LONG MapPoolBlocks(VerifyStats_s *vStats); +NINT *CreateVolBitMap(ZfsPool_s *poolInfo); +void DestroyBitMap(NINT *VolBitMap); +LONG MapTestFreeBlocks(VerifyStats_s *stats); +LONG MapTestExtent(VerifyStats_s *vStats, Extent_s *extent, NINT flag); +LONG CheckMapUnaccountedBlocks(VerifyStats_s *stats, ZfsPool_s *poolInfo, NINT *VolBitMap); +void zeroBitMap(NINT *volumeBitMap, LONG bitMapSize); +LONG MapTestFileMap(VerifyStats_s *vStats, BTStats_s *BTStats, NINT *blockCount, Fmap_s *fMap, Blknum_t numNextBlk, Zid_t volZid); +LONG MapTestFileExtent(VerifyStats_s *vStats, NINT blockType, Blknum_t poolBlk, LONG blkcnt); +STATUS MapTestSuperBlk(VerifyStats_s *vStats); +STATUS ZRB_ValidateSuperBlks(GeneralMsg_s *genMsg, RepairStats_s *stats ); +Blknum_t ZRB_getRebuildBlock(Blknum_t blknum, RepairStats_s *stats); +STATUS initX_LinkedBitMap(GeneralMsg_s *genMsg, RepairStats_s *stats); +LONG MapTestVolumeBlkPool(VerifyStats_s *stats); +LONG MapTestVolumeBlk(VerifyStats_s *stats, VDBStats_s *VDBStats, Zid_t volZid); +STATUS VerifyVolumeBlk(GeneralMsg_s *genMsg, RepairStats_s *stats, Blknum_t volumeBlock); +Blknum_t GetVolumeBlock(GeneralMsg_s *genMsg, ZfsPool_s *pool, Blknum_t leafBlk); +LONG MapTestPurgeLog(VerifyStats_s *vStats, BTStats_s *BTStats, Blknum_t purgeFirstBlk, Zid_t volZid); +STATUS VerifyFileMap(GeneralMsg_s *genMsg, ZfsPool_s *pool, BeastTreeNode_s *node, RepairStats_s *stats, RBTStats_s *RBTStats, Buffer_s *buffer); +void initNode (Buffer_s *buffer, NINT state, GUID_t *internalID); +BOOL findZnodeByZid(BeastTreeNode_s *node, Zid_t zid, NINT *i); +void deleteZnodeFromChild(BeastTreeNode_s *child, NINT recNum); +STATUS testFmapForConflict(RepairStats_s *stats, Fmap_s *fmap); +STATUS freeConflictFmap(GeneralMsg_s *genMsg, RepairStats_s *stats, Fmap_s *fmap, RBTStats_s *RBTStats); +STATUS freeConflictExtent(GeneralMsg_s *genMsg, RepairStats_s *stats, Blknum_t reqBlk, Blknum_t reqLen, RBTStats_s *RBTStats); +LONG MapTestZLogBlocks(VerifyStats_s *stats); +//gSTATUS testConflictBit(RepairStats_s *stats, Blknum_t blockNum); +STATUS ZRB_XLinkedTest(RepairStats_s *stats, Blknum_t blockNum); +STATUS ZRB_lvAllocationMapPass(GeneralMsg_s *genMsg, RepairStats_s *stats, ZlssVolumeLocator_s *lvBeast); +STATUS ZRB_FMAPFreeConflictBlocks(GeneralMsg_s *genMsg, RepairStats_s *stats); +void ZRB_ReservePoolDataBlocks(RepairStats_s *stats); +void ReBuildLogTruncateBeast( GeneralMsg_s *genMsg, RepairStats_s *stats, RBTStats_s *RBTStats, + RootBeast_s *beast, NINT reasonMask, QUAD dataEOF ); + +#endif diff --git a/src/nwnss/zlss/repairRAV.h b/src/nwnss/zlss/repairRAV.h new file mode 100644 index 0000000..eb22211 --- /dev/null +++ b/src/nwnss/zlss/repairRAV.h @@ -0,0 +1,262 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996, 2004 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Common items for Rebuild and Verify(RAV) + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2008-05-31 03:21:58 +0530 (Sat, 31 May 2008) $ + | + | $RCSfile$ + | $Revision: 2356 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Common items for Rebuild and Verify(RAV) + | + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRRAV_H_ +#define _REPAIRRAV_H_ + +#include +#include +#include +#include + +extern DQhead_t ZCheckProcessList; // FixFixFix(ZVPSkip,6,.01) remove extern when all Thread stuff in repairRAV.c +extern Latch_s ZCheckProcessListLatch;// FixFixFix(ZVPSkip,6,.01) remove extern when all Thread stuff in repairRAV.c +extern DQhead_t RAV_FinalStatList; +extern Latch_s RAV_FinalStatListLatch; + + +#define RAV_DX_DEBUG_FILE 0x00000008 // Debug status file +#define RAV_DX_LOG_FILE 0x00000004 // Log status file (Items that should be logged (made persistent) by UI) +#define RAV_DX_DETAIL_FILE 0x00000002 // Detailed status file +#define RAV_DX_STATUS_FILE 0x00000001 // Normal status file + + +/* + ZLSSCheckIOProcess_s is used by the ZLSS thread while it is rebuilding or verifing. Once + the thread completes this structure is freed. + */ +typedef struct ZLSSCheckIOProcess_s +{ + DQlink_t ZCIOP_link; + NINT ZCIOP_inuse; +// FixFixFix(ZVPDone,1,1) Remove ZCIOP_flag - NSS 4.0 is using VPS_Terminate +//g NINT ZCIOP_flag; + VP_Status_s *ZCIOP_pInfo; /* Contains element VPS_Type - which is either NSS_TYPE_VERIFY or NSS_TYPE_REBUILD */ + + +// FixFixFix(ZVPDone,5,.01) Remove next Four items when port to NSS 4.0 is done +//g LONG ZCIOP_screenHandle; +//g LONG ZCIOP_mainWinHandle; +//g PBAR ZCIOP_bar; +//g SBAR ZCIOP_sbar; +//g void *ZCIOP_bar; +//g void *ZCIOP_sbar; +//g LONG ZCIOP_logFileErrWinHandle; + + ZfsPool_s *ZCIOP_zfsPool; + ZlssPool_s *ZCIOP_zlssPool; + struct RAVStats_s *ZCIOP_ravStats; /* Used by both verify and rebuild. Can only use while + * RAV_FinalStatListLatch is held otherwise + * the RAVStats_s can be freed by another thread. This + * element should only be USED by the XML code that returns + * the status of an active verify/rebuild. + * Note that the RAVStats_s are 'saved' right before the + * thread goes away. This is done by placing them on + * the RAV_FinalStatList list. + */ + NINT ZCIOP_ravStatsKeeper; +#define ZVP_KEEPER_NONE 0 +#define ZVP_KEEPER_PDATA 1 +#define ZVP_KEEPER_FINAL 2 +// struct ZVP_Status_s *ZCIOP_uiStatus; +//g BOOL ZCIOP_rebuildPurge; +} ZLSSCheckIOProcess_s; + + +typedef struct RAVStats_s +{ + char RAVS_MagicStart[16]; + NINT RAVS_Type; /* Either NSS_TYPE_REBUILD or NS_TYPE_VERIFY */ + DQlink_t RAVS_FinalStatListLink; + ZLSSCheckIOProcess_s *RAVS_ZCProcessPtr; + QUAD RAVS_UserKey; + Time_t RAVS_StartTime; // Official time that operation started + unicode_t RAVS_PoolName[64]; + GeneralMsg_s RAVS_GenMsg; // Non-stack genmsg + GeneralMsg_s RAVS_FinalErrno; // Tracks the final results if an ERROR(See ZVP_Error_Return or ZRP_Error_Return) + const char *RAVS_Caller; // Location within RAV that RAVS_GenMsg error was detected + QUAD RAVS_LogKey; // All items that can shrink in the Log file SHARE this key!!! + QUAD RAVS_DebugKey; // All items that can shrink in the Debug file SHARE this key!!! + QUAD RAVS_DetailKey; // All items that can shrink in the Detail file SHARE this key!!! + QUAD RAVS_LogKeyRemove; // Highest Remove key done so far. + QUAD RAVS_DebugKeyRemove; // Highest Remove key done so far. + QUAD RAVS_DetailKeyRemove; // Highest Remove key done so far. +} RAVStats_s; + + +typedef struct RAV_DynamicStats_s +{ + DQhead_t RDS_Head; // Head of ALL dynamic stats within POOL object (including + // the IV). Used so certain routines can operate on all of + // the RAV_GrowingStats_s without knowing all of their + // names (RDS_BlockConflicts, RDS_LVSkiped, ...) +} RAV_DynamicStats_s; + + + +struct RAV_GrowingStats_s; + +//typedef STATUS (*GS_Record)(RAV_GrowingStats_s *rGS, ... ); +typedef unsigned int (*GS_PackSize)( struct RAV_GrowingStats_s *rGS ); +typedef void (*GS_Pack)( struct RAV_GrowingStats_s *rGS, NINT *bLen, BYTE **bAdd, NINT *rLen ); + +/* + Stats that are dynamic + */ +typedef struct RAV_GrowingStats_s +{ + DQlink_t RGS_Link; // Link through all RGS's of an Object. Used + // so certain routines do not need to known + // the names of all of the stats that are + // RAV_GrowingStats_s. + Latch_s RGS_Latch; + QUAD RGS_SectionId; // Unique ID of Section value + BOOL RGS_Growable; // True if object should be grown when currently full. + BOOL RGS_WaitType; // True if object should wait for items to be removed. + unsigned int RGS_ItemsMaximum; // Maximum number of ELEMENTs that object can grow to. + unsigned int RGS_ItemSize; // Size in bytes of each item + unsigned int RGS_ItemGrowCount; // Default number of items to grow by when we need to grow + unsigned int RGS_ItemsCurrent; // Number of items we CAN currently hold ( <= RGS_ItemsMaximum ). + unsigned int RGS_NumberOfElements; // Number of items that are in use ( <= RGS_ItemsCurrent ). +// GS_Record RGS_Record; + GS_PackSize RGS_PackSize; + GS_Pack RGS_Pack; + void *RGS_Data; +} RAV_GrowingStats_s; + + +typedef LONG ZVP_ERROR; // Indicates that an error return will cause Verify to STOP + +typedef struct RAVGSInitItems_s { + unsigned int RGII_Major; // Fields if we ever have an application that 'pokes' values. + unsigned int RGII_Minor; // Fields if we ever have an application that 'pokes' values. + unsigned int ZVP_GS_INIT_WAITER_ACTION; + unsigned int ZVP_GS_INIT_WAITER_DEBUG; + unsigned int ZVP_GS_INIT_WAITER_MESSAGE; + unsigned int ZVP_GS_INIT_UNACCOUNTABLEBLOCKS; + unsigned int ZVP_GS_INIT_CROSSLINKEDBLOCKS; + unsigned int ZVP_GS_INIT_LVSSKIPPED; + unsigned int ZVP_GS_INIT_CBS; + unsigned int ZVP_GS_INIT_BT; + unsigned int ZVP_GS_INIT_NT; + unsigned int ZVP_GS_INIT_ST; + unsigned int ZRP_GS_INIT_WAITER_ACTION; + unsigned int ZRP_GS_INIT_WAITER_DEBUG; + unsigned int ZRP_GS_INIT_WAITER_IORECORD; + unsigned int ZRP_GS_INIT_WAITER_MESSAGE; + unsigned int ZRP_GS_INIT_WAITER_TOD; + unsigned int ZRP_GS_INIT_PRUNE; + /* Next three items added May 2008 in version 1.01 */ + unsigned int ZRP_FILE_SIZE_DETAIL; + unsigned int ZRP_FILE_SIZE_LOG; + unsigned int ZRP_FILE_SIZE_OTHER; +} RAVGSInitItems_s; + +struct BlockMap_s; +STATUS RAV_BM_SetBlock( Blknum_t blockNum, struct BlockMap_s *bitMap ); +BOOL RAV_BM_Legal( struct BlockMap_s *bitMap ); +BOOL RAV_BlockOn( struct BlockMap_s *bitMap, Blknum_t blockNum ); +STATUS RAV_TestBlock( Blknum_t blockNum, struct BlockMap_s *bitMap, BOOL *blockSet ); +STATUS RAV_TestAndSetBlock( Blknum_t blockNum, struct BlockMap_s *bitMap ); +void RAV_TestAndSetBlockShutdown( char *where, struct BlockMap_s *bitMap ); +STATUS RAV_TestAndSetBlockStartup( char *where, Blknum_t numberOfBlocks, struct BlockMap_s *bitMap ); + +STATUS RAV_ProcessNew( ZLSSCheckIOProcess_s **pPData, ZlssPool_s *zlssPool, VP_Status_s *pInfo ); +void RAV_ProcessDestroy( ZLSSCheckIOProcess_s *pData ); + +STATUS RAV_ResourceFree( GeneralMsg_s *genMsg, QUAD userKey ); +void RAV_RAVStats_s_Init( RAVStats_s *ravStats, ZLSSCheckIOProcess_s *pData, NINT type ); +void RAV_VS_ActionHistoryDisplay( + struct RAV_GrowingStats_s *rGS, + NINT bLen, + BYTE **bAdd, + NINT *rLen ); +void RAV_VS_IORecordDisplay( + struct RAV_GrowingStats_s *rGS, + NINT bLen, + BYTE **bAdd, + NINT *rLen ); +Buffer_s *RAV_ReadPoolBlk(GeneralMsg_s *genMsg, IoMsg_s *ioMsg, BOOL *cacheHit ); + + +void RAV_RDS_Destroy_Pool( RAV_DynamicStats_s *rDS ); +void RAV_GS_Destroy( RAV_GrowingStats_s *rGS ); +#define RAV_GS_WAITER TRUE +STATUS RAV_GS_Init( RAV_GrowingStats_s *rGS, QUAD sectionID, BOOL waiter, BOOL growable, + unsigned int itemsMaximum, unsigned int itemsOriginal, unsigned int growCount, unsigned int itemSize, + DQhead_t *head, GS_PackSize packSizeRoutine, GS_Pack packRoutine ); +void RAV_GS_PackDefault( RAV_GrowingStats_s *rGS, NINT *bLen, BYTE **bAdd, NINT *rLen ); +unsigned int RAV_GS_PackSizeDefault( RAV_GrowingStats_s *rGS ); +BOOL RAV_GS_WaitType( RAV_GrowingStats_s *rGS ); +void RAV_GS_WaitTypeSet( RAV_GrowingStats_s *rGS, BOOL type ); +QUAD RAV_GS_SectionID( RAV_GrowingStats_s *rGS ); +STATUS RAV_GS_Grow( RAV_GrowingStats_s *rGS, unsigned int itemsToGrowBy, void *lockKey ); +STATUS RAV_GS_GrowIfNeeded( RAV_GrowingStats_s *rGS, unsigned int itemsNeeded ); +void RAV_GS_RemoveItems( RAV_GrowingStats_s *rGS, unsigned int itemsToRemove, void *gsKey ); +void *RAV_GS_Lock( RAV_GrowingStats_s *rGS, char *where ); +STATUS RAV_GS_Unlock( RAV_GrowingStats_s *rGS, void **pKey, char *where ); + + +struct ZVS_ItemRemoveWithKey_s; +struct RAV_Action_s; + +STATUS RAV_ResourceFreePartial2( + GeneralMsg_s *genMsg, + struct ZVS_ItemRemoveWithKey_s *removeItem, + RAVStats_s *ravStats ); +STATUS RAV_ResourceFreePartial( + GeneralMsg_s *genMsg, + struct ZVS_ItemRemoveWithKey_s *removeItem ); +STATIC void RAV_VS_ActionItemDisplay( + const struct RAV_Action_s *dVar, + NINT bLen, + BYTE **bAdd, + NINT *rLen ); +void RAV_delay( NINT millisec ); + +STATUS RAV_VS_MessageRecordRemove( GeneralMsg_s *genMsg, RAVStats_s *ravStats, QUAD itemKey ); +STATUS RAV_VS_DebugRecordRemove( GeneralMsg_s *genMsg, RAVStats_s *ravStats, QUAD itemKey ); +void RAV_VS_DebugRecordDisplay( RAV_GrowingStats_s *rGS, NINT bLen, BYTE **bAdd, NINT *rLen ); +void RAV_VS_DebugRecordDisplay( RAV_GrowingStats_s *rGS, NINT bLen, BYTE **bAdd, NINT *rLen ); + +void RAV_CopyRightSideOfWhere( char *dest, const char *where, size_t destSize ); + + +extern RAVGSInitItems_s RAVGSInitItems; + +#endif // #ifndef _REPAIRRAV_H_ diff --git a/src/nwnss/zlss/repairRAVDebug.h b/src/nwnss/zlss/repairRAVDebug.h new file mode 100644 index 0000000..a6b97ac --- /dev/null +++ b/src/nwnss/zlss/repairRAVDebug.h @@ -0,0 +1,43 @@ +/* + | (C) Copyright 1995-1998, 2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Service + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + +-------------------------------------------------------------------------*/ + +#include "repairRAV.h" +#include "repairZRP.h" +#include "repairZVP.h" + +void ZVP_AnalysisReport( VerifyStats_s *vStats ); +void ZVP_ConditionReport( ZVP_Status_s *vStatus, ZVP_PoolCondition_s *pC ); +void ZVP_StatusReport( ZVP_Status_s *vStatus ); diff --git a/src/nwnss/zlss/repairZRP.h b/src/nwnss/zlss/repairZRP.h new file mode 100644 index 0000000..55b1b1b --- /dev/null +++ b/src/nwnss/zlss/repairZRP.h @@ -0,0 +1,553 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996, 2004 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Zlss Rebuild Pool(ZRP) engine + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2005-07-08 00:32:35 +0530 (Fri, 08 Jul 2005) $ + | + | $RCSfile$ + | $Revision: 1095 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Structures used by Zlss Rebuild Pool(ZRP) engine + | + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRZRP_H_ +#define _REPAIRZRP_H_ + +#include +#include + +#define ZRP_LOG_ERROR_TAG(_format) "" _format "", WHERE +#define ZRP_LOG_WARNING_TAG(_format) "" _format "", WHERE +#define ZRP_LOG_WARNING_WITH_SOURCE_TAG(_source, _format) "" _format "", WHERE, _source +#define ZRP_LOG_INFO_TAG(_format) "" _format "", WHERE +#define ZRP_LOG_ACTION_REQUIRED_TAG(_format) "" _format "", WHERE +#define ZRP_LOG_FATAL_TAG(_format, _caller, _status, _setter ) \ + "" _format "", _caller, _status, _setter + +#define RAV_DEBUG_TAG(_format) "" _format "", WHERE + +#define REPAIR_PHASE_FILES 0 +#define REPAIR_PHASE_NAMES 1 +#define REPAIR_PHASE_DONE 2 +#define REPAIR_PHASE_START_TIME 0 +#define REPAIR_PHASE_END_TIME 1 + + +/* defines for rebuild orphanage sub directories */ +#define ZRB_ORPHAN_DIR 0 +#define ZRB_ORPHAN_EA_DIR 1 +#define ZRB_ORPHAN_NDS_DIR 2 +#define ZRB_ORPAHN_DELETED_DIR 3 +#define ZRB_ORPHAN_UNKNOWN_DIR 4 +#define ZRB_ORPHAN_DUP 5 +#define ZRB_ORPHAN_EA_DUP 6 +#define ZRB_ORPHAN_NDS_DUP 7 +#define ZRB_ORPHAN_DELETED_DUP 8 +#define ZRB_ORPHAN_UNKNOWN_DUP 9 +#define ZRB_ORPHAN_DIR_COUNT 10 /* Must be a count of the number different directories we can create. */ + + +#define ZRB_VIRTUAL_BLOCKS_REBUILD FALSE // Should be FALSE except when running REBUILD + // on a volume AFTER rebuild has PRUNED a + // BT. See ZRB_VIRTUAL_BLOCKS_FIND to find blocks + // that should be in list below. Rebuild will place + // all the files that were corrupted by the ALLOCed + // blocks in the prune in the RLF file. This + // list can be given to the customer so they know + // which files are corrupt. + + +#define ZRB_BUILD_BBTREE_PASS1 0 +#define ZRB_BUILD_BBTREE_PASS2 1 + +/* defines for rebuilding usr/dsr trees */ +#define ZRB_SR_OLD 0 +#define ZRB_SR_NEW 1 +#define ZRB_USR_FLAG 0 +#define ZRB_DSR_FLAG 1 +#define ZRB_USR_OLD_FLAG 2 + +/*************************/ +/* Structure Definitions */ +/*************************/ + + +#if 0 +typedef struct ZLSSRepairTempLogRecord_s // Now ZRP_TODRecord_s +{ + Zid_t beastZid; /* Added April 2003 */ + VolumeID_t volumeID; /* unique volume ID (guid) */ + Zid_t pZid; + WORD nameType; + BYTE nameSpaceID; + BYTE tmpLogFlag; /* Added April 2003 */ +#define TLF_NAMED_BEAST 0x01 + /* The *6 is to ensure when we convert from unicode to ascii we do not overflow. + * A unicode character can be converted to "[xxxx]" which means 6 times the + * expected ascii size of 1 byte. + */ + char fNameAndMsg[zMAX_COMPONENT_NAME*6]; +} ZLSSRepairTempLogRecord_s; +#endif + + +typedef struct LeafInfo_s +{ + Blknum_t blockNum; + Zid_t lowestZid; +} LeafInfo_s; + + +typedef struct LeafInfoOnDisk_s +{ + Blknum_t headBlockNum; + LeafInfo_s *headBufferStart; + LeafInfo_s *headBufferRemove; + LeafInfo_s *headBufferEnd; + Buffer_s *headBuffer; + + Blknum_t tailBlockNum; + LeafInfo_s *tailBufferStart; + LeafInfo_s *tailBufferInsert; + LeafInfo_s *tailBufferEnd; + Buffer_s *tailBuffer; + +} LeafInfoOnDisk_s; + + +typedef struct RVDBStats_s /* Volume Data Blocks stats */ +{ + Blknum_t dataBlock; // input item + Blknum_t loggedDataBlock; // input item + ZfsVolume_s *zVolume; // current logical volume +} RVDBStats_s; + + +typedef struct RBTStats_s /* Volume BT stats */ +{ + ZfsVolume_s *zVolume; //current logical volume + NINT logicalVolumeFlag; // set (1) if LV, clear (0) if pool + NINT beastTreeBuiltFlag; /* flag that the beast tree was build on the first pass */ + Zid_t RS_GreatestAllocatedZid; /* Greatest ALLOCATED Zid from the + * Beast Tree. This is not usually + * the greatest INUSE ZID because + * NamedBeast_s beasts can allocate + * a range of ZIDs. E.G. A directory + * allocates a range of ZIDs so + * that it does not have to go to + * the volume to get another zid + * every time a file is created within + * the directory. + */ + Blknum_t lastLeafBlk; // last leaf block in the beast tree + LONG leafCount; // for building the new beast tree + Zid_t prevLeafHighZid; + Blknum_t systemBeastBlkNum; + Blknum_t loggedVolumeDataBlk; + Blknum_t volumeDataBlk; + BOOL writeZVLBeast; // need to Write ZVL Beast + QUAD dataNumFiles; // Files + QUAD dataNumObjects; // Objects + QUAD dataNumDeletedFiles; // Files deleted + QUAD dataNumAddedFiles; // Files added + QUAD dataNumDeletedObjects; // Objects deleted + QUAD dataNumAddedObjects; // Objects added + QUAD inUseBlocks; // blocks used by this LV loggedpersistentvolume_s + QUAD inUseConflictBlockCount; + QUAD numDeletedFiles; // number of deleted files in the salvage system + QUAD numPurgeableBlocks; // number of blocks of data in the salvage system + + BOOL BtreePruned; // set TRUE iff errors finding next leaf by traversing BT branches + /* The following are saved when we read in a good LVDB and used only for comparison. + We assume that the numbers are good if we can read and validate the LVDB. */ + QUAD SavedDataNumFiles; // Files + QUAD SavedDataNumObjects; // Objects + QUAD SavedDataNumTotalBlocks; // Total blocks ??? not sure what that means on a volume, quota or what + QUAD SavedInUseBlocks; // blocks used by this LV loggedpersistentvolume_s + QUAD SavedNumPurgeableBlocks; // number of blocks of data in the salvage system + QUAD SavedDataNumNonPurgeableBlocks; // non purgable blocks + QUAD SavedDataNumDeletedFiles; // Files deleted + + SQhead_t RS_branchHead; /* list head struct for list of leaf node info structs */ + SQhead_t RS_deletedBeastZidHead; + NINT queSlotsTaken; + LeafInfoOnDisk_s onDiskList; + NINT leafInfoCount; + NINT leafInfoStoredToDisk; // if true, we're out of memory and have to go to disk for leaf link info + Zid_t reZidCurrentZid; // Used by rezid to keep track of the next consecutive zid + Zid_t rebuildDirNameZid; // zid of the parent directory for orphans "UTCTimeString.FPD" + + Zid_t RS_Dot2Zids[ZRB_ORPHAN_DIR_COUNT]; // The Zids of the directories we have already create. 0 if not created. + NINT numFosterParents; // count of foster parents created on this volume + Zid_t fosterParents[50]; // list of the first 50 + + Blknum_t beastTreeRightMostLeaf; // right most leaf of the beast tree + + QUAD numCompressedFiles; /* number of compressed-not-deleted files */ + QUAD numCompDelFiles; /* number of deleted-and-compressed files */ + QUAD numUncompressibleFiles; /* number of uncompressible files */ + QUAD numCompressedFileBlocks; /* number of file blocks occupied by compressed files */ + QUAD numPreCompressedFileBlocks; /* FixFixFix find out what this means */ + +} RBTStats_s; + + +typedef struct RNTStats_s /* Volume NT stats */ +{ + ZfsVolume_s *zVolume; //current logical volume +} RNTStats_s; + + +typedef struct RUBTStats_s /* Volume USRT stats */ +{ + ZfsVolume_s *zVolume; //current logical volume + NINT USR_flag; /* flag for user space restrictions on or off */ + NINT USR_TreeRebuildflag; /* flag to rebuild user space restrictions tree */ + NINT usrTreeFlag; /* flag to use existing usr tree or rebuild it */ + NINT firstUSRTreeConflictBlkCnt; + GUID_t R_unamGUID; // unique guid for usr tree rebuild UNAM stuff +} RUBTStats_s; + + +typedef struct RDBTStats_s /* Volume DSRT stats */ +{ + ZfsVolume_s *zVolume; //current logical volume + NINT DSR_flag; /* flag for dir space restrictions on or off */ + NINT DSR_TreeRebuildflag; /* flag to rebuild dir space restrictions tree */ + NINT dsrTreeFlag; /* flag to use existing usr tree or rebuild it */ + NINT firstDSRTreeConflictBlkCnt; +} RDBTStats_s; + + +typedef struct RSTStats_s /* Volume ST stats */ +{ + ZfsVolume_s *zVolume; //current logical volume +} RSTStats_s; + + +typedef struct RFTStats_s /* Pool FT stats */ +{ + ZfsVolume_s *zVolume; //current logical volume +} RFTStats_s; + + +typedef struct ZRP_LVNameInfo_s +{ + BOOL ZLNI_lvStateDeleted; // TRUE if volume is deleted. + BOOL ZLNI_lvStatePurging; // TRUE if volume is deleted and being purged. + Time_t ZLNI_dTime; // time volume deleted or purged + unicode_t ZLNI_lvName[zMAX_COMPONENT_NAME]; // lv Name (For SawTooth - the Original Name if a deleted volume) +} ZRP_LVNameInfo_s; + +typedef struct ZRP_LVData_s /* rebuild Logical Volume stats buffer */ +{ + DQlink_t link; // pointer to next logical volume + VolumeID_t lvVolGUID; // lv Volume GUID + Zid_t lvVolZid; // lv Zid +// Time_t epoch; // lv epoch for backup +// QUAD quota; // lv size + + RVDBStats_s lvRVDBStats; // lv Volume Data Block Stats + RBTStats_s lvRBTStats; // lv Beast Tree Stats + RNTStats_s lvRNTStats; // lv Name Tree Stats + RUBTStats_s lvRUBTStats; // lv User space restrictions Tree Stats + RDBTStats_s lvRDBTStats; // lv dir space restrictions Tree Stats + ZfsVolume_s *zVolume; //current logical volume + ZRP_LVNameInfo_s ZLD_Name; +} ZRP_LVData_s; + + + /* Hold items that UI can get while verify is running (this also stays around after thread terminates) */ +typedef struct ZRP_Status_s { + BOOL ZRPS_StatusValid; // Indicates that the ZVP_Status_s has valid information in it + unicode_t ZRPS_PoolName[64]; + LONG ZRPS_BlockSize; + QUAD ZRPS_BlocksTotal; + QUAD ZRPS_ObjectTotal; // Not valid until we are into pass2 + RAV_Action_s ZRPS_Action; + + Time_t ZRPS_StartTime; // Copy of official start time + + QUAD ZRPS_BlocksProcessedPass1; /* pass - blocks that we have processed */ + QUAD ZRPS_ObjectsProcessedPass2; /* pass - Objects that we have processed */ + + + BOOL ZRPS_FinalValid; // Indicates that all status are final + BOOL ZRPS_UIInputRequested; // Indicates that rebuild needs input for pruning + BOOL ZRPS_UIRemoveRequested; // Indicates that rebuild needs UI to eat some growable data. + QUAD ZRPS_UIRemoveID; // The ID that needs to be shrunk!!! + BOOL ZRPS_PruneDataComplete; // Indicates that ALL prune data is available + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(start) **/ + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(start) **/ + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(start) **/ + STATUS ZRPS_TaskStatus; // The status from the rebuild operation. This is not the + // status of the pool condition!!! The condition + // of the pool is store in ZPS_PoolCondition if + // ZRPS_TaskStatus is 0. + char ZRPS_TaskSetter[32]; // Setter of ZRPS_TaskStatus + char ZRPS_TaskCaller[32]; // Caller of ZRPS_TaskStatus + BOOL ZRPS_UserAborted; // TRUE if the verify was aborted before completed. + Time_t ZRPS_EndTime; // When rebuild completed + LONG ZRPS_PoolCondition; // One of the following +#define ZRP_STATUS_GOOD 0 // Pool is good +//#define ZRP_STATUS_WARNINGS 1 // Pool has warnings, but no errors +//#define ZRP_STATUS_UNKNOWN 2 // Verify unable to complete (could not determine if pool is good) +#define ZRP_STATUS_INCOMPLETE 3 // Rebuild unable to complete +//#define ZRP_STATUS_ERRORS 4 // Pool has errors (and may also have warnings). + + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(end) **/ + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(end) **/ + /** Items in this area are only valid when ZRPS_FinalValid is TRUE(end) **/ + + + /** Items in this area are copied from COMN so that they are valid after thread terminates(start) **/ + /** Items in this area are copied from COMN so that they are valid after thread terminates(start) **/ + /** Items in this area are copied from COMN so that they are valid after thread terminates(start) **/ + + /**** Do not use except to return values to users. All other code needs + **** to use pInfo versions as they are up-to-date. Although only + **** valid while thread running. + ****/ + + QUAD ZRPS_UIOptions; + QUAD ZRPS_DebugLevel; /* FixFixFix(ZRP,11,.2) - Copy of COMN layer item that changes!!! */ /* Ouput has comment so go with life? */ + Zid_t ZRPS_RezidThreshold; /* Threshold that LV will be re-zided */ + BOOL ZRPS_Purge; /* Perform purge */ + ZSR_LossLimits_s ZRPS_LimitStart; /* Start loss limits */ + BOOL ZPRS_UIPruneWait; /* Rebuild should wait for UI to set Post loss limit values */ + BOOL ZRPS_UIPruneSet; /* Prune Status has been set */ /* FixFixFix(ZRP,11,.2) - Copy of COMN layer item that changes!!! *//* Ouput has comment so go with life? */ + LONG ZRPS_UIPruneStatus; /* Prune Status (only valid if ZRPS_UIPruneSet is TRUE) */ /* FixFixFix(ZRP,11,.2) - Copy of COMN layer item that changes!!! *//* Ouput has comment so go with life? */ +//ggg ZSR_LossLimits_s ZRPS_LimitPost; /* Post limits (only valid if VPRS_UIPruneSet is TRUE) *//* FixFixFix(ZRPDone,11,.2) - Copy of COMN layer item that changes!!! *//* Ouput has comment so go with life? */ + QUAD ZRPS_UserKey; + + /**** Do not use except to return values to users. All other code needs + **** to use pInfo versions as they are up-to-date. Although only + **** valid while thread running. + ****/ + + /** Items in this area are copied from COMN so that they are valid after thread terminates(end) **/ + /** Items in this area are copied from COMN so that they are valid after thread terminates(end) **/ + /** Items in this area are copied from COMN so that they are valid after thread terminates(end) **/ + +} ZRP_Status_s; + + +typedef struct RepairZfsPoolStats_s /* Pool stats buffer */ +{ + ZRP_Status_s RZPS_uiStatus; /* Status available to UIs while verify is running */ + + RVDBStats_s RVDBStats; // pool Volume Data Block Stats + RBTStats_s RBTStats; // pool Beast Tree Stats + RNTStats_s RNTStats; // pool Name Tree Stats + RUBTStats_s RUBTStats; // pool User space restrictions Tree Stats + RDBTStats_s RDBTStats; // pool dir space restrictions Tree Stats + RSTStats_s RSTStats; // pool Salvage Tree Stats + RFTStats_s RFTStats; // pool Free Tree Stats +// Time_t epoch; // internal volume epoch for backup +// QUAD quota; // internal volume size + + File_s *rebuildBeast; + QUAD numDeletedFiles; // number of deleted files in the salvage system + QUAD numPurgeableBlocks; // number of blocks of data in the salvage system + unicode_t ivName[zMAX_COMPONENT_NAME]; // internal volume Name + DQhead_t RZPS_RLVStats; // logical volume stats linked list +} RepairZfsPoolStats_s; + + + +typedef struct ZRP_DynamicStats_s +{ + RAV_DynamicStats_s RDS_Common; + RAV_GrowingStats_s RDS_Action; // Actions that have been performed Object is a RAV_Action_s + RAV_GrowingStats_s RDS_Prune; // Prune information Object is a ZRP_Prune_s + RAV_GrowingStats_s RDS_IORecord; // I/O information Object is a RAV_IORecord_s + RAV_GrowingStats_s RDS_TODRecord; // Truncate or Delete info Object is a ZRP_TODRecord_s + RAV_GrowingStats_s RDS_MessageRecord; // A Message Object is a RAV_MessageRecord_s + RAV_GrowingStats_s RDS_DebugRecord; // A Debug Message Object is a RAV_DebugRecord_s +} ZRP_DynamicStats_s; + + + /* This is the rebuild structure used to orginize all global data + * for a given pool that are not stats. I.E. this is the place to put things + * that any UI would have no need to see!!!! This structure hangs off the + * thread while it runs and then off the saved data once the thread goes away. + * + * All pool stats are stored in the ZVP_PoolStats_s that we point to. All LV stats + * are stored in the ZVP_LVStats_s which we point to via the VS_LVData DQ head. + */ +typedef struct RepairStats_s +{ + RAVStats_s VS_Common; + ZRP_DynamicStats_s RS_DynamicStats; // These are STATS, but not part of ZVP_PoolStats_s + // because they are variable sized. They will be + // 'packed' before we give them to user space. +// ZLSSCheckIOProcess_s *ZCProcessPtr; + ZlssPool_s *zlssPool; + ZfsPool_s *pool; +//g BOOL reZidFlag; // rezid all vols on this pool now in pInfo->VPRS_RezidThreshold +//g BOOL ExcessiveBtreePrune; // set TRUE iff errors finding next leaf by traversing BT branches + LONG rebuildCount; // rebuild count from zlog blocks + NINT phase; // files, names, or done + +// NINT *RS_bitMap; + BlockMap_s RS_FMAPBitMap; // Bitmap of ALL FMAP blocks on given volume - Legal to be a NULL ptr. + + BlockMap_s RS_DualBitMap; // DO NOT USE DIRECTLY - use via RS_InUseBlockBM or RS_CrossLinkedBlockBM + BlockMap_s *RS_InUseBlockBM; // In use block bitmap - Only valid in PASS1 (after PASS1 use free tree) + BlockMap_s *RS_CrossLinkedBlockBM; // XLinked block bitmap - Only valid in PASS2 + + // These next three items are used by REPAIR_PHASE_FILES estimate of time left + // The new UI uses ZRPS_BlocksProcessedPass1 to track the total of these items + NINT markedBlockCount; + NINT bitmapAllocedBlockCount; + NINT bitmapFreedBlockCount; + +// FmapExt_s xMapExt[MAX_DIRECT]; // filemap for x-linked blocks bitmap +// FmapExt_s leafMapExt[MAX_DIRECT]; // filemap for leaf layer temp space +//g NINT repairTimes[6][2]; // repair Times +//g HWINDOW repairProgressLocalWinHandle; + NINT countedObjects; + NINT totalCount; + NINT filesProcessed; +// NINT filesPerSec; + NINT totalObject; + NINT blocksRead; + NINT blocksWritten; + NINT xLinkedFlag; + Blknum_t xLinkedFlagBlock; // Last block that was cross-linked. Used for User Entertainment + Blknum_t xLinkedBMBlocksNeeded; /* number of blocks needed for the x-linked bitmap */ + Blknum_t systemBMBlocksNeeded; /* number of blocks needed for the system blocks bitmap */ + +//g LONG handle; +//g LONG thandle; +//g LONG volume; // volume for log file "*.RLF" +//g LONG startOffset; +//g LONG tstartOffset; + + LONG RS_FirstIOTime; // In 1/10,000 of seconds + RepairZfsPoolStats_s *RepairZfsPoolStats; // pool repair stats buffer + BOOL okToAllocFromBitMap; + + QUAD RS_NumOrphanDirCreateErrors;// Number of times we failed to create a orphanage directory. + // Indicates the number of beast's that will not have a parent. + +// const char *RS_Caller; + char RS_OrphanageName[32]; // Name to use for all orphange directories (there is ONE per volume). + ZRP_LVData_s *RS_CurrentLVData; // NULL if working on IV/pool else LVs ZVP_LVData_s + // Current LV that we are working on. NULL if working + // on the pool. See VS_CurrentLVData + + char RS_MagicEnd[16]; +} RepairStats_s; + + +void ZRP_Startup(); +void ZRP_Shutdown(); +void ZRP_DataDestroy( RepairStats_s *rStats, RepairZfsPoolStats_s *zStats ); + +STATUS ZRP_StatusReportXML( + struct RAVStats_s *ravStats, + BOOL flags, /* RAV_DX_... */ + NINT bLen, + BYTE **bAdd, + NINT *rLen ); +STATUS ZRP_StatisticsReportBin( + struct RAVStats_s *ravStats, + NINT *bLen, + BYTE **bAdd, + NINT *rLen ); +STATUS ZRP_Main(struct GeneralMsg_s *genMsg,struct ZlssPool_s *zlssPool, NINT vmFlag, struct MaintenanceRetInfo_s *retInfo ); +STATUS ZRP_AllocFromBitMap( RepairStats_s *stats, RBTStats_s *RBTStats, Blknum_t *blockNum); +STATUS ZRP_RDS_Init_Pool( ZRP_DynamicStats_s *rDS ); + +void ZRP_ADSave( RepairStats_s *rStats, RAV_Action_s *action ); +void ZRP_ADSet( RepairStats_s *rStats, const char *subObject, ZRP_LVData_s *rLVStats ); +void ZRP_ADSetDescription( RepairStats_s *rStats, const char *aD ); +void ZRP_ADRecord( RepairStats_s *rStats ); +void ZRP_ADRestore( RepairStats_s *rStats, RAV_Action_s *action ); + +void ZRP_UnloadLVs( ZlssPool_s *zlssPool, ZLSSCheckIOProcess_s *pData ); +BOOL ZRP_UnloadRequested( RepairStats_s *rStats ); +ZVP_ERROR ZRP_Error_Return( RepairStats_s *rStats, STATUS status, const char *setter, const char *caller ); +void ZRP_VS_PruneReport( RepairStats_s *rStats, const RBTStats_s *rBTStats, const ZRP_LVData_s *rLVStats, const ZfsVolume_s *zfsVol ); +Buffer_s *ZRP_ReadPoolBlk( GeneralMsg_s *genMsg, RepairStats_s *rStats, RootBeast_s *beast, Blknum_t block, BYTE mode, const char *where ); +void ZRP_MessageRecordReport( RepairStats_s *rStats, const char *legalXML ); +void ZRP_TODRecordReport( RepairStats_s *stats, const ZRP_TODRecord_s *rec ); +void RAV_VS_MessageRecordDisplay( RAV_GrowingStats_s *rGS, NINT bLen, BYTE **bAdd, NINT *rLen ); +void ZRP_VS_TODRecordDisplay( RAV_GrowingStats_s *rGS, NINT bLen, BYTE **bAdd, NINT *rLen ); +void ZRP_VS_IORecordReport( RepairStats_s *rStats, const RAV_IORecord_s *rec ); +STATUS ZRP_VS_TODRecordRemove( GeneralMsg_s *genMsg, RAVStats_s *ravStats, QUAD itemKey ); +STATUS ZRP_VS_IORecordRemove( GeneralMsg_s *genMsg, RAVStats_s *ravStats, QUAD itemKey ); +STATUS ZRP_VS_ActionRecordRemove( + GeneralMsg_s *genMsg, + RAVStats_s *ravStats, + QUAD itemKey ); +unsigned int ZRP_VS_ActionRecordCount( const RAV_GrowingStats_s *rGS, QUAD itemKey ); + + +STATUS ZRP_vprintf_Debug( + RepairStats_s *rStats, + const char *where, + QUAD debugLevel, + const char *format, + va_list args ); +STATUS ZRP_printf_Debug( + RepairStats_s *rStats, + const char *where, + QUAD debugLevel, + const char *format, + ...); +void ZRP_DebugRecordReport( + RepairStats_s *rStats, + const char *where, + QUAD debugLevel, + const char *message ); +STATUS ZRP_vprintf_Log( + RepairStats_s *rStats, + const char *format, + va_list args ); +STATUS ZRP_printf_Log( + RepairStats_s *rStats, + const char *format, + ...); +STATUS ZRB_CreateDot1Dir( + GeneralMsg_s *genMsg, + RepairStats_s *stats, + RBTStats_s *RBTStats, + Volume_s *volume); +NamedBeast_s *ZRB_GetDestinationDirectory( + GeneralMsg_s *genMsg, + NamedBeast_s *beast, + ParentEntry_s *parentE, + RepairStats_s *stats, + RBTStats_s *RBTStats, + struct ZfsXaction_s *xaction, + BOOL *allDone); + +#endif // #ifndef _REPAIRZRP_H_ diff --git a/src/nwnss/zlss/repairZVP.h b/src/nwnss/zlss/repairZVP.h new file mode 100644 index 0000000..64ebb16 --- /dev/null +++ b/src/nwnss/zlss/repairZVP.h @@ -0,0 +1,388 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996, 2004 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Zlss Verify Pool(ZVP) engine + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Structures used by Zlss Verify Pool(ZVP) engine + | + +-------------------------------------------------------------------------*/ +#ifndef _REPAIRZVP_H_ +#define _REPAIRZVP_H_ + + +#include +#include + +#ifndef _QUE_H_ +#include +#endif + +#ifndef _VOLUME_H_ +# include +#endif + +#ifndef _ZFSDEFS_H_ +# include +#endif + +#ifndef _ZFS_H_ +# include +#endif + + +#ifndef _USERTREE_H_ +# include +#endif + +#ifndef _DIRTREE_H_ +# include +#endif + +#ifndef _ZFSPOOLSUPERBLK_H_ +# include +#endif + +#ifndef _ZLSSLOGICALVOLUME_H_ +# include +#endif + +#ifndef _REPAIRRAV_H_ +#include +#endif + +#ifndef _REPAIRZVPUSER_H_ +# include +#endif + + +#ifndef _NSS_DIR_H_ +# include +#endif + +typedef struct LVRootBlocks_s +{ + Blknum_t vlbplRootBlock; // Volume Locator Beast's Purge Log - volumes being purged may have blocks on VLB + Blknum_t vplRootBlock; // Volume Purge Log + Blknum_t specialBlock; + Blknum_t btRootBlock; + Blknum_t ntRootBlock; + Blknum_t lvdbBlock; + Blknum_t vdbBlock; + Blknum_t ubtBlock; + Blknum_t ubtFree; + Blknum_t dbtBlock; + Blknum_t mflRootBlock; + Blknum_t eflRootBlock; +} LVRootBlocks_s; + + +typedef struct NTLeafKey_s +{ + dir_key_s lastKey; + unicode_t lastKeyFname[zMAX_COMPONENT_NAME]; +} NTLeafKey_s; + + +typedef struct ZVP_NTData_s +{ + NTLeafKey_s prevNTLeafNodeLastKey; // Ordering verification + Blknum_t prevNTLeafNodeNextLeaf; // For order verification + +#if NSS_DEBUG IS_ENABLED + SNINT ovReplaceOp; + NINT ovblkFlag; +#endif + +//g ZfsVolume_s *zVolume; +} ZVP_NTData_s; + + +/* + * LV Volume DATA(non-stats) items. + * There is one of these for each LV in the pool. There is NOT one for + * the internal volume. + * + */ +typedef struct ZVP_LVData_s +{ + ZVP_LVStats_s ZLD_stats; + DQhead_t ZLD_Head; // Head of ALL dynamic stats within this LV object. + // Used so certain routines can operate on all of + // the RAV_GrowingStats_s without knowing all of their + // names. + DQlink_t link; // pointer to next logical volume + BOOL lvQuasiActivated; // Purge Tree is the only setter. + ZfsVolume_s *lvZVolume; // Purge Tree uses to have a quick + // pointer to a LV that it has QUASI + // activated. + ZVP_NTData_s lvNTData; // lv Name Tree data(non-stats info) +} ZVP_LVData_s; + + + + + +#if 0 +typedef void (*voidfunc_t)(); /* generic void function definition*/ +typedef STATUS (*statusfunc_t)(); /* generic STATUS return value function definitions*/ +typedef LONG (*longfunc_t)(); /* generic LONG return value function definition*/ +typedef BOOL (*boolfunc_t)(); /* generic BOOL return value function definition*/ +#ifdef __cplusplus +typedef void (*voidfunc_t)(...); /* generic void function definition*/ +typedef STATUS (*statusfunc_t)(...);/* generic STATUS return value function definitions*/ +typedef LONG (*longfunc_t)(...); /* generic LONG return value function definition*/ +typedef BOOL (*boolfunc_t)(...); /* generic BOOL return value function definition*/ +#else +typedef void (*voidfunc_t)(); /* generic void function definition*/ +typedef STATUS (*statusfunc_t)(); /* generic STATUS return value function definitions*/ +typedef LONG (*longfunc_t)(); /* generic LONG return value function definition*/ +typedef BOOL (*boolfunc_t)(); /* generic BOOL return value function definition*/ +#endif +#endif + + +typedef struct CBS_Variable_s +{ + RAV_GrowingStats_s CBSV_InvalidBlockList; // Contains CBSV_InvalidBlockList_s --- ZSS_TYPE_CBS_INVALID_BLOCKS + RAV_GrowingStats_s CBSV_NextLeafInvalidList; // Contains CBSV_NextLeafInvalidList_s --- ZSS_TYPE_CBS_INVALID_BLOCKS +} CBS_Variable_s; + +//RS_DynamicStats + +typedef struct ZVP_DynamicStats_s +{ + RAV_DynamicStats_s RDS_Common; // Link list of all dynamic stats for a POOL/IV (does not + // include LV dynamic stats -- they are on the + // ZVP_LVData_s.ZLD_Head list of each LV). + RAV_GrowingStats_s RDS_BlockConflicts; // Cross-linked blocks (XLinked) Object is a BlockConflicts_s + RAV_GrowingStats_s RDS_LVSkiped; // LVs that we could not verify Object is a LVSkipped_s + RAV_GrowingStats_s RDS_Action; // Actions that have been performed Object is a RAV_Action_s + RAV_GrowingStats_s RDS_MessageRecord; // A Message Object is a RAV_MessageRecord_s + RAV_GrowingStats_s RDS_DebugRecord; // A Debug Message Object is a RAV_DebugRecord_s +} ZVP_DynamicStats_s; + +typedef struct BTDynamicStats_s +{ + RAV_GrowingStats_s BTDS_UnreadableZid; // Contains BTDS_UnreadableZid_s --- ZSS_TYPE_BT_UNREADABLE_ZID + RAV_GrowingStats_s BTDS_BranchOutOfRangeZids; // Contains BTDS_BranchOutOfRangeZids_s --- ZSS_TYPE_BT_BranchOutOfRangeZids + RAV_GrowingStats_s BTDS_OutOfRangeZids; // Contains BTDS_OutOfRangeZids_s --- ZSS_TYPE_BT_OutOfRangeZids + RAV_GrowingStats_s BTDS_BTZnotInNT; // Contains BTDS_BTZnotInNT_s --- ZSS_TYPE_BT_BTZnotInNT + RAV_GrowingStats_s BTDS_BTZnotInPT; // Contains BTDS_BTZnotInPT_s --- ZSS_TYPE_BT_BTZnotInPT + RAV_GrowingStats_s BTDS_DuplicateZidsB; // Contains BTDS_DuplicateZidsB_s --- ZSS_TYPE_BT_DuplicateZidsB + RAV_GrowingStats_s BTDS_DuplicateZidsL; // Contains BTDS_DuplicateZidsL_s --- ZSS_TYPE_BT_DuplicateZidsL + RAV_GrowingStats_s BTDS_BTBadNTFiles; // Contains BTDS_BTBadNTFiles_s --- ZSS_TYPE_BT_BTBadNTFiles + RAV_GrowingStats_s BTDS_missingBeastParentEnts;// Contains BTDS_missingBeastParentEnts_s --- ZSS_TYPE_BT_missingBeastParentEnts +// Zid_t BranchOutOfRangeZids[20]; +// Zid_t UnreadableZid[50]; +} BTDynamicStats_s; + + +typedef struct STDynamicStats_s +{ + RAV_GrowingStats_s STDS_STZnotInBT; // Contains STDS_STZnotInBT_s --- ZSS_TYPE_ST_STZnotInBT + RAV_GrowingStats_s STDS_STZnotInNT; // Contains STDS_STZnotInNT_s --- ZSS_TYPE_ST_STZnotInNT + RAV_GrowingStats_s STDS_STPZnotInBT; // Contains STDS_STPZnotInBT_s --- ZSS_TYPE_ST_STPZnotInBT + RAV_GrowingStats_s STDS_STPZnotInNT; // Contains STDS_STPZnotInNT_s --- ZSS_TYPE_ST_STPZnotInNT + RAV_GrowingStats_s STDS_unaccBlks; // Contains STDS_unaccBlks_s --- ZSS_TYPE_ST_unaccBlks +} STDynamicStats_s; + +typedef struct NTDynamicStats_s +{ + RAV_GrowingStats_s NTDS_NTZnotInBT; // Contains NTDS_NTZnotInBT_s --- ZSS_TYPE_NT_NTZnotInBT +} NTDynamicStats_s; + + + /* This is the verify structure used to orginize all global data + * for a given pool that are not stats. I.E. this is the place to put things + * that any UI would have no need to see!!!! + * + * All pool stats are stored in the ZVP_PoolStats_s that we point to. All LV stats + * are stored in the ZVP_LVStats_s which we point to via the VS_LVData DQ head. + */ +typedef struct VerifyStats_s /* Global stats buffer */ +{ + RAVStats_s VS_Common; +// char VS_MagicStart[16]; +// DQlink_t VS_finalStatListLink; +// ZLSSCheckIOProcess_s *ZCProcessPtr; + ZVP_NTData_s VS_NTData; // pool's Name Tree data(non-stats info) + Zid_t VS_ivVolZid; // Pool's (internal volume) Zid (does not exists so set to 0) +// GeneralMsg_s VS_genMsg; // Tracks the errno setter of why verify was unable to complete!!! + IoMsg_s VS_iomsg; // Short term ioMsg. Added to reduce stack use +// const char *VS_Caller; +//g LONG vhandle; // +//g LONG volume; // > used for logging +//g LONG vstartOffset; // + NINT action; + ZfsPool_s *pool; + BlockMap_s VS_bitMap; // Bit map of pool blocks that are used. +//g char checkPointTime[40]; Not used +//g NINT blockConflicts; // Cross-linked Now vStats->zfsPoolStats->ZPS_uiStatus.ZVPS_BlocksXLinkedTotal +//g NINT LVsNotVerified; // number of logical volume we could NOT load. This is + // total count for pass1 and pass2 {XLinked pass}. Now vStats->zfsPoolStats->ZPS_LVsNotVerified +//g badLVName_s *badLVNames; // names of unverified logical volumes +//g BlockConflictsMemory_s VS_ConflictBlocks; // This are STATS, but not part of ZVP_PoolStats_s + // because they are variable sized. + + ZVP_DynamicStats_s VS_DynamicStats; // These are STATS, but not part of ZVP_PoolStats_s + // because they are variable sized. They will be + // 'packed' before we give them to user space. + +//g NINT countedBlocks; +//g Blknum_t findBlockNum; no one was using +//g Blknum_t xlinked[50]; we appear to use bConflictsBuffer + + Zid_t VS_zid; // ZID of beast that we are currently working on. +#define RAV_FAKE_ZID UI64_CONST(0xffffffffffffffff) + // We use -1 to indicate superblocks, VDB, LVDB, PDB or LPDB + // because these objects do not have a unique ZID assigned + // to them. + + ZVP_LVData_s *VS_CurrentLVData; // NULL if working on IV else LVs ZVP_LVData_s + CommonBlockStats_s *VS_cBS; // Current block 'object' that we are working on. + ZfsVolume_s *VS_zVolume; // Current 'volume' that we are working on. Just a kludge + // to pass the current volume to all of our verify routines. + +// QUAD VS_ActionKey; + ZVP_PoolStats_s *zfsPoolStats; // pool stats buffer + DQhead_t VS_LVData; // logical volume stats linked list (Pts to ZVP_LVData_s objects via 'link') + + char VS_MagicEnd[16]; +} VerifyStats_s; + + + + + +ZVP_ERROR ZVP_MapTestPurgeLogVolume(VerifyStats_s *vStats, PLStats_s *plStats, Blknum_t purgeFirstBlk, Zid_t volZid); +ZVP_ERROR ZVP_MapTestExtent(VerifyStats_s *vStats, struct Extent_s *extent, NINT flag); + +ZVP_ERROR ZVP_LVVerify(VerifyStats_s *vStats, ZVP_LVData_s *lvData, LVRootBlocks_s *rootBlocks); +struct MaintenanceRetInfo_s; +STATUS ZVP_Main(struct GeneralMsg_s *genMsg,struct ZlssPool_s *zlssPool, NINT vmFlag, struct MaintenanceRetInfo_s *retInfo ); +void ZVP_Startup(); +void ZVP_Shutdown(); + + +ZVP_ERROR ZVP_Error_Return( VerifyStats_s *vStats, STATUS status, const char *setter, const char *caller ); +BOOL ZVP_UnloadRequested( VerifyStats_s *vStats ); +BOOL ZVP_BlockLegal( VerifyStats_s *vStats, Blknum_t blockNum ); +void ZVP_LVDataDestroy( ZVP_LVData_s *lvData ); +ZVP_ERROR ZVP_MapTestZLogBlocks( VerifyStats_s *vStats ); +ZVP_ERROR ZVP_MapTestVolumeBlkPool( VerifyStats_s *vStats ); +ZVP_ERROR ZVP_MapTestVolumeBlk( VerifyStats_s *vStats, VDBStats_s *VDBStats, Zid_t volZid ); +ZVP_ERROR ZVP_MapTestPoolDataBlk( VerifyStats_s *vStats, Zid_t volZid ); +Blknum_t ZVP_UnaccountedBlocksRecord( VerifyStats_s *vStats ); +void ZVP_StatsSaveAndDestroy( ZLSSCheckIOProcess_s *pData, VerifyStats_s *vStats, ZVP_PoolStats_s *zStats ); +void ZVP_LSNRecord( VerifyStats_s *vStats, Lsn_t lsn ); +ZVP_ERROR ZVP_BeastTreeWalk(VerifyStats_s *vStats, BTStats_s *BTStats, Blknum_t rootBlock, Blknum_t specialBlock, Zid_t volZid); +ZVP_ERROR ZVP_MapTestPurgeLogPool(VerifyStats_s *vStats, PLStats_s *plStats, Blknum_t purgeFirstBlk, Zid_t volZid); +LONG ZVP_MapTestFileMap(VerifyStats_s *vStats, BTStats_s *BTStats, Fmap_s *fMap, Blknum_t numNextBlk, Zid_t volZid); +ZVP_ERROR ZVP_MapTestFreeBlocks(VerifyStats_s *vStats); +//gvoid ZVP_PoolPage1(VerifyStats_s *vStats, NINT blockTotal, LONG unaccountedBlocks, LONG usedBlocks); + +STATUS ZLSS_RAVItems2XML( GeneralMsg_s *genMsg, NINT type, LONG flags, NINT parmLen, utf8_t *parm, NINT bLen, + BYTE **bAdd, NINT *rLen, struct VirtInfo_s *virtInfo ); +STATUS CBS_Construct( DQhead_t *head, CommonBlockStats_s *cBS, const char *name ); +void CBS_Destruct( CommonBlockStats_s *cBS ); +ZVP_ERROR CBS_LevelDown( VerifyStats_s *vStats, CommonBlockStats_s *cBS, Blknum_t blknum ); +void CBS_LevelUp( CommonBlockStats_s *cBS ); +void CBS_LevelTop( CommonBlockStats_s *cBS ); +void CBS_LevelReportAdjustObject( CommonBlockStats_s *cBS, unsigned int mode, int numRecs ); +void CBS_LevelReportAdjust( CommonBlockStats_s *cBS, unsigned int mode, int numRecs ); +void CBS_LevelReport( CommonBlockStats_s *cBS, unsigned int mode, unsigned int numRecs ); +void CBS_Restore( VerifyStats_s *vStats, CommonBlockStats_s *saveCBS ); +void CBS_Save( const VerifyStats_s *vStats, CommonBlockStats_s **saveCBS ); + +void ZVP_ADSave( VerifyStats_s *vStats, RAV_Action_s *action ); +void ZVP_ADRestore( VerifyStats_s *vStats, RAV_Action_s *action ); +void ZVP_ADSetDescription( VerifyStats_s *vStats, const char *aD ); +void ZVP_ADSet( VerifyStats_s *vStats, const char *subObject, ZVP_LVData_s *lvData ); +void ZVP_ADRecord( VerifyStats_s *vStats ); + + +STATUS ZVP_RDS_Init_Pool( ZVP_DynamicStats_s *rDS ); +void ZVP_RDS_Pack_Pool( VerifyStats_s *vStats, NINT *bLen, BYTE **bAdd, NINT *rLen ); +unsigned int ZVP_RDS_PackSize_Pool( VerifyStats_s *vStats, unsigned int *uSections ); + + +BOOL ZVP_CBS_NextNodeLeaf( VerifyStats_s *vStats, Blknum_t currentBlock, Blknum_t nextLeaf ); +void ZVP_CBS_BadMiscReport( VerifyStats_s *vStats, Blknum_t block, STATUS error, const char *setter ); +void ZVP_CBS_BadChecksumReport( VerifyStats_s *vStats, Blknum_t block, STATUS error, const char *setter ); +void ZVP_CBS_BadMagicReport( VerifyStats_s *vStats, Blknum_t block, STATUS error, const char *setter ); +void ZVP_CBS_BadNumRecsReport( VerifyStats_s *vStats, Blknum_t block, STATUS error, const char *setter ); +ZVP_ERROR ZVP_CBS_BadReadReport( VerifyStats_s *vStats, Blknum_t block, GeneralMsg_s *error ); + +BOOL ZVP_LV_StatePurging( VerifyStats_s *vStats ); + +STATUS ZVP_BT_Construct( BTStats_s *btStats, DQhead_t *head, BOOL isLogicalVolume ); +STATUS ZVP_NT_Construct( NTStats_s *ntStats, DQhead_t *head ); +STATUS ZVP_ST_Construct( STStats_s *stStats, DQhead_t *head ); +void ZVP_BT_Destruct( BTStats_s *btStats ); +void ZVP_NT_Destruct( NTStats_s *ntStats ); +void ZVP_ST_Destruct( STStats_s *stStats ); + +void ZVP_RDS_Destroy_LV( ZVP_LVData_s *lvData ); +void ZVP_RDS_Pack_LV( ZVP_LVData_s *lvData, NINT *bLen, BYTE **bAdd, NINT *rLen ); +unsigned int ZVP_RDS_PackSize_LV( ZVP_LVData_s *lvData, unsigned int *uSections ); + +unsigned int ZVP_GS_PackSizeDefault( RAV_GrowingStats_s *rGS ); +void ZVP_GS_PackDefault( RAV_GrowingStats_s *rGS, NINT *bLen, BYTE **bAdd, NINT *rLen ); + +void ZVP_ST_unaccBlksReport( VerifyStats_s *vStats, STStats_s *stStats, Blknum_t sBlk, Blknum_t eBlk ); + +ZVP_ERROR ZVP_LVDataNew( VerifyStats_s *vStats, ZlssVolumeLocator_s *lvBeast, ZVP_LVData_s **pLVStats ); + +STATUS ZVP_ResourceFree( QUAD userKey ); +BOOL COMN_RAV_Terminate( VP_Status_s *pInfo ); +void COMN_RAV_LSSFilesReady( VP_Status_s *pComn ); + +STATUS ZVP_StatusReportXML( + RAVStats_s *ravStats, + BOOL flags, /* RAV_DX_... */ + NINT bLen, + BYTE **bAdd, + NINT *rLen ); +void ZVP_DataDestroy( + VerifyStats_s *vStats, + ZVP_PoolStats_s *zStats ); +STATUS ZVP_StatisticsReportBin( + RAVStats_s *ravStats, + NINT *bLen, + BYTE **bAdd, + NINT *rLen ); +Buffer_s *ZVP_ReadPoolBlk( GeneralMsg_s *genMsg, IoMsg_s *ioMsg, VerifyStats_s *vStats, const char *where ); +STATUS ZVP_printf_Debug( VerifyStats_s *vStats, const char *where, QUAD debugLevel, const char *format, ...); +STATUS ZVP_printf_Log( VerifyStats_s *vStats, const char *format, ...); + +#endif // #ifndef _REPAIRZVP_H_ diff --git a/src/nwnss/zlss/salvageLog.c b/src/nwnss/zlss/salvageLog.c new file mode 100644 index 0000000..1731afb --- /dev/null +++ b/src/nwnss/zlss/salvageLog.c @@ -0,0 +1,146 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2005-08-10 01:03:51 +0530 (Wed, 10 Aug 2005) $ + | + | $RCSfile$ + | $Revision: 1177 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | The SalvageLog file + +-------------------------------------------------------------------------*/ +#ifdef NSS_USERSPACE +#else +#include +#endif +#include "msgGen.h" +#include "zfs.h" +#include "zParams.h" + +///**************************************************************************** +// * ZFS B-Tree beast constructor +// *****************************************************************************/ +//STATUS ZSALVAGELOG_Construct( +// GeneralMsg_s *genMsg, +// ZSalvageLog_s *beast) +//{ +// return zOK; +//} + +///**************************************************************************** +// * ZFS B-Tree beast destructor +// *****************************************************************************/ +//void ZSALVAGELOG_Destruct( +// ZSalvageLog_s *beast) +//{ +//} + +/**************************************************************************** + * ZSALVAGELOG COMMON BEAST OPERATIONS definition + *****************************************************************************/ + +///*--------------------------------------------------------------------------- +// * Defines all of the ZFS B-Tree beast operations +// *---------------------------------------------------------------------------*/ +//CommonBeastOps_s ZSALVAGELOG_ComnBeastOps = +//{ +// NULL, /*construct*/ +// NULL, /*destruct*/ +// +// NULL, /* changeVolumeState*/ +// NULL, /* allocStorageInfo*/ +// NULL, /* freeStorageInfo*/ +// NULL, /* getBeastFromVolume*/ +// NULL, /* updateBeastToVolume*/ +// NULL, /* insertBeastIntoVolume*/ +// NULL, /* removeBeastFromVolume*/ +// NULL, /* allocateZIDs*/ +// NULL, /* getExtentList*/ +// NULL, /* isBlockInBeast*/ +// NULL, /* flushSystemBeasts*/ +// NULL, /* beginXLocal */ +// NULL, /* endXLocal */ +// NULL, /* addPurgeLogEntry */ +// NULL, /* removePurgeLogEntry */ +// NULL, /* getID*/ +// NULL, /* lookupByNameInDirectory*/ +// NULL, /* initDirectory*/ +// NULL, /* isDirectoryEmpty*/ +// NULL, /* addNameToDirectory*/ +// NULL, /* removeNameFromDirectory*/ +// NULL, /* modifyNameSpaceMaskInDirectory*/ +// NULL, /* wildcardLookup*/ +// NULL, /* beastNotify*/ +// NULL, /* getInfo*/ +// NULL, /* modifyInfo*/ +// NULL, /* matchAttributes*/ +// NULL, /* asyncReadFileBlk*/ +// NULL, /* getFileBlk*/ +// NULL, /* dfsReadUnits*/ +// NULL, /* dfsWriteUnits*/ +// NULL /* truncateFile*/ +//}; +// +// +///**************************************************************************** +// * EXTENT BASED storage pack routine +// *****************************************************************************/ +//STATIC NINT ZSALVAGELOG_PackedSize( +// ZSalvageLog_s *beast) +//{ +// return 0; /*sizeof(PersistentZSalvageLog_s);*/ +//} +// +///**************************************************************************** +// * EXTENT BASED storage pack routine +// *****************************************************************************/ +//STATIC BYTE *ZSALVAGELOG_Pack( +// ZSalvageLog_s *beast, +// BYTE *storeBuffer) +//{ +// /*memcpy(storeBuffer,&beast->p,sizeof(PersistentZSalvageLog_s));*/ +// return (storeBuffer /*+ sizeof(PersistentZSalvageLog_s)*/); +//} +// +///**************************************************************************** +// * EXTENT BASED storage pack routines +// *****************************************************************************/ +//STATIC BYTE *ZSALVAGELOG_Unpack( +// GeneralMsg_s *genMsg, +// ZSalvageLog_s *beast, +// BYTE *storeBuffer) +//{ +// /*memcpy(&beast->p,storeBuffer,sizeof(PersistentZSalvageLog_s));*/ +// return (storeBuffer /*+ sizeof(PersistentZSalvageLog_s)*/); +//} +// +///*--------------------------------------------------------------------------- +// * file beast STORAGE ops definition +// *---------------------------------------------------------------------------*/ +//LSSBeastOps_s ZSALVAGELOG_lssOps[] = +// {zFTYPE_ZFS_POOL,ZSALVAGELOG_PackedSize,ZSALVAGELOG_Pack,ZSALVAGELOG_Unpack}; diff --git a/src/nwnss/zlss/sdZLSS.h b/src/nwnss/zlss/sdZLSS.h new file mode 100644 index 0000000..4f978af --- /dev/null +++ b/src/nwnss/zlss/sdZLSS.h @@ -0,0 +1,656 @@ +/**************************************************************************** + | + | (C) Copyright 2002 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | sdBasic - Structure Display Basic. + / Displays Basic data types. + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2007-04-18 23:26:20 +0530 (Wed, 18 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1954 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Display NSS 3.00 Persistent structures. + / + / Warning - This file is used by NT Utilities like zedRemote, ZlogGet and + / etc. DO NOT ADD NSS specific code. The define NTLIB is only defined + / when source file is compiled with NT Utilities. + +-------------------------------------------------------------------------*/ +#ifndef _SDPERSISTENT_H_ +#define _SDPERSISTENT_H_ + +#ifndef _NWGREENRIVER_ +#define _NWGREENRIVER_ /* This define helps asyncio.h */ +#endif + +//#include + +#include "zParams.h" +#include "zError.h" +#include "zlog.h" +#include "zfs.h" +#include "zasAuthModel.h" +#include "unixAuthModel.h" + +#include "eventSys.h" +#include "zEvent.h" +#include "volume.h" +#include "comnPublics.h" +#include "zfsSuperBlk.h" +#define NAMETREE_MAGIC 0x48726944 /* Can't include nametree.h because dup structures */ +//#ifndef SAI_NT +#include "beastTree.h" +//#endif +#include "purgeTree_new.h" +#include "purgeLog.h" +#include "zlog.h" +#include "mflBTree.h" +#include "zfsXTree.h" +#include "zlssLogicalVolume.h" +#include "eflTree.h" +#include "eflLog.h" +#include "zlssMSAP.h" +#include "extAttrBeast.h" + +#include "guid.h" + +#ifdef DFI_INTERNAL +#include "comnCompress.h" +#include "nameSpace.h" +#include "macNSpace.h" +#include "unixNSpace.h" + +#if 0 +typedef struct PackedCompInfo_s /* This was in a C file so I just copied */ +{ + WORD rvdID; + WORD rvdLayout; + PersistentCompressInfo_s cmInfo; +} PackedCompInfo_s; +#endif + +#endif + +#include "sdBasic.h" +#include "sdNSS.h" +#include "snp.h" +#include "dfi.h" + +/* Pre-declare the following structure(s) */ +struct PersistentAuthBeast_1Dot0_s; + +extern SDM_Table_s SDM_TableZLSS[]; + +typedef void (*BN_Function_f)( + DFI_CallerOptions_s *co, + ZnodeHeader_s *znode, + void *specificBeast ); + +/* This is for the inline structure in RecoveryStats_s */ +typedef struct SD_Fake_s +{ + NINT redo; + NINT undo; +} SD_Fake_s; + + +extern DFI_DataFormatInformation_s DFI_ZlogHistory_s[]; +extern DFI_DataFormatInformation_s DFI_ZlogHistogram_s[]; +extern DFI_DataFormatInformation_s DFI_LocalXid_t[]; +extern DFI_DataFormatInformation_s DFI_ZfsXasRecovery_s[]; +extern DFI_DataFormatInformation_s DFI_ZlogHistogramPersistent_s[]; +extern DFI_DataFormatInformation_s DFI_ZlogHighWatermarkSlot_s[]; +extern DFI_DataFormatInformation_s DFI_ZlogBeast_s[]; +extern DFI_DataFormatInformation_s DFI_ZlogBeastPersistent_s[]; +extern DFI_DataFormatInformation_s DFI_ZlssBarrier_s[]; +extern DFI_DataFormatInformation_s DFI_SD_Fake_s[]; +extern DFI_DataFormatInformation_s DFI_RecoveryStats_s[]; +extern DFI_DataFormatInformation_s DFI_PoolReadStatistics_s[]; +extern DFI_DataFormatInformation_s DFI_PoolWriteStatistics_s[]; +extern DFI_DataFormatInformation_s DFI_ZfsPool_s[]; +extern DFI_DataFormatInformation_s DFI_ZfsVolume_s[]; +extern DFI_DataFormatInformation_s DFI_PersistentZfsVolume_s[]; +extern DFI_DataFormatInformation_s DFI_LoggedPersistentZfsVolume_s[]; +extern DFI_DataFormatInformation_s DFI_ZlssPool_s[]; +extern DFI_DataFormatInformation_s DFI_PersistentZlssPool_s[]; +extern DFI_DataFormatInformation_s DFI_LoggedPersistentZlssPool_s[]; + + +SIZEOF SDM_LoggedPersistentZfsVolume_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_LoggedPersistentZlssPool_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_PersistentZfsVolume_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_PersistentZlssPool_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_PoolReadStatistics_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_PoolWriteStatistics_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_RecoveryStats_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZfsPool_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZfsVolume_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogBeast_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogBeastPersistent_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogHighWatermarkSlot_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogHistogram_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogHistory_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlogHistogramPersistent_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlssBlock_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZlssPool_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + +SIZEOF SDM_ZfsXasRecovery_s( + DFI_CallerOptions_s *co, + DFI_DataFormatInformation_s *dfi, + BYTE *buffer, + NINT offset, + NINT index ); + + + + + +int ZSD_Display_Type_QBlknum_t( + DFI_CallerOptions_s *co, + char *tag, + SQUAD *block ); + +int ZSD_Display_Struct_FmapExt_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + FmapExt_s *branch ); /* Array of branches */ + +int ZSD_Display_Struct_xBranch_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + xBranch_s *branch ); /* Array of branches */ + +int ZSD_Display_Struct_BTBranch_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + int arrayElements, + BTBranch_s *branch ); + +int ZSD_Display_Struct_Extent_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + Extent_s *extent ); + +int ZSD_Display_Struct_Extent_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int numberOfElements, + Extent_s *extent ); + +int ZSD_Display_Type_char_STR( + DFI_CallerOptions_s *co, + char *tag, + unsigned int arrayElements, /* Number of array elements */ + char *name ); + +int ZSD_Display_Struct_ZASPersistentAuthInfo_s( + DFI_CallerOptions_s *co, + ZASPersistentAuthInfo_s *zasAuth, + char *name ); + +int ZSD_Display_Struct_PersistentAuthBeast_1Dot0_s( + DFI_CallerOptions_s *co, + struct PersistentAuthBeast_1Dot0_s *auth, + char *name ); + +int ZSD_Display_Struct_V1_PersistentFile_s( + DFI_CallerOptions_s *co, + V1_PersistentFile_s *file, + char *name ); + +int ZSD_Display_Struct_PersistentFile_s( + DFI_CallerOptions_s *co, + PersistentFile_s *file, + char *name ); + +int ZSD_Display_Struct_PersistentNameEntry_s( + DFI_CallerOptions_s *co, + PersistentNameEntry_s *namedParentEntry, + char *name ); + +int ZSD_Display_Struct_PersistentNamed_s( + DFI_CallerOptions_s *co, + PersistentNamed3_s *named, + char *name ); + +int ZSD_Display_Struct_PersistentParentEntry_s( + struct DFI_CallerOptions_s *co, + PersistentParentEntry_s *namedParent, + char *name ); + +int ZSD_Display_Struct_Fmap_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + Fmap_s *data, + unsigned int size ); + +int ZSD_Display_Struct_ZFSPackedRoot_s( + struct DFI_CallerOptions_s *co, + ZFSPackedRoot_s *packedHeader2, + char *name, + BOOL doZnodeHeader ); + +int ZSD_Display_Struct_V1_ZFSPackedRoot_s( + struct DFI_CallerOptions_s *co, + V1_ZFSPackedRoot_s *packedHeader1, + char *name, + BOOL doZnodeHeader ); + +int ZSD_Display_Struct_ZnodeHeader_s( + struct DFI_CallerOptions_s *co, + ZnodeHeader_s *znodeHeader, + char *name ); + +int ZSD_Display_Struct_PersistentZlssVolumeLocator_s( + struct DFI_CallerOptions_s *co, + PersistentZlssVolumeLocator_s *pzvl, + char *name ); + +int ZSD_Display_Struct_PersistentZfsPurgeLog_s( + DFI_CallerOptions_s *co, + PersistentZfsPurgeLog_s *purgeLog, + char *name ); + +int ZSD_Display_Struct_PersistentZfsBtree_s( + DFI_CallerOptions_s *co, + PersistentZfsBtree_s *btree, + char *name ); + +int ZSD_Display_Struct_ZlogBeastPersistent_s( + DFI_CallerOptions_s *co, + ZlogBeastPersistent_s *zlog, + char *name ); + +int ZSD_Display_Struct_BTBranch_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, /* If 0 then we assume NOT an array */ + BTBranch_s *data ); + +int ZSD_Display_Type_unicode_t_STR( + DFI_CallerOptions_s *co, + char *tag, + unsigned int numberOfElements, // Must be a NULL before end of ARRAY + unicode_t *name ); + +int ZSD_Display_Type_unicode_t_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int numberOfElements, + unicode_t *name ); + +int ZSD_Display_Struct_Znode_s( + Znode_s *znode, + DFI_CallerOptions_s *co, + char *name ); + +STATUS BeastUnpackBV2( + ZFSPackedRoot_s *packedHeader2, + DFI_CallerOptions_s *co, + void **systemBeastSpecific, + char *name ); + +int BeastUnpackBV1( + V1_ZFSPackedRoot_s *packedHeader, + DFI_CallerOptions_s *co, + void **systemBeastSpecific, + char *name ); + +int BeastUnpack( + ZFSPackedRoot_s *packedHeader, + DFI_CallerOptions_s *co, + void **systemBeastSpecific, + char *name ); + +void BN_NotifyRegister( + LONG type, + BN_Function_f notifyRoutine ); + +void BN_NotifyUnRegister( + LONG type, + BN_Function_f notifyRoutine ); + +void BN_Notify( + LONG type, + DFI_CallerOptions_s *co, + ZnodeHeader_s *znode, + void *specificBeast ); + +int ZSD_Display_Struct_V1_ZASPersistentAuthInfo_s( + DFI_CallerOptions_s *co, + V1_ZASPersistentAuthInfo_s *zasAuth, + char *name ); + +int ZSD_Display_Struct_V1_ACLEntry_s_Element( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + V1_ACLEntry_s *entry ); + +int ZSD_Display_Struct_V1_ACLEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int arrayElements, + V1_ACLEntry_s *entry ); + + +int ZSD_Display_Struct_V1_VisEntry_s_Element( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + V1_VisEntry_s *entry ); + +int ZSD_Display_Struct_V1_VisEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int arrayElements, + V1_VisEntry_s *entry ); + +int ZSD_Display_Struct_RootVariable_s( + struct DFI_CallerOptions_s *co, + BYTE *variable, + int variableSize, + char *name ); + +int ZSD_Display_Struct_PackedMacInfo_s( + struct DFI_CallerOptions_s *co, + BYTE *variable, + int variableSize, + char *name ); + +int ZSD_Display_Type_BYTE_ARRAY( + struct DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + BYTE *data ); + +int ZSD_Display_Type_LONG_ARRAY( + struct DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + LONG *data ); + +int ZSD_Display_Struct_V1_ACLEntry_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, /* Number of array elements */ + V1_ACLEntry_s *entry ); + +int ZSD_Display_Struct_V1_ACLEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int arrayElements, /* Number of array elements */ + V1_ACLEntry_s *entry ); /* Array of .. */ + +int ZSD_Display_Struct_V1_VisEntry_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, /* Number of array elements */ + V1_VisEntry_s *entry ); + +int ZSD_Display_Struct_V1_VisEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + V1_VisEntry_s *data ); + +int ZSD_Display_Struct_ACLEntry_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, /* Number of array elements */ + ACLEntry_s *entry ); + +int ZSD_Display_Struct_ACLEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + unsigned int arrayElements, /* Number of array elements */ + ACLEntry_s *data ); + +int ZSD_Display_Struct_VisEntry_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, /* Number of array elements */ + VisEntry_s *entry ); + +int ZSD_Display_Struct_VisEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + VisEntry_s *data ); /* Array of .. */ + +int ZSD_Display_Struct_MYBTBranchEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + MYBTBranchEntry_s *data ); /* Array of .. */ + + +//#ifndef SAI_NT +int ZSD_Display_Type_NodeLen_t_ARRAY( + DFI_CallerOptions_s *co, + char *tag, + int arrayElements, + NodeLen_t *branch ); + +int ZSD_Display_Type_NodeLen_t( + DFI_CallerOptions_s *co, + char *tag, + int index, + int arrayElements, + NodeLen_t *nodeOffset ); + +int ZSD_Display_Struct_PurgeQNewKey_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + PurgeQNewKey_s *data ); + +int ZSD_Display_Struct_PurgeQNewValue_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + PurgeQNewValue_s *data ); + +int ZSD_Display_Struct_PurgeNewInfo_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + PurgeNewInfo_s *data ); + +int ZSD_Display_Struct_PurgeNewInfo_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + PurgeNewInfo_s *data ); /* Array of .. */ +//#endif // #ifndef SAI_NT + +int ZSD_Display_Struct_EFLBranch_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the element */ + unsigned int arrayElements, /* Number of array elements */ + EFLBranchEntry_s *data ); /* Array of branches */ + +int ZSD_Display_Struct_EFLLeafEntry_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the element */ + unsigned int arrayElements, /* Number of array elements */ + EFLLeafEntry_s *data ); /* Array of branches */ + +int ZSD_Display_Struct_ELogHeader_s_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the element */ + unsigned int arrayElements, /* Number of array elements */ + ELogHeader_s *data ); /* Array of headers */ + +int DFI_Display_Struct_ELogEntry_s( + DFI_CallerOptions_s *co, + char *tag, + unsigned int index, + unsigned int arrayElements, + ELogEntry_s *data ); + +int ZSD_Display_Struct_GUID_t_ARRAY( + DFI_CallerOptions_s *co, + char *tag, /* Generally the name of the branch element */ + unsigned int arrayElements, /* Number of array elements */ + GUID_t *data ); + +int ZSD_Display_Struct_PersistentZfsBeastTree_s( + DFI_CallerOptions_s *co, + PersistentZfsBeastTree_s *data, + char *name ); + +int ZSD_Display_Type_EFLEpochMask_t( + DFI_CallerOptions_s *co, + char *tag, + EFLEpochMask_t *epoch ); + +int ZSD_Display_Type_ELogLink_s( + DFI_CallerOptions_s *co, + char *tag, + ELogLink_s *data ); + +int ZSD_Display_Struct_DeletedPersistentParentEntry_s( + DFI_CallerOptions_s *co, + struct DeletedPersistentParentEntry_s *deletedInfo, + char *name ); + +#endif // #ifndef _SDPERSISTENT_H_ diff --git a/src/nwnss/zlss/userTree.h b/src/nwnss/zlss/userTree.h new file mode 100644 index 0000000..16e392b --- /dev/null +++ b/src/nwnss/zlss/userTree.h @@ -0,0 +1,528 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2006-11-14 05:57:30 +0530 (Tue, 14 Nov 2006) $ + | + | $RCSfile$ + | $Revision: 1632 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | This defines all of the primitive BEASTS inside of PSS + | + | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! + | + | This header file should ONLY be used for NSS internal development. + | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). + | Any other use may cause conflicts which NSS will NOT fix. + +-------------------------------------------------------------------------*/ +#ifndef _USERTREE_H_ +#define _USERTREE_H_ + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +#ifndef DCONST_H +#include "dconst.h" +#endif + +#if NSS_DEBUG IS_ENABLED +#define UBT_VALIDATE_NODE(_node) (UBT_validateNode(_node)) +#else +#define UBT_VALIDATE_NODE(_node) ((void)0) +#endif + +/* + * Type of operations to do while decending the tree (bitmap) + */ +#define UBT_CHECK_FOR_SPLIT 0x00000001 +#define UBT_CHECK_FOR_JOIN 0x00000002 + +/* state of a node */ +#define UBT_LEAF 0x1 /* Leaf node of a B-tree */ +#define UBT_ROOT 0x2 /* Root node of a B-tree */ + +#define UBT_SMALL DISABLE +//#define UBT_SMALL ENABLE + + +#if UBT_SMALL IS_ENABLED && NSS_DEBUG IS_ENABLED +#define UBT_MAX_BRANCH_ENTRIES 7 +#define UBT_MAX_LEAF_ENTRIES 5 +#else +#define UBT_MAX_BRANCH_ENTRIES ((PAGE_SIZE - 32) / sizeof(UserBranchEntry_s)) +#define UBT_MAX_LEAF_ENTRIES ((PAGE_SIZE - (32 + 4)) / sizeof(UserLeafEntry_s)) +#endif +#define UBT_MAX_NAME_ENTRIES ((PAGE_SIZE - 64) / sizeof(ObjectNameEntry_s)) + +#define UBT_IS_LEAF(_n) ((_n)->state & UBT_LEAF) +#define UBT_IS_ROOT(_n) ((_n)->state & UBT_ROOT) + +#define UBT_MIN_BRANCH_ENTRIES (UBT_MAX_BRANCH_ENTRIES / 2) +#define UBT_MIN_LEAF_ENTRIES (UBT_MAX_LEAF_ENTRIES / 2) + +#define UBT_IS_MAX_ENTRIES(_node, _parms) \ + (UBT_IS_LEAF(_node) \ + ? ((_node)->numRecs >= UBT_MAX_LEAF_ENTRIES) \ + : ((_node)->numRecs >= UBT_MAX_BRANCH_ENTRIES)) + +#define UBT_IS_MIN_ENTRIES(_node) \ + (UBT_IS_LEAF(_node) \ + ? ((_node)->numRecs <= UBT_MIN_LEAF_ENTRIES) \ + : ((_node)->numRecs <= UBT_MIN_BRANCH_ENTRIES)) + +#define UBT_IS_LESSTHAN_MAX(_node, _sibling) \ + (UBT_IS_LEAF(_node) \ + ? (((_node)->numRecs + (_sibling)->numRecs) < UBT_MAX_LEAF_ENTRIES) \ + : (((_node)->numRecs + (_sibling)->numRecs) < UBT_MAX_BRANCH_ENTRIES)) + +#define UBRANCH(_entry) n.branch.entry[(_entry)] +#define ULEAF(_entry) n.leaf.entry[(_entry)] + +#define UBT_ZERO_USERID zZERO_GUID + +/* + * structure to pass info and state between beast b-tree routines + */ +typedef struct UserTreeParms_s +{ + UserID_t userID; /* the user to be used */ + Volume_s *volume; + Blknum_t readBlkNum; /* Next block to be read */ + NINT index; /* Where last record was found in parent*/ + SQUAD value; /* The value being set or adjusted */ + NINT type; /* The type of data contained in the value -- see defines below */ + Buffer_s *parent; /* Parent buffer */ + Buffer_s *child; /* Child buffer */ + Buffer_s *sibling; /* Sibling buffer */ + struct ZfsXaction_s *xaction; /* Transaction being used */ + struct ZfsUserTreeBeast_s *userTreeBeast; /* The pointer to the b-tree beast */ +} UserTreeParms_s; + +/* + * Defines for "type" in UserTreeParms_s (not a bit mask) + */ + #define UBT_TYPE_USED_AMOUNT 1 + #define UBT_TYPE_RESTRICTION 2 + + +/* + * structures for defining what the old tree nodes used to look like + */ + +#define OLD_UBT_MAX_BRANCH_ENTRIES ((PAGE_SIZE - 32) / sizeof(OldUserBranchEntry_s)) +#define OLD_UBT_MAX_LEAF_ENTRIES ((PAGE_SIZE - (32 + 4)) / sizeof(OldUserLeafEntry_s)) + +typedef struct OldUserBranchEntry_s +{ + LONG userID; + Blknum_t child; +} NSS_MEDIA_STRUCTURE(OldUserBranchEntry_s,child) OldUserBranchEntry_s; + + +typedef struct OldUserBranch_s +{ + OldUserBranchEntry_s entry[OLD_UBT_MAX_BRANCH_ENTRIES]; +} NSS_MEDIA_STRUCTURE(OldUserBranch_s,entry[OLD_UBT_MAX_BRANCH_ENTRIES]) OldUserBranch_s; + +typedef struct OldUserLeafEntry_s +{ + LONG userID; + SQUAD usedAmount; + SQUAD restrictionAmount; +} NSS_MEDIA_STRUCTURE(OldUserLeafEntry_s,restrictionAmount) OldUserLeafEntry_s; + + +typedef struct OldUserLeaf_s +{ + /* + * If the size of the header portion changes then change + * OLD_UBT_MAX_LEAF_ENTRIES. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + OldUserLeafEntry_s entry[OLD_UBT_MAX_LEAF_ENTRIES]; +} NSS_MEDIA_STRUCTURE(OldUserLeaf_s,entry[OLD_UBT_MAX_LEAF_ENTRIES]) OldUserLeaf_s; + +typedef struct OldUserTreeNode_s +{ + /* + * If the size of the header portion changes then change + * OLD_UBT_MAX_BRANCH_ENTRIES and OLD_UBT_MAX_LEAF_ENTRIES. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t utn_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). utn -> User Tree Node. + */ + union + { + OldUserBranch_s branch; + OldUserLeaf_s leaf; + } NSS_MEDIA_UNION(NamelessUnion,leaf.entry[OLD_UBT_MAX_LEAF_ENTRIES]) n; +} NSS_MEDIA_STRUCTURE(OldUserTreeNode_s,n.leaf.entry[OLD_UBT_MAX_LEAF_ENTRIES]) OldUserTreeNode_s; + +/* + * structures for defining what the tree nodes look like + */ + +typedef struct UserBranchEntry_s +{ + UserID_t userID; + Blknum_t child; +} NSS_MEDIA_STRUCTURE(UserBranchEntry_s,child) UserBranchEntry_s; + + +typedef struct UserBranch_s +{ + UserBranchEntry_s entry[UBT_MAX_BRANCH_ENTRIES]; +} NSS_MEDIA_STRUCTURE(UserBranch_s,entry[UBT_MAX_BRANCH_ENTRIES]) UserBranch_s; + +typedef struct UserLeafEntry_s +{ + UserID_t userID; + SQUAD usedAmount; + SQUAD restrictionAmount; + Blknum_t infoBlock; + WORD infoIndex; + WORD reserved; +} NSS_MEDIA_STRUCTURE(UserLeafEntry_s,reserved) UserLeafEntry_s; + + +typedef struct UserLeaf_s +{ + /* + * If the size of the header portion changes then change + * UBT_MAX_LEAF_ENTRIES. + */ + Blknum_t nextLeaf; /* link to the next leaf in the tree */ + UserLeafEntry_s entry[UBT_MAX_LEAF_ENTRIES]; +} NSS_MEDIA_STRUCTURE(UserLeaf_s,entry[UBT_MAX_LEAF_ENTRIES]) UserLeaf_s; + +typedef struct UserTreeNode_s +{ + /* + * If the size of the header portion changes then change + * UBT_MAX_BRANCH_ENTRIES and UBT_MAX_LEAF_ENTRIES. + */ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t utn_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). utn -> User Tree Node. + */ + union + { + UserBranch_s branch; + UserLeaf_s leaf; + } NSS_MEDIA_UNION(NamelessUnion,leaf.entry[UBT_MAX_LEAF_ENTRIES]) n; +} NSS_MEDIA_STRUCTURE(UserTreeNode_s,n.leaf.entry[UBT_MAX_LEAF_ENTRIES]) UserTreeNode_s; + +typedef struct ObjectNameEntry_s +{ + /* + * The size of one entry is 676 bytes + */ + LONG state; + unicode_t name[MAX_DN_CHARS]; + Time_t timeNotFound; /* Used by checker */ + LONG numberOfTimesNotFound; /* Used by checker */ + BYTE reserved[152]; +} NSS_MEDIA_STRUCTURE(ObjectNameEntry_s,reserved[152]) ObjectNameEntry_s; + +#define UBT_NAME_ENTRY_USED 0x00000001 + +typedef struct ObjectNameNode_s +{ + /* + * If the size of the header portion changes then change + * UBT_MAX_NAME_ENTRIES + */ + LONG magic; + LONG reserved1; + Lsn_t lsn; + GUID_t utn_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). utn -> User Tree Node. + */ + LONG reserved2; /* This is an unused field */ + GUID_t verifyGuid; /* Space for verify to mark this block as already + * in the bitmap. + */ + LONG verifyCount; /* Space for verify to count use of the block + */ + LONG extraSpace[2]; /* bring the total to 64 bytes */ + ObjectNameEntry_s entry[UBT_MAX_NAME_ENTRIES]; +} NSS_MEDIA_STRUCTURE(ObjectNameNode_s,entry[UBT_MAX_NAME_ENTRIES]) ObjectNameNode_s; + + +/* + * Structures and defines for log records for the user b-tree. + */ + +typedef struct UBTEntry_s +{ + UserID_t userID; /* User to be modified */ + SQUAD usedAmount; /* Value for used amount */ + SQUAD restrictionAmount; /* Value for restriction amount */ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTEntry_s,internalID) UBTEntry_s; + +typedef struct UBTModify_s +{ + UserID_t userID; /* User to be modified */ + SQUAD oldValue; /* Value before change */ + SQUAD value; /* Value for change */ + LONG type; /* type of value ("used amount" or "restriction") */ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTModify_s,internalID) UBTModify_s; + +typedef struct UBTSplit_s +{ + GUID_t internalID; + UserID_t userIDForParent; /* zid to insert in the parent */ + Blknum_t leafLink; /* link to the next leaf in the tree */ + Blknum_t blockForParent; /* block number to insert in the parent */ + LONG indexForParent; /* index where zid is inserted in the parent */ + WORD numToMove; /* number of entries logged */ + LONG totalLength; /* length of tree information being moved */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(UBTSplit_s,data[1]) UBTSplit_s; + +typedef struct UBTOverflow_s +{ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries logged */ + WORD nodeType; /* whether the new node is a branch or a leaf */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(UBTOverflow_s,data[1]) UBTOverflow_s; + +typedef struct UBTGrow_s +{ + GUID_t internalID; + Blknum_t blockForParent; /* block number to insert in the parent */ +} NSS_MEDIA_STRUCTURE(UBTGrow_s,blockForParent) UBTGrow_s; + +typedef struct UBTBalance_s +{ + UserID_t userIDForParent; /* user to insert in the parent */ + UserID_t oldUserID; /* previous user in the parent */ + LONG indexForParent; /* index where entry is changed in the parent */ + LONG totalLength; /* length of tree information being moved */ + WORD numToMove; /* number of entries moved */ + BYTE data[1]; /* data to move */ +} NSS_MEDIA_STRUCTURE(UBTBalance_s,data[1]) UBTBalance_s; + +typedef struct UBTTreeInit_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTTreeInit_s,internalID) UBTTreeInit_s; + +typedef struct UBTModifyName_s +{ + UserID_t objectID; + unicode_t oldName[MAX_DN_CHARS]; + unicode_t newName[MAX_DN_CHARS]; + LONG index; + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTModifyName_s,internalID) UBTModifyName_s; + +typedef struct UBTModifyNameEntry_s +{ + UserID_t objectID; + ObjectNameEntry_s oldEntry; + ObjectNameEntry_s newEntry; + LONG index; + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTModifyNameEntry_s,internalID) UBTModifyNameEntry_s; + +typedef struct UBTAddNameRecord_s +{ + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTAddNameRecord_s,internalID) UBTAddNameRecord_s; + +typedef struct UBTAddName_s +{ + LONG blockNum; + LONG nameIndex; + LONG leafIndex; + unicode_t name[MAX_DN_CHARS]; + UserID_t objectID; + GUID_t internalID; +} NSS_MEDIA_STRUCTURE(UBTAddName_s,internalID) UBTAddName_s; + +typedef struct UBTRemoveNameRecord_s +{ + LONG nameIndex; +} NSS_MEDIA_STRUCTURE(UBTRemoveNameRecord_s,nameIndex) UBTRemoveNameRecord_s; + +typedef struct UBTRemove_s +{ + UserID_t userID; /* User to be modified */ + SQUAD usedAmount; /* Value for used amount */ + SQUAD restrictionAmount; /* Value for restriction amount */ + GUID_t internalID; + LONG nameIndex; + unicode_t name[MAX_DN_CHARS]; +} NSS_MEDIA_STRUCTURE(UBTRemove_s,name[MAX_DN_CHARS]) UBTRemove_s; + +typedef struct UBTRemoveName_s +{ + GUID_t internalID; + UserID_t userID; + LONG nameIndex; + unicode_t name[MAX_DN_CHARS]; +} NSS_MEDIA_STRUCTURE(UBTRemoveName_s,name[MAX_DN_CHARS]) UBTRemoveName_s; + +/* defines for direction */ + +#define UBT_LEFT_TO_RIGHT 0 +#define UBT_RIGHT_TO_LEFT 1 + +typedef struct UserLog_s +{ + union + { + UBTEntry_s entry; + UBTModify_s modify; + UBTSplit_s split; + UBTOverflow_s overflow; + UBTGrow_s grow; + UBTBalance_s balance; + UBTTreeInit_s initTree; + UBTModifyName_s modifyName; + UBTModifyNameEntry_s modifyNameEntry; + UBTAddNameRecord_s addNameRecord; + UBTAddName_s addName; + UBTRemoveNameRecord_s removeNameRecord; + UBTRemove_s remove; + UBTRemoveName_s removeName; + } NSS_MEDIA_UNION(NamelessUnion,remove.name[MAX_DN_CHARS]) u; +} NSS_MEDIA_STRUCTURE(UserLog_s,u.remove.name[MAX_DN_CHARS]) UserLog_s; + +/**************************************************************************** + * + * Function Prototypes + * + ****************************************************************************/ + +STATUS ZFSVOL_VOL_GetUserSpaceInfo( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + const UserID_t *userID, + SQUAD *restrictionAmount, + SQUAD *usedAmount); + +STATUS ZFSVOL_VOL_SetUserSpaceRestriction( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Xaction_s *xAction, + const UserID_t *userID, + SQUAD restrictionAmount); + +void ZFSVOL_VOL_AdjustUsedUserSpace( + struct Xaction_s *xAction, + struct RootBeast_s *beast, + SQUAD usedAdjustment); + +STATUS ZFSVOL_VOL_RemoveUser( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + const UserID_t *userID); + +STATUS ZFSVOL_VOL_ResetAllUsers( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume); + +STATUS ZFSVOL_VOL_BrowseUsersInVolume( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT numEntriesRequested, + UserID_t *lastUserReturned, /* inout */ + struct COMNUserRest_s *userEntries, /* out */ + NINT *numEntriesReturned, /* out */ + LONG allUsersFlags); + +STATUS ZFSVOL_VOL_ResetAllObjects( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume); + +STATUS ZFSVOL_VOL_GetObjectName( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + UserID_t *objectID, + unicode_t *name, + Time_t *timeNotFound, + NINT *numberOfTimesNotFound); + +STATUS ZFSVOL_VOL_InsertObjectName( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Xaction_s *xAction, + UserID_t *objectID, + unicode_t *name); + +STATUS ZFSVOL_VOL_ModifyObjectName( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct Xaction_s *xAction, + UserID_t *objectID, + unicode_t *name, + Time_t timeNotFound, + NINT numberOfTimesNotFound); + +STATUS UBT_CreateUserTreeBeast( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *volume); + +STATUS UBT_OLD_ResetAllUsers( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + struct ZfsUserTreeBeast_s *userTreeBeast); + +/**************************************************************************** + * + * Externals + * + ****************************************************************************/ +STATUS UBT_modifyUserValue ( + struct GeneralMsg_s *genMsg, + struct UserTreeParms_s *parms); + + +#ifdef NW5X_UPGRADE +STATUS ZFSPOOL_upgradeUserTree( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *volume, + struct ZfsUserTreeBeast_s *oldTree); +#endif + + +#endif diff --git a/src/nwnss/zlss/xaction.h b/src/nwnss/zlss/xaction.h new file mode 100644 index 0000000..12952f8 --- /dev/null +++ b/src/nwnss/zlss/xaction.h @@ -0,0 +1,1668 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2007-04-26 04:35:22 +0530 (Thu, 26 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1962 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Definitions used by transactions + +-------------------------------------------------------------------------*/ +#ifndef _XACTION_H_ +#define _XACTION_H_ + +#ifndef _QUE_H_ +#include "que.h" +#endif + +#ifndef _XCACHE_H_ +#include +#endif + +#ifndef _VOLUME_H_ +#include "volume.h" +#endif + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +/* Pre-declare the following structure(s) */ +struct ZfsXasRecovery_s; + +#if LOG_TEST IS_ENABLED +#define LOG_TEST_MAX 6 +#endif + +/* + * Structure used by transactions (xaction). Active xactions are kept + * in a linked list from oldest to youngest by ZLOG. This structure + * was going to be generic, but we made it ZSTORE specific in Feb 1997 + * becuase ??? + */ + + /* States for an active transaction. */ +#define X_COMMITTED 0x0001 /* Xaction has been committed */ +#define X_PREPARED 0x0002 /* Prepared to commit */ +#define X_DONT_COMMIT 0x0004 /* Do not commit */ + /* These are the ZXR_TransactionState defines */ +#define XAS_XR_TS_START 0x0010 +#define XAS_XR_TS_MIDDLE 0x0020 +#define XAS_XR_TS_END 0x0040 +#define X_REDO_THEN_UNDO 0x0080 /* Debug. Do redo then undo verses + * undo then redo. + */ +#define XAS_XR_TS_UNDO_LOGICAL_COPY 0x0100 + + /* xflags */ +#define XFLAG_LOGICAL_UNDO 0x0001 +#define XFLAG_LOGICAL_UNDO_FREE_TREE_INSERT 0x0002 + + +#define zX_LOGICAL 0x584c4f47 /*XLOG*/ + +typedef STATUS (*LogTestCompareFunc_t)( + void *src1, + void *src2, + NINT length); + +typedef struct LocalXid_t +{ + LONG unique; /* Unique number -- starts at 1 */ + LONG restartCount; /* Set to RestartCount */ +} NSS_MEDIA_STRUCTURE(LocalXid_t,restartCount) LocalXid_t; + +typedef struct ZfsXaction_s +{ + Xaction_s xaction; /* ZfsXaction_s is derived from Xaction_s */ + Lsn_t ZX_lsn; + /* LSN associated with the first log record + * of this transaction. Protected by ZLOG's + * beastLatch. + */ + LocalXid_t localXid; /* Transaction's ID - unique for all transactions */ +// void (*signalHomed)(struct Xaction_s *); + /* Who to tell when transaction homed. This routine + * must run as a FSM. The routine can use home.fsm + * to to a FSM LATCH. + */ + struct ZlogBeast_s *ZX_zlogBeast; + /* Filled in at BeginXLocal(). This is for a + * quick/cheap way of accessing ZLOG. Placed in generic + * part of Xaction_s just to get transaction stuff + * working. + */ +// struct ZfsPool_s *ZX_zfsPool; /* Pool for transaction */ + struct ZfsVolume_s *ZX_zfsVol; /* Volume for transaction */ + DQlink_t ZX_seniorityList; + /* ZFS transactions are linked by oldest to + * youngest by ZLOG so ZLOG can determine when + * home can be moved. The oldest transaction has + * the lowest LSN, while the youngest transaction + * has the highest LSN. The head of this list is + * stored in the ZlogBeast_s. Concurrent access + * is protected by ZlogBeast_s data latch. + */ + Blknum_t ZX_logBlockNumber; + /* Log block number of first log record of this + * transaction. Protected by ZLOG Beast's + * dataLatch. + */ + DQhead_t ZX_deleteBlkQ; /* Queue of pool blocks to be deleted */ + WORD xstate; /* Current transaction state */ + WORD xflags; /* Current transaction flags */ + DQhead_t freeUserDataBlks; /* Linked list of all the user data blks + * that were freed during this xaction + */ + DQhead_t freePurgeLogEntries; /* Linked list of all purgeLog entries + * that were removed during this xaction + */ + Lsn_t ZX_logicalUndoLSN; + /* LSN associated with the logical undo record + * that initiated this transaction + */ + +#if NSS_DEBUG IS_ENABLED + DQlink_t inuse; /* List of Xactions being used */ + Seq_t timeStamp; /* Time stamp of when this tranaction + * was started. + */ + Seq_t commitStamp; /* Time stamp on commit */ + LONG caller; + LONG callerCaller; + LONG numFreeNonusableBlks; /* This is the count of user data blkd + * that were freed by this transaction, + * but will be available for reuse only + * when the xaction ends + */ +#endif +#if LOG_TEST IS_ENABLED + /* + * Used by test code that makes the code do and immediate + * redo/undo after releasing a log record. + */ + struct Buffer_s *ZX_Buffers[LOG_TEST_MAX]; + LogTestCompareFunc_t ZX_Compare[LOG_TEST_MAX]; + #endif +} ZfsXaction_s; + +#define BXL_DEFAULT 0 /* Default for storage specific callers + * of BeginXLocal(). Note that this + * define is passed to BeginXLocal() which + * currently is used as the BeginXLocal + * common op function. Therefore, this + * define must adhere to the definition + * of the common op flags. See X_CF... + * defines in comnBeasts.h before changing + * this value. + */ +#define BXL_LOGICAL_UNDO 0x80000000 /* Transaction was started during + * logical undo pass. + */ +#define BXL_LOGICAL_UNDO_FREE_TREE_INSERT 0x40000000 /* Transaction was + * started during + * logical undo of + * free tree insert + */ + +#define SET_LUNDO_LSN(_xaction, _log, _status) \ +{ \ + (_xaction)->ZX_logicalUndoLSN = (_log)->ZXR_Lsn; \ + if ((_status) != zOK) \ + { \ + (_xaction)->xstate |= X_DONT_COMMIT; \ + } \ +} + +Xaction_s *ZFSVOL_VOL_beginXLocal(Volume_s *volume, NINT flags); +void ZFSVOL_VOL_endXLocal(Xaction_s *xaction); + +extern ZfsXaction_s *BeginXLocal(Volume_s *volume, NINT flags); +extern void EndXlocal(ZfsXaction_s *xaction); +extern void EndXlocalAsync(ZfsXaction_s *xaction); +extern void XdeferPoolBlk(ZfsXaction_s *xaction, Blknum_t poolBlk); +extern void freeXaction(ZfsXaction_s *xaction); + +extern STATUS XactionRecover( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode); + +extern STATUS XactionRecoverLogicalUndoPass1To6( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode); + +extern STATUS XactionRecoverLogicalUndoPass7( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool); + +extern void XfreePoolBlks( + struct ZfsPool_s *pool, + Lsn_t maxlsn); + + +extern STATUS XACT_Startup(void); +extern void XACT_Shutdown(void); +STATUS XDEL_Startup(void); +void XDEL_Shutdown(void); +void XDEL_DeactivateVolume(struct ZfsVolume_s *zfsVol); + +extern ControlStore_s FreeUserDataBlksControl; +extern STATUS XACT_holdFreeUserDataBlks( + Extent_s *extent, + ZfsXaction_s *xaction); + +extern STATUS XACT_releaseFreeUserDataBlks( + ZfsXaction_s *xaction); + +extern BOOL XACT_blksNotOnFreeList( + ZfsPool_s *pool, + Extent_s *nodeExtent, + Extent_s *reqExtent); + +typedef struct FreeUserDataBlks_s { + DQlink_t xactionLink; + DQlink_t globalListLink; + Extent_s freeExt; +} FreeUserDataBlks_s; + +#if FREE_DATA_STATS IS_ENABLED +typedef struct FreeUserDataBlksStats_s { + QUAD listEmpty; /* freeDataBlksList was empty during + * block alloc */ + QUAD listNotEmpty; /* Not empty */ + QUAD retBlockUnAvail; /* The block F-Tree wanted was on + * freeDataBlksList */ + QUAD retBlockAvail; /* Not on list */ + QUAD totalFreeExtents; /* Number of extents placed onto + * freeDataBlksList */ + QUAD freeExtentsProcessed;/* Number of extents searched on + * freeDataBlksList during block alloc */ + QUAD currentFreeExtents; /* Number of extents on freeDataBlksList + * at this moment. */ + QUAD processedNodeTwice; + /* All these stats are for 'higher block' logic */ + QUAD FUDBS_ListEmpty; /* No blocks on freeDataBlksList */ + QUAD FUDBS_Free; /* Able to alloc some of node extent */ + QUAD FUDBS_PartNotFree; /* Not able to alloc some of node extent */ + QUAD FUDBS_NotFree; /* Not able to alloc ANY of node extent */ +} FreeUserDataBlksStats_s; + +extern FreeUserDataBlksStats_s UserFreeStats; + +#endif + +#if FREE_DATA_STATS IS_ENABLED +#define BLKS_CAN_BE_ALLOCATED(_pool, _nodeExt, _reqExt) \ + (DQ_EMPTY(&(_pool)->freeDataBlksList) ? (UserFreeStats.listEmpty++,TRUE): \ + XACT_blksNotOnFreeList(_pool, _nodeExt,_reqExt)) +#else +#define BLKS_CAN_BE_ALLOCATED(_pool, _nodeExt, _reqExt) \ + (DQ_EMPTY(&(_pool)->freeDataBlksList) ? TRUE : \ + XACT_blksNotOnFreeList(_pool, _nodeExt,_reqExt)) +#endif + +#define RELEASE_FREE_DATA_BLKS(_xaction) \ + XACT_releaseFreeUserDataBlks(_xaction) + +#define IS_LOGICAL_UNDO_XACTION(_xaction) \ + ((_xaction != NULL) && (_xaction->xflags & XFLAG_LOGICAL_UNDO)) + +#define IS_LOGICAL_UNDO_FREE_TREE_INSERT_XACTION(_xaction) \ + ((_xaction != NULL) && \ + (_xaction->xflags & XFLAG_LOGICAL_UNDO) && \ + (_xaction->xflags & XFLAG_LOGICAL_UNDO_FREE_TREE_INSERT)) +/* + * Macros and functions for manipulating transaction strucutures. + */ + + /* + * The Transaction Recovery Table is used to find the functions that + * need to called to undoing/redoing transactions. + */ +#define X_REDO 1 +#define X_UNDO 2 +#define X_L_UNDO 3 + + /* + * Developers will need to make #define's for their respecitive + * recovery functions. These are indexes into an array of + * pointers to functions and MUST be unique. Each #define will + * index 2 functions. One to be called during the Redo pass and + * the other to be called during the Undo pass. + */ +#define XFUNC_DUMMY 0 + +/* administrative and Debug */ +#define XFUNC_IGNORE 1 /*** If this value changes you need + to re-build the dumpzlog utility ***/ + +/* beast b-tree */ +#define XFUNC_BTREE_INSERT_ZNODE 2 /*used for special systems block only*/ +#define XFUNC_BTREE_DELETE_ZNODE 3 /*used for special systems block only*/ +#define XFUNC_BTREE_SPLIT 4 +#define XFUNC_BTREE_JOIN 5 +#define XFUNC_BTREE_BALANCE 6 +#define XFUNC_BTREE_OVERFLOW 7 +#define XFUNC_BTREE_GROW 8 +#define XFUNC_BTREE_SHRINK 9 +#define XFUNC_BTREE_INIT 10 + +/* purge log */ +#define XFUNC_PLOG_INIT 11 +#define XFUNC_PLOG_GROW 12 +#define XFUNC_PLOG_INSERT 13 +#define XFUNC_PLOG_DELETE 14 + +/* file map b-tree */ +#define XFUNC_FMAP_INIT_ROOT 15 +#define XFUNC_FMAP_INSERT 16 +#define XFUNC_FMAP_INSERT_SPARSE 17 +#define XFUNC_FMAP_GROW 18 +#define XFUNC_FMAP_SPLIT 19 +#define XFUNC_FMAP_REMOVE 20 +#define XFUNC_FMAP_JOIN 21 +#define XFUNC_FMAP_TOSS 22 + +/* name log */ +#define XFUNC_NAME_INIT 23 /*unused after name tree added*/ +#define XFUNC_NAME_ADD 24 /*unused after name tree added*/ +#define XFUNC_NAME_REMOVE 25 /*unused after name tree added*/ +#define XFUNC_NAME_MODIFY 26 /*unused after name tree added*/ + +/* free tree */ +#define XFUNC_FXLOG_SHRINK 27 +#define XFUNC_FXLOG_DELETE 28 /*used for special blk only*/ +#define XFUNC_FXLOG_BALANCE 29 /*used for special blk only*/ +#define XFUNC_FXLOG_JOIN 30 +#define XFUNC_FXLOG_GROW 31 +#define XFUNC_FXLOG_SPLIT 32 +#define XFUNC_FXLOG_INSERT 33 + +/* volume info */ +#define XFUNC_VOLINFO_MODIFY 34 + +/* Naming B-Tree */ +#define XFUNC_NTREE_OLD_OP 35 + +/* Old Purge b-tree left here for backwards compatibility */ +#define XFUNC_PTREE_INSERT_LENTRY 36 +#define XFUNC_PTREE_DELETE_LENTRY 37 +#define XFUNC_PTREE_SPLIT 38 +#define XFUNC_PTREE_JOIN 39 +#define XFUNC_PTREE_BALANCE 40 +#define XFUNC_PTREE_OVERFLOW 41 +#define XFUNC_PTREE_GROW 42 +#define XFUNC_PTREE_SHRINK 43 +#define XFUNC_PTREE_INIT 44 + +/* user b-tree */ +#define XFUNC_USERTREE_MODIFY_ENTRY 45 /*unused starting with 6-pack*/ +#define XFUNC_USERTREE_INSERT_ENTRY 46 /*unused starting with 6-pack*/ +#define XFUNC_USERTREE_DELETE_ENTRY 47 /*unused starting with 6-pack*/ +#define XFUNC_USERTREE_SPLIT 48 +#define XFUNC_USERTREE_JOIN 49 +#define XFUNC_USERTREE_BALANCE 50 +#define XFUNC_USERTREE_GROW 51 +#define XFUNC_USERTREE_SHRINK 52 +#define XFUNC_USERTREE_INIT 53 +#define XFUNC_USERTREE_REMOVE 54 + +/* LV delete operations */ +#define XFUNC_LV_SHRINK_ROOT 55 +#define XFUNC_LV_BT_SHRINK 56 +#define XFUNC_LV_NT_SHRINK 57 +#define XFUNC_LV_NT_SHRINK_LEAF_OVERFLOW 58 +#define XFUNC_LV_NT_SHRINK_BRANCH_OVERFLOW 59 + +/* LV create operations */ +#define XFUNC_LV_BT_INIT 60 +#define XFUNC_LV_PL_INIT 61 +#define XFUNC_LV_VDB_INIT 62 +#define XFUNC_LV_LVDB_INIT 63 + +/* pool info */ +#define XFUNC_POOLINFO_MODIFY 64 + +/* Logical undo operations */ +#define XFUNC_BTREE_L_INSERT 65 +#define XFUNC_BTREE_L_DELETE 66 +#define XFUNC_FXLOG_L_INSERT 67 +#define XFUNC_FXLOG_L_DELETE 68 +#define XFUNC_PTREE_L_INSERT 69 /* unused after switching to */ +#define XFUNC_PTREE_L_DELETE 70 /* Generic Purge Tree */ +#define XFUNC_UTREE_L_MODIFY 71 +#define XFUNC_UTREE_L_INSERT 72 +#define XFUNC_UTREE_L_DELETE 73 + +/* Name tree physical operations */ +#define XFUNC_NTREE_INTERNAL_OP 74 + +/* Superblock header */ +#define XFUNC_SB_HEADER 75 + +/* LPDB and PDB redo/undo init functions */ +#define XFUNC_LV_PDB_INIT 76 +#define XFUNC_LV_LPDB_INIT 77 +#define XFUNC_LV_VDB_UPDATE 78 + +/* directory b-tree */ +#define XFUNC_DIRTREE_MODIFY_ENTRY_UNUSED 79 /*unused starting with 6-pack*/ +#define XFUNC_DIRTREE_INSERT_ENTRY_UNUSED 80 /*unused starting with 6-pack*/ +#define XFUNC_DIRTREE_DELETE_ENTRY_UNISED 81 /*unused starting with 6-pack*/ +#define XFUNC_DIRTREE_SPLIT 82 +#define XFUNC_DIRTREE_JOIN 83 +#define XFUNC_DIRTREE_BALANCE 84 +#define XFUNC_DIRTREE_GROW 85 +#define XFUNC_DIRTREE_SHRINK 86 +#define XFUNC_DIRTREE_INIT 87 +#define XFUNC_DIRTREE_REMOVE 88 +#define XFUNC_DIRTREE_L_MODIFY 89 +#define XFUNC_DIRTREE_L_INSERT 90 +#define XFUNC_DIRTREE_L_DELETE 91 + +/* + * New Purge B-tree is an instance of generic MYBTree + * 3 for interface operations + * 6 for internal operations + * All numbers from 92 to 101 are in use! + */ +#define XFUNC_PTREE_LOGICAL_OP_START 92 +#define XFUNC_PTREE_LOGICAL_OP_END 94 /* 92 + 3 - 1 */ +#define XFUNC_PTREE_INTERNAL_OP_START 95 +#define XFUNC_PTREE_INTERNAL_OP_END 101 /* 95 + 7 - 1 */ + +/*************************************************************************** + * "XFUNC_PTREE_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_INSERT_ENTRY" 92 + * "XFUNC_PTREE_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_DELETE_ENTRY" 93 + * "XFUNC_PTREE_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_MODIFY_ENTRY" 94 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_SPLIT" 95 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_JOIN" 96 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_BALANCE" 97 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_GROW" 98 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_SHRINK" 99 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_INIT" 100 + * "XFUNC_PTREE_INTERNAL_OP_START + MYBT_RECOVERY_OP_REMOVE_NODE" 101 + ****************************************************************************/ + +/* + * MFL B-tree: an instance of generic MYBTree + * 3 for interface operations + * 6 for internal operations + * All numbers from 102 to 111 are in use! + */ +#define XFUNC_MFL_LOGICAL_OP_START 102 +#define XFUNC_MFL_LOGICAL_OP_END 104 /* 101 + 3 - 1 */ +#define XFUNC_MFL_INTERNAL_OP_START 105 +#define XFUNC_MFL_INTERNAL_OP_END 111 /* 104 + 7 - 1 */ + +/**************************************************************************** + * "XFUNC_MFL_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_INSERT_ENTRY" 102 + * "XFUNC_MFL_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_DELETE_ENTRY" 103 + * "XFUNC_MFL_LOGICAL_OP_START + MYBT_RECOVERY_L_OP_MODIFY_ENTRY" 104 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_SPLIT" 105 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_JOIN" 106 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_BALANCE" 107 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_GROW" 108 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_SHRINK" 109 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_INIT" 110 + * "XFUNC_MFL_INTERNAL_OP_START + MYBT_RECOVERY_OP_REMOVE_NODE" 111 + ****************************************************************************/ + +/* Name Tree Logical Op */ +#define XFUNC_NTREE_LOGICAL_OP 112 + +#define XFUNC_COMPENSATION 113 + +/* User tree object name operations */ +#define XFUNC_UTREE_MODIFY_NAME 114 +#define XFUNC_UTREE_ADD_NAME_RECORD 115 +#define XFUNC_UTREE_ADD_NAME 116 +#define XFUNC_UTREE_REMOVE_NAME_RECORD 117 +#define XFUNC_UTREE_DELETE_NAME_RECORD 118 +#define XFUNC_UTREE_MODIFY_NAME_ENTRY 119 +#define XFUNC_UTREE_DELETE_ALL 120 +#define XFUNC_UTREE_DELETE_NAME 121 + +/* Event File List operations */ +#define XFUNC_EFLTREE_SPLIT 122 +#define XFUNC_EFLTREE_JOIN 123 +#define XFUNC_EFLTREE_BALANCE 124 +#define XFUNC_EFLTREE_GROW 125 +#define XFUNC_EFLTREE_SHRINK 126 +#define XFUNC_EFLTREE_INIT 127 +#define XFUNC_EFLTREE_L_INSERT 128 +#define XFUNC_EFLTREE_L_DELETE 129 +#define XFUNC_EFLTREE_L_MODIFY 130 +#define XFUNC_EFLTREE_REMOVE 131 +#define XFUNC_EFLTREE_REMOVE_LOG 132 +#define XFUNC_EFLLOG_ADD_NODE 133 +#define XFUNC_EFLLOG_ADD_ENTRY 134 +#define XFUNC_EFLLOG_ADD_ENTRY_NAME 135 +#define XFUNC_EFLLOG_REMOVE_NODE 136 +#define XFUNC_EFLLOG_MODIFY_EPOCH 137 + + +/* READ THIS before adding more operations !!!! */ +/* Talk to Vandana (or Greg or Randy) before adding more + * logging operations. Logical undo functionality and rules need to + * be considered. Redo routines have to be physical, undo routines + * physical and/or logical. Then change #if on #error below to match new max + */ + + +/* + * #define XFUNC_MAX 137+1 + * + * This define is now in ZFS.h! Be sure to update it if you increase + * the number of REDO/UNDO functions. + * + */ +#if XFUNC_MAX != 138 +/* Talk to Vandana (or Greg ) before adding more + * logging operations. Logical undo functionality and rules need to + * be considered. Redo routines have to be physical, undo routines + * physical and/or logical. Then change above #if to match new max + */ +#error You did not read (or follow) the above comment!!! +#endif + +typedef STATUS (*XRecovery_f)( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logRecord, + NINT pass); + +typedef struct RedoUndo_s +{ + XRecovery_f redo; + XRecovery_f undo; +} RedoUndo_s; + +#define BLOCK_TABLE_ALLOC_SIZE 4//256 /* number of block entries in each allocation. */ +#define INITIAL_XTABLE_SIZE 4//256 /* Initial number of transaction entries. */ +#define INITIAL_DTABLE_SIZE 4//64 /* Initial number of deleted block entries. */ +#define INITIAL_UTABLE_SIZE 4//64 /* Initial number of uncommitted entries. */ +#define INITIAL_UNDO_TABLE_SIZE 4//128 /* Initial number of uncommitted entries. */ +#define XTABLE_GROWTH_FACTOR 4 /* Factor we grow by when we have + * to grow the table. + */ + +extern RedoUndo_s XRecoveryTable[XFUNC_MAX]; + + /* + * The undo table holds entries we know need to be undone later. + */ +typedef struct UndoTable_s +{ + NINT size; /* current size of the table */ + NINT numEntries; /* number of entries in the table */ + LocalXid_t *xids; /* pointer to the first entry */ +} UndoTable_s; + + /* + * The uncommitted table holds entries we know are uncommitted until we + * can process them against the transaction table. + */ +typedef struct UncommittedTable_s +{ + NINT size; /* current size of the table */ + NINT numEntries; /* number of entries in the table */ + LocalXid_t *xids; /* pointer to the first entry */ +} UncommittedTable_s; + +// /* +// * The deleted block table holds an entry for each block that has the purge +// * bit set. +// */ +//typedef struct DeletedBlockEntry_s +//{ +// Blknum_t block; +// NINT generation; +//} DeletedBlockEntry_s; +// +//typedef struct DeletedBlockTable_s +//{ +// NINT size; /* current size of the table */ +// NINT numEntries; /* number of entries in the table */ +// DeletedBlockEntry_s *entry; /* pointer to the first entry */ +//} DeletedBlockTable_s; + + /* + * The block table holds an entry for blocks associated with a transaction. + * The blocks are linked off from a transaction. + */ +typedef struct BlockNumberEntry_s +{ + STKlink_t link; /* link to next block number entry for this xaction */ + Blknum_t block; +// NINT generation; + WORD sequence; +// WORD state; /* log state */ +} BlockNumberEntry_s; + +typedef struct BlockTableMem_s +{ + STKlink_t nextMem; /* link to the next memory block */ + BlockNumberEntry_s entry[BLOCK_TABLE_ALLOC_SIZE]; /* space for block info */ +} BlockTableMem_s; + +typedef struct BlockTable_s +{ + STKtop_t availList; /* start of the linked list of available entries*/ + STKtop_t memList; /* a linked list of the memory use to hold blocks */ +} BlockTable_s; + + /* + * Transaction table used during recovery. It is designed to be + * dynamically grown during recovery. It keeps track of which + * transactions have not been committed. + */ +typedef struct XactionTableEntry_s +{ + NINT state; + LocalXid_t xid; + STKtop_t blockList; /* head of linked list in block table */ +} XactionTableEntry_s; + + /* State values of XactionTableEntry */ +#define XTE_COMMITTED 0x01 +#define XTE_COMPLETED 0x02 + +typedef struct XactTable_s +{ + NINT size; /* Current size of the transaction table */ + NINT numEntries; /* number of entries in the table */ + NINT numUncommittedEntries; + /* After PASS 1 numUncommittedEntries is the number + * of transactions that are not committed. + * During PASS 2 the count is decremented as the + * uncommitted transaction is removed from this + * table. This occurs when PASS 2 hits the + * transaction start log record (PASS 2 is a + * backwards search). This count is incremented + * during PASS 2 when a committed xaction is + * convertted to an uncommitted xaction because + * of matching block numbers. When the count + * reaches 0 we are done with PASS 2. If it + * does not reach 0 before reaching the end of + * the expanded ZLOG search it means we can not + * recovery successfully. + */ +#if NSS_DEBUG IS_ENABLED + Time_t xactionTime; /* UTC when transaction recorded */ +#endif + XactionTableEntry_s *xEntry; /* Space for allocation */ +} XactTable_s; + + /* + * Table of blocks freed in log. It keeps track + * of the blocks we can't apply transactions because + * the block was later freed and may have been reallocated. + */ +typedef struct XfreedBlk_s +{ + Blknum_t poolBlk; /* Pool block deleted */ +// The LSN is commented out because: +// we should not need to check for allocated blocks because a deleted block +// should not be reallocated until it is no longer affected by the log. +// Lsn_t lsn; /* Log sequence where we can begin +// * using this log. +// */ +} XfreedBlk_s; + +typedef struct XfreeTable_s +{ + NINT size; /* Current size of the freed block table */ + NINT free; /* Where free space starts */ + XfreedBlk_s *blks; /* Space for allocation */ +} XfreeTable_s; + +/************************************************************************ + * External declarations for the recovery routines * + ************************************************************************/ + +extern STATUS recoveryInsertZnode( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryDeleteZnode( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryInsertZnodeLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryDeleteZnodeLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoverySplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryBalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryInsertOverflow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryRemoveOverflow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryVDBInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryVDBUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryLVDBInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryLVDBUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS redoInitRoot( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoInitRoot( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapInsert( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapInsert( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapInsertSparse( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapInsertSparse( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapSplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapSplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFmapToss( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFmapToss( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogInsert( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS recoveryPurgeLogRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXshrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXshrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXdelete( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXdelete( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXdeleteLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXbalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXbalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXjoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXjoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXgrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXgrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXsplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXsplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoFXinsert( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXinsert( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoFXinsertLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern void undoFXinsertLogicalHoldBlks( + struct ZfsPool_s *zfspool, + struct ZfsXasRecovery_s *logBuffer); + +extern STATUS recoveryVolumeInfo( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +/* Name B-Tree recovery routines */ +extern STATUS dlog_recovery_common( + struct GeneralMsg_s *gm, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *dlbuf, + NINT action); + +extern STATUS dlog_logical_recovery_common( + struct GeneralMsg_s *gm, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *dlbuf, + NINT action); + +#ifdef NSSOLD_NAMING +extern STATUS redoNameInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoNameInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS addNameToDir( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS removeNameFromDir( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS redoModifyNSMask( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); + +extern STATUS undoModifyNSMask( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT pass); +#endif + +/* Old Purge B-Tree recovery routines */ +extern STATUS pbt_recoveryInsertEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryDeleteEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* Not yet being used */ +extern STATUS pbt_recoveryInsertEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* Not yet being used */ +extern STATUS pbt_recoveryDeleteEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoverySplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryBalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryInsertOverflow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryRemoveOverflow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_recoveryUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* New Purge B-Tree recovery routines */ +extern STATUS pbt_internalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS pbt_logicalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* User B-Tree recovery routines */ +extern STATUS UBT_recoveryInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryBalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoverySplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryInsertEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyName( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryAddNameRecord( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteNameRecord( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryInsertNameRecord( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryRemoveNameRecord( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryAddName( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryInsertEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyNameLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteNameLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyNameEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryModifyNameEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteAll( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryAddAll( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryDeleteName( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS UBT_recoveryAddOnlyName( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZLSSPOOL_RecoverySuperblockHeader( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZLSSPOOL_RecoveryPoolInfo( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZLSSVOL_LVD_RecoveryBTShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZLSSVOL_LVD_RecoveryBTShrinkRoot( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZLSSVOL_LVD_RecoveryNTShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryPDBInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryPDBUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryLPDBInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS recoveryLPDBUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS recoveryVDBUpdate( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* MFL recovery routine */ +extern STATUS MFL_internalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS MFL_logicalRecoveryCommon( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* EFL recovery routines */ +extern STATUS EFL_recoverySplit ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryJoin ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryBalance ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryGrow ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryShrink ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryInit ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryUninit ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryInsertEntry ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryDeleteEntryLogical ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryDeleteEntry ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryInsertEntryLogical ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryModifyEntry ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryModifyEntryLogical ( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS EFL_recoveryRemoveLog( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryAddNode( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryAddNodeUndo( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryAddEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryRemoveEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryAddEntryName( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryRemoveEntryNameLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryRemoveNode( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryRemoveNodeUndo( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS ELOG_recoveryModifyEpoch( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +/* Directory Tree routines */ +extern STATUS DBT_recoveryInit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryUninit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryShrink( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryGrow( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryBalance( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryJoin( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoverySplit( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryInsertEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryDeleteEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryModifyEntry( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryInsertEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryDeleteEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryModifyEntryLogical( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +extern STATUS DBT_recoveryRemove( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); +#endif diff --git a/src/nwnss/zlss/z_aes.h b/src/nwnss/zlss/z_aes.h new file mode 100644 index 0000000..608e45c --- /dev/null +++ b/src/nwnss/zlss/z_aes.h @@ -0,0 +1,113 @@ +/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * 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. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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 HEADER_AES_H +#define HEADER_AES_H + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +/* Because array size can't be a const in C, the following two are macros. + Both sizes are in bytes. */ +#define AES_MAXNR 14 +#define AES_BLOCK_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { +// unsigned long rd_key[4 *(AES_MAXNR + 1)]; + u32 rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +const char *AES_options(void); + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num); +void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char ivec[AES_BLOCK_SIZE], + unsigned char ecount_buf[AES_BLOCK_SIZE], + unsigned int *num); + + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_AES_H */ diff --git a/src/nwnss/zlss/z_aes_locl.h b/src/nwnss/zlss/z_aes_locl.h new file mode 100644 index 0000000..91630d1 --- /dev/null +++ b/src/nwnss/zlss/z_aes_locl.h @@ -0,0 +1,85 @@ +/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * 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. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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 HEADER_AES_LOCL_H +#define HEADER_AES_LOCL_H + +//#include /* Removed by Brenda */ + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#include +#include +#include + +#if defined(_MSC_VER) && !defined(OPENSSL_SYS_WINCE) +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +//typedef unsigned long u32; +//typedef unsigned short u16; +//typedef unsigned char u8; + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +/* This controls loop-unrolling in aes_core.c */ +#undef FULL_UNROLL + +#endif /* !HEADER_AES_LOCL_H */ diff --git a/src/nwnss/zlss/zedExport.h b/src/nwnss/zlss/zedExport.h new file mode 100644 index 0000000..b3cb335 --- /dev/null +++ b/src/nwnss/zlss/zedExport.h @@ -0,0 +1,60 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Service (NSS) Debug Menu module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + | Export data for ZED. + | + +-------------------------------------------------------------------------*/ + +#ifndef _ZEDEXPORT_H_ +#define _ZEDEXPORT_H_ + +#ifndef _ZFSSUPERBLK_H_ +#include +#endif +/* Function prototypes */ + +struct zedPoolStruc +{ + ZfsPool_s *poolAddr; + LONG blockSize; + LONG totalBlocks; +}; + +STATUS GetZedStuff(ADDR **zedList); +//STATUS GetZedPoolInfo(LONG poolID, struct zedPoolStruc *poolPtr); +void ZedStuffInit(); + + +#endif diff --git a/src/nwnss/zlss/zfs.h b/src/nwnss/zlss/zfs.h new file mode 100644 index 0000000..8a12e36 --- /dev/null +++ b/src/nwnss/zlss/zfs.h @@ -0,0 +1,2770 @@ +/**************************************************************************** + | + | (C) Copyright 1995-2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: cteerlink $ + | $Date: 2008-04-18 03:39:54 +0530 (Fri, 18 Apr 2008) $ + | + | $RCSfile$ + | $Revision: 2319 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | zfs.h defines information that affects the format of the data + | on the disk. This file needs to be referenced by utilities like + | install and diskedit. The classes used by ZFS are defined here too. + | + | WARNING: Data structures and QUADs should be designed to align + | on 64 bit boundries. So when we get a 64 bit processor things + | are aligned correctly. + +-------------------------------------------------------------------------*/ +#ifndef _ZFS_H_ +#define _ZFS_H_ + +#ifndef _XCACHE_H_ +#include +#endif + +#ifndef _XSTDLIB_H_ +#include +#endif + +#ifndef _COMNBEASTS_H_ +#include "comnBeasts.h" +#endif + +#ifndef _VOLUME_H_ +#include "volume.h" +#endif + +#ifndef _HMC_H_ +#include "hmc.h" +#endif + +/* Pre-declare the following structure(s) */ +struct ZfsXaction_s; +struct ZlssPool_s; +struct ZfsPool_s; +struct MediaSuperBlockHeader_s; +struct ZfsXasRecovery_s; +struct PCLSwitchDef_s; +struct XML_ElementInfo_s; +struct MediaSuperBlockHeader_s; + +#define ZFS_RESERVED_BLOCKS_FOR_INTERNAL_ALLOCATION 128 +#define ZFS_RESERVED_BLOCKS_FOR_RECOVERY 48 +#define ZFS_BLOCK_SHIFT 12 +#define ZFSVOL_HAS_SYSTEM_BEASTS (!VOL_DOES_ROOTDIR) + +#define LV_POOL_BLOCKS 2 /* Number of pool data blocks (one logged; one non-logged) */ + + +/* The read ahead used to be 2 -- don't know why. I have increased the + * default read ahead to 16, as we see better read performance for large + * files. + */ +#define ZLSS_DEFAULT_READ_AHEAD 16 + +/************************************************************************** + * Well known ZIDS in a ZLSS pool + ***************************************************************************/ +#define ZFSPOOL_VOLBSTTREE_ZID (zINVALID_ZID+1) /* 1 */ +#define ZFSPOOL_FREETREE_ZID (zINVALID_ZID+2) /* 2 */ +#define ZFSPOOL_LOGFILE_ZID (zINVALID_ZID+3) /* 3 */ +#define ZFSPOOL_PURGELOG_ZID (zINVALID_ZID+4) /* 4 */ +#define ZFSPOOL_PURGETREE_ZID (zINVALID_ZID+5) /* 5 */ +#define ZFSPOOL_VOLNAMETREE_ZID (zINVALID_ZID+6) /* 6 */ +#define ZFSPOOL_REBUILDFILE_ZID (zINVALID_ZID+7) /* 7 */ +#define ZFSPOOL_VOLUSERTREE_ZID (zINVALID_ZID+8) /* 8 */ +#define ZFSVOL_PURGELOG_ZID (zINVALID_ZID+9) /* 9 */ +#define ZFSVOL_USERTREE_ZID (zINVALID_ZID+10) /* 10 */ +#define ZFSVOL_MFL_ZID (zINVALID_ZID+11) /* 11 */ +#define ZFSVOL_DIRTREE_ZID (zINVALID_ZID+12) /* 12 */ +#define ZFSVOL_EFL_ZID (zINVALID_ZID+13) /* 13 */ + +#define ZFSPOOL_MAX_RESERVED_SUPERBLK_ZID (zINVALID_ZID+14) /* 14 */ + + +typedef struct PersistentAuthBeast_1Dot0_s +{ + LONG ownerID; /* PERSISTENT - owner of this beast */ +} NSS_MEDIA_STRUCTURE(PersistentAuthBeast_1Dot0_s,ownerID) PersistentAuthBeast_1Dot0_s; + + + +/* Set ZLSS_IO_GATHER to ENABLE when you want to gather ZLSS + * detailed I/O log. This log can be saved with the ZLSSDebugIOStatsSave + * command. This is a hidden command. The program ZIOA (ZLSS IO + * Analysis) will convert this file into a text analysis file. ZIOA + * is in the nss\dev\util\zioa directory. NT, OS/2 and DOS versions exist. + * + * The log is stored into memory. + * + * The follow commands are active when ZLSS_IO_GATHER is enabled. + * + * ZLSSDebugIOLogSave - + * Hidden command only valid if ZLSS_IO_GATHER is enabled in the + * compile. This is not a DEBUG only command. Causes the ZLSS + * I/O log to be written as SYS:\ZLSS.ZSF. This file can then + * be processed by the ZIOA (ZLSS I/O Analysis utility). This + * utility is at nss\dev\util\zioa. This log file is used + * to analysis I/O. + * + * ZLSSDebugIOLogSize - + * Hidden command only valid if ZLSS_IO_GATHER is enabled in the + * compile. This is not a DEBUG only command. Sets the ZLSS I/O + * log size in bytes. Must be specified at startup only. + * + */ +//#define ZLSS_IO_GATHER ENABLE +#define ZLSS_IO_GATHER DISABLE + + +#define ZLSS_POOL_IO_TRACK( _zlssPool ) (_zlssPool)->ZP_PoolTrackIO + +/** FREE_DATA_STATS when enabled keeps instrumentation counts of how many + ** free chunks there are on the unusable list, and how often we hit + ** that list, and how many times we try to allocate blocks that cannot + ** be allocated etc. + **/ +#define FREE_DATA_STATS ENABLE /* TODO(Perf,FCS): turn this off for FCS? */ +//#define FREE_DATA_STATS DISABLE + +//#define DEBUG_MAX_FILE_BLK 0xffffffff /*50000000*/ + +#define ZLSS_PRS_SB_COUNT 16 +typedef struct { + QUAD PRS_SystemBeast[ZLSS_PRS_SB_COUNT]; + /* + * For the first 16 Zids we just store into our buffer. + * Zid 0 is used by all LVDB and VDB reads since the + * volume beast uses Zids from the Admin. + * Zid 15 is used for all other system beasts. + */ + QUAD PRS_SuperBlock; + QUAD PRS_UserBlock; + QUAD PRS_DirectIOBlock; /* Number of DIO UNITS(512) byte reads */ + QUAD PRS_Reserved[5]; +} NSS_MEDIA_STRUCTURE(PoolReadStatistics_s,PRS_Reserved[5]) PoolReadStatistics_s; + +typedef struct { + QUAD PWS_SystemBeast[ZLSS_PRS_SB_COUNT]; + /* + * For the first 16 Zids we just store into our buffer. + * Zid 0 is used by all LVDB and VDB reads since the + * volume beast uses Zids from the Admin. + * Zid 15 is used for all other system beasts. + */ + QUAD PWS_SuperBlock; + QUAD PWS_UserBlock; + QUAD PWS_DirectIOBlock; /* Number of DIO UNITS(512) byte writes */ + QUAD PWS_Reserved[4]; + QUAD PWS_BarrierIO; /* Number of times we have done a barrier flush */ +} NSS_MEDIA_STRUCTURE(PoolWriteStatistics_s,PWS_Reserved[4]) PoolWriteStatistics_s; + +extern Time_t ZLSSStartUpTime; /* UpTime when ZLSS started. */ +extern PoolWriteStatistics_s gZLSSPWS; +extern PoolReadStatistics_s gZLSSPRS; +extern LONG gZLSSIOStartUpTime; +extern BOOL gCLPoolTrackDeactive; +extern BOOL gCLPoolTrackActive; +extern BOOL gCLPoolTrackMaintenance; + +/**************************************************************************** + * ZFS Supported Attributes + *****************************************************************************/ +#define ZLSS_SUPPORTED_ATTRIBUTES (zATTR_SALVAGE | \ + zATTR_USER_SPACE_RESTRICTIONS /*| zATTR_READONLY*/ | zATTR_COMPRESSION | \ + zATTR_EXTENDED_ATTRIBUTES | zATTR_DATA_STREAMS | zATTR_DOS_METADATA | \ + zATTR_NETWARE_METADATA | zATTR_MAC_METADATA | zATTR_UNIX_METADATA | \ + zATTR_HARD_LINKS | zATTR_TRANSACTION | zATTR_SPARSE_FILES | \ + zATTR_PHYSICAL_EOF | zATTR_DIRECT_IO | zATTR_PERSISTENT_ATTRIBUTES | \ + zATTR_VERIFY | zATTR_REBUILD | zATTR_COW | zATTR_VIRTUAL_FILES | \ + zATTR_USER_TRANSACTION | zATTR_USER_TRANSACTION_ACTIVE | \ + zATTR_DONT_BACKUP | zATTR_MFL | zATTR_DIR_QUOTAS | zATTR_SHRED_DATA |\ + zATTR_HIGH_INTEGRITY | zATTR_MIGRATION | zATTR_CFS_MASTER | zATTR_ENCRYPTED |\ + zATTR_EXTENDED_MAC_NAMESPACE | zATTR_NO_ATIME) + + /* If you add bits to ZLSS_DEFAULT_ENABLED_ATTRIBUTES, you need to + * look at code in ZFSPOOL_LoadPersistentPool that uses this define + * to upgrade volumes and do what is being done for zATTR_SALVAGE + */ +#define ZLSS_DEFAULT_ENABLED_ATTRIBUTES (zATTR_SALVAGE | \ + zATTR_EXTENDED_ATTRIBUTES | zATTR_DATA_STREAMS | zATTR_DOS_METADATA | \ + zATTR_NETWARE_METADATA | zATTR_MAC_METADATA | zATTR_UNIX_METADATA | \ + zATTR_TRANSACTION | zATTR_SPARSE_FILES | \ + zATTR_PHYSICAL_EOF | zATTR_DIRECT_IO | zATTR_PERSISTENT_ATTRIBUTES | \ + zATTR_VERIFY | zATTR_REBUILD | zATTR_EXTENDED_MAC_NAMESPACE) + + /* If attribute bit is set in the next define then ZLSS modify info + * function will not allow the user to DISABLE the feature. + */ +/* fixfixfix@nextMediaFormatChange - zATTR_EXTENDED_MAC_NAMESPACE should be non-changeable at nextMediaFormatChange */ +#define ZLSS_NON_CHANGABLE_ATTRIBUTES ( zATTR_EXTENDED_ATTRIBUTES | \ + zATTR_DATA_STREAMS | zATTR_DOS_METADATA | zATTR_NETWARE_METADATA | \ + zATTR_MAC_METADATA | zATTR_UNIX_METADATA | \ + zATTR_TRANSACTION | zATTR_SPARSE_FILES | zATTR_PHYSICAL_EOF | \ + zATTR_DIRECT_IO | zATTR_PERSISTENT_ATTRIBUTES | zATTR_VERIFY | \ + zATTR_REBUILD | zATTR_VIRTUAL_FILES | zATTR_ENCRYPTED) + + + +/**************************************************************************** + * ZLSS POOL Supported features + *****************************************************************************/ +#define ZLSSPOOL_SUPPORTED_FEATURES \ + (zPOOL_FEATURE_PERSISTENT_FEATURES | \ + zPOOL_FEATURE_SHARED_CLUSTER | \ + /* zPOOL_FEATURE_READ_ONLY | */ \ + zPOOL_FEATURE_VERIFY | \ + zPOOL_FEATURE_REBUILD | \ + zPOOL_FEATURE_MULTIPLE_VOLUMES | \ + zPOOL_FEATURE_SNAPSHOT | \ + zPOOL_FEATURE_MSAP) + +#define ZLSSPOOL_DEFAULT_ENABLED_FEATURES \ + (zPOOL_FEATURE_PERSISTENT_FEATURES | \ + zPOOL_FEATURE_VERIFY | \ + zPOOL_FEATURE_REBUILD | \ + zPOOL_FEATURE_MULTIPLE_VOLUMES | \ + zPOOL_FEATURE_MSAP) + +#define ZLSSPOOL_NON_CHANGEABLE_FEATURES \ + (zPOOL_FEATURE_PERSISTENT_FEATURES | \ + zPOOL_FEATURE_SHARED_CLUSTER | \ + zPOOL_FEATURE_VERIFY | \ + zPOOL_FEATURE_REBUILD | \ + zPOOL_FEATURE_MULTIPLE_VOLUMES | \ + zPOOL_FEATURE_SNAPSHOT) + + /* zPOOL_FEATURE items that are NOT persistent stored with + * the other bits in the Pool Data Block + */ +#define ZLSSPOOL_PERSISTENT_ELSEWHERE \ + (zPOOL_FEATURE_SHARED_CLUSTER | \ + zPOOL_FEATURE_SNAPSHOT) + +#if zPOOL_FEATURE_LIST != 0xff + #error Please check if the new FEATURE needs to be added to the above defines. +#endif + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFS StorageInfo definitions + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +#define MAX_DIRECT 16 + +#define POOLBLK_TO_INDIRECT(_blk) ((Blknum_t)(-(ADDR)(_blk))) + +#define DATA_SHREDDING_ENABLED(_zfsvol) \ + ((_zfsvol)->ZFSVOLenabledAttributes & zATTR_SHRED_DATA) + +//#define DATA_SHREDDING_CHUNK 32 +// We have changed this to 8 to work with XEN. It should be fixed +// to work with a variable size. +#define DATA_SHREDDING_CHUNK 8 + +extern STATUS DataShredInit(LONG patCount); +extern void DataShredCleanup(void); + +/************************************************************************ + ** The sizeof this structure cannot be bigger than the sizeof(LONG) times + ** MAX_PLOG_LOCATION_SIZE which is defined in comnBeasts.h + ************************************************************************/ +typedef struct ZfsPurgeLogLoc_s /* zfs specific purge log location */ +{ + Blknum_t block; /* pool block where the entry is */ + LONG slot; /* slot in the array of entries in a block */ +} NSS_MEDIA_STRUCTURE(ZfsPurgeLogLoc_s,slot) ZfsPurgeLogLoc_s; + +typedef struct Extent_s +{ + Blknum_t lengthOfExtent; /*- length of this entent in blocks -*/ + Blknum_t poolBlkNum; /*- pool block offset for this extent -*/ +} NSS_MEDIA_STRUCTURE(Extent_s,poolBlkNum) Extent_s; + + +typedef struct FmapExt_s +{ + Blknum_t count; + Blknum_t poolBlk; +} NSS_MEDIA_STRUCTURE(FmapExt_s,poolBlk) FmapExt_s; + +typedef struct Fmap_s +{ + /* packing code assumes fields are contiguous */ + LONG numRecs; + Blknum_t root; + FmapExt_s dirExt[MAX_DIRECT]; +} NSS_MEDIA_STRUCTURE(Fmap_s,dirExt[MAX_DIRECT]) Fmap_s; + +#define ZSTORE_BEAST_LAYOUT 1 /* Layout version of the beasts that are + * on the media. Used so if ZSTORE changes + * how beasts are stored - ZSTORE can detect + * how a beast is stored. ZSTORE may + * change how beasts are stored because + * NSS changes the items that need to be + * persistent. + * A change to this define should also + * require a change to the media version + * number -> SUPERBLOCK_SB_VM_MEDIA_MAJOR. + */ + +/** If persistent data fields are changed in this structure, verify to make + ** sure that the packing code for the root beast has the same change + **/ +typedef struct ZFSStorageInfo_s +{ + StorageInfo_s comnInfo; /* NSS requires this to be first? */ +#if ZSTORE_BEAST_LAYOUT != 1 + /* This stuff not in layout 1 because code assumes the only + * beast layouts that exist are 1. The ZSTORE compilied with + * the layout at 1 will not load future versions of ZSTORE + * pools because the SUPERBLOCK_SB_VM_MEDIA_MAJOR will not + * match. + */ + BYTE beastLayout;/* PERSISTENT: Layout number of this beast */ + BYTE reserved1; /* Must be 0 */ + WORD reserved2; /* Must be 0 */ +#endif + Blknum_t nextBlk; /* PERSISTENT: Block after the last block in the + * the file after the EOF. */ + Blknum_t fmapDataBlks;/* PERSISTENT: Num of data blocks alloc'd */ + Blknum_t fmapTreeBlks;/* PERSISTENT: Num of blks used by fmap tree*/ + Fmap_s fmap; /* PERSISTENT: File map */ + LONG rebuildMagic; /* PERSISTENT: Rebuild file state */ + ZfsPurgeLogLoc_s deletePurgeLogLoc; /* The location of the purge log entry */ + /* for delete. Can be in use at the */ + /* same time as the regular entry. */ + /* Beasts can be marked as deleted */ + /* long before they are actually */ + /* removed. */ + ZfsPurgeLogLoc_s compCleanupPurgeLogLoc;/* the location of the + compCleanup purge log entry */ + ZfsPurgeLogLoc_s purgeLogLoc;/* the location of the purge log entry */ +} ZFSStorageInfo_s; + + +#if NSS_DEBUG IS_ENABLED + /* WRite debug globals */ +extern NINT WRTestCnt; /* Number of writes that we have done while + * WRErrTestSeed is non-zero. + */ +extern NINT WRErrTestSeed; /* The write number to start failing on. + * The value zero idicates we will not + * simulate write failures. + */ +extern NINT WRErrTestInterval; /* Frequency of which write calls will + * fail. Note that ZLSS attempts to + * never do another REAL write attempt + * after detecting a failure. + */ +#endif + + /* Information about bitmaps used to ensure that the Purge Log + * is not hooked into itself. Used to prevent hangs. + */ +#ifndef HAVE_BLOCK_MAP_s +#define HAVE_BLOCK_MAP_s +typedef struct BlockMap_s { + char *BM_Startup; /* Who allocated (I.E. WHERE macro) */ + char *BM_Shutdown; /* Who allocated (I.E. WHERE macro) */ + Blkcnt_t BM_NumberOfBits; /* Number of bits in map */ + NINT *BM_Map; /* Actual bitmap */ +} BlockMap_s; + + // + // Caller must ensure that bitmap is legal and block is within + // range before using this MACROS. + // +#define BM_TST_BIT( _bitMap, _blockNum ) (TST_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_SET_BIT( _bitMap, _blockNum ) (SET_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_CLR_BIT( _bitMap, _blockNum ) (CLR_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_XOR_BIT( _bitMap, _blockNum ) (XOR_BIT( (_bitMap)->BM_Map, _blockNum )) +#endif + +/*--------------------------------------------------------------------------- + * ZFS function prototypes + *---------------------------------------------------------------------------*/ + +void ZFSVOL_VOL_asyncReadFileBlk( + struct Asyncio_s *asyncio); + +struct Buffer_s *ZFSVOL_VOL_getFileBlk( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *ioMsg); + +STATUS ZFSVOL_VOL_truncateFile( + struct GeneralMsg_s *genMsg, + struct RootBeast_s *beast, + Blknum_t fileBlk, + Blkcnt_t count); + +STATUS ZFSVOL_VOL_getExtentList( + struct GeneralMsg_s *genMsg, + struct RootBeast_s *beast, + Blknum_t startingBlock, + NINT extentListSize, + Blknum_t (*extentList)[], + NINT *retNumExtents, + Blknum_t *retNextBlock); + +STATUS ZFSVOL_VOL_getPhysicalExtent( + struct zNSSMsg_s *msg, + RootBeast_s *beast); + +BOOL ZFSVOL_VOL_isBlockInBeast( + RootBeast_s *beast, + Blknum_t blockNum); + +Blknum_t ZFS_fileBlk2volBlk( + RootBeast_s *beast, + Blknum_t fileBlk, + NINT *length); + +STATUS ZLSSPOOL_RebuildFileExtend( + GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + Blknum_t totalBlocks ); + +File_s *ZLSSPOOL_RebuildFileCreate( + GeneralMsg_s *genMsg, + struct ZfsPool_s *pool ); + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFS VOLUME + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSVOL_ComnBeastOps; +extern CommonVolumeOps_s ZFSVOL_ComnVolOps; +extern LSSSpecificPackUnpackOps_s ZFSVOL_lssOps[]; + +#define ZLSSPOOLINFO_MAGIC (0x6f6f505AuL) /* "ZPoo" on Little-Endian */ +#define ZLSSPOOLINFO_VERSION 1uL /* */ + +#define ZLSSLOGGEDPOOLINFO_MAGIC (0x6f4c505AuL) /* "ZPLo" on Little-Endian */ +#define ZLSSLOGGEDPOOLINFO_VERSION 1uL /* */ + +#define ZFSVOLUMEINFO_MAGIC (0x6c6f565AuL) /* "ZVol" on Little-Endian */ +#define ZFSVOLUMEINFO_VERSION_5 5uL /* Greg changed to 5 from 1 when + * he added Volume name to after + * the checksum area. Re-link can + * use to see that volume name is + * present. Skipped numbers just + * in case Cobra needs some. + */ +#define ZFSVOLUMEINFO_VERSION_6 6uL /* Vandana changed to 6 from 5 + * Version 6 has: + * 1) the reserved area zeroed out. + * 2) rezid count added + * 3) rezid time added + */ + +#define ZFSVOLUMEINFO_VERSION_7 7uL /* Vandana changed to 7 from 6 + * Version 7 has: + * 1) readAheadBlocks added. + */ + +#define ZFSVOLUMEINFO_VERSION 8uL /* Craig/Greg changed to 8 from 7 + * Version 8 has: + * 1) Encryption information in it + */ + +#define ZFSLOGGEDVOLUMEINFO_MAGIC (0x6f4c565AuL) /* "ZVLo" on Little-Endian */ +#define ZFSLOGGEDVOLUMEINFO_VERSION 1uL /* */ + +#define MAX_IO_RETRY_COUNT 8 + + +typedef struct PersistentZfsVolume_s { + LONG PZV_magic; /* volinfo magic number */ + LONG PZV_version; + LONG PZV_checksum; + /* Calculated before each NON-LOGGED write of the block. + * Checksum is for all NON LOGGED data. Checksum is + * valid if the NON-LOGGED contents (including this field) + * add up to zero. Use ZFSVOL_CalculateChecksum() to + * perform checksumming. We do not include the LOGGED + * data in the checksum for the following reasons. + * 1) We update the block too often for LOGGING + * 2) All the LOGGED data can be reproduced by Rebuild. + * 3) This LSS stores the LOGGED data in a different + * volume block. + */ + WORD PZV_rezidCount; /* Number of times volume has been rezid */ + WORD PZV_readAheadBlocks;/* Number of blocks to read ahead */ + GUID_t PZV_internalID; /* Internal ID of volume - needs to be at ofsset 16 */ + SQUAD PZV_loggedVolumeDataBlk; /* Block number where the persistent + * LOGGED volume information is stored. + */ + SQUAD PZV_volumeDataBlk; /* Block number where the persistent + * NON-LOGGED volume information is stored. + */ + SQUAD PZV_systemBeastBlkNum; /* Block number where the super beasts + * are located. Its nextleaf link + * points to the left most leaf of + * the beast b-tree. + */ + LONG PZV_ActivationCount; /* Number of times that this volume + * has had an attempt to activate it. + * Used by purge log code to detect + * if a purge log entry should be played + * or if it has been added during purge + * log play. + */ + VolumeID_t PZV_volumeID; /* Volume ID of volume. Note this is + * just a redundent copy of the actual + * volume ID that is placed into the + * beast with VOL_BstNew(). The value + * in bst new is either from the superblock + * (for the _IV_ volume) or from the ZVL + * beasts for Logical Volumes. + */ + Lsn_t PZV_lsn; + Time_t PZV_lastRezidTime; /* UTC time the last time a rezid was done + */ + LONG PZV_reserved[32-8-6-1-4-2-1]; + /* Space for modifications that do not require media format change. + * The size of the ZFSVOL persistent area is 128 bytes. + */ +} NSS_MEDIA_STRUCTURE(PersistentZfsVolume_s,PZV_reserved[32-8-6-1-4-2-1]) PersistentZfsVolume_s; + + +typedef struct LoggedPersistentZfsVolume_s { + LONG LPZV_magic; /* volinfo magic number */ + LONG LPZV_version; + Lsn_t LPZV_lsn; /* log sequence number -- needs to be + * at the eighth byte offset. This is not + * part of the checksum because it is + * updated when LOGGED data is changed! + */ + GUID_t LPZV_internalID; /* Internal ID of volume - needs to be at ofsset 16 */ + LONG LPZV_reserved[32-8]; + /* Space for modifications that do not require media format change. + * The size of the logged ZFSVOL persistent area is 128 bytes. + */ +} NSS_MEDIA_STRUCTURE(LoggedPersistentZfsVolume_s,LPZV_reserved[32-8]) LoggedPersistentZfsVolume_s; + + +typedef struct ZfsVolume_s +{ + Volume_s vol; + PersistentZfsVolume_s p; /* holds persistent volume information*/ + LoggedPersistentZfsVolume_s logged; /* contains persistent information that is logged*/ + /* The next three block number are where we stored the + * values obtained from the ZVL Beast at LV load time. + * These values MUST only be used to init the same + * block numbers in the persistent area at ACTIVATION + * time. This is done so we can clear the persistent + * area when the volume is not ACTIVE. This is done + * to help find bugs (someone accessing area when LV + * is not ACTIVE). + */ + Blknum_t ZV_loggedVolumeDataBlk; /* Block number where the persistent + * LOGGED volume information is stored. + */ + Blknum_t ZV_volumeDataBlk; /* Block number where the persistent + * NON-LOGGED volume information is stored. + */ + Blknum_t ZV_systemBeastBlkNum; /* Block number where the super beasts + * are located. Its nextleaf link + * points to the left most leaf of + * the beast b-tree. + */ + QUAD zv_bookedInUseBlocks; /* Blocks that have been 'booked' as in + * use. Free B-Tree code uses to track + * 'in use blocks' relative to threads + * that are actively allocating blocks. + * The 'in use blocks' in Volume_s is + * not used because it is a logged + * item (much more overhead to change). + * The 'in use blocks' is only changed + * after we have allocated the blocks. + */ + struct ZfsPool_s *pool; /* Pointer to the internal volume + * that the volume is on. Note that + * the Volume_s has a pointer to the + * pool that the volume is on. Which + * also has a pointer to the internal + * volume. The internal volume is + * the volume that the pool uses to + * store the pool's system objects. The + * pool can not store directly because + * we do not have pool common ops (we + * have volume common ops). + */ + struct ZfsBeastTreeBeast_s *beastTree; /* Beast ZFS B-tree file*/ + struct ZfsNameTree_s *nameTree; /* Name ZFS B-tree file*/ + struct ZfsMFLBeast_s *mfl; /* Modified Files List */ + struct ZfsEFLTreeBeast_s *eflTree; /* Event File List */ + struct ZfsUserTreeBeast_s *userTree; /* User ZFS B-tree file */ + struct ZfsDirTreeBeast_s *dirTree; /* Directory ZFS B-tree file */ + struct ZfsPurgeLogBeast_s *ZV_volumePurgeLog; /* This is the Volume's purge log. Do not + * confuse with the Pool's purge log. This + * is the one added for LV support that contains + * volume specific log items. For example, delete + * beast and truncate beast. This was done so + * that LVs would not have to be activated + * to play the POOL's purge log. + */ + struct ZlogBeast_s *zv_zfsLogBeast; /* Quick pointer to ZLOG Beast. We + * include it here just so we do not + * have to go to the ZFS Pool to get*/ + DQhead_t ZV_deleteBlkQ; /* Queue of pool blocks to be deleted. + * This QUEUE is protected by NetWare + * being non-pre-emptive!!! + */ + SNINT unusableFreeBlkCnt; /* Number of blks that are + * currently on the free + * data blks list */ + struct ZLSSVOL_LVD_DeleteQueueInfo_t *ZV_dqi; + /* DQI pointer. Only + * valid while the LV is on the ZLSS master + * delete list. In addition, you must own + * the ZLSSLVDeleteList.ZDL_listLatch to + * ensure that the LV stays on the list. + */ + BOOL ZV_stopPurge; /* When TRUE the Delete LV thread will + * stop its purging. Used by stop API + * to tell thread to actually stop. + */ + GUID_t ZV_internalID; /* Internal GUID used to mark all + * volume blocks. Stopped using the + * volume ID has no one would commit + * to NEVER changing it. For example, + * when a mirror is split apart we + * may re-volumeID one set of volumes + * so that the user can use both + * set of volumes. + */ + Latch_s ZV_vdbLatch; + LONG ZV_RepairFlags; /* Flags describing how the vol loaded for + * rebuild. Bits are defined for conditions + * that failed in loading the vol prior to + * rebuild so rebuild will know what parts + * need to be re-initialized during rebuild. + */ +#define ZV_REPAIRFLAGS_REBUILD_VOL_DATA_BLOCKS 0x0001 /* could not read in volume data block */ +#define ZV_REPAIRFLAGS_REBUILD_VOL_LDATA_BLOCKS 0x0002 /* could not read in volume logged data block */ +#define ZV_REPAIRFLAGS_MANUAL_VOL_LOAD 0x2000 /* Rebuild is doing the LoadPersistentPool */ + +} ZfsVolume_s; + +#define ZFSVOLroot vol.avfile.file.auth.named.root +#define ZFSVOLnamed vol.avfile.file.auth.named +#define ZFSVOLauth vol.avfile.file.auth +#define ZFSVOLfile vol.avfile.file +#define ZFSVOLavfile vol.avfile +#define ZFSVOLvol vol + +#define ZFSVOLbeastLatch ZFSVOLroot.mycache.agent.latch +#define ZFSVOLbeastClass ZFSVOLroot.beastClass +#define ZFSVOLcomnOps ZFSVOLbeastClass->comnOps + +#define ZFSVOLmayIDoThis ZFSVOLauth.mayIDoThis + +#define ZFSVOLstorageIndex ZFSVOLvol.storageIndex +#define ZFSVOLrootdir ZFSVOLvol.rootdir +#define ZFSVOLpool pool +#define ZFSVOLagent ZFSVOLvol.agent +#define ZFSVOLbeastList ZFSVOLvol.beastList +#define ZFSVOLstate ZFSVOLvol.state +#define ZFSVOLmaxBeastSize ZFSVOLvol.maxBeastSize +#define ZFSVOLfreeBlockAdjustment ZFSVOLvol.freeBlockAdjustment + +#define ZFSVOLpoolComnOps pool->ZFSPOOLbeastClass->comnOps +#define ZFSVOLpurgeTree pool->purgeTree + +#define ZFSVOLvolumeID ZFSVOLvol.VOLvolumeID +#define ZFSVOLnameSpaceMask ZFSVOLvol.p.nameSpaceMask +#define ZFSVOLoldVolAttributes ZFSVOLvol.p.oldVolAttributes +#define ZFSVOLenabledAttributes ZFSVOLvol.p.enabledAttributes +#define ZFSVOLsupportedAttributes ZFSVOLvol.supportedAttributes +#define ZFSVOLmaximumFileSize ZFSVOLvol.maximumFileSize +#define ZFSVOLblockSize ZFSVOLvol.p.blockSize +#define ZFSVOLblockShift ZFSVOLvol.p.blockShift +#define ZFSVOLminKeepSeconds ZFSVOLvol.p.minKeepSeconds +#define ZFSVOLmaxKeepSeconds ZFSVOLvol.p.maxKeepSeconds +#define ZFSVOLlowWaterMark ZFSVOLvol.p.lowWaterMark +#define ZFSVOLhighWaterMark ZFSVOLvol.p.highWaterMark +#define ZLSSVOLndsObjectID ZFSVOLvol.VOLndsObjectID +#define ZLSSVOLmediaFormatMajor ZFSVOLvol.VOLmediaFormatMajor +#define ZLSSVOLmediaFormatMinor ZFSVOLvol.VOLmediaFormatMinor +#define ZLSSVOLmediaFormatMajorCreate ZFSVOLvol.VOLmediaFormatMajorCreate +#define ZLSSVOLmediaFormatMinorCreate ZFSVOLvol.VOLmediaFormatMinorCreate +#define ZFSVOLshredCount ZFSVOLvol.p.PV_shredCount + +#define ZFSVOLnextZid ZFSVOLvol.logged.nextZid +#define ZFSVOLtotalBlocks ZFSVOLvol.logged.totalBlocks +#define ZFSVOLinUseBlocks ZFSVOLvol.logged.inUseBlocks +#define ZFSVOLnumFiles ZFSVOLvol.logged.numFiles +#define ZFSVOLnumObjects ZFSVOLvol.logged.numObjects +#define ZFSVOLbookedInUseBlocks zv_bookedInUseBlocks +#define ZFSVOLpurgeableBlocks ZFSVOLvol.VOLpurgeableBlocks + +#define ZFSVOLinternalID ZV_internalID +#define ZFSVOLvolumePurgeLog ZV_volumePurgeLog +#define ZFSVOLactivationCount p.PZV_ActivationCount +#define ROOTinternalID vol.zfsVol->ZFSVOLinternalID + +#define ZFSVOLRebuildFlags ZV_repairFlags + +// +// This is what a ZFS volume block looks like. This is the layout +// on the MEDIA. The ZFS volume is not written like any other +// beast. It has special read/write common ops that only write +// write/read the Zfs volume and Volume_s persistent information. +// Neal did this for performance reasons. +// + +typedef struct ZfsVolumeBlock_s { + PersistentZfsVolume_s ZVD_zfsVol; + PersistentVolume_s ZVD_volume; + /* IN ADDITION, the volume name in UNICODE is appended here by + * the low level VDB write routines. This is done so that + * re-link can have TWO places to pick up the name of the + * volume (offical place is the Volume Locator Beast). The + * name is not part of this structure for two reasons. + * 1) Saves a little memory (name is already in NamedBeast_s) + * 2) Makes In place upgrade easier as not part of checksum. + * + * Also note that the version of VDBs with the volume name is 5. + */ +} NSS_MEDIA_STRUCTURE(ZfsVolumeBlock_s,ZVD_volume) ZfsVolumeBlock_s; + +typedef struct Zfs4KVolumeBlock_s { + ZfsVolumeBlock_s ZVD4K_Persistents; /* all the persistent volume data, only this area is currently checksummed */ + unicode_t ZVD4K_VolName[0x100]; /* backup copy of the volume name, not checksummed */ + PersistentVolumeCrypt_s ZVD4K_zfsCrypt; /* starts at ADDR 0x380-0x3ff */ + /*the crypto data is packed and umpacked in ZFSVOL_WritePersistentVolumeData */ + /* ZFSVOL_WriteInitialVDB, and ZFSVOL_ReadPersistentVolumeData in zfsvolumedata.c */ + BYTE reserved[0x1000 - sizeof(ZfsVolumeBlock_s) - (0x100*sizeof(unicode_t)) - sizeof(PersistentVolumeCrypt_s)]; + /* the reserved area is checkek in compile time calculaton in zfsVolumeData.c */ +} NSS_MEDIA_STRUCTURE(Zfs4KVolumeBlock_s,reserved[0x1000 - sizeof(ZfsVolumeBlock_s) - (0x100*sizeof(unicode_t)) - sizeof(PersistentVolumeCrypt_s)]) Zfs4KVolumeBlock_s; + + +typedef struct ZfsLoggedVolumeBlock_s { + LoggedPersistentZfsVolume_s ZLVD_zfsVol; + LoggedPersistentVolume_s ZLVD_volume; +} NSS_MEDIA_STRUCTURE(ZfsLoggedVolumeBlock_s,ZLVD_volume) ZfsLoggedVolumeBlock_s; + + /* Log record for VDB updates */ +typedef struct { + ZfsVolumeBlock_s ZVULR_ValuesOld; + ZfsVolumeBlock_s ZVULR_ValuesNew; +} NSS_MEDIA_STRUCTURE(ZfsVDBUpdateLogRecord_s,ZVULR_ValuesNew) ZfsVDBUpdateLogRecord_s; + + /* Log record for VDB inits */ +typedef struct { + ZfsVolumeBlock_s ZVILR_ValuesNew; +} NSS_MEDIA_STRUCTURE(ZfsVDBInitLogRecord_s,ZVILR_ValuesNew) ZfsVDBInitLogRecord_s; + +/* + * This defines the passes that specific actions are done by ZLSS's + * volume and pool during the Volume common op to change volume state. + * These numbers are set relative to each other and relative to why + * the Volume_s beast does things. + */ + + +#define ZLSSPOOL_ACTIVATE 3 /* Loads pool system beasts. FixFixFix6 + * this includes the Beast and Name Tree + * which are volume beasts. Don't need + * to fix until Logical Volumes. + */ + +#define ZLSSVOL_ACTIVATE 4 /* Loads rootdir which is in Beast Tree + * so must be after beast tree load. + */ + +#define ZLSSVOL_ACTIVATE_TIME 9 /* Sets the PV_activationTimeUTC field + * and writes the VDB. + */ + +#define ZLSSVOL_DEACTIVATE 4 /* Unloads rootdir which is in Beast Tree + * so must be while beast tree still loaded. + */ +#define ZLSSPOOL_DEACTIVATE 5 /* Unloads pool system beasts. */ + + +#define ZLSSPOOL_DEACTIVATE_CLEANUP_LV_DELETES 2 + /* Removes all the pools information + * from the ZLSSLVDeleteList. This + * must be done before the Volume_s + * tosses and flushes because we have + * InUseCounts on the zvlBeasts. + */ + +#define ZLSSVOL_ACTIVE_TO_MAINTENANCE ZLSSVOL_DEACTIVATE +#define ZLSSPOOL_ACTIVE_TO_MAINTENANCE ZLSSPOOL_DEACTIVATE + +#define ZLSSPOOL_LAST 10 /* This is the pass that we play the purge + * log. The purge log likes everything to + * be up and running before doing anything. + * + * Also auto in-place-upgrade also takes place in this pass. + * + * Media 32 -> 33 (add PurgeTree Beast) + * This auto upgrade occurs AFTER the purge log is played. + * This way beasts that were deleted in the last run are not + * placed into the salvage area. Not a big issue because + * salvage is off anyway. + */ +#define ZLSSVOL_LAST 10 /* Pass that we play the volume purge log */ + +#define XFUNC_MAX (137+1) /* This is the last XFUNC_ plus 1. It + * is the size that arrays need to + * be to hold the last XFUNC_ item. The + * plus one is needed because 0 is a + * legal item. + */ + +typedef struct RecoveryStats_s +{ + NINT pass1; + NINT pass2; + NINT pass3; + NINT pass4; + NINT pass5; + NINT alloc; + NINT realloc; + struct + { + NINT redo; + NINT undo; + } func[XFUNC_MAX]; + NINT redid; /* How many blocks actually where UNDOne or + * REDOne by REDO/UNDO routine. + */ +} RecoveryStats_s; + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFS POOL + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern DQhead_t ZLSSPhyPoolList; +extern CommonBeastOps_s ZFSPOOL_ComnBeastOps; +extern CommonVolumeOps_s ZFSPOOL_ComnVolOps; + +typedef struct ZfsPool_s +{ + ZfsVolume_s zfsVol; /* Derived from ZFS Vol Beast*/ + NINT ZP_NextCheckpoint; /* Next checkpoint number to + * write to */ + NINT ZP_BadCheckpoints; /* Number of bad checkpoints + * found during activation of + * the pool. */ +// DQlink_t poolLink; /* link all pools */ +// struct zfsSegment_s *mstsegment; /* master pool/group/segment +// * (storage) */ + struct StorPool_s *storagepool; /* zlss owned storage pool */ + struct ZFSMemorySuperBlk_s *ZP_super; /* Super block in-memory copy. + * This is only a few of the total blocks. This area + * is just an easy location for the owner of each super + * block block to store their block while the volume is + * active. The activate code allocates this memory and + * the deactivate code frees it. The owner of each block + * in this memory must read and write their own block. + */ + struct ZlogBeast_s *zfsLogBeast; /* Log for pool*/ + struct ZfsPurgeLogBeast_s *purgeLogBeast; /* Log of files being purged + * and extents being freed */ + struct ZfsMYBTreeBeast_s *purgeTree; /* ZfsSalvage system purgeq */ + SQUAD nblks_to_salvage; /* Pending work for purgeThrd */ + struct ZfsFreeExtent_s *freeExtent; /* Free extents in pool*/ + DQhead_t freeDataBlksList; /* List of user data blks that + * have been freed, are kept on + * this list until the + * transaction ends */ +// SQUAD nblks_to_salvage;/* Pending work for purgeThread */ + DQhead_t ZP_deleteBlkQ; /* Queue of pool blocks to be deleted. + * This QUEUE is protected by NetWare + * being non-pre-emptive!!! This list + * contains ALL the blocks for the ALL + * the pool's volumes. The list is in + * in LSN order. + */ + struct RecoveryStats_s zp_stats; + NINT ZP_RepairFlags; /* flags for repair/verify */ +#define ZP_REPAIRFLAGS_REBUILD_POOL_DATA_BLOCKS 0x0001 /* could not read in pool data block */ +#define ZP_REPAIRFLAGS_REBUILD_POOL_LDATA_BLOCKS 0x0002 /* could not read in pool logged data block */ +#define ZP_REPAIRFLAGS_REBUILD_POOL_SUPER_BLOCKS 0x0010 /* could not read in super blocks */ +#define ZP_REPAIRFLAGS_NO_LOGGING_ALLOWED 0x1000 /* must NOT log during initial pass */ +#define ZP_REPAIRFLAGS_MANUAL_POOL_LOAD 0x2000 /* Rebuild is doing the LoadPersistentPool */ + +#if 0 + DQhead_t ZP_VolumeList; /* List of all memory resident + * volumes on this pool */ + /** + * We keep the Pool's name tree and beast tree in the pool + * so that we are less dependent on the ZLSS Volume load + * order. This solves the problem that the beast tree + * contains pool beasts that should be loaded before the + * nametree and root directory. + */ + struct ZfsBeastTreeBeast_s *ZP_BeastTree; /* Beast ZFS B-tree file*/ + struct ZfsNameTree_s *ZP_NameTree; /* Name ZFS B-tree file*/ +#endif + GUID_t ZP_OldInternalID; /* Old INTERNAL ID of pool. This is the ID + * the pool had before it was converted + * into a Logical Volume. The LV ended + * up with this ID, but I did not + * feel it was important enough to + * go through all POOL specific system + * beasts to re-ID them. A scan program + * will have to look for one of two + * IDs when looking for POOL specific + * system blocks. + */ +// FsmLite_s ZP_makeFreeSpaceFsm; + Latch_s ZP_SuperblockHeaderLatch; +} ZfsPool_s; + + +#define ZFSPOOLroot zfsVol.vol.avfile.file.auth.named.root +#define ZFSPOOLnamed zfsVol.vol.avfile.file.auth.named +#define ZFSPOOLauth zfsVol.vol.avfile.file.auth +#define ZFSPOOLfile zfsVol.vol.avfile.file +#define ZFSPOOLavfile zfsVol.vol.avfile +#define ZFSPOOLvol zfsVol.vol +#define ZFSPOOLzfsvol zfsVol +#define ZFSPOOLzfsVol zfsVol +#define ZFSPOOLzlssvol zfsVol + +#define ZFSPOOLmycache ZFSPOOLroot.mycache +#define ZFSPOOLbeastLatch ZFSPOOLroot.mycache.agent.latch +#define ZFSPOOLbeastClass ZFSPOOLroot.beastClass +#define ZFSPOOLcomnOps ZFSPOOLbeastClass->comnOps + +#define ZFSPOOLmayIDoThis ZFSPOOLauth.mayIDoThis + +#define ZFSPOOLstorageIndex ZFSPOOLvol.storageIndex +#define ZFSPOOLrootdir ZFSPOOLvol.rootdir +#define ZFSPOOLagent ZFSPOOLvol.agent +#define ZFSPOOLbeastList ZFSPOOLvol.beastList +#define ZFSPOOLstate ZFSPOOLvol.state + +#define ZFSPOOLzfsvolp ZFSPOOLzfsvol.p +#define ZFSPOOLmagic ZFSPOOLzfsvol.p.PZV_magic +#define ZFSPOOLversion ZFSPOOLzfsvol.p.PZV_version +#define ZFSPOOLloggedMagic ZFSPOOLzfsvol.logged.LPZV_magic +#define ZFSPOOLloggedVersion ZFSPOOLzfsvol.logged.LPZV_version + +#define ZFSPOOLinternalID ZFSPOOLzlssvol.ZFSVOLinternalID +#define ZFSPOOLvolumeID ZFSPOOLvol.VOLvolumeID +#define ZFSPOOLnameSpaceMask ZFSPOOLvol.p.nameSpaceMask +#define ZFSPOOLoldVolAttributes ZFSPOOLvol.p.oldVolAttributes +#define ZFSPOOLenabledAttributes ZFSPOOLvol.p.enabledAttributes +#define ZFSPOOLsupportedAttributes ZFSPOOLvol.supportedAttributes +#define ZFSPOOLmaximumFileSize ZFSPOOLvol.maximumFileSize +#define ZFSPOOLrebuildCount ZFSPOOLvol.p.rebuildCount +#define ZFSPOOLauthModelID ZFSPOOLvol.p.authModelID +#define ZFSPOOLbeastVersionMask ZFSPOOLvol.p.beastVersionMask +#define ZFSPOOLblockShift ZFSPOOLvol.p.blockShift +#define ZFSPOOLblockSize ZFSPOOLvol.p.blockSize +#define ZFSPOOLminKeepSeconds ZFSPOOLvol.p.minKeepSeconds +#define ZFSPOOLmaxKeepSeconds ZFSPOOLvol.p.maxKeepSeconds +#define ZFSPOOLlowWaterMark ZFSPOOLvol.p.lowWaterMark +#define ZFSPOOLhighWaterMark ZFSPOOLvol.p.highWaterMark +#define ZFSPOOLmediaFormatMajor ZFSPOOLzlssvol.ZLSSVOLmediaFormatMajor +#define ZFSPOOLmediaFormatMinor ZFSPOOLzlssvol.ZLSSVOLmediaFormatMinor +#define ZFSPOOLmediaFormatMajorCreate ZFSPOOLzlssvol.ZLSSVOLmediaFormatMajorCreate +#define ZFSPOOLmediaFormatMinorCreate ZFSPOOLzlssvol.ZLSSVOLmediaFormatMinorCreate + + +#define ZFSPOOLnextZid ZFSPOOLvol.logged.nextZid +#define ZFSPOOLtotalBlocks ZFSPOOLvol.logged.totalBlocks +#define ZFSPOOLinUseBlocks ZFSPOOLvol.logged.inUseBlocks +#define ZFSPOOLnumFiles ZFSPOOLvol.logged.numFiles +#define ZFSPOOLnumObjects ZFSPOOLvol.logged.numObjects +#define ZFSPOOLpurgeableBlocks ZFSPOOLvol.logged.purgeableBlocks + +#define ZFSPOOLzfsvollogged ZFSPOOLzfsvol.logged +#define ZFSPOOLlsn ZFSPOOLzfsvol.logged.LPZV_lsn +#define ZFSPOOLbookedInUseBlocks ZFSPOOLzfsvol.zv_bookedInUseBlocks +#define ZFSPOOLpool ZFSPOOLzfsvol.pool +#define ZFSPOOLbeastTree ZFSPOOLzfsvol.beastTree +#define ZFSPOOLnameTree ZFSPOOLzfsvol.nameTree +#define ZFSPOOLuserTree ZFSPOOLzfsvol.userTree +#define ZFSPOOLdirTree ZFSPOOLzfsvol.dirTree +#define ZFSPOOLmfl ZFSPOOLzfsvol.mfl +#define ZFSPOOLefl ZFSPOOLzfsvol.efl +#define ZFSPOOLzfsvolzlog ZFSPOOLzfsvol.zv_zfsLogBeast + +#define ZFSPOOLoldInternalID ZP_OldInternalID +#define ZFSPOOLpurgeTree purgeTree +#define ZFSPOOLpurgeLogBeast purgeLogBeast +#define ZFSPOOLrepairFlags ZP_RepairFlags +#define ZFSPOOLmasterVolLink ZFSPOOLvol.masterVolLink + + +/* + * Some MACROs to go between ZLSS POOLs and ZLSS VOLUMEs and other + * common objects. + */ + +#define ZLSS_POOL_TO_ZFS_POOL( _pool ) ( _pool->ZLSSPOOLzfsPool ) + +#define ZFS_POOL_TO_ZLSS_VOLUME( _pool ) ( &(_pool->zfsVol) ) +#define ZFS_POOL_TO_VOLUME( _pool ) ( (Volume_s *)(ZFS_POOL_TO_ZLSS_VOLUME( _pool )) ) +#define ZFS_POOL_TO_POOL(_pool) ( (_pool)->ZFSPOOLvol.v_pool ) +#define ZFS_POOL_TO_ZLSS_POOL(_pool) ((ZlssPool_s *)(ZFS_POOL_TO_POOL(_pool))) + +#define ZLSS_VOLUME_TO_VOLUME(_volume) ( &((_volume)->ZFSVOLvol) ) +#define ZLSS_VOLUME_TO_POOL(_volume) ( (_volume)->ZLSSVOLpool ) +#define ZLSS_VOLUME_TO_ZLSS_POOL(_volume) ( (ZlssPool_s *)(ZLSS_VOLUME_TO_POOL(_volume)) ) +#define ZLSS_VOLUME_TO_ZFS_POOL(_volume) ( ZLSS_POOL_TO_ZFS_POOL((ZLSS_VOLUME_TO_ZLSS_POOL(_volume))) ) + +#define VOLUME_TO_ZLSS_VOLUME(_volume) ( (ZfsVolume_s *)(_volume) ) + + +#define ZLSS_VOLUME_IO_DISABLED( _zlssVolume ) \ + ( ( (_zlssVolume)->ZFSVOLvol.v_ioFlag & VOL_IOF_DISABLE ) || \ + ( ZLSS_POOL_IO_DISABLED(ZLSS_VOLUME_TO_ZLSS_POOL(_zlssVolume)) ) ) + +#define ZLSS_POOL_IO_DISABLED( _zlssPool ) \ + ( _zlssPool->ZLSSPOOLpool.v_ioFlag & VOL_IOF_DISABLE ) + +/* + * ZLSS_INTERNAL_VOLUME_GET( RootBeast_s *_rootBeast, ZfsPool_s *_poolVolume ); + * + * This MACRO will fill in the _poolVolume pointer with the internal + * volume (I.E. the ZfsPool_s) that the _rootBeast resides on. + * + * Because the NSS_ADMIN 'owns' all volumes/pools we must work at getting + * the internal volume that the volume/pool beasts are actually stored in. + */ +#define ZLSS_INTERNAL_VOLUME_GET( _rootBeast, _poolVolume ) \ + if ( _rootBeast->bstState & BST_STATE_IS_VOLUME_OR_POOL ) \ + { /* Volumes and Pools are SPECIAL because of _ADMIN volume */ \ + switch ( _rootBeast->beastClass->classID ) \ + { \ + case zFTYPE_ZLSS_VOL: /* A ZfsVolume_s */ \ + _poolVolume = ((ZfsVolume_s *)_rootBeast)->pool; \ + break; \ + case zFTYPE_ZLSS_ZFSPOOL: /* A ZfsPool_s */ \ + _poolVolume = (ZfsPool_s *)_rootBeast; \ + break; \ + case zFTYPE_ZLSS_LOGICAL_POOL: /* A ZlssPool_s */ \ + _poolVolume = ((ZlssPool_s *)_rootBeast)->ZP_ZfsPool; \ + break; \ + default: \ + zASSERT( "Not a legal class ID"==NULL ); \ + _poolVolume = NULL; \ + break; \ + } \ + } \ + else \ + { \ + _poolVolume = _rootBeast->vol.zfsVol->pool; \ + } \ + zASSERT( _poolVolume != NULL ); + +/* + * ZLSS_VOLUME_GET( RootBeast_s *_rootBeast, Volume_s *_volume ); + * + * This MACRO will fill in the _volume pointer with the volume that the + * _rootBeast resides on. + * + * Because the NSS_ADMIN 'owns' all volumes we must work at getting + * the volume that the volume beasts are actually stored in. + * + * We handle ZlssPool_s objects by saying that the volume is the ZlssPool_s + * internal volume (i.e. ZfsPool_s). + */ +#define ZLSS_VOLUME_GET( _rootBeast, _volume ) \ + if ( _rootBeast->bstState & BST_STATE_IS_VOLUME_OR_POOL ) \ + { /* Volumes and Pools are SPECIAL because of _ADMIN volume */ \ + switch ( _rootBeast->beastClass->classID ) \ + { \ + case zFTYPE_ZLSS_VOL: /* A ZfsVolume_s */ \ + _volume = (Volume_s *)_rootBeast; \ + break; \ + case zFTYPE_ZLSS_ZFSPOOL: /* A ZfsPool_s */ \ + _volume = (Volume_s *)_rootBeast; \ + break; \ + case zFTYPE_ZLSS_LOGICAL_POOL: /* A ZlssPool_s */ \ + _volume = (Volume_s *)(((ZlssPool_s *)_rootBeast)->ZP_ZfsPool);\ + break; \ + default: \ + zASSERT( "Not a legal class ID"==NULL ); \ + _volume = NULL; \ + break; \ + } \ + } \ + else \ + { \ + _volume = _rootBeast->vol.volume; \ + } \ + zASSERT( _volume != NULL ); \ + zASSERT( COMN_IsDerivedFrom(_volume, zFTYPE_ZLSS_VOL) ); + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSPURGELOG BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSPURGELOG_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSPURGELOG_lssOps[]; + +typedef struct PersistentZfsPurgeLog_s +{ + Blknum_t firstBlock; +} NSS_MEDIA_STRUCTURE(PersistentZfsPurgeLog_s,firstBlock) PersistentZfsPurgeLog_s; + +typedef struct ZfsPurgeLogBeast_s +{ + File_s file; /* Derived from File_s */ + PersistentZfsPurgeLog_s p; + ZfsPurgeLogLoc_s freeList; /* head of the free list */ + ZfsPurgeLogLoc_s nextUnused; /* next entry that has never been used */ +} ZfsPurgeLogBeast_s; + +#define ZFSPURGELOGroot file.auth.named.root +#define ZFSPURGELOGnamed file.auth.named +#define ZFSPURGELOGauth file.auth +#define ZFSPURGELOGfile file + +#define ZFSPURGELOGzid ZFSPURGELOGroot.zid +#define ZFSPURGELOGstate ZFSPURGELOGroot.state +#define ZFSPURGELOGbeastLatch ZFSPURGELOGroot.mycache.agent.latch + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSBTREE Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSBTREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSBTREE_lssOps[]; + +typedef struct PersistentZfsBtree_s +{ + Blknum_t btRoot; /* Btree Root */ + Blknum_t btFree; /* Free B-Tree uses for special block + * that tracks free blocks to be + * used only by the free tree to + * do grows and shrinks. Other + * B-Trees can use for their own purpose. + */ + Blknum_t btLeftMostLeaf; /* left most leaf of the b-tree*/ +} NSS_MEDIA_STRUCTURE(PersistentZfsBtree_s,btLeftMostLeaf) PersistentZfsBtree_s; + +typedef struct ZfsBtreeBeast_s +{ + File_s file; /* A ZFS B-tree "is a" file */ + PersistentZfsBtree_s p; /* Persistent portion*/ + NINT levelsInTree; /* Levels in the tree, if the root it is + * a leaf then it has 1 level + */ +} ZfsBtreeBeast_s; + +#define ZFSBTREEroot file.auth.named.root +#define ZFSBTREEnamed file.auth.named +#define ZFSBTREEauth file.auth +#define ZFSBTREEfile file + +#define ZFSBTREEzid ZFSBTREEroot.zid + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSFREEEXT Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSFREEEXT_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSFREEEXT_lssOps[]; + +typedef struct ZfsFreeExtent_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s + */ +// FsmLite_s wtdFsm; /* Fsm used to schedule a thread +// * to replenish btFree block +// */ + zWorkProc_s xtreeWtd; /* Work to do to start a thread + * to replenish btFree block + */ + LONG xtreeFlags; /* Non-persistent flag to keep track + * of whether the thread to replenish + * btFree has been scheduled of not + * and if the scheduling needs to + * be stopped. + */ +#define XTREE_THREAD_SCHEDULED 0x00000001 +#define XTREE_STOP_THREADS 0x00000002 +/* The free tree can be called without a transaction. During upgrade to add + * system blocks, it is ok to do transactions, but I do not want to transaction + * the alloc, because if we crash then it will logically try to undo the + * alloc, which is a free. A free can cause a split, which requires the + * special block to be setup. We are in the process of setting up special + * blk. So instead I have the functionality of saying ok to do local xactions. + * + * Another note is if join or shrink is called without a xaction the blk + * can be lost + */ +#define XTREE_OK_TODO_LOCAL_XACTION 0x00000004 + + Blknum_t freeTreeSeed; /* If a freeTree block is requested with + * a seed of zero, use a global seed to move + * across the disk + */ +//TODO(Perf,doc): Doc relationship between freeTreeSeed and ZFE_AreaSeed + Latch_s ZFE_AreaLatch; /* Watch out for FT calling (i.e. don't have + FT allocate blocks with this routine) */ + NINT ZFE_AreaSizeDefault; + /* The perferred area size to use for the pool.*/ + NINT ZFE_AreaSizeSmallest; + /* Smallest area size to use before reverting to + old global seed logic. */ + NINT ZFE_AreaSizeCurrent; + /* Current area size. This is normally the same + as ZFE_AreaSizeDefault. In low space conditions + ZFE_AreaSizeCurrent will be reduced so to still + benefit from the area logic. I.E. related blocks + will be near each other. + */ + uBlknum_t ZFE_AreaSeed; /* Seed to used when XTREE_AF_CONTIGUOUS_TREE + is passed to zfsAllocExtent and fail in getting + the passed in block. */ + SQUAD ZFE_GrowAreaSize; + /* Number of free blocks needed to up the + ZFE_AreaSizeCurrent size. */ +#if 0 + Blkcnt_t ZFE_AreaSizeCounts[FT_AREA_SIZE_MAX+1]; + /* A 'close' count of the number areas that are + free for a given size. Can be negative because + we do not track totally correctly. */ + BOOL ZFE_AreaSizeCountsTrack[FT_AREA_SIZE_MAX+1]; + /* Set to TRUE when we are tracking the equivilant + area size count. */ +#endif +} ZfsFreeExtent_s; + +#define ZFSFXroot zfsBtree.file.auth.named.root +#define ZFSFXnamed zfsBtree.file.auth.named +#define ZFSFXauth zfsBtree.file.auth +#define ZFSFXfile zfsBtree.file +#define ZFSFXbtree zfsBtree + +#define ZFSFXzid ZFSFXroot.zid +#define ZFSFXvolLink ZFSFXroot.volLink +#define ZFSFXstate ZFSFXroot.state +#define ZFSFXstorage ZFSFXroot.storage +#define ZFSFXbeastLatch ZFSFXroot.mycache.agent.latch +#define ZFSFXpool ZFSFXroot.vol.zfsVol->pool +#define ZFSFXvolume ZFSFXroot.vol.volume + + +#define ZFSFXfirstParentZID ZFSFXnamed.firstParent.p.zid + +#define ZFSFXnumextents ZFSFXroot.storage.zfsInfo.numExtents + +#define ZFSFXbtRoot ZFSFXbtree.p.btRoot +#define ZFSFXbtFree ZFSFXbtree.p.btFree + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSNAMETREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSNAMETREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSNAMETREE_lssOps[]; + +typedef struct ZfsNameTree_s +{ + ZfsBtreeBeast_s zfsBtree; +} ZfsNameTree_s; + +#define ZFSNAMETREEroot zfsBtree.file.auth.named.root +#define ZFSNAMETREEnamed zfsBtree.file.auth.named +#define ZFSNAMETREEauth zfsBtree.file.auth +#define ZFSNAMETREEfile zfsBtree.file + +#define ZFSNAMETREEzid ZFSNAMETREEroot.zid +#define ZFSNAMETREEstate ZFSNAMETREEroot.state +#define ZFSNAMETREEvolLink ZFSNAMETREEroot.volLink +#define ZFSNAMETREEstorage ZFSNAMETREEroot.storage +#define ZFSNAMETREEbeastLatch ZFSNAMETREEroot.mycache.agent.latch + +#define ZFSNAMETREEfirstParentZID ZFSNAMETREEnamed.firstParent.p.zid +#define ZFSNAMETREEinternalID ZFSNAMETREEroot.ROOTinternalID + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSBEASTTREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSBEASTTREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSBEASTTREE_lssOps[]; + +typedef struct PersistentZfsBeastTree_s +{ + Blknum_t deletevolumeDataBlk; /* FixFixFix6 remove from Beast B-Tree */ +} NSS_MEDIA_STRUCTURE(PersistentZfsBeastTree_s,deletevolumeDataBlk) PersistentZfsBeastTree_s; + +typedef struct ZfsBeastTreeBeast_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s */ + PersistentZfsBeastTree_s p; + Blknum_t specialSystemBstsBlk; +} ZfsBeastTreeBeast_s; + +#define ZFSBEASTTREEroot zfsBtree.file.auth.named.root +#define ZFSBEASTTREEnamed zfsBtree.file.auth.named +#define ZFSBEASTTREEauth zfsBtree.file.auth +#define ZFSBEASTTREEfile zfsBtree.file +#define ZFSBEASTTREEzbtree zfsBtree + +#define ZFSBEASTTREEmycache ZFSBEASTTREEroot.mycache +#define ZFSBEASTTREEzid ZFSBEASTTREEroot.zid +#define ZFSBEASTTREEstate ZFSBEASTTREEroot.state +#define ZFSBEASTTREEvolLink ZFSBEASTTREEroot.volLink +#define ZFSBEASTTREEstorage ZFSBEASTTREEroot.storage +#define ZFSBEASTTREEbeastLatch ZFSBEASTTREEroot.mycache.agent.latch +#define ZFSBEASTTREEvolume ZFSBEASTTREEroot.vol.volume + +#define ZFSBEASTTREEfirstParentZID ZFSBEASTTREEnamed.firstParent.p.zid +#define ZFSBEASTTREEbtRoot ZFSBEASTTREEzbtree.p.btRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSMYBTREE BEAST Class Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +/* + * Generic fixed-key, fixed-value Btree beast. + * Currently purgetree is an instance of this Btree class. + */ +typedef struct ZfsMYBTreeBeast_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s */ +// PersistentZfsPurgeTree_s p; +} ZfsMYBTreeBeast_s; + +extern LSSSpecificPackUnpackOps_s ZFSMYBTREE_lssOps[]; + +#define ZFSMYBTREEroot zfsBtree.file.auth.named.root +#define ZFSMYBTREEnamed zfsBtree.file.auth.named +#define ZFSMYBTREEauth zfsBtree.file.auth +#define ZFSMYBTREEfile zfsBtree.file +#define ZFSMYBTREEzbtree zfsBtree + +#define ZFSMYBTREEzid ZFSMYBTREEroot.zid +#define ZFSMYBTREEstate ZFSMYBTREEroot.state +#define ZFSMYBTREEvolLink ZFSMYBTREEroot.volLink +#define ZFSMYBTREEstorage ZFSMYBTREEroot.storage +#define ZFSMYBTREEbeastLatch ZFSMYBTREEroot.mycache.agent.latch +#define ZFSMYBTREEvolume ZFSMYBTREEroot.vol.volume + +#define ZFSMYBTREEfirstParentZID ZFSMYBTREEnamed.firstParent.p.zid +#define ZFSMYBTREEbtRoot ZFSMYBTREEzbtree.p.btRoot + + +#define KEY_COMP(_t1_, _t2_) \ + ((SNINT)(((_t1_) != (_t2_)) ? (((_t1_) > (_t2_)) ? 1 : -1) : 0)) + + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSPURGETREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +//typedef struct PersistentZfsPurgeTree_s +//{ +// Blknum_t deletevolumeDataBlk; /* FixFixFix remove from Purge B-Tree */ +//} PersistentZfsPurgeTree_s; + +typedef ZfsMYBTreeBeast_s ZfsPurgeTreeBeast_s; + +#define ZFSPURGETREEroot ZFSMYBTREEroot +#define ZFSPURGETREEzid ZFSMYBTREEzid +#define ZFSPURGETREEstate ZFSMYBTREEstate +#define ZFSPURGETREEvolLink ZFSMYBTREEvolLink +#define ZFSPURGETREEstorage ZFSMYBTREEstorage +#define ZFSPURGETREEbeastLatch ZFSMYBTREEbeastLatch +#define ZFSPURGETREEvolume ZFSMYBTREEvolume +#define ZFSPURGETREEzbtree ZFSMYBTREEzbtree + +#define ZFSPURGETREEfirstParentZID ZFSMYBTREEfirstParentZID +#define ZFSPURGETREEbtRoot ZFSMYBTREEbtRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSMFL BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSMFL_ComnBeastOps; + +typedef struct ZfsMFLBeast_s +{ + ZfsMYBTreeBeast_s myBTree; + BOOL incomplete; /* Are any modified files missing from MFL? */ +} ZfsMFLBeast_s; + +#define ZFSMFLBTREE myBTree +#define ZFSMFLincomplete incomplete +#define ZFSMFLroot ZFSMFLBTREE.ZFSMYBTREEroot +#define ZFSMFLzid ZFSMFLBTREE.ZFSMYBTREEzid +#define ZFSMFLstate ZFSMFLBTREE.ZFSMYBTREEstate +#define ZFSMFLvolLink ZFSMFLBTREE.ZFSMYBTREEvolLink +#define ZFSMFLstorage ZFSMFLBTREE.ZFSMYBTREEstorage +#define ZFSMFLbeastLatch ZFSMFLBTREE.ZFSMYBTREEbeastLatch +#define ZFSMFLvolume ZFSMFLBTREE.ZFSMYBTREEvolume + +#define ZFSMFLfirstParentZID ZFSMFLBTREE.ZFSMYBTREEfirstParentZID +#define ZFSMFLbtRoot ZFSMFLBTREE.ZFSMYBTREEbtRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSUSERTREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSUSERTREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSUSERTREE_lssOps[]; + +typedef struct ZfsUserTreeBeast_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s */ +} ZfsUserTreeBeast_s; + +#define ZFSUSERTREEroot zfsBtree.file.auth.named.root +#define ZFSUSERTREEnamed zfsBtree.file.auth.named +#define ZFSUSERTREEauth zfsBtree.file.auth +#define ZFSUSERTREEfile zfsBtree.file +#define ZFSUSERTREEzbtree zfsBtree + +#define ZFSUSERTREEmycache ZFSUSERTREEroot.mycache +#define ZFSUSERTREEzid ZFSUSERTREEroot.zid +#define ZFSUSERTREEuseCount ZFSUSERTREEroot.useCount +#define ZFSUSERTREEstate ZFSUSERTREEroot.state +#define ZFSUSERTREEvolLink ZFSUSERTREEroot.volLink +#define ZFSUSERTREEstorage ZFSUSERTREEroot.storage +#define ZFSUSERTREEbeastLatch ZFSUSERTREEroot.mycache.agent.latch + +#define ZFSUSERTREEfirstParentZID ZFSUSERTREEnamed.firstParent.p.zid +#define ZFSUSERTREEbtRoot ZFSUSERTREEzbtree.p.btRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSDIRTREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSDIRTREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSDIRTREE_lssOps[]; + +typedef struct ZfsDirTreeBeast_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s */ +} ZfsDirTreeBeast_s; + +#define ZFSDIRTREEroot zfsBtree.file.auth.named.root +#define ZFSDIRTREEnamed zfsBtree.file.auth.named +#define ZFSDIRTREEauth zfsBtree.file.auth +#define ZFSDIRTREEfile zfsBtree.file +#define ZFSDIRTREEzbtree zfsBtree + +#define ZFSDIRTREEmycache ZFSUSERTREEroot.mycache +#define ZFSDIRTREEzid ZFSUSERTREEroot.zid +#define ZFSDIRTREEstate ZFSUSERTREEroot.state +#define ZFSDIRTREEvolLink ZFSUSERTREEroot.volLink +#define ZFSDIRTREEstorage ZFSUSERTREEroot.storage +#define ZFSDIRTREEbeastLatch ZFSUSERTREEroot.mycache.agent.latch + +#define ZFSDIRTREEfirstParentZID ZFSUSERTREEnamed.firstParent.p.zid +#define ZFSDIRTREEbtRoot ZFSUSERTREEzbtree.p.btRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFSEFLTREE BEAST Area + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +extern CommonBeastOps_s ZFSEFLTREE_ComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZFSEFLTREE_lssOps[]; + +typedef LONG EFLEpochMask_t; + +#define MAX_ZFS_EFL_EPOCHS sizeof(EFLEpochMask_t) * 8 + +extern BOOL EFLDisplay; + +typedef struct ZfsEFLEpoch_s +{ + EFLEpoch_t epoch; + Time_t lastAlive; +} NSS_MEDIA_STRUCTURE(ZfsEFLEpoch_s,lastAlive) ZfsEFLEpoch_s; + +typedef struct PersistentZfsEFLTree_s +{ + EFLEpochMask_t activeEpochs; + EFLEpochMask_t usedEpochs; + LONG nameSpace; + LONG inactiveInterval; /* epoch inactive interval, in seconds */ + Blknum_t logHeaderBlock; /* the header block for the EFL log */ + LONG extra[3]; + ZfsEFLEpoch_s epochs[MAX_ZFS_EFL_EPOCHS]; +} NSS_MEDIA_STRUCTURE(PersistentZfsEFLTree_s,epochs[MAX_ZFS_EFL_EPOCHS]) PersistentZfsEFLTree_s; + +typedef struct ZfsEFLTreeBeast_s +{ + ZfsBtreeBeast_s zfsBtree; /* Derived from ZfsBtreeBeast_s */ + PersistentZfsEFLTree_s p; +} ZfsEFLTreeBeast_s; + +#define ZFSEFLTREEroot zfsBtree.file.auth.named.root +#define ZFSEFLTREEnamed zfsBtree.file.auth.named +#define ZFSEFLTREEauth zfsBtree.file.auth +#define ZFSEFLTREEfile zfsBtree.file +#define ZFSEFLTREEzbtree zfsBtree + +#define ZFSEFLTREEmycache ZFSEFLTREEroot.mycache +#define ZFSEFLTREEzid ZFSEFLTREEroot.zid +#define ZFSEFLTREEstate ZFSEFLTREEroot.state +#define ZFSEFLTREEvolLink ZFSEFLTREEroot.volLink +#define ZFSEFLTREEstorage ZFSEFLTREEroot.storage +#define ZFSEFLTREEbeastLatch ZFSEFLTREEroot.mycache.agent.latch +#define ZFSEFLTREEvolume ZFSEFLTREEroot.vol.volume +#define ZFSEFLTREEbeastVersion ZFSEFLTREEroot.beastVersion +#define ZFSEFLTREEbstState ZFSEFLTREEroot.bstState + +#define ZFSEFLTREEfirstParentZID ZFSEFLTREEnamed.firstParent.p.zid +#define ZFSEFLTREEbtRoot ZFSEFLTREEzbtree.p.btRoot + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFS Common Area 2 (Main Area) + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +typedef struct ZnodeHeader_s +{ + WORD length; /* PERSISTENT - length of the znode */ + WORD magic; /* PERSISTENT - Znode magic number */ + LONG type; /* PERSISTENT - Type - beast class ID */ + Zid_t zid; /* PERSISTENT - Id for znode */ + /* + * DO NOT ADD TO THIS STRUCTURE - unless you place the beast layout + * at offset 16. It is currently located there via the structure + * ZFSPackedRoot_s. + */ +} NSS_MEDIA_STRUCTURE(ZnodeHeader_s,zid) ZnodeHeader_s; + +/* + * the defines below describe the nodes for each of the btrees within + * the z files store + */ + + /*- beast btree -*/ +#define ZERO_MAGIC 0x3030 /* "00" */ +#define NODE_MAGIC 0x444e /* "ND" */ +#define LEAF_MAGIC 0x4641454c /* "LEAF" */ +#define BRANCH_MAGIC 0x48435242 /* "BRCH" */ +#define FREEBLK_MAGIC 0x45455246 /* "FREE" */ + +/*- free extent btree -*/ +#define FXLEAF_MAGIC 0x46454c58 /* "XLEF" */ +#define FXBRANCH_MAGIC 0x48524258 /* "XBRH" */ + +/* filemap btree */ +#define FMAP_BT_ROOT 0x524D4150 /* RMAP */ +#define FMAP_BT_LEAF 0x4C4D4150 /* LMAP */ +#define FMAP_BT_BRANCH 0x424D4150 /* BMAP */ + +/* User btree */ +#define UBT_LEAF_MAGIC 0x46454c55 /* "ULEF" */ +#define UBT_BRANCH_MAGIC 0x48524255 /* "UBRH" */ +#define UBT_NAME_MAGIC 0x4D414E55 /* "UNAM" */ + +/* Directory btree */ +#define DBT_OLD_LEAF_MAGIC 0x46454c55 /* "ULEF" */ +#define DBT_OLD_BRANCH_MAGIC 0x48524255 /* "UBRH" */ +#define DBT_LEAF_MAGIC 0x46454c44 /* "DLEF" */ +#define DBT_BRANCH_MAGIC 0x48524244 /* "DBRH" */ + +/* EFL btree */ +#define EFL_LEAF_MAGIC 0x46454c45 /* "ELEF" */ +#define EFL_BRANCH_MAGIC 0x48524245 /* "EBRH" */ +#define EFL_LOG_MAGIC 0x474f4c45 /* "ELOG" */ + +/* Pool snapshot (Media Manager also has a copy so do not change the next 4 lines) */ +#define SNAP_ADMIN_STAMP 0x534E5041 /* SNPA */ +#define SNAP_HEADER_STAMP 0x534E5048 /* SNPH */ +#define SNAP_MAP_STAMP 0x534E504D /* SNPM */ +#define SNAP_LEAF_STAMP 0x534E504C /* SNPL */ + +typedef struct Znode_s +{ + ZnodeHeader_s header; + BYTE data[1]; /* Variable length data from the beast */ +} NSS_MEDIA_STRUCTURE(Znode_s,data[1]) Znode_s; + + +#define MAX_BLK_NUM 0x80000000 /* All logical block numbers must be less + * than this value. (signed values are + * reserved for file map blocks.) + */ +#define INVALID_BLK MAX_BLK_NUM /* Used to designate an invalid block number */ +#define INVALID_BLK_ZERO 0 /* Used to designate an invalid block number in new structures*/ + + +/*--------------------------------------------------------------------------- + * Physical layout of the ROOTBEAST in the ZSTORE + *---------------------------------------------------------------------------*/ +#if CURRENT_BEAST_VERSION != BEAST_VERSION_3 +#error "Check to see if we still need the structure V1_ZFSPackedRoot_s." +#endif +typedef struct V1_ZFSPackedRoot_s +{ + ZnodeHeader_s header; + BYTE beastLayout; /* OFFSET 16. Beast layout version number. + * Indicates the format of the rest of the + * persistent information. + */ + BYTE blkSizeShift; + WORD sizeFmap; + LONG metaDataSeqNum; + QUAD eof; + Blknum_t nextBlk; + Blknum_t fmapDataBlks; + Blknum_t fmapTreeBlks; + LONG rebuildMagic; + LONG rebuildReZid; /* Save the low part of the zid here while + * while reZidding + */ + BYTE rebuildReZidState; /* Use this field to determine is this + * beast has been rezid. + */ + BYTE rebuildReserved;/* If rebuildMagic == REBUILD_DELETE_BEAST_MAGIC then reason (valid during rebuild only) */ + WORD variableSize; /* Size of variable packed root data */ +/* Extent_s fmap[];*/ /*the extent map starts at this location*/ +} NSS_MEDIA_STRUCTURE(V1_ZFSPackedRoot_s,variableSize) V1_ZFSPackedRoot_s; + + +typedef struct ZFSPackedRoot_s +{ + ZnodeHeader_s header; + BYTE beastLayout; /* OFFSET 16. Beast layout version number. + * Indicates the format of the rest of the + * persistent information. + */ + BYTE blkSizeShift; + WORD sizeFmap; + LONG metaDataSeqNum; + QUAD eof; + UserID_t ownerID; + Blknum_t nextBlk; + Blknum_t fmapDataBlks; + Blknum_t fmapTreeBlks; + LONG rebuildMagic; /* We only pack a good value in this field + * for rebuild. It is not unpacked */ + LONG rebuildReZid; /* Save the low part of the zid here while + * while reZidding + */ + BYTE rebuildReZidState; /* Use this field to determine is this + * beast has been rezid. + */ + BYTE rebuildReserved;/* If rebuildMagic == REBUILD_DELETE_BEAST_MAGIC then reason (valid during rebuild only) */ + WORD variableSize; /* Size of variable packed root data */ +/* Extent_s fmap[];*/ /*the extent map starts at this location*/ +} NSS_MEDIA_STRUCTURE(ZFSPackedRoot_s,variableSize) ZFSPackedRoot_s; + +/* rebuildReZidState */ +#define REBUILD_REZID_STATE_CLEAR 0 +#define REBUILD_REZID_STATE_REZID_DONE 1 + +/* rebuildMagic */ +#define REBUILD_FILE_IS_GOOD 0x4F4F4752 /* "RGOO" */ +#define REBUILD_FILE_IS_SNAPSHOT 0x574F4352 /* "RCOW" */ +#define REBUILD_DELETE_UNREADABLE_BEAST_MAGIC 0x44414252 /* "RBAD" */ +#define REBUILD_DELETE_BEAST_MAGIC 0x4c454452 /* "RDEL" */ +#define REBUILD_FILE_HAS_INVALID_PARENT 0x52415052 /* "RPAR" */ + + + +typedef struct { + LONG ZPIOH_SignatureMajor; /* ZLSS Pool Signature */ + LONG ZPIOH_SignatureMinor; /* I/O Log information */ + WORD ZPIOH_VersionMajor; + WORD ZPIOH_VersionMinor; + LONG ZPIOH_Pws; /* Index */ + + LONG ZPIOH_Prs; + LONG ZPIOH_DataOffset; /* Index of where data starts in + * the dump file (0 relative). + */ + LONG pad0; + LONG pad1; + + char ZPIOH_Servername[16]; + + LONG ZPIOH_ZSTOREMajorVersion; + LONG ZPIOH_ZSTOREMinorVersion; + LONG ZPIOH_ZSTORESubVersion; + LONG ZPIOH_ZSTOREBuildNumber; + + LONG ZPIOH_UTCTime; /* Time that data was obtained */ + LONG ZPIOH_Start; /* Index of start of circular buffer */ + LONG ZPIOH_Next; /* Next free slot (IE end of buffer) */ + LONG ZPIOH_Size; + +} ZLSSPoolIOHeader_s; + +typedef struct { + BYTE ZPIOLH_Size; /* Number of bytes in record. Used + * so some readers can just skip + * records they do not know format + * of. + */ + BYTE ZPIOLH_Format; /* */ + #define ZPIOLH_FORMAT_STANDARD 0x0001 + WORD ZPIOLH_State; /* */ + #define ZPIOLH_STATE_WRITE_START 0x0001 + #define ZPIOLH_STATE_WRITE_COMPLETE 0x0002 + #define ZPIOLH_STATE_READ_START 0x0003 + #define ZPIOLH_STATE_READ_ASYNC_START 0x0004 + #define ZPIOLH_STATE_READ_COMPLETE 0x0005 + #define ZPIOLH_STATE_DIO_WRITE_START 0x0006 /* Only used for summary information */ + #define ZPIOLH_STATE_DIO_READ_START 0x0007 /* No details are logged for DIO items */ + + LONG ZPIOLH_Time; /* High Res timer time */ + LONG ZPIOLH_ZidVolume; /* Zid of volume write occuring on */ +} ZLSSPoolIOLogHeader_s; + +typedef struct { + ZLSSPoolIOLogHeader_s ZPIOL_Header; + Blknum_t ZPIOL_C_BlockPool; /* Physical block number */ + LONG ZPIOL_C_Data; /* First 4 bytes of DATA wrote. We + * store on write complete so that + * record matches the read complete + * record. Read does not know what + * was read until after the read + * completes. + */ +} ZLSSPoolIOLog_Complete_s; + +typedef struct { + ZLSSPoolIOLogHeader_s ZPIOL_Header; + LONG ZPIOL_S_ZidBeast; /* Zid of beast doing write */ + Blknum_t ZPIOL_S_BlockFile; /* File's logical block number */ + Blknum_t ZPIOL_S_BlockPool; /* Physical block number */ +} ZLSSPoolIOLog_Start_s; + + +/* + * IOErrorLog_s - + * Tracks physical I/Os Error information. Used to quickly tell + * if I/O errors are occuring within a ZLSS pool. + */ + +typedef struct IOErrorLog_s +{ + Time_t IOEL_UTCTime; + BOOL IOEL_System; /* TRUE - System else User */ + BOOL IOEL_Read; /* TRUE - Read else Write */ + Blknum_t IOEL_VolumeBlock; + Blknum_t IOEL_FileBlock; + LONG IOEL_ErrorMediaManager; + STATUS IOEL_Status; + Zid_t IOEL_Zid; + unicode_t IOEL_PoolName[64]; +} IOErrorLog_s; + +/* + * this struct is used to produce information about the IOs being + * processed by the zlss module. + */ + +typedef struct { + LONG writeIn; + LONG writeOut; + LONG writeInXdata; /* Other objects dependent on this being written */ + LONG writeOutXdata; + LONG readIn; + LONG readOut; + LONG readWIn; + LONG readWOut; +} ZLSSIOsInst_s; + + +#define ZLSS_POOL_IO_LOG_SPACE 256 /* Amount of spare at end of buffer. This + * spare space is used so that wrap is + * easier. Note that space must be greater + * than largest record placed into the + * circular buffer. + */ + +extern ZLSSIOsInst_s IOsInst; +extern PoolWriteStatistics_s gZLSSPWS; +extern PoolReadStatistics_s gZLSSPRS; +extern LONG gZLSSIOStartUpTime; +extern NINT gZLSSGatherDetailedIOInformation; + +/*------------------------------------------------------------------------- + * Function prototypes and macros + *-------------------------------------------------------------------------*/ + + +void ZIO_GatherDetailedSummaryInformationDIO( + RootBeast_s *beast, + int state, + LONG dioUnits ); /* Each unit is DIO_UNIT_SIZE bytes */ + +STATUS ZLSSPOOL_MediaIsCorrupt( + GeneralMsg_s *genMsg, + Buffer_s *corruptedBuffer, + struct IoMsg_s *iomsg ); + +STATUS ZFSPOOL_Activate( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode, + NINT zmode ); + +STATUS ZFSPOOL_ActivateAllLVsQuasi( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool); + +void ZFSPOOL_DeactivateAllQuasiActiveLVs( + struct ZfsPool_s *pool); + +STATUS ZPSPOOL_AIPU32To33( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode ); + +STATUS ZLVAIPU_AIPU4001To4006( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode ); + +STATUS ZFSPOOL_Deactivate( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT mode ); + +STATUS ZFSVOL_Activate( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *zfsVol, + NINT mode ); + +STATUS ZFSVOL_Deactivate( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *zfsVol, + NINT mode ); + +void ZFSVOL_UnLoadSystemBeasts( + struct ZfsVolume_s *vol); + +STATUS ZFSVOL_DoFlushSystemBeasts( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *vol, + BOOL deactivating); /* if TRUE we are deactivating the volume, else flushing */ + +STATUS ZFSPOOL_LoadPersistentPool( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + NINT volmode, /* Must be a VOLMODE_ define */ + NINT flags, /* Must be a LPP_FLAGS_ define */ + BOOL ioStateTransition, + NINT requestedState ); /* Required only if ioStateTransition is TRUE */ + +#define LPP_FLAGS_NO_VERSION_MESSAGES 0x0001 /* Don't display version + * info or errors. + */ +STATUS ZFSVOL_WriteInitialLVDB( + GeneralMsg_s *genMsg, + ZfsVolume_s *zlssVol, + struct ZfsXaction_s *zfsXaction ); + +STATUS ZFSVOL_WriteInitialVDB( + GeneralMsg_s *genMsg, + ZfsVolume_s *zlssVol, + struct ZfsXaction_s *zfsXaction ); + +void ZLSSPOOL_PoolDataInitialize( + struct ZlssPool_s *zlssPool, + Blknum_t totalBlocks, + LONG blockShift, + QUAD persistentElsewhere ); + +void ZFSPOOL_UnloadPersistentPool( + ZfsPool_s *pool, + NINT mode ); + +STATUS ZFSPOOL_SuperBlockMove( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + struct StorPool_s *storagepool, + struct ZfsXaction_s *zfsXaction ); + +STATUS ZFSPOOL_SuperBlockPoolInitialize( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool); + +STATUS ZFSPOOL_SuperBlock12Initialize( + struct GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + struct MediaSuperBlockHeader_s *super ); + +STATUS ZFSPOOL_SuperBlockWriteByBlock( + struct GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + struct MediaSuperBlockHeader_s *super, + NINT superblockNumber, /* 0, 1, 2 or 3 */ + NINT section, /* 0, 1, ... 14 or 15 */ + void *data ); + +STATUS ZFSPOOL_SuperBlockReadByBlock( + struct GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + struct MediaSuperBlockHeader_s *super, + NINT superblockNumber, /* 0, 1, 2 or 3 */ + NINT section, /* 0, 1, ... 14 or 15 */ + void *data ); + +STATUS ZFSMAL_PhysicalExtent( + ZfsVolume_s *zfsVol, + QUAD poolOffset, + QUAD poolLength, + ADDR *deviceID, + QUAD *deviceOffset, + QUAD *deviceLength ); + +void ZFSMAL_asyncReadBlk(struct Asyncio_s *zio); +STATUS ZFSMAL_ReadBlk(struct GeneralMsg_s *genMsg, struct Buffer_s *buffer); + +void ZFS_BlockSignalHandler( + struct Agent_s *agent); + +void ZFS_DoBlockWriteFromSignal( + struct Agent_s *agent, + AgentSignalFunc_t writeDoneHandler); + +struct zConPool_s; +STATUS ZFS_WritePoolBlk( + struct GeneralMsg_s *genMsg, + struct zConPool_s *phypool, + struct Buffer_s *buffer ); + +struct Buffer_s *ZFS_ReadPoolBlk( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *iomsg); + + + +Buffer_s *ZFS_AllocPoolBlkSpecialWithFlags( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *iomsg, + struct Buffer_s **specialBuffer, + NINT allocFlags); + +#define XTREE_SYSTEM_REQUEST 0x01 +#define XTREE_CONTIGUOUS_BLKS 0x02 +#define XTREE_AF_NEAR_TREE 0x04 /* If we can not allocate 'near' the + seed block then we allocate from a new free + area. Used to indicate you want the blocks + of a tree contiguous with each other. */ +#define XTREE_AF_NEW_AREA 0x08 /* Allocate in a 'new area' */ + +static inline Buffer_s *ZFS_AllocPoolBlkSpecial( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *iomsg, + struct Buffer_s **specialBuffer) +{ + return ZFS_AllocPoolBlkSpecialWithFlags(genMsg,iomsg,specialBuffer,XTREE_SYSTEM_REQUEST); +} + +static inline Buffer_s *ZFS_AllocPoolBlk( + struct GeneralMsg_s *genMsg, + struct IoMsg_s *iomsg ) +{ + return ZFS_AllocPoolBlkSpecialWithFlags(genMsg,iomsg,NULL,XTREE_SYSTEM_REQUEST); +} + +void ZFS_ReadAheadPoolBlk( + struct IoMsg_s *iomsg); + +STATUS ZFSVOL_ReadPersistentVolumeData( + struct GeneralMsg_s *genMsg, + struct ZfsVolume_s *zlssVol); + +void ZFSVOL_WritePersistentVolumeData( + struct ZfsVolume_s *vol); + +void ZFSVOL_VOL_WriteVolumeLoggedData( + struct Volume_s *vol, + struct Xaction_s *xaction, + struct VolInfoLog_s *volLog); + +void ZFSVOL_WritePersistentVolumeDataXactioned( + struct ZfsVolume_s *zlssVol, + struct ZfsXaction_s *xaction); + +STATUS ZLSSPOOL_WriteVolumeLoggedData( + struct GeneralMsg_s *genMsg, + struct ZlssPool_s *zlssPool, + struct Xaction_s *xaction, /* Can not be NULL */ + struct VolInfoLog_s *volLog); + +STATUS ZFSVOL_VOL_FlushSystemBeasts( + struct GeneralMsg_s *genMsg, + void *vol); + +/*------------------------------------------------------------------------- + * ZLSS General macros + *-------------------------------------------------------------------------*/ + /* Both tests needed because + System beast with file maps don't use negative fileblock + numbers(ZLOG, REbuild file, ...). While File Map Blocks use + the beast's ZID the file map represents. + */ +#define ZLSS_IS_SYSTEM_BLOCK(_rootBeast, _buf ) \ + ((_buf->pBuf.fileBlk < 0) || (_buf->volBlk == 0) || (_rootBeast->zid < zFIRST_ALLOCATABLE_ZID)) + + /* Is the volume (or its pool) doing MAINTENANCE IO? */ +#define ZLSS_IS_MAINTENANCE_IO( _volume ) \ + ( (_volume->maintenanceStatus & \ + (VOLMAINTSTATUS_CHECKING|VOLMAINTSTATUS_REPAIRING) ) || \ + ( (ZLSS_VOLUME_TO_POOL(VOLUME_TO_ZLSS_VOLUME(_volume)))-> \ + maintenanceStatus & \ + (VOLMAINTSTATUS_CHECKING|VOLMAINTSTATUS_REPAIRING) ) ) + + +/*------------------------------------------------------------------------- + * I/O message setup macros + *-------------------------------------------------------------------------*/ +#define READBLK_IO_MSG(_io, _beast, _volBlk, _mode) \ +{ \ + SETUP_IO_MSG(_io, _beast, _mode); \ + (_io).fileBlk = -(_volBlk); \ + (_io).volBlk = (_volBlk); \ + (_io).allocNumBlks = 1; \ +} + +#define ALLOCBLK_IO_MSG(_io, _beast, _mode) \ +{ \ + SETUP_IO_MSG(_io, _beast, _mode); \ + (_io).fileBlk = INVALID_BLK; \ + (_io).volBlk = 0; \ + (_io).allocNumBlks = 1; \ +} + +#define XALLOCBLK_IO_MSG(_io, _beast, _xaction, _mode) \ +{ \ + XSETUP_IO_MSG(_io, _beast, _xaction, _mode); \ + (_io).fileBlk = INVALID_BLK; \ + (_io).volBlk = 0; \ + (_io).allocNumBlks = 1; \ +} + +#define ALLOC_SEED_IO_MSG(_io, _beast, _seed, _mode) \ +{ \ + SETUP_IO_MSG(_io, _beast, _mode); \ + (_io).fileBlk = INVALID_BLK; \ + (_io).volBlk = (_seed); \ + (_io).allocNumBlks = 1; \ +} + +#define XALLOC_SEED_IO_MSG(_io, _beast, _xaction, _seed, _mode) \ +{ \ + XSETUP_IO_MSG(_io, _beast, _xaction, _mode); \ + (_io).fileBlk = INVALID_BLK; \ + (_io).volBlk = (_seed); \ + (_io).allocNumBlks = 1; \ +} + +#define DELETEBLK_IO_MSG(_io, _beast, _volBlk) \ +{ \ + SETUP_IO_MSG(_io, _beast, 0); \ + (_io).fileBlk = 0; \ + (_io).volBlk = (_volBlk); \ + (_io).allocNumBlks = 1; \ +} + +#define XDELETEBLK_IO_MSG(_io, _beast, _xaction, _volBlk) \ + \ + XSETUP_IO_MSG(_io, _beast, _xaction, 0); \ + (_io).fileBlk = 0; \ + (_io).volBlk = (_volBlk); \ + (_io).allocNumBlks = 1; \ +} + +#if NSS_DEBUG IS_ENABLED +#define SET_DEBUG_ID(_io, _id) (_io).debugID = (_id) +#else +#define SET_DEBUG_ID(_io, _id) ((void) 0) +#endif + +/*========================================================================= + *========================================================================= + *========================================================================= + * + * ZFS repair + * + *========================================================================= + *========================================================================= + *=========================================================================*/ +void REPAIR_Startup(void); +void REPAIR_Shutdown(void); + + + + + + + + +extern CommonBeastOps_s ZLSSPOOL_ComnBeastOps; +extern CommonVolumeOps_s ZLSSPOOL_ComnVolOps; +extern BOOL ZLSS_UpgradeMediaFormat; + + +typedef struct PersistentZlssPool_s +{ + LONG PZP_magic; /* pool info magic number */ + LONG PZP_version; + LONG PZP_checksum; + /* Calculated before each NON-LOGGED write of the block. + * Checksum is for all NON LOGGED data. Checksum is + * valid if the NON-LOGGED contents (including this field) + * add up to zero. Use ZFSVOL_CalculateChecksum() to + * perform checksumming. We do not include the LOGGED + * data in the checksum for the following reasons. + * 1) We update the block too often for LOGGING + * 2) All the LOGGED data can be reproduced by Rebuild. + * 3) This LSS stores the LOGGED data in a different + * volume block. + */ + LONG PZP_reserved1; /* For alignment of next item */ + GUID_t PZP_internalID; /* GUID of pool - needs to be at ofsset 16 */ + SQUAD PZP_loggedPoolDataBlk; /* Block number where the persistent + * LOGGED pool information is stored. + */ + SQUAD PZP_poolDataBlk; /* Block number where the persistent + * NON-LOGGED pool information is stored. + */ + QUAD PZP_initUTCTime; /* UTC time of when pool block initialized + * last. Stored as a QUAD so when UTC + * time changes we might still hold a + * time_t. time_t is not used as not + * a fixed size. + */ + QUAD PZP_rebuildUTCTime; /* UTC time of when pool last rebuilt. Set + * to zero when pool is created. + */ + VolumeID_t PZP_volumeID; /* Volume ID of pool */ + LONG PZP_reserved[64-16-4]; + /* Space for modifications that do not require media format change. + * The size of the ZFSVOL persistent area is 256 bytes. + */ +} NSS_MEDIA_STRUCTURE(PersistentZlssPool_s,PZP_reserved[64-16-4]) PersistentZlssPool_s; + + + +typedef struct LoggedPersistentZlssPool_s +{ + LONG LPZP_magic; /* poolinfo magic number */ + LONG LPZP_version; + Lsn_t LPZP_lsn; /* log sequence number -- needs to be + * at the eighth byte offset. This is not + * part of the checksum because it is + * updated when LOGGED data is changed! + */ + VolumeID_t LPZP_internalID; /* Internal GUID of pool - needs to be at ofsset 16 */ + LONG LPZP_reserved[64-8]; + /* Space for modifications that do not require media format change. + * The size of the logged ZLSS Pool logged area is 256 bytes. + */ +} NSS_MEDIA_STRUCTURE(LoggedPersistentZlssPool_s,LPZP_reserved[64-8]) LoggedPersistentZlssPool_s; + + +typedef struct ZlssLoggedPoolBlock_s { + LoggedPersistentZlssPool_s ZLPB_zlssPool; + LoggedPersistentPool_s ZLPB_pool; +} NSS_MEDIA_STRUCTURE(ZlssLoggedPoolBlock_s,ZLPB_pool) ZlssLoggedPoolBlock_s; + +typedef struct ZlssPoolBlock_s { + PersistentZlssPool_s ZPB_zlssPool; + PersistentPool_s ZPB_pool; +} NSS_MEDIA_STRUCTURE(ZlssPoolBlock_s,ZPB_pool) ZlssPoolBlock_s; + + + /** + * ZLSS Pool is the logical pool structure create to enable + * easier addition of Logical Volumes. I decided to use the + * ZfsPool_s as the ZLSS Pool's physical volume. This way + * most of the current code could be left as is. + * + * Overview - + * ZlssPool_s - The pool that NSS knowns about. + * ZfsPool_s - The Physical Volume used to implement + * many of the ZlssPool features. The + * ZfsPool_s is not seen by the common + * layer. + * ZfsVolume_s - The volume that NSS knows about. + * + */ +typedef struct ZlssPool_s +{ + Pool_s ZP_Pool; /* ZLSS pool 'is a' pool */ + PersistentZlssPool_s ZP_p; + LoggedPersistentZlssPool_s ZP_logged; + ZfsPool_s *ZP_ZfsPool; /* Has a ZfsPool Beast */ + QUAD ZP_bookedInUseBlocks; + /* */ + FsmLite_s ZP_MakeFreeSpaceFsm; + SQUAD ZP_BlocksToSalvage; + SNINT ZP_UnusableFreeBlkCnt; /* Number of blks that are + * currently on the free + * data blks list */ + GUID_t ZP_InternalID; + LONG ZP_Version; /* Version of pool in Major * 0x100L + + * minor format. Used to quickly + * determine where LV AIPU is at. + * Valid only after the pool has + * been persistently loaded. I.E. + * after ZFSPOOL_LoadPersistentPool() + * has been called. Because LV AIPU + * re-loads the pool after each minor + * upgrade you will not find ZP_Version + * being updated as the media major + * and minor version fields are. + */ +#define ZLSS_MEDIA_VERSION_4007 0x2807 +#define ZLSS_MEDIA_VERSION_4008 0x2808 + + PoolWriteStatistics_s ZP_PWS; + PoolReadStatistics_s ZP_PRS; + Time_t ZP_StatisticsResetCommandUTCTime; + Time_t ZP_StatisticsResetUTCTime; + BOOL ZP_PoolTrackIO; /* TRUE when we are tracking I/O + * to the pool. Normally, set + * when pool is ACTIVE. + */ + BOOL ZP_Loading; /* The pool is in the process of + * being loaded. It is used + * to prevent NON upgraded pools + * from being used (ACTIVATED). + */ + BOOL ZP_Snapshot; /* The pool is a snapshot of another + * pool. General this means another + * pool on the same server. This + * flag is retrieved from the super + * block at POOL LOAD time only. + * Snapshot pools do magic to their + * LVs at load time to ensure their + * LVs have unique names and volume + * IDs. This magic is done ONCE + * on the first LOAD after the + * superblock is updated. The super + * block should be updated when the + * pool is not loaded. + */ + GUID_t ZP_SnapshotID; /* If ZP_Snapshot then the unique + * ID of the snapshot. Used to + * tell if LVs have been snapshoted + * and if the information about + * the LVs snapshot is valid. See + * PersistentZlssVolumeLocator_s + * for more information. + */ + struct MSAP_PoolStateInfo_s *ZP_MSAPInfo; + /* Used by new MSAP code to store MSAP specific + * information. See the specification + * "ZLSS's Multiple Activation Inhibitor" and + * zlssMSAP.c for details. + */ + Blknum_t ZP_MSAPBlock; /* Block number that MSAP is stored. This + * is block 11 (0 rel) of superblock 1 (0 rel). + */ +} ZlssPool_s; + + +#define ZLSSPOOLroot ZP_Pool.avfile.file.auth.named.root +#define ZLSSPOOLnamed ZP_Pool.avfile.file.auth.named +#define ZLSSPOOLauth ZP_Pool.avfile.file.auth +#define ZLSSPOOLfile ZP_Pool.avfile.file +#define ZLSSPOOLavfile ZP_Pool.avfile +#define ZLSSPOOLpool ZP_Pool + + /* ZLSS Pool items */ +#define ZLSSPOOLzfsPool ZP_ZfsPool + + /* Derived from items */ +#define ZLSSPOOLmVolumeID ZLSSPOOLpool.POOLvolumeID +#define ZLSSPOOLmInternalID ZP_InternalID +#define ZLSSPOOLbeastLatch ZLSSPOOLpool.POOLbeastLatch +#define ZLSSPOOLstateAttributes ZLSSPOOLpool.POOLstateAttributes +#define ZLSSPOOLbeastClass ZLSSPOOLroot.beastClass +#define ZLSSPOOLmycache ZLSSPOOLroot.mycache + + +#define ZLSSPOOLblockSize ZLSSPOOLpool.POOLblockSize +#define ZLSSPOOLblockShift ZLSSPOOLpool.POOLblockShift +#define ZLSSPOOLrebuildCount ZLSSPOOLpool.POOLrebuildCount +#define ZLSSPOOLminKeepSeconds ZLSSPOOLpool.POOLminKeepSeconds +#define ZLSSPOOLmaxKeepSeconds ZLSSPOOLpool.POOLmaxKeepSeconds +#define ZLSSPOOLlowWaterMark ZLSSPOOLpool.POOLlowWaterMark +#define ZLSSPOOLhighWaterMark ZLSSPOOLpool.POOLhighWaterMark +#define ZLSSPOOLreserved2 ZLSSPOOLpool.POOLreserved2 +#define ZLSSPOOLstate ZLSSPOOLpool.POOLstate +#define ZLSSPOOLstateAttributes ZLSSPOOLpool.POOLstateAttributes +#define ZLSSPOOLndsObjectID ZLSSPOOLpool.POOLndsObjectID +#define ZLSSPOOLenabledFeatures ZLSSPOOLpool.POOLenabledFeatures +#define ZLSSPOOLmediaFormatMajor ZLSSPOOLpool.POOLmediaFormatMajor +#define ZLSSPOOLmediaFormatMinor ZLSSPOOLpool.POOLmediaFormatMinor +#define ZLSSPOOLfreeBlockAdjustment ZLSSPOOLpool.POOLfreeBlockAdjustment + +#define ZLSSPOOLblockSize ZLSSPOOLpool.POOLblockSize +#define ZLSSPOOLnumFiles ZLSSPOOLpool.POOLnumFiles +#define ZLSSPOOLnumObjects ZLSSPOOLpool.POOLnumObjects +#define ZLSSPOOLtotalBlocks ZLSSPOOLpool.POOLtotalBlocks +#define ZLSSPOOLinUseBlocks ZLSSPOOLpool.POOLinUseBlocks +#define ZLSSPOOLpurgeableBlocks ZLSSPOOLpool.POOLpurgeableBlocks +#define ZLSSPOOLnonPurgeableBlocks ZLSSPOOLpool.POOLnonPurgeableBlocks +#define ZLSSPOOLnumDeletedFiles ZLSSPOOLpool.POOLnumDeletedFiles +#define ZLSSPOOLnumLogicalVolumes ZLSSPOOLpool.POOLnumLogicalVolumes + + +#define ZLSSPOOLpMagic ZP_p.PZP_magic +#define ZLSSPOOLpVersion ZP_p.PZP_version +#define ZLSSPOOLchecksum ZP_p.PZP_checksum +#define ZLSSPOOLpVolumeID ZP_p.PZP_volumeID +#define ZLSSPOOLpInternalID ZP_p.PZP_internalID +#define ZLSSPOOLloggedPoolDataBlk ZP_p.PZP_loggedPoolDataBlk +#define ZLSSPOOLpoolDataBlk ZP_p.PZP_poolDataBlk +#define ZLSSPOOLinitUTCTime ZP_p.PZP_initUTCTime +#define ZLSSPOOLloggedMagic ZP_logged.LPZP_magic +#define ZLSSPOOLloggedVersion ZP_logged.LPZP_version +#define ZLSSPOOLlsn ZP_logged.LPZP_lsn +#define ZLSSPOOLloggedInternalID ZP_logged.LPZP_internalID + + +#define ZLSSPOOLbookedInUseBlocks ZP_bookedInUseBlocks +#define ZLSSPOOLsupportedFeatures ZLSSPOOLpool.POOLsupportedFeatures + +#define ZLSSPOOLpurgeTree ZLSSPOOLzfsPool->ZFSPOOLpurgeTree +#define ZLSSPOOLkeepActiveUseCount ZLSSPOOLpool.POOLkeepActiveUseCount +#define ZLSSPOOLstatusFlag ZLSSPOOLpool.POOLstatusFlag + +typedef struct BTShrinkLogRecord_s { + Blknum_t block; /* Previous 'child' block number */ + WORD slot; /* Index of previous 'child' block number */ +} NSS_MEDIA_STRUCTURE(BTShrinkLogRecord_s,slot) BTShrinkLogRecord_s; + +ZfsVolume_s *ZLSS_VolumeIDLookup( + GeneralMsg_s *genMsg, + GUID_t *internalID, + BOOL onlineOnly, + ZfsPool_s *poolVolume ); + +ZfsVolume_s *ZLSS_VolumeIDLookupRecovery( + GeneralMsg_s *genMsg, + GUID_t *internalID, + ZfsPool_s *poolVolume ); + +STATUS ZLSS_VolumeIDLookupID( + GeneralMsg_s *genMsg, + GUID_t *internalID, + ZfsPool_s *poolVolume, + VolumeID_t *retVolumeID); + +void ZLSSPOOL_WritePersistentPoolData( + ZlssPool_s *zlssPool); + +STATUS ZLSSPOOL_ReadPersistentPoolData( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool); + +STATUS ZLSSPOOL_RecoveryPoolInfo( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + struct ZfsXasRecovery_s *logBuffer, + NINT action); + +STATUS ZFSREPAIR_VOL_CheckRepair( + GeneralMsg_s *genMsg, + void *volPool, + NINT maintenanceType, + NINT flag, + void *userInfo); + +STATUS ZLSSPOOL_VOL_VolumeMaintenance( + GeneralMsg_s *genMsg, + void *zlssPool_LX, + NINT maintenanceCmd, + NINT vmFlag, + void *userInfo); + +STATUS doZLSSPoolIOErrors( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doZLSSPoolIOState( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doZLSSPoolIOStatistics( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doZLSSPoolIOReset( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doZLSSVolumeUpgrade( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doZLSSPoolSnapshot( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +STATUS doDisplayESMCachePerf( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, + void *userParm); + +extern BOOL TrackESMPerfStats; + +extern BOOL HL_ClusterApprovesUpgrade(); + +#ifdef NW5X_UPGRADE +STATUS ZLSSCON_Upgrade( + GeneralMsg_s *genMsg, + ZfsPool_s *zfsPool ); +#endif + +ZfsPool_s *ZFSPOOL_LoadPool( + struct GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + BOOL verbose, + NINT loadFlag, + BOOL snapshot, + unicode_t *snapshotInfo, + BOOL newGuids ); + + /* Pool Load flag is one of the following */ +#define ZLSS_PLF_NORMAL 0x0000 /* Normal value. */ +#define ZLSS_PLF_NO_UPGRADE 0x0001 /* Use to force us NOT to try upgrade. + * Works on Pools with a version less than + * 40.06. Causes load pool to leave the + * pool in deactive state with no upgrade + * attempted. + */ +#define ZLSS_PLF_UPGRADE 0x0002 /* Used to force us to upgrade a pool to + * version 40.06. We will force an + * activation if the policies did + * not set the pool to ACTIVE. Again, + * this only applies to pools if they + * are not already 40.06. + */ + +STATUS ZLSS_VFCDelete( GeneralMsg_s *genMsg ); +STATUS ZLSS_VFCCreate( GeneralMsg_s *genMsg ); +void ZLSS_removePoolMgmtFile( unicode_t *poolName ); +STATUS ZLSS_addPoolMgmtFile(GeneralMsg_s *genMsg, unicode_t *poolName); + +STATUS MSAP_MSAPActivate( + ZlssPool_s *zlssPool, + GeneralMsg_s *genMsg ); +STATUS MSAP_MSAPBlockInitializePhysical( + ZlssPool_s *zlssPool, + GeneralMsg_s *genMsg ); +void MSAP_MSAPDeactivate( + ZlssPool_s *zlssPool ); +STATUS MSAP_MSAPRebuild( + ZlssPool_s *zlssPool, + GeneralMsg_s *genMsg ); +#define ZLSS_SIGNATURE 0x7a4c5373 /* "zLSs" This should be in the 2nd long of + * all new block types so that SCAN will + * automatically detect new block types. + */ +STATUS RAV_Startup(); +void RAV_Shutdown(); + +void MSAP_MSAPShutdown( ); +void MSAP_MSAPStartup( ); +STATUS MSAP_AIPU4007To4008( + ZlssPool_s *zlssPool, + GeneralMsg_s *genMsg ); + +STATUS ZFSVOL_VDBNDSObjectClear( + GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + Blknum_t blkVDB ); + +STATUS ZFSVOL_PDBNDSObjectClear( + GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + Blknum_t blkPDB ); + +BOOL ZFSPOOL_PoolVerifySupported( struct MediaSuperBlockHeader_s *superHeader ); +BOOL ZFSPOOL_PoolLoadSupported( struct MediaSuperBlockHeader_s *superHeader ); + +//#ifndef __linux__ // LINUX_Install +BOOL ZFSPOOL_IsInstallTime( ); +//#endif + +STATIC STATUS ZFSVOL_LoadSystemBeasts( + GeneralMsg_s *genMsg, + ZfsVolume_s *vol); + +void ZSTORE_NEBEventRegister(); + +void ZSTORE_NEBEventUnregister(); + + +STATUS RAV_DisplayXML( GeneralMsg_s *genMsg, NINT type, LONG flags, struct ZlssPool_s *zlssPool, + NINT bufferLength, BYTE **bufferAddress, NINT *retLen ); +STATUS RAV_VerifyStatisticsDisplayBin( GeneralMsg_s *genMsg, NINT type, struct ZlssPool_s *zlssPool, + NINT *bufferLength, BYTE **bufferAddress, NINT *retLen ); + +#define INIT_BIO_REQ(_bioReq, _callback) \ +{ \ + (_bioReq)->br_status = zOK; \ + (_bioReq)->br_callback = _callback; \ + NULLIFY(&(_bioReq)->br_link); \ +} + +STATUS zlssBioIOData( + int rw, + struct block_device *blockDevice, + void *data, + Blknum_t startBlock); + +STATUS zlssBioIOBuffer( + int rw, + struct block_device *blockDevice, + Buffer_s *buf); + +STATUS zlssBioIOPages ( + int rw, + struct block_device *blockDevice, + struct page *page, + Blknum_t startBlock, + LONG pageCount, + LONG blockSize); + +void zlssBioIOBufferAsync ( + int rw, + struct block_device *blockDevice, + Buffer_s *buf, + BioReq_s *bioReq); + +/* This is called without the NSSMPK spinlock */ +STATUS zlssBioIOSync( + int rw, + struct block_device *blockDevice, + struct page *page, + Blknum_t startBlock, + LONG pageCount, + LONG blockSize); + +void ZLSS_BioProcessStart(); +void ZLSS_BioProcessStop(); + +STATUS ZLSS_BarrierStart( GeneralMsg_s *genMsg ); +void ZLSS_BarrierStop(void); + +void ZLSS_AsyncMetaDataReadDone( + Asyncio_s *asyncio); +void ZLSS_AsyncMetadataReadAhead( + MyCache_s *mycache, + Blknum_t *blockList, + NINT blockCount); + +/**************************************************************************** + * Defines and inline functions for AreaSize in the Free Tree and related + * read-ahead of btree metadata. + ****************************************************************************/ +//TODO(Perf): What should the max value be?? +#define FT_AREA_SIZE_MAX 128 /* Maximum value of any area size */ +#define FT_AREA_SIZE_MAX_MASK (FT_AREA_SIZE_MAX - 1) + +extern NINT FT_AreaSizeSmallest; +extern NINT FT_AreaSizeDefault; + +/* + AREA_UP() - + Returns the first area that is equal to or higher than the + given pool block. In other words, if the pool block is the start of + an area then that area is returned else the next area is returned. + + Warnings - + This routine will return the same value as INVALID_BLK if + blocks higher than the last area size boundary are passed to it + on a 8 TB pool. I.E. there is really no next area within the + pool block range (pool block numbers are always positive). + +*/ +static inline uBlknum_t AREA_UP( Blknum_t block, int areaSize ) +{ + return (block + areaSize - 1) & ~(areaSize-1); // TODO(Perf) - Why require a power of two? +} + +static inline Blknum_t FIRST_BLOCK_IN_AREA( Blknum_t block, int areaSize ) +{ + return (block) & ~(areaSize-1); // TODO(Perf) - Why require a power of two? +} + +/** + * This routine checks if nextBlock and startBlock are in the same area, and + * adds it to the readahead list. If the readahead list reaches the AreaSize + * limit it returns 1 to indicate to the calling routine to stop processing + * the branch entries. + **/ +static inline NINT BTREE_CheckAndAddRABlock( + Blknum_t nextBlock, + Blknum_t startBlock, + Blknum_t **blockList, + NINT *blockCount) +{ + if (FIRST_BLOCK_IN_AREA(nextBlock, FT_AreaSizeDefault) == + FIRST_BLOCK_IN_AREA(startBlock, FT_AreaSizeDefault)) + { + *(*blockList)++ = nextBlock; + (*blockCount)++; + if (*blockCount == FT_AreaSizeDefault) + { + /* The blockCount list is full */ + return 1; + } + } + return 0; +} + +static inline void BTREE_ReadAheadMetadata( + RootBeast_s *root, + void *node, + NINT indexInNode, + NINT (*getBlockList)(void *node, + SNINT indexInNode, + Blknum_t *blockList), + Blknum_t readBlock) +{ + struct inode *inode = NULL; + NINT numBlocks; + typedef struct Stack_s { + Blknum_t blockList[FT_AREA_SIZE_MAX]; + } Stack_s; + + if (root->ROOTvolume->v_pool) + { + inode = root->ROOTvolume->v_pool->P_Inode; + } + /* If the readBlock is in cache, we will not do a readAhead, + * because no need to do a disk I/O if we are not reading the + * metadata block. We only want to do read aheads if we can + * do "free" reads. */ + if ((!cacheFind(&root->mycache, -readBlock)) && + (!HMC_MarkNewestIfCached(inode, readBlock))) + { + STACK_ALLOC(); + numBlocks = getBlockList(node, indexInNode, aStack->blockList); + + if (numBlocks > 1) + { + ZLSS_AsyncMetadataReadAhead(&root->mycache, aStack->blockList, + numBlocks); + } + STACK_FREE(); + } + return; +} + +#endif /* _ZFS_H_ */ diff --git a/src/nwnss/zlss/zfsAsyncio.h b/src/nwnss/zlss/zfsAsyncio.h new file mode 100644 index 0000000..2ac334c --- /dev/null +++ b/src/nwnss/zlss/zfsAsyncio.h @@ -0,0 +1,71 @@ + /**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | zfs.h defines information that affects the format of the data + | on the disk. This file needs to be referenced by utilities like + | install and diskedit. The classes used by ZFS are defined here too. + | + | WARNING: Data structures and QUADs should be designed to align + | on 64 bit boundries. So when we get a 64 bit processor things + | are aligned correctly. + +-------------------------------------------------------------------------*/ +#ifndef _ZFSASYNCIO_H_ +#define _ZFSASYNCIO_H_ + +#ifndef _XCACHE_H_ +#include +#endif + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +/*--------------------------------------------------------------------------- + * used by the filemap code + *---------------------------------------------------------------------------*/ + +typedef struct FmapOps_s +{ + Blknum_t saveFileBlk; + Extent_s extent; /* location to send/receive extents */ +} FmapOps_s; + +typedef struct ZioFmap_s +{ + Asyncio_s io; + FmapOps_s fmap; +} ZioFmap_s; + + +#endif diff --git a/src/nwnss/zlss/zfsFileMap.h b/src/nwnss/zlss/zfsFileMap.h new file mode 100644 index 0000000..ae7784f --- /dev/null +++ b/src/nwnss/zlss/zfsFileMap.h @@ -0,0 +1,184 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2006-12-30 03:27:16 +0530 (Sat, 30 Dec 2006) $ + | + | $RCSfile$ + | $Revision: 1799 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define stuctures and + +-------------------------------------------------------------------------*/ + +#ifndef _ZFSFILEMAP_H_ +#define _ZFSFILEMAP_H_ + +#ifndef _OMNI_H_ +#include +#endif + +#ifndef _ZFS_H_ +#include "zfs.h" +#endif + +/*--------------------------------------------------------------------------- + | Global definitions + +-------------------------------------------------------------------------*/ + +#define BT_LEAF 0x1 /* Leaf state of a B-tree */ +#define BT_ROOT 0x2 /* Root state of a B-tree */ + +#define ALLOC_AHEAD_SPARSE 16 + +/*- extent structure for file map -*/ + +typedef struct FmapNodeHead_s +{ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; + GUID_t fnh_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). fnh stands for Fmap Node Head. + */ + Zid_t fnh_zid; /* ZID of beast that this FMAP is part of */ + Blknum_t leafLink; +} NSS_MEDIA_STRUCTURE(FmapNodeHead_s,leafLink) FmapNodeHead_s; + +#define FMAP_MAX (PAGE_SIZE - sizeof(FmapNodeHead_s)) / sizeof(FmapExt_s) +#define FMAP_MAX_SMALL 10 +#define MAX_FILE_BLK 0x7fffffff + +#define PERIODIC_RELEASE_COUNT 25 + +typedef struct FmapNode_s +{ + FmapNodeHead_s head; + FmapExt_s extent[FMAP_MAX]; +} NSS_MEDIA_STRUCTURE(FmapNode_s,extent[FMAP_MAX]) FmapNode_s; + +#define TRUNC_DONE 0 +#define TRUNC_CONTINUE 1 +#define TRUNC_ERROR 2 + +typedef struct FmapRoot_s +{ + GUID_t fr_internalID; + Zid_t fr_zid; + WORD numRecs; + FmapExt_s extent[2]; +} NSS_MEDIA_STRUCTURE(FmapRoot_s,extent[2]) FmapRoot_s; + +typedef struct FmapInsert_s +{ + Blknum_t fileBlk; + WORD numRecs; + FmapExt_s extent; +} NSS_MEDIA_STRUCTURE(FmapInsert_s,extent.poolBlk) FmapInsert_s; + +typedef struct FmapInsertSparse_s +{ + FmapExt_s origExt[3]; + FmapExt_s finalExt[3]; + WORD origNumRecs; + WORD finalNumRecs; + LONG index; +} NSS_MEDIA_STRUCTURE(FmapInsertSparse_s,index) FmapInsertSparse_s; + +typedef struct FmapGrow_s +{ + GUID_t fg_internalID; + Zid_t fg_zid; + FmapExt_s extent[2]; +} NSS_MEDIA_STRUCTURE(FmapGrow_s,extent[2].count) FmapGrow_s; + +typedef struct FmapSplit_s +{ + GUID_t fs_internalID; + Zid_t fs_zid; + FmapExt_s parentExt[2]; + LONG pIndex; + Blknum_t childLink; + Blknum_t sibLink; + LONG childMagic; + WORD childState; + WORD numRecs; + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(FmapSplit_s,data[1]) FmapSplit_s; + +typedef struct FmapRemove_s +{ + FmapExt_s origExt; + FmapExt_s finalExt; + WORD numRecs; +} NSS_MEDIA_STRUCTURE(FmapRemove_s,numRecs) FmapRemove_s; + +typedef struct FmapJoin_s +{ + GUID_t fj_internalID; + Zid_t fj_zid; + FmapExt_s parentExt[2]; + FmapExt_s childExt; + LONG childMagic; + WORD childState; + WORD childNumRecs; +} NSS_MEDIA_STRUCTURE(FmapJoin_s,childNumRecs) FmapJoin_s; + +typedef struct FmapToss_s +{ + GUID_t ft_internalID; + Zid_t ft_zid; + FmapExt_s extent[2]; + LONG magic; + WORD state; + WORD numRecs; +} NSS_MEDIA_STRUCTURE(FmapToss_s,numRecs) FmapToss_s; + +typedef struct FmapLog_s +{ + union + { + FmapRoot_s root; + FmapInsert_s insert; + FmapInsertSparse_s insertSparse; + FmapGrow_s grow; + FmapSplit_s split; + FmapRemove_s remove; + FmapJoin_s join; + FmapToss_s toss; + } NSS_MEDIA_UNION(NamelessUnion,join.childNumRecs) u; +} NSS_MEDIA_STRUCTURE(FmapLog_s,u.join.childNumRecs) FmapLog_s; + +/*- this is for IPU only and was not exposed in zfs.h -*/ +extern STATUS ZFS_appendFileMap( + GeneralMsg_s *genMsg, + RootBeast_s *beast, + Blknum_t holeBlkCnt, + Extent_s *extent); + +#endif /* _ZFSFILEMAP_H_ */ diff --git a/src/nwnss/zlss/zfsSuperBlk.h b/src/nwnss/zlss/zfsSuperBlk.h new file mode 100644 index 0000000..e023112 --- /dev/null +++ b/src/nwnss/zlss/zfsSuperBlk.h @@ -0,0 +1,893 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1998 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | define all of the prototypes and globals for the managment of + | the file system pool super block physical information. + | + +-------------------------------------------------------------------------*/ +#ifndef _ZFSPOOLSUPERBLK_H_ +#define _ZFSPOOLSUPERBLK_H_ +#include + +#ifndef _OMNI_H_ +# include +#endif + +#ifndef _ZLSSCONSUMER_H_ +# include "zlssConsumer.h" +#endif + +#ifndef _ZFS_H_ +# include "zfs.h" +#endif + +/* Pre-declare the following structure(s) */ +struct ZfsXaction_s; + +/*--------------------------------------------------------------------------- + | Super Block Specific Items + +-------------------------------------------------------------------------*/ + +#define SUPERBLOCK_NUMBER 4 +#define SUPERBLOCK_PHYSICAL_SIZE (MAL_BUFSZ64K) /* 64 K */ +#define SUPERBLOCK_SECTION_SIZE (MAL_BUFSZ4K) +#define SUPERBLOCK_BLKCOUNT \ + (sizeof(ZFSMediaSuperBlk_s) / SUPERBLOCK_SECTION_SIZE) + +/*--------------------------------------------------------------------------- + * This is where all of the beasts that are part of the super block are + * packed too. + *---------------------------------------------------------------------------*/ + +#define CHECKPOINT_SYNCSTARTVALUE (0x00000010) +#define CHECKPOINT_NUMBER (4) /* Number of checkpoints */ + +#define CHECKPOINT_BLKCOUNT \ + (sizeof(MediaCheckpoint_s)/SUPERBLOCK_SECTION_SIZE) +#define CHECKPOINT_SECTION \ + (offsetof(ZFSMediaSuperBlk_s,SB_Checkpoint)/SUPERBLOCK_SECTION_SIZE) + +/* + * Be sure to update Template Checkpoint_s in magic.ztm if you change + * Checkpoint_s. Also tell Greg so he can update the Superblock Physical + * Layout Diagram. + */ + +typedef struct Checkpoint_s +{ + LONG CP_Signature; /* Signature of block, must always be first*/ + WORD CP_VersionMajor; + /* The major version of the checkpoint. Changes when + * checkpoint is no longer compatible with an older version + * of the checkpoint. The first release will have this + * set to 1. To display use "%u.%02u" as the format string. + */ + WORD CP_VersionMinor; + /* The minor version of the checkpoint. Changes when old + checkpoints are still compatible. This will be 0 in the + first release. */ + LONG CP_PackedSize; + /* Total packed size of checkpoint. This includes + * the packed beast area as well as all the CP_xxx + * elements of the checkpoint. This is the number of bytes + * to checksum.*/ + LONG CP_Checksum; + /* Checksum of active bytes (includes bytes in + * CP_PackedData[]). */ + QUAD CP_SyncId; + /* increasing number to verify current instance */ + Time_t CP_ModifiedTime; /* when checkpoint was last modified(written) */ + LONG CP_NumPackedBeasts; /* how many beasts are in the SUPERBLK */ + LONG CP_ZasRestartId; /* used for ZAS effective rights cache */ + LONG CP_State; /* State that indicates what caused checkpoint. + * See CHECKPOINT_CT_S_ defines below for legal + * values. + */ + LONG CP_Reserved[20]; /* growth space plus align to QUAD boundry*/ + + /* CP_PackedData must be the last item in the checkpoint and + located on a QUAD boundary. Code will ASSERT if not located + on QUAD boundary */ + BYTE CP_PackedData[8]; /* space where packed data goes */ +} NSS_MEDIA_STRUCTURE(Checkpoint_s,CP_PackedData[8]) Checkpoint_s; + +/* + * Be sure to update Template Checkpoint_s in magic.ztm if you change + * Checkpoint_s. + */ + +#define CHECKPOINT_CP_VM_MAJOR 8 /* */ +#define CHECKPOINT_CP_VM_MINOR 0 /* */ + +#define CHECKPOINT_CP_S_SIGNATURE (0x37504b43uL) /* 'CKP7' */ + + + /*** State values for ZFSPOOL_CheckpointTake ***/ + + /* These are the three 'modes' of the checkpoint */ +#define CHECKPOINT_CT_S_NORMAL 0x00000001u +#define CHECKPOINT_CT_S_CLEAN 0x00000002u +#define CHECKPOINT_CT_S_LAST 0x00000004u +#define CHECKPOINT_CT_S_MODE (CHECKPOINT_CT_S_NORMAL| \ + CHECKPOINT_CT_S_CLEAN|CHECKPOINT_CT_S_LAST) + /* These are the 13 'reasons' a checkpoint is taken */ +#define CHECKPOINT_CT_S_NO_UNDO_COMMITTED 0x00000010u +#define CHECKPOINT_CT_S_DEFERED_DELETE 0x00000020u +#define CHECKPOINT_CT_S_THROTTLE_BACK 0x00000040u +#define CHECKPOINT_CT_S_DEBUG 0x00000080u +#define CHECKPOINT_CT_S_POOL_INITIALIZE 0x00000100u +#define CHECKPOINT_CT_S_SET_RESTART_ID 0x00000200u +#define CHECKPOINT_CT_S_HOME_MOVEMENT 0x00000400u +#define CHECKPOINT_CT_S_ACTIVE_MOVEMENT 0x00000800u +#define CHECKPOINT_CT_S_TIMER 0x00001000u +#define CHECKPOINT_CT_S_MIRACLE 0x00002000u +#define CHECKPOINT_CT_S_DEACTIVATION 0x00004000u +#define CHECKPOINT_CT_S_RECOVERY 0x00008000u +#define CHECKPOINT_CT_S_L_UNDO 0x00010000u +#define CHECKPOINT_CT_S_REASON (CHECKPOINT_CT_S_DEFERED_DELETE| \ + CHECKPOINT_CT_S_THROTTLE_BACK|CHECKPOINT_CT_S_NO_UNDO_COMMITTED|\ + CHECKPOINT_CT_S_DEBUG|CHECKPOINT_CT_S_POOL_INITIALIZE| \ + CHECKPOINT_CT_S_SET_RESTART_ID|CHECKPOINT_CT_S_HOME_MOVEMENT| \ + CHECKPOINT_CT_S_ACTIVE_MOVEMENT|CHECKPOINT_CT_S_TIMER| \ + CHECKPOINT_CT_S_MIRACLE|CHECKPOINT_CT_S_DEACTIVATION| \ + CHECKPOINT_CT_S_RECOVERY|CHECKPOINT_CT_S_L_UNDO) + + +/*--------------------------------------------------------------------------- + * Contains the physical size of a checkpoint on media. + *---------------------------------------------------------------------------*/ +typedef struct MediaCheckpoint_s +{ + Checkpoint_s chkPnt; + BYTE reserved[SUPERBLOCK_SECTION_SIZE - sizeof(Checkpoint_s)]; /* ZEROED */ +} NSS_MEDIA_STRUCTURE(MediaCheckpoint_s,reserved[SUPERBLOCK_SECTION_SIZE - sizeof(Checkpoint_s)]) MediaCheckpoint_s; + +/*--------------------------------------------------------------------------- + * Gets the next checkpoint number i.e. handles wrap. This macro must + * work on both signed and unsigned numbers. + *---------------------------------------------------------------------------*/ +#define CHECKPOINT_GET_NEXT( _checkpoint ) \ + *(_checkpoint) += 1; \ + if ( *(_checkpoint) >= CHECKPOINT_NUMBER ) \ + { \ + *(_checkpoint) = 0; \ + } + +/*--------------------------------------------------------------------------- + * Gets the previous checkpoint number i.e. handles wrap. This macro + * must work on both signed and unsigned numbers. + *---------------------------------------------------------------------------*/ +#define CHECKPOINT_GET_PREVIOUS( _checkpoint ) \ + if ( *(_checkpoint) == 0 ) \ + { \ + *(_checkpoint) = CHECKPOINT_NUMBER - 1; \ + } \ + else \ + { \ + *(_checkpoint) -= 1; \ + } + +/*--------------------------------------------------------------------------- + | Super Block Header Specific Items + +-------------------------------------------------------------------------*/ + +#define SUPERBLOCKHEADER_SECTION \ + (offsetof(ZFSMediaSuperBlk_s, SB_Header)/SUPERBLOCK_SECTION_SIZE) +#define SUPERBLOCKHEADER_BLKCOUNT \ + (sizeof(MediaSuperBlockHeader_s) / SUPERBLOCK_SECTION_SIZE) +#define SUPERBLOCKHEADER_SYNCSTARTVALUE (0x0000000e) + + +/* + * Be sure to update Template SuperBlockHeader_s in magic.ztm if you change + * SuperBlockHeader_s. Also tell Greg so he can update the Superblock Physical + * Layout Diagram. + */ + +typedef struct SuperBlockHeader_s +{ + /* general information */ + LONG SBH_Signature; /* Signature of block, must always be first*/ + WORD SBH_VersionMajor; + /* The major version of the super block header. Changes + * when the super block is no longer compatible + * with an older version of the super block header. + * The first release will have this set to 1. The + * define SUPERBLOCK_SB_VM_MAJOR specifies the current + * major version number of the header. To display + * use "%u.%02u" as the format string. + */ + WORD SBH_VersionMinor; + /* The minor version of the super block header. + * Changes when old super block header are still + * compatible. This will be 0 in the first release. + * The define SUPERBLOCK_SB_VM_MINOR specifies the + * current minor version number of the header. + */ + WORD SBH_VersionMediaMajor; + /* Major version of media. This is used to limit + * older ZSTORE systems from running on newer media when + * no changes occur in the superblock or checkpoint. It + * can also be used to prevent newer systems from running + * on old media that the system does not support. The + * define SUPERBLOCK_SB_VM_MEDIA_MAJOR specifies the current + * major media version. + */ + WORD SBH_VersionMediaMinor; + /* The minor version of the media. Indicates a compatible + * change has occurred to the media. This will be 0 + * in the first release. The define + * SUPERBLOCK_SB_VM_MEDIA_MINOR specifies the + * current minor version number of the media. + */ + LONG SBH_ItemsMoved; + /* Items moved is used in a specific auto in-place + * upgrade when we added logical volumes. Once + * the upgrade is done then this field can be re-used. + * It will be zero. + */ + GUID_t SBH_InternalID; + /* Must be at OFFSET 16 - unique 128 bit GUID used + * for internal ZLSS identification. + */ + LONG SBH_PackedSize; + /* Number of packed bytes in the header. */ + LONG SBH_Checksum; + /* Checksum of active bytes (SuperBlockHeader_s). */ + + LONG supersyncid; /* increasing number to verify current */ + SQUAD superlocation[SUPERBLOCK_NUMBER]; + /* Pool block location of super block (4 each) */ + LONG physSizeUsed; /* bytes used by super block physical */ + LONG sizeUsed; /* size of the super block in bytes */ + Time_t superTimeStamp; /* last time of superblk write (UTC) */ + LONG reserved0[1]; + SQUAD SBH_LoggedPoolDataBlk; /* Block number of the ZLSS Pool's + * data block. + */ + SQUAD SBH_PoolDataBlk; /* Block number of the ZLSS Pool's + * logged data block. + */ + GUID_t SBH_OldInternalID; /* 'LV Support */ + /* Old unique 128 bit GUID used for identification. This + * field will be 0 for pools that were created AFTER + * Logical Volumes added. The LV conversion code stores + * the OLD GUID of the pool here so that scan utilities + * can detect POOL specific system beast blocks that + * existed before conversion. Both this GUID and + * the SBH_VolumeID are legal for pool specific system + * beast blocks. For example, in the purge log or + * free tree. While the Beast Tree and Name Tree + * blocks will not have SBH_OldVolumeIDs in them. The + * scanner MUST not use SBH_OldVolumeIDs when matching + * NON POOL system beasts because it may find some blocks + * that belong to the Logical Volume that was created + * when the pool was converted to a LV. + */ + Time_t SBH_PoolToLVStartUTC; /* 'LV Support */ + Time_t SBH_PoolToLVEndUTC; /* 'LV Support */ + /* The above two times are FYI as to when the pool + * started and endded conversion from the old + * pool/volume format into the new LV format. + */ + WORD SBH_VersionMediaMajorCreate; /* 'LV Support */ + WORD SBH_VersionMediaMinorCreate; /* 'LV Support */ + /* The Create media versions above is the media + * version at the time the pool was created. This + * allows us to detect what auto in place upgrades + * have been applied to a pool. This can be useful + * in detecting things. For example, if the media + * version is 36.05 then we know that the volume + * has no 32 bit trustee information on it. Note + * that this field was first supported by LV upgrade + * which took place at 36.01. The AIPU that took + * place at 36.01 would save the current media version + * at the time of AIPU. Therefore any version less + * than 36.01 only indicates the media version at + * conversion. The actual media version at creation + * is unknown if create media version is 36.01 or less! + */ + LONG SBH_BlocksMoved; + /* Blocks moved is used in a specific auto in-place + * upgrade when we added logical volumes. Once + * the upgrade is done then this field can be re-used. + * It will be zero. + */ + LONG SBH_TempBTSpBlk; + /* This is the block allocated for beasttree special + * block, to be used during upgrades. When upgrade is + * complete it is reset back to zero + */ + LONG SBH_TempFTSpBlk; + /* This is the block allocated for freetree special + * block, to be used during upgrades. When upgrade is + * complete it is reset back to zero + */ + LONG SBH_TempFTSpBlk1; + /* This is the block allocated to put in FT special + * block, to be used during upgrades. When upgrade is + * complete it is reset back to zero + */ + LONG SBH_TempFTSpBlk2; + /* This is another block allocated to put in FT special + * block, to be used during upgrades. When upgrade is + * complete it is reset back to zero + */ +/* LONG reserved1[4-4]; */ + /* Extra space and keep aligned to QUAD boundary + * (4 longs). This space contains zeros. + */ + + /* pool information */ + LONG nssMagicNumber; /* NSS data layout on disk */ + LONG poolClassID; /* classID of this pool */ + LONG poolID; /* unique id for this pool */ + Time_t createTime; /* time pool was created */ + SQUAD SBH_LoggedVolumeDataBlk;/* blk number of ZfsPool's Volume_s logged into */ + SQUAD SBH_VolumeDataBlk; /* blk number of ZfsPool's Volume_s beast */ + SQUAD SBH_SystemBeastBlkNum;/* blk that has all the system beasts */ + QUAD totalblocks; /* total number of blocks in pool */ +#if MAL_MAXNAME != 64 +#error MAL_MAXNAME is assumed to be 64 by the next line. +#endif + unicode_t SBH_Name[MAL_MAXNAME]; /* unicode_t string of pool name. + * As of Feb 5, 2001. + * After verifying a supber block header + * we ALWAYS fill in the name that MAL + * has for the pool. This was done so that + * we only have ONE offical keeper of the + * pool name. + */ + VolumeID_t SBH_VolumeID; /* Moved from offset 16 during AIPU 34 to + * 35. This is the ID of the Internal + * volume(i.e. the ZfsPool_s object). + */ + VolumeID_t SBH_PoolID; /* Created during AIPU 34 to 35. This is + * the Pool_s objects ID. + */ + GUID_t SBH_PoolInternalID; /* Created during AIPU 34 to 35. This is + * the Pool_s objects Internal ID. The + * one that NEVER changes. + */ + + Lsn_t SBH_Lsn; /* LSN of last time block written as + * part of a xaction. + */ + + LONG SBH_SS_Enabled; /* When set to "SnAp" then this pool + * is a snapshot of another pool. + */ +#define ZLSS_SBH_SNAPSHOT_ENABLED 0x70416e53 // "SnAp" + Time_t SBH_SS_CreateTime; /* UTC of when snapshot created */ + VolumeID_t SBH_SS_OriginalPoolID; + /* Pool ID when snapshot taken. This should be + * the Pool ID of another pool that this pool + * is the snapshot of. + */ + VolumeID_t SBH_SS_OriginalVolumeID; + /* Volume ID when snapshot taken. This should be + * the Volume ID of another internal volume that + * this pool is the snapshot of. + */ + GUID_t SBH_SS_Guid; + /* Unique ID given to the 'snapshot' */ + unicode_t SBH_SS_OriginalName[MAL_MAXNAME]; + /* Pool name when snapshot taken. This should be + * the name of another pool that this pool + * is the snapshot of. + */ + LONG reserved2[64-(2+46)]; /* Extra space and keep aligned to QUAD + * boundary (16 longs). ZEROED. Extra + * zero space added in AIPU 34 to 35. + */ + // This structure must not be greater than 3*512 or logging code will be broken +} NSS_MEDIA_STRUCTURE(SuperBlockHeader_s,reserved2[64-(2+46)]) SuperBlockHeader_s; + +/* + * Be sure to update Template SuperBlockHeader_s in magic.ztm if you change + * SuperBlockHeader_s. + */ + +#define SUPERBLOCK_SB_VM_MAJOR 3 /* */ +#define SUPERBLOCK_SB_VM_MINOR 1 /* Greg updated to 1 to indicate + * that some fields where added + * of LV support. This fields + * are marked with 'LV Support' + */ + +#if ZSTORE_BEAST_LAYOUT == 1 +#define SUPERBLOCK_SB_VM_MEDIA_MAJOR 43 // Greg did 32 to 33; Vandana to 34; Randy to 35; Greg/Randy(COBRA) to 36; Randy 39; Greg 40; Greg 43 + /* POOL verson of media. The system that creates or updates + * the media places this value into SB_VersionMediaMajor + * to indicate the media format. Currently NSS will only + * run on media that has the same major media version as + * this define. + * + * Media 32 - Offical layout of MOAB Beta III release + * + * Media 33 - Auto in-place-upgrade to add purge tree beast + * to media. This was done for Salvage support. This + * was done May 1, 1998 and will be in FCS of MOAB. + * + * Media 34 - The official layout for FCS. + * It will require the BETA III volumes to be recreated. + * + * Media 35 - User Space Restriction Tree. + * + * Media 36, 37 and 38 - Reserved for COBRA and/or MOAB + * service packs. Still requires change to Six-Pack. + * + * Media 39 - Change in layout caused by changing from + * 32 bit IDs to 128 GUIDs for all object IDs. Also, + * moved owner ID to the root. Cleared extra bits + * on in the persistent attribute field. + * + * Media 40 - System beasts into special beast tree block and + * Added Logical Volumes. + * + * Media 40.08 - Has a MSAP block used to prevent multiple + * servers from activating the same pool. + * + * Media 40.84 - Pool has been activated under Nakoma + * + * Media 40.85 - Clustering has given permission to upgrade pool. + * Non 'SHARED' pools do not need clustering permission to + * go to media format 40.85 + * + * Media 40.86 - Pool made it 7 days under Nakoma OR EFL would + * like to be enabled. + * + * Media 40.87 - Pool made it 14 days under Nakoma OR EFL would + * like to be enabled. + * + * Media 40.88 - Pool made it 21 days under Nakoma OR EFL would + * like to be enabled. + * + * Media 43.00 - Volumes on Pool can be upgraded to 36.00. + * + * Media 43.01 - All volumes are at 36.01 or higher. + * + * Media 43.02 - All volumes are at 36.03, 37.03, 40.03 or higher + * + * Media 43.03 - All volumes are at 38.05 or higher + * + * Volume versions explanation is in zlssUpgrade.h + * + */ +#define SUPERBLOCK_SB_VM_MEDIA_MINOR 3 // Craig did 43.02 to 43.03 for hardlink upgrade + /* Current minor version of the media that this code + * understands. This is the minor version number placed + * on the media if this code 'creates' a pool. + * Set to 0 at release and erase comment. + */ +#else +#error "Be sure to update the MEDIA version when changing the ZSTORE_BEAST_VERSION" +#endif + +#define SUPERBLOCK_SB_S_SIGNATURE 0x35425053uL /* 'SPB5' on little endian */ +#define SUPERBLOCK_SB_S_SIGNATURE_OLD 0x356f6273uL + /* 'sbo5' on little endian. This is placed in + * super blocks that are old. IE when we expand + * a pool and move the last 2 super blocks the + * old last two super block headers get updated. + * If the update fails we ignore the error. + */ + +/*--------------------------------------------------------------------------- + * This is the media representation of the Super Block Header + *---------------------------------------------------------------------------*/ +typedef struct MediaSuperBlockHeader_s +{ + SuperBlockHeader_s hdr; + BYTE reserved[SUPERBLOCK_SECTION_SIZE-sizeof(SuperBlockHeader_s)];/*ZEROED*/ +} NSS_MEDIA_STRUCTURE(MediaSuperBlockHeader_s,reserved[SUPERBLOCK_SECTION_SIZE-sizeof(SuperBlockHeader_s)]) MediaSuperBlockHeader_s; + +/* + * This is SECTION 12 of superblock 0. This block does not exist in + * superblocks 1, 2 or 3. + */ + +#define SUPERBLOCK_SBD_SIGNATURE 0x30444253uL /* 'SPD0' on little endian */ + +typedef struct SuperBlockDebug_s +{ + /* general information */ + LONG SBD_Signature; /* Signature of block, must always be first*/ + WORD SBD_VersionMajor; + /* The major version of the super block header. Changes + * when the super block is no longer compatible + * with an older version of the super block header. + * The first release will have this set to 1. The + * define SUPERBLOCK_SB_VM_MAJOR specifies the current + * major version number of the header. To display + * use "%u.%02u" as the format string. + */ + WORD SBD_VersionMinor; + /* The minor version of the super block header. + * Changes when old super block header are still + * compatible. This will be 0 in the first release. + * The define SUPERBLOCK_SB_VM_MINOR specifies the + * current minor version number of the header. + */ + Lsn_t SBD_LsnReserved; + /* Reserved if we need to log this block. Should + * not need as should just use section 12 of 2nd + * superblock if need a logged block. + */ + GUID_t SBD_InternalID; + /* Must be at OFFSET 16 - unique 128 bit GUID used + * for internal ZLSS identification. + */ + QUAD SBD_WriteCrashFailureCount; + /* Count of writes that should be done before + * crashing the machine. Used in debug systems + * only when the /ZLSSWriteCrash switch is on. + * Note that the /ZLSSWriteCrashIncrement switch + * can be used to increase the value by one. + */ + BYTE reserved2[4096-32-8]; +} NSS_MEDIA_STRUCTURE(SuperBlockDebug_s,reserved2[4096-32-8]) SuperBlockDebug_s; + +/* + * This is SECTION 12 of superblock 1. This block does not exist in + * superblocks 0, 2 or 3. + */ + +#define SUPERBLOCK_SBDX_SIGNATURE 0x58444253uL /* 'SPDX' on little endian */ + +typedef struct SuperBlockDebugXaction_s +{ + /* general information */ + LONG SBDX_Signature; /* Signature of block, must always be first*/ + WORD SBDX_VersionMajor; + /* The major version of the super block header. Changes + * when the super block is no longer compatible + * with an older version of the super block header. + * The first release will have this set to 1. The + * define SUPERBLOCK_SB_VM_MAJOR specifies the current + * major version number of the header. To display + * use "%u.%02u" as the format string. + */ + WORD SBDX_VersionMinor; + /* The minor version of the super block header. + * Changes when old super block header are still + * compatible. This will be 0 in the first release. + * The define SUPERBLOCK_SB_VM_MINOR specifies the + * current minor version number of the header. + */ + Lsn_t SBDX_Lsn; + GUID_t SBDX_InternalID; + /* Must be at OFFSET 16 - unique 128 bit GUID used + * for internal ZLSS identification. + */ + BYTE reserved2[4096-32]; +} NSS_MEDIA_STRUCTURE(SuperBlockDebugXaction_s,reserved2[4096-32]) SuperBlockDebugXaction_s; + + + + + /* + * This structure is used to store validation items about the super + * block headers + */ +typedef struct SuperBlockHeaderValidate_s +{ + Blknum_t SBHV_MathematicalBlock; + MediaSuperBlockHeader_s *SBHV_MediaCopy; + NINT SBHV_Flag; +#define SUPERBLOCK_SBHV_F_CHECKSUM_GOOD 1 /* Valid checksum, ver, sign... */ +#define SUPERBLOCK_SBHV_F_DIFFERENT 2 /* Different from main header */ +} SuperBlockHeaderValidate_s; + +/*--------------------------------------------------------------------------- + | Super Block Header Copy Specific Items + +-------------------------------------------------------------------------*/ + +#define SUPERBLOCKHEADERCOPY_SECTION \ + (offsetof(ZFSMediaSuperBlk_s,SB_HeaderCopy)/SUPERBLOCK_SECTION_SIZE) +#define SUPERBLOCKHEADERCOPY_BLKCOUNT SUPERBLOCKHEADER_BLKCOUNT + + +/*--------------------------------------------------------------------------- + | Super Block Debug Specific Items + +-------------------------------------------------------------------------*/ + +#define SUPERBLOCKDEBUG_SECTION \ + (offsetof(ZFSMediaSuperBlk_s,SB_Debug)/SUPERBLOCK_SECTION_SIZE) +#define SUPERBLOCKDEBUG_BLKCOUNT SUPERBLOCKHEADER_BLKCOUNT + +/*--------------------------------------------------------------------------- + | Reserved Section Specific Items + +-------------------------------------------------------------------------*/ + +typedef struct MediaReservedHeader_s +{ + LONG reserved[SUPERBLOCK_SECTION_SIZE/4]; +} NSS_MEDIA_STRUCTURE(MediaReservedHeader_s,reserved[SUPERBLOCK_SECTION_SIZE/4]) MediaReservedHeader_s; + +#define SUPER_BLOCK_RESERVED_SECTION_MASK( _superBlock, _section) \ + (0x42530000ul + (_section << 8) + _superBlock) + /* Number of blocks in each reserved section (I.E. 1) */ +#define SUPERBLOCKRESERVED_BLKCOUNT \ + (sizeof(MediaReservedHeader_s)/SUPERBLOCK_SECTION_SIZE) + + + +/*--------------------------------------------------------------------------- + | Super Block Specific Items + +-------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + | Media super block structure (64k) + | + | When you assign yourself a reserved section be sure to remove the + | section number that you have taken from the SuperBlockReservedTable + | array in zfssuperblk.c. There is debug code that validates that all + | reserved sections have specific patterns in them. + | + +-------------------------------------------------------------------------*/ +typedef struct ZFSMediaSuperBlk_s +{ + MediaReservedHeader_s SB_Block0; /* Block 0 */ + MediaSuperBlockHeader_s SB_Header; /* Block 1 */ + MediaCheckpoint_s SB_Checkpoint; /* Block 2 */ + MediaReservedHeader_s SB_Block3; /* Block 3 */ + MediaReservedHeader_s SB_Block4; /* Block 4 */ + MediaReservedHeader_s SB_Block5; /* Block 5 */ + MediaReservedHeader_s SB_Block6; /* Block 6 */ + MediaReservedHeader_s SB_Block7; /* Block 7 */ + MediaReservedHeader_s SB_Block8; /* Block 8 */ + MediaReservedHeader_s SB_Block9; /* Block 9 */ + MediaReservedHeader_s SB_Block10; /* Block 10 */ + MediaReservedHeader_s SB_PoolSnapshot; /* Block 11 (Nakoma Pool snapshot and MSAP) */ + MediaReservedHeader_s SB_Debug; /* Block 12 */ + MediaReservedHeader_s SB_Repair1; /* Block 13 */ + MediaReservedHeader_s SB_Repair2; /* Block 14 */ + MediaSuperBlockHeader_s SB_HeaderCopy; /* Block 15 */ +} NSS_MEDIA_STRUCTURE(ZFSMediaSuperBlk_s,SB_HeaderCopy.reserved[SUPERBLOCK_SECTION_SIZE-sizeof(SuperBlockHeader_s)]) ZFSMediaSuperBlk_s; + +#define MSAP_SUPERBLOCK_NUMBER 1 /* 0 relative number */ +#define MSAP_SUPERBLOCK_SECTION 11 /* 0 relative number */ + +/*--------------------------------------------------------------------------- + | In-memory super block structure. Items we keep in memory next to each + | other in a running system. + +-------------------------------------------------------------------------*/ +typedef struct ZFSMemorySuperBlk_s +{ +// MediaReservedHeader_s block0; /* Block 0 */ + MediaSuperBlockHeader_s SB_Header; /* Block 1 */ + MediaCheckpoint_s SB_Checkpoint; /* Block 2 */ +} ZFSMemorySuperBlk_s; + +/*--------------------------------------------------------------------------- + | Superblock Header Log Record. We simply store old and new value + | of superblock header (like beast b-tree). + +-------------------------------------------------------------------------*/ +typedef struct { + BYTE SLR_ValuesOld[3*512]; + BYTE SLR_ValuesNew[3*512]; +} NSS_MEDIA_STRUCTURE(SbhLogRecord_s,SLR_ValuesNew[3*512]) SbhLogRecord_s; /* Sbh stands for "Superblock Header" */ + +/*--------------------------------------------------------------------------- + | Data Prototypes needed + +-------------------------------------------------------------------------*/ +typedef struct PoolBeastCtrl_s +{ + NINT beastClass; /* class ID*/ + Zid_t zid; /* desired zid of the beast */ + NINT poolOffset; /* offset into "ZfsPool_s" beast where this goes*/ + unicode_t *name; +} PoolBeastCtrl_s; + +extern PoolBeastCtrl_s SuperBeasts[]; + +/*--------------------------------------------------------------------------- + | Function Prototypes needed + +-------------------------------------------------------------------------*/ +extern struct ZfsPool_s *ZFSPOOL_CreatePoolBeast( + struct GeneralMsg_s *genMsg); + +extern STATUS ZFSPOOL_InitNewRootDir( + struct GeneralMsg_s *genMsg, + File_s *rootdir, + ZfsVolume_s *zVolume); + +extern STATUS ZFSPOOL_InitNewBeast( + struct GeneralMsg_s *genMsg, + File_s *file, + Zid_t zid, + Zid_t parentZid, + NINT fileAttributes, + unicode_t *name); + +extern STATUS ZFSPOOL_InitNewPool( + struct GeneralMsg_s *genMsg, + StorPool_s *storagepool); + +STATUS ZFSPOOL_SuperBlockRead( + StorPool_s *storagepool, + void *ioBuffer, + Blknum_t blockNum, + NINT blockCnt); + +STATUS ZFSPOOL_SuperBlockWrite( + StorPool_s *storagepool, + void *ioBuffer, + Blknum_t blockNum, + NINT blockCnt); + + +#if NSS_DEBUG IS_ENABLED +void ZFSPOOL_SuperBlockReservedValidate( + ZfsPool_s *pool ); +#endif + +Blknum_t ZFSPOOL_SuperBlockMathematicalBlock( + NINT superBlockNumber, + QUAD totalNumberOfBlocks); + +LONG ZFSPOOL_SuperBlockHeaderCalculateChecksum( + LONG *buffer, + NINT numberOfLONGs ); + +STATUS ZFSPOOL_SuperBlockHeaderChecker( + GeneralMsg_s *genMsg, + StorPool_s *storagepool, + MediaSuperBlockHeader_s *superblockHeaderMedia, + struct SuperBlockHeaderValidate_s si[] ); + +STATUS ZFSPOOL_SuperBlockHeaderRepair( + GeneralMsg_s *genMsg, + StorPool_s *storagepool, + MediaSuperBlockHeader_s *superblockHeaderMedia, + struct SuperBlockHeaderValidate_s si[], + int verbose ); + +STATUS ZFSPOOL_SuperBlockHeaderReadByBlock( + StorPool_s *storagepool, + MediaSuperBlockHeader_s *superblockHeaderMedia, + Blknum_t block); + +STATUS ZFSPOOL_SuperBlockHeaderValidate( + GeneralMsg_s *genMsg, + StorPool_s *storagepool, + MediaSuperBlockHeader_s *superblockHeaderMedia ); + +STATUS ZFSPOOL_SuperBlockHeaderVerify( + StorPool_s *storagepool, + MediaSuperBlockHeader_s *superblockHeaderMedia ); + +STATUS ZFSPOOL_SuperBlockHeaderWriteInitial( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + unicode_t *poolName); + +//extern STATUS ZFSPOOL_FlushSuperBlock( +// struct GeneralMsg_s *genMsg, +// struct ZfsPool_s *pool, +// LONG superblknum); + +STATUS ZFSPOOL_CheckpointSetRestartID( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool); + + +STATUS ZFSPOOL_CheckpointTake( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + NINT state); + +LONG ZFSPOOL_CheckpointCalculateChecksum( + LONG *buffer, + NINT numberOfLONGs ); + +void ZFSPOOL_CheckpointTimerPop( + struct OneShot_s *alarm); + +STATIC void ZFSPOOL_CheckpointWorkToDo( + FsmLite_s *fsm); + +STATUS ZFSPOOL_CheckpointWriteSpecific( + struct ZfsPool_s *pool, + NINT checkpointNumber); + +STATUS ZFSPOOL_CheckpointWriteNext( + struct ZfsPool_s *pool); + +STATUS ZFSPOOL_CheckpointVerify( + struct MediaCheckpoint_s *mediaCheckpoint ); + +STATUS ZFSPOOL_CheckpointFindNewest( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + struct MediaCheckpoint_s *mediaCheckpoint, + unicode_t *poolName); + +void ZFSPOOL_CheckpointFlushFiles( + struct ZfsPool_s *pool, + BOOL deactivating); /* if TRUE, toss the cache buffers also */ + +STATUS ZFSPOOL_CheckpointPoolInitialize( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool ); + +STATUS ZFSPOOL_CheckpointReadSpecific( + struct ZfsPool_s *pool, + struct MediaCheckpoint_s *mediaCheckpoint, + NINT checkpointNumber); + +void ZFSPOOL_CheckpointCheckAndMakeBest( + struct Checkpoint_s *currentBest, + struct Checkpoint_s *challenger ); + +STATUS ZFSPOOL_DoFlushSystemBeasts( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *pool, + BOOL deactivating); + +STATUS ZFSPOOL_SetNewPoolSizeWhileActive( + struct GeneralMsg_s *gsnMsg, + struct StorPool_s *storagepool ); + +STATUS ZFSPOOL_SetNewPoolSizeDuringActivation( + struct GeneralMsg_s *gsnMsg, + struct ZfsPool_s *zfsPool ); + +STATUS ZFSPOOL_SuperBlockHeaderWrite( + StorPool_s *storagepool, + void *ioBuffer, + Blknum_t blockNum, + NINT blockCnt); + +STATUS ZFSPOOL_SuperBlockUpdate( + struct GeneralMsg_s *gsnMsg, + struct ZfsPool_s *zfsPool ); + +STATUS ZFSPOOL_SuperBlockUpdate2( + struct GeneralMsg_s *genMsg, + struct StorPool_s *storagepool, + struct MediaSuperBlockHeader_s *super ); + +STATUS ZFSPOOL_SuperBlockUpdateXaction( + struct GeneralMsg_s *genMsg, + struct ZfsPool_s *zfsPool, + struct ZfsXaction_s *xaction ); + +STATUS ZFSPOOL_SetNewPoolName( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + unicode_t *poolname); + +#endif /* _ZFSPOOLSUPERBLK_H_ */ diff --git a/src/nwnss/zlss/zfsXTree.h b/src/nwnss/zlss/zfsXTree.h new file mode 100644 index 0000000..0a384b3 --- /dev/null +++ b/src/nwnss/zlss/zfsXTree.h @@ -0,0 +1,412 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996, 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Storage Services (NSS) + | + |--------------------------------------------------------------------------- + | + | $Author: mvijai $ + | $Date: 2008-08-21 12:21:10 +0530 (Thu, 21 Aug 2008) $ + | + | $RCSfile$ + | $Revision: 2445 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Free Extent Btree + | + +-------------------------------------------------------------------------*/ + +#ifndef _ZFSXTREE_H_ +#define _ZFSXTREE_H_ + +#ifndef _OMNI_H_ +# include +#endif + +#ifndef _XACTION_H_ +# include "xaction.h" +#endif + +#ifndef _ZFS_H_ +# include "zfs.h" +#endif + +/*- all extent nodes are 4K one cache block -*/ + +#define FXBT_LEAF 0x01 /*- leaf node of the btree -*/ +#define FXBT_ROOT 0x02 /*- root node of the btree -*/ +#define FXBT_SPECIAL_BLK 0x04 /*- special node of the free tree -*/ + +#define FXBT_MAXFREEBLKS ((PAGE_SIZE - sizeof(struct xNodeHeader_s)) / sizeof(Blknum_t)) + + +#define FXBT_MAXEXTENTS ((PAGE_SIZE - sizeof(struct xNodeHeader_s)) / sizeof(Extent_s)) +#define FXBT_MAXBRANCHES ((PAGE_SIZE - sizeof(struct xNodeHeader_s)) / sizeof(xBranch_s)) + +#define FXBT_MAXEXTENTS75 ((((PAGE_SIZE - sizeof(struct xNodeHeader_s)) / sizeof(Extent_s)) * 75) / 100) +#define FXBT_MAXBRANCHES75 ((((PAGE_SIZE - sizeof(struct xNodeHeader_s)) / sizeof(xBranch_s)) * 75) / 100) + +#define FXBT_MINEXTENTS 100 +#define FXBT_MINBRANCHES 100 + + /* August 10, 2001 + * Increased from 20 to 50 because rebuild caused as to run + * out of blocks doing a lot of splits. We worried that + * this could also happen in 'normal' code so we increased. + * Rebuild was fixed by checking if special blocks are + * needed and waiting for them. + * + * August 10, 2008 + * Increased from 50 to 256 because Linux Customer was running + * out on truncates of large fragmented files. Testing was + * also hitting when they ran the new fragment FS tool and then + * did truncates(delete). + */ +#define FXBT_MINBLKS_SPECIAL 256 // Do not increase to more than FXBT_MAXEXTENTS-1 + // without code changes because code assumes that + // all the blocks are in one FT leaf. The minus + // one is needed because of the (0,0) entry in all + // FT leafs. + +/*- macros for xtree -*/ +#define FXBT_IS_LEAF(_n) ((_n)->header.state & FXBT_LEAF) +#define FXBT_IS_ROOT(_n) ((_n)->header.state & FXBT_ROOT) +#define FXBT_IS_SPECIAL_BLK(_n) ((_n)->header.state & FXBT_SPECIAL_BLK) + + +#define FXBT_IS_MAX_XBRANCHES(_node) \ + (FXBT_IS_LEAF(_node) \ + ? ((_node)->header.numRecs == FXBT_MAXEXTENTS) \ + : ((_node)->header.numRecs == FXBT_MAXBRANCHES)) + +#define FXBT_IS_MIN_XBRANCHES(_node) \ + (FXBT_IS_LEAF(_node) \ + ? ((_node)->header.numRecs <= FXBT_MINEXTENTS) \ + : ((_node)->header.numRecs <= FXBT_MINBRANCHES)) + +#define FXBT_IS_LESSTHAN_MAX(_node, _sibling) \ + (FXBT_IS_LEAF(_node) \ + ? (((_node)->header.numRecs + (_sibling)->header.numRecs) < FXBT_MAXEXTENTS) \ + : (((_node)->header.numRecs + (_sibling)->header.numRecs) < FXBT_MAXBRANCHES)) + +#define FXBT_IS_LESSTHAN_JOINMAX(_node, _sibling) \ + (FXBT_IS_LEAF(_node) \ + ? (((_node)->header.numRecs + (_sibling)->header.numRecs) < FXBT_MAXEXTENTS75) \ + : (((_node)->header.numRecs + (_sibling)->header.numRecs) < FXBT_MAXBRANCHES75)) + + +/************************************************************************* + ** This macro will count the total number of free blks available in the + ** specified free tree leaf node. numRecs is the count of extents. + *************************************************************************/ +#define FXBT_NUM_BLKS(_node, _nBlks) \ +{ \ + NINT _i; \ + for (_nBlks = 0, _i = 1; _i < _node->header.numRecs; _i++) \ + _nBlks += node->n.extents[_i].lengthOfExtent; \ +} + + +/*- xtree structure defs -*/ +typedef struct xNodeHeader_s +{ + LONG magic; + WORD state; + WORD numRecs; + Lsn_t lsn; /* Must be at OFFEST 8 - log sequence number */ + GUID_t xnh_internalID; /* Must be at OFFSET 16 - unique internal ID (used + * by scanning repair). xnh is x Node Header. + */ + + WORD nextrec; + WORD pad; /* Put on LONG boundary */ + LONG pad2; /* Put on QUAD boundary */ +} NSS_MEDIA_STRUCTURE(xNodeHeader_s,pad2) xNodeHeader_s; + +/*- sizeof(xBranch_s) == sizeof(Extent_s), they can not be different -*/ +typedef struct xBranch_s +{ + Blknum_t start; + Blknum_t child; +} NSS_MEDIA_STRUCTURE(xBranch_s,child) xBranch_s; + +typedef struct xNode_s +{ + xNodeHeader_s header; + union + { + Extent_s extents[FXBT_MAXEXTENTS]; + xBranch_s branch[FXBT_MAXBRANCHES]; + } NSS_MEDIA_UNION(NamelessUnion,branch[FXBT_MAXBRANCHES]) n; +} NSS_MEDIA_STRUCTURE(xNode_s,n.branch[FXBT_MAXBRANCHES]) xNode_s; + + +enum { FXBT_MINBLKS_SPECIAL_FXBT_MAXEXTENTS = 1/(FXBT_MINBLKS_SPECIAL < FXBT_MAXEXTENTS ? 1 : 0) }; +enum { Validate_xBranch_s_Extent_s = 1/((sizeof(xBranch_s) == sizeof(Extent_s)) ? 1 : 0 ) }; + +#define XTREE zio->xtree +#define XTREEchildBlk zio->childBlk +#define XTREEindex zio->index +#define XTREEparent zio->parent +#define XTREEchild zio->child +#define XTREEsibling zio->sibling +#define XTREEspecialBuf zio->specialBuf + +#define EXTENTptr zio->extent +#define EXTENTlen zio->extent.lengthOfExtent +#define EXTENTblk zio->extent.poolBlkNum + + +/*- xNode macro -*/ +#define EXT n.extents +#define BRA n.branch + +typedef struct ZioTh_s +{ + GeneralMsg_s *genMsg; + Blknum_t childBlk; + Buffer_s *child; + Buffer_s *sibling; + Buffer_s *parent; + NINT index; + Extent_s extent; + struct ZfsXaction_s *xaction; + struct ZfsFreeExtent_s *xtree; + NINT zt_flags; +#define ZT_FLAGS_NEAR_MATCH 0x00000001 /* On block allocate, + try to find a block in the area */ +#define ZT_FLAGS_GLOBAL_SEED 0x00000002 /* We are using GlobalSeed */ +} ZioTh_s; + +#define INIT_ZIO_TH(_zio, _genMsg, _xtree, _blkNum, _extLen, _xact) \ +{ \ + (_zio)->genMsg = (_genMsg); \ + (_zio)->xtree = (_xtree); \ + (_zio)->extent.poolBlkNum = (_blkNum); \ + (_zio)->extent.lengthOfExtent = (_extLen); \ + (_zio)->xaction = (_xact); \ + (_zio)->zt_flags = 0; \ +} + +/*- log record count for each operation -*/ +#define FXLOG_SHRINK_COUNT 2 +#define FXLOG_DELETE_COUNT 2 +#define FXLOG_BALANCE_COUNT 3 +#define FXLOG_JOIN_COUNT 3 +#define FXLOG_GROW_COUNT 2 +#define FXLOG_SPLIT_COUNT 3 +#define FXLOG_INSERT_COUNT 1 + +/*- insert action type -*/ +#define FXBT_DONOTHING 0 +#define FXBT_MERGELEFT 1 +#define FXBT_MERGELEFTTHENRIGHT 2 +#define FXBT_MERGERIGHT 3 +#define FXBT_INSERTATRIGHT 4 +#define FXBT_INSERTAPPEND 5 + + + +/*- log data structures -*/ + + /*- shrink has no structure -*/ + +typedef struct FXdelete_s +{ + Extent_s oriext; + Extent_s newext; + Extent_s splitext; + WORD orinumRecs; + WORD newnumRecs; + WORD recnuml; + WORD recnumb; + xBranch_s oribra; + xBranch_s newbra; + Extent_s delExt; +} NSS_MEDIA_STRUCTURE(FXdelete_s,delExt) FXdelete_s; + +typedef struct FXbalance_s +{ + WORD recnum; + WORD bytestomove; + WORD orichildnumRecs; + WORD newchildnumRecs; + WORD orisiblingnumRecs; + WORD newsiblingnumRecs; + WORD braindex; + xBranch_s oribra; + xBranch_s newbra; + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(FXbalance_s,data[1]) FXbalance_s; + +typedef struct FXjoin_s +{ + WORD orisiblingstate; + WORD orichildnumRecs; + WORD newchildnumRecs; + WORD oriparentnumRecs; + WORD newparentnumRecs; + WORD braindex; + xBranch_s oribra; + Extent_s meroriextlt; + Extent_s meroriextrt; + Extent_s mernewext; + LONG mergeflag; + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(FXjoin_s,data[1]) FXjoin_s; + +typedef struct FXgrow_s +{ + WORD orichildstate; + WORD newparentstate; + WORD newparentnumRecs; + xBranch_s oribra; +} NSS_MEDIA_STRUCTURE(FXgrow_s,oribra) FXgrow_s; + +typedef struct FXsplit_s +{ + WORD orisiblingstate; + WORD orisiblingnumRecs; + WORD bytestomove; + WORD newchildnumRecs; + WORD braindex; + xBranch_s newbra; + BYTE data[1]; +} NSS_MEDIA_STRUCTURE(FXsplit_s,data[1]) FXsplit_s; + +typedef struct FXinsert_s +{ + WORD extindex; + WORD orinumRecs; + WORD newnumRecs; + WORD action; + Extent_s oriextlt; + Extent_s oriextrt; + Extent_s newextlt; + Extent_s newextrt; + Extent_s newext; + Extent_s insExt; +} NSS_MEDIA_STRUCTURE(FXinsert_s,insExt) FXinsert_s; + +typedef struct FXlog_s +{ + union + { + FXdelete_s delete; + FXbalance_s balance; + FXjoin_s join; + FXgrow_s grow; + FXsplit_s split; + FXinsert_s insert; + } NSS_MEDIA_STRUCTURE(u,insert) u; +} NSS_MEDIA_STRUCTURE(FXlog_s,u.insert) FXlog_s; + + + +/*--------------------------------------------------------------------------- + | Data Prototypes needed + +-------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- + | Function Prototypes + +-------------------------------------------------------------------------*/ + +extern STATUS zfsAllocExtent( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + Extent_s *request, + NINT allocFlags, + ZfsXaction_s *xaction); + +extern STATUS zfsAllocExtentFromSpecialBlk( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + Extent_s *request, + ZfsXaction_s *xaction, + Buffer_s **specialBuffer); + +extern STATUS ZFSPOOL_AllocExtent(ZioTh_s *zio, ZfsVolume_s *zfsVol); + +extern STATUS zfsFreeExtent( + GeneralMsg_s *genMsg, + ZfsVolume_s *zfsVol, + Extent_s *request, + ZfsXaction_s *xaction); + +STATUS zfsFreePoolExtent( + GeneralMsg_s *genMsg, + ZfsPool_s *poolVolume, + Extent_s *request, + ZfsXaction_s *xaction); + +extern STATUS ZFSPOOL_FreeExtent(ZioTh_s *zio, ZfsVolume_s *zfsVol); + +extern STATUS InitRootNode( + GeneralMsg_s *genMsg, + ZfsFreeExtent_s *beast, + Blknum_t poolblk); + +extern STATUS InitSpecialNode( + GeneralMsg_s *genMsg, + ZfsFreeExtent_s *beast, + Blknum_t poolblk); + +extern STATUS Add2BlksToSpecialNode( + GeneralMsg_s *genMsg, + ZfsFreeExtent_s *beast, + Blknum_t spBlk, + Blknum_t blk1, + Blknum_t blk2); + +extern void CheckSpecialBlkAndAdd( + ZfsPool_s *pool, + Extent_s *allocExtent, + LONG flags); + +#define XTREE_SPBLK_XACTION 0x00000001 +#define XTREE_SPBLK_THREAD_SCH 0x00000002 + +extern Blknum_t getABlkFromSpecialBlk( + Blknum_t specialBlk, + ZfsFreeExtent_s *xtree, + ZfsXaction_s *xaction, + Buffer_s **specialBuf); + +extern BOOL FT_ExtentIsStillFree( + ZfsPool_s *pool, + Extent_s *extent); + +#if NSS_DEBUG IS_ENABLED +void VerifyFXnode(xNode_s *node, NINT action); +#endif + +void FT_ValidateNode( struct Buffer_s *buffer, SNINT index ); + +STATUS insertXNodeGetChild(ZioTh_s *zio); + +STATUS deleteExtent(ZioTh_s *zio); + +STATUS deleteXNodeGetChild(ZioTh_s *zio); + +#endif /* _ZFSXTREE_H_ */ diff --git a/src/nwnss/zlss/zfsdefs.h b/src/nwnss/zlss/zfsdefs.h new file mode 100644 index 0000000..b3c4e57 --- /dev/null +++ b/src/nwnss/zlss/zfsdefs.h @@ -0,0 +1,284 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2007-04-18 23:26:20 +0530 (Wed, 18 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1954 $ + | + |--------------------------------------------------------------------------- + | This header file is used to: + | Glue Naming B-Tree code to the rest of the NSS environment. + +-------------------------------------------------------------------------*/ +#ifndef _ZFSDEFS_H_ +#define _ZFSDEFS_H_ + +/* + * Some stub definitions to interface naming B-tree code with the rest of NSS + * environment. + */ +#include /* NSS Library */ +#include +#include +#include +#include +#include + +#include "msgGen.h" +#include "zParams.h" +#include "comnPublics.h" +#include "searchMap.h" +#include "nameSpace.h" +#include "zlog.h" +#include "xaction.h" +#include "zfs.h" +#include "comnBeastClass.h" +#include "comnAuthorize.h" +#include "fullDirectoryInfo.h" + +#undef inline +#define inline + +#define ZFSNAMETREE_DEBUG NSS_DEBUG IS_ENABLED +#define DB_PRINTF(_cmd_) DBG_DebugPrintf _cmd_ + +#define TOLOWER(_c) unitolower(_c) +#define zOUT_OF_BUFFERS zFAILURE +#define zERR_INVALID_ARG zFAILURE + +typedef NINT Latch_mode_t; +typedef unicode_t fname_char_t; +typedef LONG nsmask_t; +typedef SNINT node_ind_t; + +#define NAMECMP_EXACT unicmp + +typedef struct NameTreeParms_s +{ + GeneralMsg_s *genMsg; + ZfsNameTree_s *ntree; + struct ZfsXaction_s *xaction; + IoMsg_s iomsg; +#if ZFSNAMETREE_DEBUG + NINT validate_ntree_nodes; +#endif +} NameTreeParms_s; +#define NTREE_IS_READONLY(_parms) \ + (((_parms)->ntree->ZFSNAMETREEroot.vol.volume->VOLenabledAttributes & \ + zATTR_READONLY) || \ + ((_parms)->ntree->ZFSNAMETREEroot.vol.volume->maintenanceStatus & \ + VOLMAINTSTATUS_CHECKING)) + +#define SMAPcursor nextSrch.zfsNext +#define SMAPvalidLink SMAPcursor.validLink +#define SMAPcleanup cleanup +#define SMAP_CURSOR(_smap) (&(_smap)->SMAPcursor) +#define SMAP_MATCH_ALL_ENTRIES(_smap) \ + ((_smap)->options & SMAPOPT_matchAllEntries) + +/* Test & Set the RETURN_PREVMATCH flag in SMAP structure */ +#define SMAP_TSET_RETURN_PREVMATCH(_smap, _ret_prev_match) \ + ((((_ret_prev_match) = (_smap)->options & SMAPOPT_returnLastEntry)), \ + ((_smap)->options &= ~(SMAPOPT_returnLastEntry))) + +#define DIR_SCTRL_INIT(_sm_, _pat_) \ + do { \ + SMAP_CURSOR(_sm_)->leafhint = INVALID_BLK; \ + SMAP_CURSOR(_sm_)->ovflow_hint = INVALID_BLK; \ + SMAP_CURSOR(_sm_)->zid = zINVALID_ZID; \ + SMAP_CURSOR(_sm_)->name = 0; \ + SMAP_CURSOR(_sm_)->namelen = 0; \ + SMAP_CURSOR(_sm_)->buflen = 0; \ + (_sm_)->SMAPcleanup = 0; \ + NULLIFY(&(_sm_)->SMAPvalidLink); \ + } while (0) + +#define DIR_SCTRL_CLEANUP(_smap_) \ + ZFSNAMETREE_smap_cursor_cleanup(_smap_) + +#define PATCMP(_sm, _ns_mask, _pat, _e, _pcmpfn) \ + (((_e)->ns_mask & (_ns_mask)) && \ + (((_sm)->options & SMAPOPT_matchAllEntries) || \ + (_pcmpfn)(_pat, (_e)->k.name, \ + (_e)->k.namelen & ~(NAMEnameLenMask|NAMEool)))) + +#define MODE_NONE 0 +#define MODE_READ CACHE_READ +#define MODE_WRITE CACHE_WRITE +#define MODE_UPDATE CACHE_UPDATE + +#define DIRBLKSIZE PAGE_SIZE +#define ZLOG_MAX_BLK_SIZE PAGE_SIZE + +#define DIR_ROOT(_ntree) ((_ntree)->zfsBtree.p.btRoot) +//#define DIR_EOF(_ntree) ((_ntree)->zfsBtree.p.btFree) + +#define BUFblknum volBlk + +#define BEGIN_XACTION(_parms) \ + BeginXLocal((_parms)->ntree->ZFSNAMETREEroot.vol.volume,BXL_DEFAULT) +#define END_XACTION(_xaction) \ + EndXlocal(_xaction) + +#define LATCH_NTREE(_ntree) X_LATCH(&(_ntree)->ZFSNAMETREEbeastLatch) +#define UNLATCH_NTREE(_ntree) UNX_LATCH(&(_ntree)->ZFSNAMETREEbeastLatch) + +#define SET_NTREE_BLK_DIRTY(_buf_) (_buf_)->state |= CACHE_DIRTY + +#define RELEASE_NTREE_BLK(_parms, _buf) \ + (POST_VALIDATE_NTREE_NODE(_parms, (Node_s *)(_buf)->pBuf.data), \ + CACHE_RELEASE(_buf)) + +#define RELEASE_NTREE_BLK_DEBUG(_parms, _buf) \ + RELEASE_NTREE_BLK(_parms, _buf) +#define RELEASE_NTREE_BLK_DEALLOC(_parms, _buf_) \ + CACHE_RELEASE(_buf_) + +#define DEALLOC_NTREE_BLKS(_parms, _nblks, _buf) \ + do { \ + SNINT _i; \ + for (_i = 0; _i < (_nblks); ++ _i) \ + RELEASE_NTREE_BLK_DEALLOC(_parms, (_buf)[_i]); \ + } while (0) + +#define UPGRADE_BUF_LATCH(_parms, _buf, _rc) UP_LATCH(&(_buf)->agent.latch) +#define DOWNGRADE_BUF_LATCH(_parms, _buf) DOWN_LATCH(&(_buf)->agent.latch) + +#if NSS_DEBUG IS_ENABLED +extern STATUS fetch_ntree_blk( + NameTreeParms_s *_parms, + Blknum_t _blk, + Buffer_s **_buf, + Latch_mode_t _mode, + BOOL verify_magic, + NINT _debug_id); +#else +extern STATUS fetch_ntree_blk( + NameTreeParms_s *_parms, + Blknum_t _blk, + Buffer_s **_buf, + Latch_mode_t _mode, + BOOL verify_magic); +#endif + +extern STATUS node_verify_magic( + NameTreeParms_s *parms, + Buffer_s *buf); + +extern STATUS alloc_ntree_blks( + NameTreeParms_s *_parms, + ZfsXaction_s *_xact, + NINT nblks, + Buffer_s **_buf); + +/* Prototypes for naming btree SNINTerface functions to the rest of ZFS */ +extern Zid_t ZFSVOL_VOL_LookupByNameInDirectory( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *directory, + struct NameSpace_s *nameSpace, + NINT nameType, + unicode_t *name, +// cnt NINT nameUniquifier, +// cnt NINT *retNameUniquifier, + struct FullDirectoryInfo_s *retInfo); /* may be null */ + +//extern STATUS ZFSVOL_InitDirectory( +// struct GeneralMsg_s *genMsg, +// struct NamedBeast_s *directory); + +extern NINT ZFSVOL_VOL_IsDirectoryEmpty( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *directory, + NINT nameType); + +extern STATUS ZFSVOL_VOL_AddNameToDirectory( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *beast, + struct NamedBeast_s *directory, + NINT nameSpaceMask, + NINT nameType, + unicode_t *name, + NINT nsFlags, +// cnt NINT nameUniquifier, + NINT addNameFlags, + NINT matchAttributes, + Xaction_s *xaction, + TypeSpecificPersistentParentEntry_s *nameTypeInfo); + +extern STATUS ZFSVOL_VOL_RemoveNameFromDirectory( + struct GeneralMsg_s *genMsg, + Zid_t beastZid, + struct NamedBeast_s *directory, + NINT nameSpaceMask, + NINT nameType, + unicode_t *name, +// cnt NINT nameUniquifier, + NINT removeNameFlags, + Xaction_s *xaction, + TypeSpecificPersistentParentEntry_s *nameTypeInfo); + +extern STATUS ZFSVOL_VOL_ModifyNameSpaceMaskInDirectory( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *beast, + struct NamedBeast_s *directory, + NINT curNameSpaceMask, + NINT nameType, + unicode_t *curName, +// cnt NINT nameUniquifier, + NINT newNameSpaceMask, + Xaction_s *xaction); + +extern STATUS ZFSVOL_VOL_SetMatchAttributesInDirectory( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *beast, + struct NamedBeast_s *directory, + NINT nameSpaceMask, + NINT nameType, + unicode_t *name, +// cnt NINT nameUniquifier, + NINT newMatchAttributes, + Xaction_s *xaction); /* may be NULL */ + +extern Zid_t ZFSVOL_VOL_WildcardLookup( + struct GeneralMsg_s *genMsg, + struct NamedBeast_s *directory, + struct NameSpace_s *nameSpace, + NINT nameType, + unicode_t *pattern, + struct SearchMap_s *smap, +// cnt NINT *retNameUniquifier, + struct FullDirectoryInfo_s *retInfo); /* may be null */ + +extern STATUS ZFSVOL_VOL_FCNTL( + struct GeneralMsg_s *genMsg, + struct Volume_s *volume, + NINT opCode, + FCNTL_In_s *data, + FCNTL_Out_s *retData, /* may be NULL */ + Xaction_s *xaction); /* may be NULL */ + +#endif /* _ZFSDEFS_H_ */ diff --git a/src/nwnss/zlss/zlog.h b/src/nwnss/zlss/zlog.h new file mode 100644 index 0000000..0da1de9 --- /dev/null +++ b/src/nwnss/zlss/zlog.h @@ -0,0 +1,2148 @@ +/**************************************************************************** + | + | (C) Copyright 1996-2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | The ZFS Log (ZLOG) component of ZFS. + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2007-05-08 05:01:53 +0530 (Tue, 08 May 2007) $ + | + | $RCSfile$ + | $Revision: 1979 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Definitions used by ZLOG. + | For detailed information about the ZLOG see the ZLOG Specification. + | + +-------------------------------------------------------------------------*/ +#ifndef _ZLOG_H_ +#define _ZLOG_H_ + +#ifndef _QUE_H_ +# include +#endif + +#ifndef _NCACHE_H_ +# include +#endif + +#ifndef _XACTION_H_ +# include "xaction.h" +#endif + +#ifndef _COMNBEASTS_H_ +# include "comnBeasts.h" +#endif + +#ifndef _ZFSSUPERBLK_H_ +# include "zfsSuperBlk.h" /* Number of checkpoints define */ +#endif + +#ifndef _ZLOGFTEST_H_ +#include "zlogFtest.h" /* Special information to pass to FTEST */ +#endif + + + /* ZLOG_CHECKSUM_LOG_RECORDS is used if we decide to turn off + * checksumming of each ZLOG log record (the whole buffer is + * checksummed also). If we set ZLOG_CHECKSUM_LOG_RECORDS to + * DISABLE then we can NOT turn it back on as there will be + * ZLOG files without checksum (although I am putting zeros + * in the checksum so we could look at it). At this point in + * time Six-Pack I do not fell we need to checksum each + * log record. + */ +#define ZLOG_CHECKSUM_LOG_RECORDS DISABLE /* DISABLE has not been TESTED */ + +/* + * FixFixFix6(Cleanup) Remove #if 0's and 1's. Update comments with spec + * comments. Remove unused/old defines. Remove unused elements. General + * clean-up before release. + */ + + + /* The next three defines are used to specify the ZLOG file size. The + file size is the total file size. Be careful if ZLOG has both original + and duplicate blocks. */ + + +#define ZLOG_FILE_SIZE_FRACTION (50) /* Was 100 in MOAB and COBRA */ + /* ZLOG file size is at least 1/50 (2.0%) of total pool size + * when the pool size <= 3.13GB. Otherwise, the ZLOG file size is + * th greater of 64MB or 12.5/4096 (.296%) of pool size. + * The .296% is a requirement of rebuild (to rebuild the Beast Tree). + * + * Pool sizes when a K is 1024. The table is only valid for + * pools created under 6Pack with the initial sizes given. If space + * is added to a POOL the ZLOG file does NOT grow. + * + * Pool Size Journal Size + * ----------------------------- -------------------- + * Less than 400MB 8MB + * Between 400MB and 3.13GB 2% of Pool Size + * Between 3.13GB and 21.11GB 64MB + * Over 21.1GB .296% of Pool Size + * + */ + +#define ZLOG_REBUILD_BYTES_PER_BLOCK (96+1)/(8) + /* Don't add () because need left to right multiplication + * so not to get massive rounding errors. + * ZLOG file size is 12.5/4096 (.296%) of total pool size. + * 1 bit per block for crossed linked blocks. + * 96 bits (12 bytes) per block for beast tree branch repair. + */ +#define ZLOG_REBUILD_FUDGE_BLOCKS 2 /* Number of extra blocks that the + * rebuild needs because it divides + * the file into two sections each + * on 4k boundary. + */ + +#define ZLOG_FILE_SIZE_MINIMUM (1024*4096uL) +#define ZLOG_FILE_SIZE_MINIMUM_AT_CREATE (2048*4096uL) /* Not in MOAB/COBRA */ + /* Minimum size if 4 Meg because that was the minimum in + * MOAB and COBRA. For Six-Pack the minimum size was + * double to 8 Megs. This was done as 4 Meg is a pretty small + * ZLOG file. Added the define ZLOG_FILE_SIZE_MINIMUM_AT_CREATE + * because we do not grow MOAB/COBRA zlog files so ASSERTS + * and the likes still need the 4 Meg value. + */ + +#define ZLOG_FILE_SIZE_CROSS_OVER (4*4096*4096uL) /* No 4 in MOAB/COBRA */ + /* The cross over point is where ZLOG is happy with the size + * of the ZLOG file, but if because of the beast tree rebuild + * requirements (.296% of disk space) rebuild needs more space + * then ZLOG is not going to complain if this space is ADDED + * to the ZLOG file. + */ + + /* + * Maximum number of homed transactions (ones with log records) that + * will occur before a checkpoint is taken. + */ +#define ZLOG_CHECKPOINT_HOMED_TRANSACTIONS_MAXIMUM 500 + /* Maximum number of blocks to fill in before a checkpoint is taken */ +#define ZLOG_CHECKPOINT_BLOCK_FILLED_IN_MAXIMUM 500 + /* + * Percent of ZLOG file that must be in use before going into the + * respective throttle. The throttle full percent is used to + * indicate when we should leave throttle back mode and enter throttle + * full. Throttle full means we are NOT delaying anyone. The throttle + * back percent is used to indicate when we should start throttling + * back transactions. This number must be >= the throttle full + * percent. + */ +#define ZLOG_THROTTLE_BACK_PERCENT 50 /* If the number of in use blocks + * is >= to this percent of total + * zlog blocks then we enter + * throttle back mode and start + * delaying new common layer + * transactions. + */ +#define ZLOG_THROTTLE_FULL_PERCENT 50 /* If in use is less than we + * are in throttle full mode. DO + * NOT SET TO 0. Should not be set to + * less than 25 because the number + * of checkpoints writes will start + * slowing down the system. + */ + /* + * Minimum number of checkpoints to take per pass through ZLOG file. + * This number must be high enough that we that we take six checkpoints + * before the throttle full point in the file. Otherwise, we will stay + * in throttle back mode longer than needed. If throttle full is + * 50% then the following define equals 12. + */ +#define ZLOG_CHECKPOINTS_BEFORE_WARP_MINIMUM(_percent) \ + (((6*1000/(_percent))+9)/10) + + /* + * Number of millisecs to delay between each check of if a ZLOG + * scheduled checkpoint has completed, This is only used in shutdown. + */ +#define ZLOG_WORK_CHECKPOINT_WAIT_DELAY 20 + + /* + * Number of millisecs to delay between each check of if the ZLOG + * buffer flush has completed, This is only used in shutdown. + */ +#define ZLOG_WORK_FLUSH_WAIT_DELAY 100 + + + /* + * Set ZLOG_USE_SYSTEMS_WORK_TO_DO to TRUE if async checkpoints + * should directly use ScheduleWork(). Set to FALSE if async + * checkpoints should use WORK_Schedule(). The WORK_Schedule() + * routine limits the number of work-to-do threads that NSS uses. + * + * September 18, 1997 - We are going with ScheduleWork() because + * on MOAB running a lot of PFM tests checkpoints would not be + * scheduled for 10+ minutes. + */ +#define ZLOG_USE_SYSTEMS_WORK_TO_DO TRUE + + + +#define ZLOG_HISTOGRAM_EVENT( _histogram, _event ) \ + zlog_HistogramEvent( (_histogram), (_event) ) + +typedef struct ZlogHistogramPersistent_s +{ + QUAD ZHP_CurrentEvent; /* Current event */ + QUAD ZHP_EventCount; /* Total number of events */ +} NSS_MEDIA_STRUCTURE(ZlogHistogramPersistent_s,ZHP_EventCount) ZlogHistogramPersistent_s; + + +typedef struct ZlogHistogram_s +{ + LONG ZH_BucketCount; /* Number of buckets */ + LONG ZH_BucketSize; /* Number of events a bucket holds */ + LONG ZH_Flags; /* Flags as follows */ +#define ZH_F_LONG 0x0001 /* Track with LONGs */ +#define ZH_F_QUAD 0x0002 /* Track with QUADs */ + ZlogHistogramPersistent_s *ZH_P; + void *ZH_Bucket; /* Pointer to bucket area (buckets are persistent)*/ +} ZlogHistogram_s; + + + +#define ZLOG_HISTORY_EVENT( _histogram, _event ) \ + zlog_HistoryEvent( (_histogram), (_event) ) + + +typedef struct ZlogHighWatermarkSlot_s +{ + Time_t ZHWB_Time; + QUAD ZHWB_Event; +} NSS_MEDIA_STRUCTURE(ZlogHighWatermarkSlot_s,ZHWB_Event) ZlogHighWatermarkSlot_s; + +typedef struct ZlogHistory_s +{ + LONG ZH_WatermarkCount; /* # of high watermark slots */ + ZlogHighWatermarkSlot_s *ZH_Slots; +} ZlogHistory_s; + + + +#define ZLOG_COUNT_INIT( _count, _value ) \ + { \ + (_count)->ZC_Count = _value; \ + (_count)->ZC_CountTime = GetUTCTime(); \ + (_count)->ZC_CountResetTime = (_count)->ZC_CountTime; \ + } + +typedef struct ZlogCounts_s +{ + QUAD ZC_Count; /* The count */ + Time_t ZC_CountTime; /* When the count was recorded */ + Time_t ZC_CountResetTime; /* When the count was last reset */ +} ZlogCounts_s; + +/* + * + * struct ZlogZfsAsyncio_s + * + * This structure is included within the ZioLog_s structure that can + * be found in zfsasyncio.h. + * + * The elements in this structure should not be referenced directly + * because their locations may change. Use the defines located + * after the structure definition. + * + */ + +#if 0 +typedef struct ZlogZfsAsyncio_s { +#if ZLOG_TEST IS_ENABLED + NINT ZZA_logRecordsLeft; + /* Used by unit test code to randomly generate different + * number of log records within a transactions. + */ + NINT ZZA_bufferLength; + /* Used by unit test code. Amount of data space + * required by caller of ZLOG_ObtainRecord() in BYTEs. + */ +#else + NINT ZAA_happy; + /* Keep the compiler happy by having a dummy element. */ +#endif +} ZlogZfsAsyncio_s; + + /* + * Below are the defines to use when referencing ZLOG specific + * ZFS Asynchronous I/O items. They must be combined with + * a pointer to a ZfsAsyncio_s structure. For example. + * + * ZfsAsyncio_s *zio; + * Lsn_t myLsn; + * + * zio->ZLOG_ZaTransactionState = XAS_XR_TS_START; + * myLsn = zio->ZLOG_ZaLsn; + * + */ + + /* + * Internal direct references - these are undocumented elements that + * reside within ZlogZfsAsyncio_s. + */ + +#define ZLOG_zaBuffer zza.ZZA_buffer + + /* Public direct references - the are documented elements that + * reside within ZlogZfsAsyncio_s. + */ + +#define ZLOG_ZaBufferLength zza.ZZA_bufferLength +//#define ZLOG_ZaZfsXasRecovery zza.ZZA_zfsXasRecovery +#define ZLOG_ZaZlogXas xaction +#define ZLOG_ZaTransactionState xaction->xstate +#define ZLOG_ZaHomeBond zza.ZZA_homeBond + + /* Public indirect references - these are documented elements that + * do not reside within ZlogZfsAsyncio_s. + */ + +#define ZLOG_ZaCommitAgent ZLOG_zaBuffer->agent + /* Output. ZLOG's Commit Agent used by callers to bind + * with ZLOG. ZLOG will use to signal that the log + * block has been flushed. Commit agent used to bind the log + * block to a transaction so that the transaction can be + * signaled when the log block has been flushed. This + * indicates to the transaction that it has been committed. + * Note that technically, ZLOG does not care what it's commit + * agent is bond to. A signal will be sent to whoever is + * bond to the log block when the block is written + * (committed). The PLB_CommitAgent is actually stored + * in the agent that is in the Buffer_s structure. + */ +#define ZLOG_ZaLsn ZLB_ZfsXasRecovery->ZXR_Lsn + /* Output. LSN of log record. This points into the + * log record header location that stores the LSN. The + * define will unpack the value if it is required. + */ + + /* Internal direct references - these are undocumented elements that + * reside within ZlogZfsAsyncio_s. + */ + +#define ZLOG_zaTransactionId io.xaction->localXid + /* Transaction ID of data owner. The transaction + * ID is obtained from the Transaction System. This is in the + * XAS structure. ZLOG uses to fill in the log record header. + */ +#define ZLOG_zaLogRecordsLeft zza.ZZA_logRecordsLeft + /* Unit test code uses. */ +#endif /* #if 0 */ + +/* + * Pool Log's block header. + * This structure is documented in the ZLOG Specification. + * + * The packed size of this structure must be on a QUAD boundary. + * + */ + +typedef struct ZLOGBlockHeader_s { +// +// ZLBH_VolumeID at OFFSET 16 must stay there!!! +// + LONG ZLBH_Signature; + /* Signature that identifies this as a pool log file + * header of a pool log block. Can be used by zrepair + * and debug/ASSERT. The signature is 'ZLBH'. + */ + LONG ZLBH_Checksum; + /* Checksum for the pool log block header and + * all of the log records. Does not include unused longs + * at the end of the log block. + */ + Time_t ZLBH_TimeStart; + /* When block started to be used. Right after + * we obtain the buffer. + */ + Time_t ZLBH_TimeEnd; + /* Right before checksum calculated. Which occurs + * right before we tell system to write the log + * block. Note that we do not know when the actual + * write occurs. + */ + GUID_t ZLBH_InternalID; + /* MUST BE AT OFFSET 16 - Internal ID of the volume + * that 'owns' this metadata. Because ZLOG is only + * in a POOL this is the Internal ID of the ZfsPool_s + * beast. + */ + WORD ZLBH_NumberOfUnusedLongs; + /* Number of LONGs left at end of block. Used while + * in memory to see if have room for a new log record. + * Placed on disk for debugging. + */ + WORD ZLBH_NumberOfRecords; + /* Number of log records in the block. */ + WORD ZLBH_Status; + /* Why block was written. + * ZLBH_S_TOOBIG - Next record too big. + * ZLBH_S_TIMEOUT - Time-out occurred. + * ZLBH_S_SHUTDOWN - Shutdown wrote. + * ZLBH_S_CHECKPOINT - Checkpoint wrote. + * ZLBH_S_INSTALL - Install created. + * Are Log Record time values meaningful? + * ZLBH_S_DEBUG - Yes. + */ + WORD ZLBH_Reserved; + /* Used to make sizeof our structure a QUAD value */ + LONG ZLBH_RebuildCount; + /* Pool's rebuilt count when the block was written. + * This is used to determine if a ZLOG block is old. + * This was added, Feb 1998, so that ReBuild does not + * have to initialize all the ZLOG blocks. Note this + * became an issue because ZLOG no longer needs to + * initialize blocks because the GUID is unigue. In + * addition when we added the ReBuild beast tree .296% + * of pool needs to be reserved to the ZLOG we really + * did not want to spend time initializing the ZLOG + * when a pool was created. + */ + LONG ZLBH_FileBlockNumber; + /* Debug - File block number (low LONG portion) */ + /* Keep us on a QUAD alignment */ +} NSS_MEDIA_STRUCTURE(ZLOGBlockHeader_s,ZLBH_FileBlockNumber) ZLOGBlockHeader_s; + +/* Defines used in Pool Log Block Header elements. */ + + /* ZLBH_Signature value */ +#define ZLBH_S_SIGNATURE (0x48424c5AuL) /* 'ZLBH' on Little Endian */ + + /* ZLBH_Status values */ + + /* The first five defines are mutually exclusive and indicate + * why a log block was written (what code wrote). + */ +#define ZLBH_S_TOOBIG 0x0001 /* Debug */ +//#define ZLBH_S_TIMEOUT 0x0002 /* Debug */ +//#define ZLBH_S_SHUTDOWN 0x0004 /* Debug */ +//#define ZLBH_S_CHECKPOINT 0x0008 /* Debug */ +#define ZLBH_S_INSTALL 0x0010 /* Required. */ +#define ZLBH_S_TIME_OR_BOND 0x0020 /* Debug */ +#define ZLBH_S_CHECKSUM 0x0040 /* Required - checksum not calculated. + * FixFixFix6(Future,If reading ZLOG file + * supported) - This bit is not + * implemented or in spec at this time. It + * would be needed so that reader knows + * that the log buffer's checksum has + * not been calculated because we are + * not done filling it in. OR we could + * cause it to be flushed and checksummed + * when user wishes to read it. + */ +#if ZLOG_DEBUG IS_ENABLED +#define ZLBH_S_DEBUG 0x0100 /* Required. Debug fields of block and + * log headers are valid. Do not change + * this bit mask dumpzlog uses hard + * coded 0x0100. + */ +#else +#define ZLBH_S_DEBUG 0x0000 +#endif + + +/* + * *** Special Notes *** + * + * ZFS's ZLOG stores this data structure directly into its log file. + * To accomplish this ZLOG makes two major assumptions about this + * structure. + * + * 1) ZLOG assumes that these items are hand packed. If you change + * this structure so that it can not be stored in a processor + * independent way then you must change ZLOG. + * + * 2) ZLOG also assumes the size of this structure. It has asserts + * to verify this size. If you keep this structure on a QUAD + * size then ZLOG will be ok. Otherwise, ZfsXasRecovery_s and/or + * ZLOGRecordHeader_s may need padding added or removed. + * + */ + +typedef struct ZfsXasRecovery_s { + Lsn_t ZXR_Lsn; + /* + * Log Sequence Number. This number does not ever + * wrap (it does but it takes ~586 years when incremented + * once every nanosecond). The LSN needs to be this + * big for users of ZLOG and not ZLOG itself. The users + * of ZLOG will be storing LSN into metadata blocks to + * make these blocks idempotent. So even if the LSN is not + * currently in the log file we must ensure that we do + * not reuse a LSN. + */ + LocalXid_t ZXR_LocalXid; /* Transaction ID. */ + LONG ZXR_FunctionIndex; /* Function index */ + WORD ZXR_TransactionState; + /* + * State of transaction. + * XAS_XR_TS_START + * XAS_XR_TS_MIDDLE + * XAS_XR_TS_END + */ + WORD ZXR_PoolBlockCount; +// BYTE ZXR_Padding[0]; + /* + * Because the next item may have 0 items we do not actually include + * in our definition. In addition, the user must ask ZLOG_ObtainRecord + * for the space in the log file to handle the number of BlockInfo_s that + * they need. + */ +// BlockInfo_s ZXR_BlockInfo[ZXR_PoolBlockCount] + +} NSS_MEDIA_STRUCTURE(ZfsXasRecovery_s,ZXR_PoolBlockCount) ZfsXasRecovery_s; + + +/* + * + * Pool Log's record header. + * This structure is documented in the ZLOG Specification. + * + * The packed size of this structure must be on a QUAD boundary. + * + */ + + +typedef struct ZLOGRecordHeader_s { + + /**** The following items are ZLOG specific. Only ZLOG + * can access. + */ + + LONG ZLRH_Checksum; + /* Calculated after ZLOG caller has filled in data + * portion of log record. Checksum is for log header + * and data portion. Checksum is valid if the block + * contents (including this field) add up to zero. Use + * zlog_CalculateChecksum() to perform checksumming. + */ + LONG ZLRH_StartTime; + /* Debug. When ZLOG_ObtainRecord() was called. This + * time is in 100s of microseconds. Is not relative + * to anything. + */ + LONG ZLRH_EndTime; + /* Debug. When ZLOG_RecordFilledIn() was called. Used + * with StartTime to verify callers of ZLOG are not + * holding records too long. We have specified a 1/2 + * second maximum hold time. + */ + WORD ZLRH_LongLength; + /* Number of packed LONGs in this record. This + * length includes the log record header LONG length. + */ + BYTE ZLRH_Reserved1[2]; /* Get structure aligned again */ + + /**** The following items are ZFS/XAS specific. They are + * given to XAS at recovery time (XAS will give + * to ZFS). ZLOG assumes that it does not have + * to pack/unpack these items. A pointer to + * this is also return from ZLOG_ObtainRecord() so + * that the caller can access needed information. + ****/ + + ZfsXasRecovery_s ZLRH_Zxr; + /* ZFS and ZAS specific items. ZLOG has no real + * interest in these items, but it is required to + * fill them in when logging and return them on recovery. + * It is documented that the user data portion of the + * log record start immediatily after this element. + */ + /*** Do not add items here. Read above comment ***/ +} NSS_MEDIA_STRUCTURE(ZLOGRecordHeader_s,ZLRH_Zxr) ZLOGRecordHeader_s; + + + + +typedef struct LogTest_s { + Buffer_s *LT_Buffer; + void *LT_Copy; +} LogTest_s; + + + + /* The 128 is for future growth in the headers. By + * substracting off 128 the define size will not change though + * numerous ZFS releases. This should make life easier on us. + * Currently, we need 72 bytes for our two required headers. This + * gives us 56 bytes of growth. Our constructor has ASSERT code + * to note when actual required size is smaller than published + * required size. + */ + + /* Documented in ZLOG specification. */ +#define ZLOG_MAXIMUM_RECORD_SIZE (4096 - 128) + /* Internal actual record size. */ +#define zlog_MAXIMUM_RECORD_SIZE ( 4096 - sizeof(ZLOGBlockHeader_s) - \ + sizeof(ZLOGRecordHeader_s) ) + +/*=========================================================================== + *=========================================================================== + * + * ZLSS LOG(ZLOG) Beast Definition + * + *=========================================================================== + *===========================================================================*/ + + /* These are all of ZLOG specific persistent items within a ZLOG Beast. + * The items should be fixed size (e.g. don't declare as a int), but they + * can be stored in native format. + */ + + /* This structure helps in determining the length of persistent + * data in our beast. It also makes the coder aware of exactly + * what items are persistent and which are not. + */ + + /* Warning - This is a persistent data structure. If you change it + * in a way that makes it incompatible with older systems you must + * update the media version in the superblock OR the major version number + * of the checkpoint. You should also update the major version number + * of the ZLOG Beast below. + */ + + +typedef struct ZlogBeastPersistent_s { + LONG ZLBP_Signature2; + /* Signature that identifies this is a log file header + * of a pool log block. Can be used by zrepair and + * debug/ASSERT. The signature is 'ZLOG' on Little + * Endian CPUs. + */ + WORD ZLBP_VersionMajor; + /* The major version of the pool log file. Changes when + * ZLOG is no longer compatible with an older version + * of the pool log file. The first release will have this + * set to 1. When changing see if ZLBP_Reserved should + * be changed. + */ + WORD ZLBP_VersionMinor; + /* The minor version of the pool log file. Changes when + * old ZFS are still compatible. This will be 0 in the + * first release. + */ + LONG ZLBP_ZSTOREMajorVersion; + LONG ZLBP_ZSTOREMinorVersion; + LONG ZLBP_ZSTORESubVersion; + LONG ZLBP_ZSTOREBuildNumber; + /* The above four items hold values of the current running + * ZSTORE system. By storing them in the ZLOG they will be + * made persistent in the checkpoint. Currently, only used + * by Novell internal ZAD (ZLOG Analysis Dumper) utility. + */ + Lsn_t ZLBP_ActivePointerLsn; + /* Can never be zero or wrap. During Logging this + * LSN is the next LSN to assign to a log record. + * + * During + * Recovery this value is used to verify if log records + * where written after a checkpoint was taken. Recovery + * figures out the current value of this LSN by scanning + * the log and adding a fudge factor. See ZLOG + * specification for more information. + */ + Lsn_t ZLBP_HomePointerLsn; + /* Current home pointer LSN. Indicates what LSNs + * have made it to home. LSN numbers LESS THAN this value + * have had their transactions homed. This value is used + * to quickly see + * if recovery is needed. When ZLBP_ActivePointerLSN + * equals ZLBP_HomePointerLSN we took a clean checkpoint. + * Note - taking a clean checkpoint does not mean that there + * is no recovery to be done. ZLBP_HomePointerLSN is + * compared with the LSN of the first record of the + * ZLBP_HomePointerBlockNumber to see if recovery is + * needed. If we did not store this value we would have + * to read the block before ZLBP_HomePointerBlockNumber + * so we could retrieve the highest LSN in that block. We + * would then add one to that value to get + * ZLBP_HomePointerLsn. We do not do this because of + * performance and code simplification reasons. + */ + Lsn_t ZLBP_OldHomePointerLsn[CHECKPOINT_NUMBER]; + Blknum_t ZLBP_FileThrottleFull; /* Use NSS_LOCK to protect */ + /* Number of in use blocks that we switch from + * ZLOG_THROTTLE_BACK into ZLOG_THROTTLE_FULL mode. This + * number is set using ZLBP_FileThrottleFullPercent. In + * persistent area for debug only. + */ + Blknum_t ZLBP_FileThrottleBack; /* Use NSS_LOCK to protect */ + /* Number of in use blocks that we switch from + * ZLOG_THROTTLE_FULL into ZLOG_THROTTLE_BACK mode. this + * number is set by ZLBP_FileThrottleBackPercent. + */ + QUAD ZLBP_FileThrottleWaitCount; /* Use NSS_LOCK to protect */ + /* Accounting. Number of times we delayed a BeginXLocal + * when in ZLOG_THROTTLE_BACK mode. + */ + QUAD ZLBP_FileThrottleWait1Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_FileThrottleWait2Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_FileThrottleWait3Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_FileThrottleWait4Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_FileThrottleWait5Count; /* Use NSS_LOCK to protect */ + /* Accounting. Number of times we delayed a BeginXLocal + * by a specific amount when in ZLOG_THROTTLE_BACK mode. + */ + QUAD ZLBP_FileThrottleFullCount; /* Use NSS_LOCK to protect */ + /* Accounting. Number of times we left ZLOG_THROTTLE_BACK + * mode and went back to ZLOG_THROTTLE_FULL. Should be + * equal to ZLB_FileThrottleBackCount when mode is + * ZLOG_THROTTLE_FULL. Otherwise, should be one less than + * ZLB_FileThrottleBackCount. + */ + QUAD ZLBP_FileThrottleCheckpointCount; /* Use NSS_LOCK to protect */ + /* Accounting. Number of checkpoints taken while + * in ZLOG_THROTTLE_BACK mode. + */ + QUAD ZLBP_FileThrottleSkipCount; /* Use NSS_LOCK to protect */ + /* Accounting(debug systems only). Number of times we let + * an obtain pass through when in ZLOG_THROTTLE_BACK mode. + */ + QUAD ZLBP_FileThrottleBackCount; /* Use NSS_LOCK to protect */ + /* Accounting. Number of times that we had to throttle + * back. Note that one throttle back can cause many + * obtains to have to 'wait'. + */ + Time_t ZLBP_FileThrottleTimeStart; /* Use NSS_LOCK to protect */ + /* UTC time of last time ZLOG went into throttle + * back mode. If we have never been in throttle back + * mode then this time is 0. + */ + Time_t ZLBP_FileThrottleTimeEnd; /* Use NSS_LOCK to protect */ + /* UTC time of last time ZLOG went into throttle + * full mode from throttle back mode. Note if we never + * have been in throotle back mode then this time is 0. + */ + Blknum_t ZLBP_OldHomePointerBlockNumber[CHECKPOINT_NUMBER]; + Blknum_t ZLBP_ActivePointerBlockNumber; + /* Logical number of current buffer/block. This is + * always the original block number which is even all of + * the time. The first logical block number of the pool + * log file is 0. This is the lowest block number + * that we have not tried to write. + * + * During Recovery this + * value is used to start the scan for the current + * active pointer. Recovery sets this value before it + * completes to the current active pointer. + */ + Blknum_t ZLBP_HomePointerBlockNumber; + /* Current home pointer block number. Indicates what + * has made it to home. Block numbers LESS THAN this value + * have had all of their transactions homed. + * + * During Recovery this + * value is used to start the scan for the current + * active pointer. Recovery sets this value before it + * completes to the current active pointer. + */ + Blknum_t ZLBP_PreOldestHomePointerBlockNumber; + /* This will be one before the oldest home pointer. This + * solves the headache of detecting empty verses full. I.E. + * the only time oldest home and active pointer are + * the same is when the file is one block from being + * full (we will say the file is full at this point). + * The pre block to block 0 is NOT -1 it is the last + * original block in the file! + */ + Time_t ZLBP_TimeActivation; + /* UTC of last activation of the pool */ + Time_t ZLBP_TimeDeactivation; + /* UTC of last deactivation of the pool */ + Time_t ZLBP_TimePoolCreate; + /* UTC of when the pool was created */ + LONG ZLBP_RecoveryRecoverCount; + /* Number of times recovery performed. */ + LONG ZLBP_RecoveryActivationCount; + /* Number of times we checked if recovery needed. */ +#if 0 + LONG ZLBP_LastRecoveryStatus; + /* Error code from last recovery. This is always zOK + * because on activation errors we do not write the + * checkpoints(i.e. ZLOG beast) + */ +#endif + Time_t ZLBP_LastRecoveryTimeStart; /* Date/Time that last recovery + * started. + */ + Time_t ZLBP_LastRecoveryTimeEnd; /* Date/Time that last recovery + * ended. + */ + LONG ZLBP_LastRecoveryActivationCount; + /* The ActivationCount value when + * recovery was performed. + */ + WORD ZLBP_Mode; + /* Current mode. This is a persistent item currently + * so ZAD can view. BEWARE that our unpack routine + * sets the persistent copy of this item to + * ZLOG_MODE_DEFAULT! This is important for the + * THROTTLE specific item, but may be wrong for other + * items added in the future. + * + * THROTTLE specific + * BACK means that the ZLOG file is getting too full + * so we are backing off on the number of + * transactions that are being allowed to + * obtain log records. The design here is to + * let transactions that are already started + * to home. New transaction will be delayed. + */ +#define ZLOG_MODE_DEFAULT 0 /* Default for when pool is initialize + * and when unpacked! + */ +#define ZLOG_THROTTLE_BACK 1 /* Let current transactions home */ + + WORD ZLBP_FileVersion; + /* Used to see if the ZLOG File format has changed + * (I.E. ZLOG's block header, record header, the + * block info or any beast specific information). If the + * format has changed and we need to do a recovery then + * ZLOG will fail the recovery. The user can then run an + * old nss.nlm to get a clean shutdown and then re-run + * the new nss.nlm. By having this file version the + * user can do the above verses being forced to do a + * /reset to the pool. + * Note this variable only works on the ZLOG file + * and NOT the ZLOG Beast. If the beast changes + * then the checkpoint changes and we still must + * force the user to do a /reset. Note we could modify + * the checkpoint code to allow for in place checkpoint + * update. An error will occur when this number does not + * match ZLOG_ZLBP_FV_VERSION during recovery. + */ + BYTE ZLBP_FileThrottleFullPercent; + /* Percent that the file must be at to exit BACK mode + * and to enter FULL mode. In persistent area so + * utilities can set. Does not address setting while + * pool is up. + */ + BYTE ZLBP_FileThrottleBackPercent; + /* Percent that the file must be at to exit FULL mode + * and to enter BACK mode. In persistent area so + * utilities can set. Does not address setting while + * pool is up. + */ + BYTE ZLBP_Padding[6]; + /* Our persistent items are required to be on a QUAD + * boundary so add some padding. Our constructor has + * ASSERT code to verify that this is correct. + */ + +/*** + *** This is the point that version 4.0 differs from version 1.0. + *** + ***/ + /* + * The following items are all instrucmentation items. The current + * view is that they add very little overhead to the system + * therefore we will not compile out of the production system. + */ + + /* + * The Reference Block Count histogram tracks the number of + * blocks that are referenced by the log records that would + * have to be played if we crashed immediately before + * writing the current checkpoint. This item is updated + * when we write a checkpoint. + */ + QUAD ZLBP_PreHomePointerReferenceBlockCount; + QUAD ZLBP_HomePointerReferenceBlockCount; + QUAD ZLBP_ActivePointerReferenceBlockCount; +// ZlogHistory_s ZLBP_ReferenceBlockCountHistory; + ZlogHighWatermarkSlot_s ZLBP_ReferenceBlockCountHistorySlots[10]; +// ZlogHistogram_s ZLBP_ReferenceBlockCountHistogram; + ZlogHistogramPersistent_s ZLBP_ReferenceBlockCountHistogramPersistent; + QUAD ZLBP_ReferenceBlockCountBucket[10]; +#define ZLOG_RBCB_BUCKET_SIZE (4000) +#define ZLOG_RBCB_BUCKET_TYPE ZH_F_QUAD + /* + * The Function histogram tracks the number of time each + * redo/undo function index is used in a log record. This + * could be a debug only item as it has limited use in + * viewing in a end-user system. + */ + ZlogHistogramPersistent_s ZLBP_FunctionHistogramPersistent; + QUAD ZLBP_FunctionBucket[50+85]; +#define ZLOG_FB_BUCKET_SIZE 1 +#define ZLOG_FB_BUCKET_TYPE ZH_F_QUAD + /* The Size histogram tracks the sizes of all log records. The + * size tracked is the total log record size (header, block + * info and user specific info) rounded to a 8 byte bondary. + */ + ZlogHistogramPersistent_s ZLBP_SizeHistogramPersistent; + QUAD ZLBP_SizeBucket[8]; +#define ZLOG_SB_BUCKET_SIZE (512) +#define ZLOG_SB_BUCKET_TYPE ZH_F_QUAD + /* + * The Block In-use Count histogram tracks the block size of the + * in-use portion of the ZLOG file. By looking at the high + * watermarks of this histogram one can determine if the ZLOG + * file is too small. NSS does not handle the ZLOG file becoming + * full. + */ +// ZlogHistory_s ZLBP_BlockInuseCountHistory; + ZlogHighWatermarkSlot_s ZLBP_BlockInuseCountHistorySlots[10]; + ZlogHistogramPersistent_s ZLBP_BlockInuseCountHistogramPersistent; +// ZlogHistogram_s ZLBP_BlockInuseCountHistogram; + LONG ZLBP_BlockInuseCountBucket[12]; +#define ZLOG_BICB_BUCKET_SIZE (1000) +#define ZLOG_BICB_BUCKET_TYPE ZH_F_LONG + /* + * The Recovery Time histogram tracks the time it took to + * do recovery. The time does not include runnning the + * Purge Log. + */ +// ZlogHistory_s ZLBP_RecoveryTimeHistory; + ZlogHighWatermarkSlot_s ZLBP_RecoveryTimeHistorySlots[10]; +// ZlogHistogram_s ZLBP_RecoveryTimeHistogram; + ZlogHistogramPersistent_s ZLBP_RecoveryTimeHistogramPersistent; + Time_t ZLBP_RecoveryTimeBucket[4]; +#define ZLOG_RTB_BUCKET_SIZE (30) +#define ZLOG_RTB_BUCKET_TYPE ZH_F_LONG + /* + * The Out-of-order Writes histogram tracks the number of + * out-of-order blocks we have when an out-of-order write + * occurs. + */ +// ZlogHistory_s ZLBP_DeferredWritesHistory; + ZlogHighWatermarkSlot_s ZLBP_DeferredWritesHistorySlots[10]; +// ZlogHistogram_s ZLBP_DeferredWritesHistogram; + ZlogHistogramPersistent_s ZLBP_DeferredWritesHistogramPersistent; + QUAD ZLBP_DeferredWritesBucket[5]; +#define ZLOG_DWB_BUCKET_SIZE 10 +#define ZLOG_DWB_BUCKET_TYPE ZH_F_QUAD + + /* + * The Recovery History histogram tracks when we did + * recoveries. We track 16 instead of the normal 10 + * and do not have any buckets. + */ +// ZlogHistogram20_s ZLBP_RecoveryUTCHistory; + /* + * The Recovery History histogram tracks when we did + * recoveries. We track 16 instead of the normal 10 + * and do not have any buckets. + */ +// ZlogHistogram20_s ZLBP_PendingIOHighHistory; + /* + * The highest 16 pending I/Os. + */ +// ZlogHistogram20_s ZLBP_RebuildUTCHistory; + +// ZlogHistory_s ZLBP_History[4]; +#define ZLOG_HISTORY_SLOTS 16 + ZlogHighWatermarkSlot_s ZLBP_HistorySlots[4*ZLOG_HISTORY_SLOTS]; +#define ZH16_RECOVERY_UTC 0 +#define ZH16_REBUILD_UTC 1 +#define ZH16_PENDING_IO_HIGH 2 /* Not implemented */ +#define ZH16_LAST_USED 2 /* The index of the last used element + * in the ZLBP_History arrary. + */ + +// ZlogCounts_s ZLBP_Count[6]; +//#define ZC_IO_READS 0 /* Not implemented */ +//#define ZC_IO_WRITES 1 /* Not implemented */ +//#define ZC_IO_CACHE_HITS 2 /* Not implemented */ +//#define ZC_IO_CACHE_MISS 3 /* Not implemented */ +//#define ZC_LAST_USED 3 + /* The index of the last used element + * in the ZLBP_Counts arrary. + */ + +/*** + *** + ***/ + + Lsn_t ZLBP_CompensationPtrLsn; + /* This is the LSN value where the compensation records + * begin. It is NULL initially and once we are done + * writing compensation records and they have been + * flushed to disk + */ + Lsn_t ZLBP_LogicalUndoPtrLsn; + /* The logical undo records are copies of the original + * undo records. They have newer LSNs. This is the + * LSN where the Logical Undo records begin. + */ + Blknum_t ZLBP_CompensationPtrBlkNum; + /* This is the blknum which has the first compensation + * record. + */ + Blknum_t ZLBP_LogicalUndoPtrBlkNum; + /* The block number that points to the first + * Logical Undo record. + */ + PoolReadStatistics_s ZLBP_StatisticsRead; + PoolWriteStatistics_s ZLBP_StatisticsWrite; + /* Numerous persistent statistics about physical I/O + * to this pool. Vandana and I decided to store in + * ZLOG as a cheap way of making persistent. ZLOG + * is written to all of the time (unless no changes + * to pool occuring. + * + * Note that their is some reserved space in the + * PoolWriteStatistics_s and PoolReadStatistics_s + * structures that can be used for new counters. + */ + QUAD ZLBP_Reserved[12]; + /* This space is reserved for use of minor changes + * to the ZLOG Beast. When changing major version number + * increase the size of this back to 10. + */ + + LONG ZLBP_Signature; + /* Signature that identifies this is a log file header + * of a pool log block. The signature is 'ZLOG' on Little + * Endian CPUs. This signature is the one that ZAD + * verifies while running. Because it is at the end + * of the persistent area ZAD can detect more changes + * than the signature at the beginning of the persistent + * area. During development the version numbers we + * have set up do not tend to get updated everytime a + * change is made. ZAD uses this signature to catch + * these changes so that ZAD can be re-compiled. + */ + LONG ZLBP_StatisticsResetUTCTime; + /* When the read and write statistics where last set + * to zero. + */ +// LONG ZLBP_Pad2; /* QUAD alignment */ +} NSS_MEDIA_STRUCTURE(ZlogBeastPersistent_s,ZLBP_StatisticsResetUTCTime) ZlogBeastPersistent_s; + + +#define ZLOG_ZLBP_S_SIGNATURE (0x474f4c5auL) /* 'ZLOG' on Little Endian */ +#define ZLOG_ZLBP_VM_MAJOR 4 /* Version 2 & 3 have been skipped + * just in case MOAB/Corba needs. + */ +#define ZLOG_ZLBP_VM_MINOR 0 + + /* ZLBP_FileVersion value. */ +#define ZLOG_ZLBP_FV_VERSION 5 /* + * Update this value if the ZLOG File + * changes. E.G. if the ZLOG Beast's + * block header or record header change + * and you do not wish to require the user + * to /reset their pool then add one to + * this define. You can also + * update this value if the block + * information structure or any of the + * beast specific information changes + * in the ZLOG File Format. See the + * ZLOG Physical File Format diagram + * in the ZLOG Specification for a diagram + * of the items that can change the + * ZLOG file. + */ + + + + + + +/*** DO not modify ANY of the _1Dot1_ structures as they + *** MUST be defined as they were in MOAB/COBRA release + *** of ZLSS. + ***/ + +#define ZLOG_HWB_DEFAULT_1Dot0 10 + +typedef struct ZlogHighWatermarkBucket_1Dot0_s +{ + QUAD ZHWB_1Dot0_Event; + Time_t ZHWB_1Dot0_Time; + LONG ZHWB_1Dot0_Padding[1]; +} NSS_MEDIA_STRUCTURE(ZlogHighWatermarkBucket_1Dot0_s,ZHWB_1Dot0_Padding[1]) ZlogHighWatermarkBucket_1Dot0_s; + +typedef struct ZlogHighWatermark_1Dot0_s +{ + ZlogHighWatermarkBucket_1Dot0_s ZHW_1Dot0_Bucket[ZLOG_HWB_DEFAULT_1Dot0]; +} NSS_MEDIA_STRUCTURE(ZlogHighWatermark_1Dot0_s,ZHW_1Dot0_Bucket[ZLOG_HWB_DEFAULT_1Dot0]) ZlogHighWatermark_1Dot0_s; + +typedef struct ZlogHistogram_1Dot0_s +{ + ZlogHighWatermark_1Dot0_s ZH_1Dot0_Watermarks; + QUAD ZH_1Dot0_CurrentEvent; + QUAD ZH_1Dot0_EventCount; + LONG ZH_1Dot0_BucketCount; + LONG ZH_1Dot0_BucketSize; + LONG ZH_1Dot0_Flags; +#define ZH_F_LONG 0x0001 +#define ZH_F_QUAD 0x0002 +#define ZH_F_HIGH_WATERMARK 0x8000 + LONG ZH_1Dot0_Bucket; +} NSS_MEDIA_STRUCTURE(ZlogHistogram_1Dot0_s,ZH_1Dot0_Bucket) ZlogHistogram_1Dot0_s; + +typedef struct ZlogBeastPersistent_1Dot0_s { + LONG ZLBP_1Dot0_Signature2; + WORD ZLBP_1Dot0_VersionMajor; + WORD ZLBP_1Dot0_VersionMinor; + LONG ZLBP_1Dot0_ZSTOREMajorVersion; + LONG ZLBP_1Dot0_ZSTOREMinorVersion; + LONG ZLBP_1Dot0_ZSTORESubVersion; + LONG ZLBP_1Dot0_ZSTOREBuildNumber; + Lsn_t ZLBP_1Dot0_ActivePointerLsn; + Lsn_t ZLBP_1Dot0_HomePointerLsn; + Lsn_t ZLBP_1Dot0_OldHomePointerLsn[CHECKPOINT_NUMBER]; + Blknum_t ZLBP_1Dot0_FileThrottleFull; /* Use NSS_LOCK to protect */ + Blknum_t ZLBP_1Dot0_FileThrottleBack; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWaitCount; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWait1Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWait2Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWait3Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWait4Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleWait5Count; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleFullCount; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleCheckpointCount; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleSkipCount; /* Use NSS_LOCK to protect */ + QUAD ZLBP_1Dot0_FileThrottleBackCount; /* Use NSS_LOCK to protect */ + Time_t ZLBP_1Dot0_FileThrottleTimeStart; /* Use NSS_LOCK to protect */ + Time_t ZLBP_1Dot0_FileThrottleTimeEnd; /* Use NSS_LOCK to protect */ + Blknum_t ZLBP_1Dot0_OldHomePointerBlockNumber[CHECKPOINT_NUMBER]; + Blknum_t ZLBP_1Dot0_ActivePointerBlockNumber; + Blknum_t ZLBP_1Dot0_HomePointerBlockNumber; + Blknum_t ZLBP_1Dot0_PreOldestHomePointerBlockNumber; + Time_t ZLBP_1Dot0_TimeActivation; + Time_t ZLBP_1Dot0_TimeDeactivation; + Time_t ZLBP_1Dot0_TimePoolCreate; + LONG ZLBP_1Dot0_RecoveryRecoverCount; + LONG ZLBP_1Dot0_RecoveryActivationCount; + Time_t ZLBP_1Dot0_LastRecoveryTimeStart; + Time_t ZLBP_1Dot0_LastRecoveryTimeEnd; + LONG ZLBP_1Dot0_LastRecoveryActivationCount; + WORD ZLBP_1Dot0_Mode; + WORD ZLBP_1Dot0_FileVersion; + BYTE ZLBP_1Dot0_FileThrottleFullPercent; + BYTE ZLBP_1Dot0_FileThrottleBackPercent; + BYTE ZLBP_1Dot0_Padding[6]; + QUAD ZLBP_1Dot0_PreHomePointerReferenceBlockCount; + QUAD ZLBP_1Dot0_HomePointerReferenceBlockCount; + QUAD ZLBP_1Dot0_ActivePointerReferenceBlockCount; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_ReferenceBlockCountHistogram; + QUAD ZLBP_1Dot0_ReferenceBlockCountBucket[50]; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_FunctionHistogram; + QUAD ZLBP_1Dot0_FunctionBucket[50]; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_SizeHistogram; + QUAD ZLBP_1Dot0_SizeBucket[41]; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_BlockInuseCountHistogram; + LONG ZLBP_1Dot0_BlockInuseCountBucket[40]; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_RecoveryTimeHistogram; + Time_t ZLBP_1Dot0_RecoveryTimeBucket[12]; + ZlogHistogram_1Dot0_s ZLBP_1Dot0_DeferredWritesHistogram; + QUAD ZLBP_1Dot0_DeferredWritesBucket[30]; + /*** Note that the next 4 items (3 quads) are not present in + *** MOAB/Cobra. They are present in the numerous Six-Pack + *** volumes. Our 1Dot0 unpack code will assume that they + *** are present so that we do not have to blow away + *** pre-existing Six-Pack volumes. All this means for + *** the real AIPU is that 3 QUADs worth of zeros will be + *** moved. + ***/ + Lsn_t ZLBP_1Dot0_CompensationPtrLsn; + Lsn_t ZLBP_1Dot0_LogicalUndoPtrLsn; + Blknum_t ZLBP_1Dot0_CompensationPtrBlkNum; + Blknum_t ZLBP_1Dot0_LogicalUndoPtrBlkNum; + QUAD ZLBP_1Dot0_Reserved[37]; + LONG ZLBP_1Dot0_Signature; + LONG ZLBP_1Dot0_Pad2; /* QUAD alignment */ +} NSS_MEDIA_STRUCTURE(ZlogBeastPersistent_1Dot0_s,ZLBP_1Dot0_Pad2) ZlogBeastPersistent_1Dot0_s; + + +/* + struct ZlssBarrier_s + Used to ensure that a device flush (barrier) is done prior to + signaling that journal blocks have been written. This object is needed + because some devices cache writes, but do not ensure the writes + get written. The Journal MUST ensure that journal blocks are written + prior to meta-data otherwise corruption may occur. See the journal + specification for more information. +*/ +typedef struct ZlssBarrier_s +{ + NINT ZB_Signature; +#define ZLSS_BARRIER_SIGNATURE 0x785e7f79 + SQlink_t ZB_BarrierLink; /* Barrier agents that are ready for + barrier flush. The head of this list + is ZlogBeast_s.ZLB_BarrierListHead */ + struct ZlogBeast_s *ZB_Zlog; /* The Journal/Pool that barrier is for */ + Agent_s ZB_Agent; /* For bonds, latching and oneshot timer */ +} ZlssBarrier_s; + + +/*=========================================================================== + *=========================================================================== + *=========================================================================== + * + * ZFSLOG BEAST Area + * + *=========================================================================== + *=========================================================================== + *===========================================================================*/ + + /*------------------------------------------------------------------------- + * Global defines for ZFS log beasts. + *-------------------------------------------------------------------------*/ + + +/*=========================================================================== + *=========================================================================== + * + * ZFSLOG BEAST Definition + * + *=========================================================================== + *===========================================================================*/ + +typedef struct ZlogBeast_s +{ +/* + * Note - By convention a 'is a' is the first element + * Note - The class can not have class data (i.e. static data). + * Note - All instance data is initialized to zero by the system (i.e. Neal). + * Note - Use the class constructor to initialize instance data to + * non-zero values. + * Note - All persistent items must be placed into zlogBeastPersistent_s. + * Note - If you create an element that starts with ZLB_P... then you + * should first rename the ZLB_P element so that greps can find + * only it. Yes we have cscope, but let's not assume everyone does. + */ + + File_s file; /* Derived from file */ + + /*** Items in this area are not persistent ***/ + QUAD ZLB_LogRecordFilledInCount; + /* Accouting. Number of log record filled in since + * activation. + */ + QUAD ZLB_LogBlockFilledInCount; + /* Accounting. Number of blocks filled in since + * activation. + */ + QUAD ZLB_TransactionsHomedSinceCheckpointCount; + /* Accounting. Number of transactions homed since last + * checkpoint. We only count transactions with log + * records. + */ + QUAD ZLB_TransactionsHomedCount; + /* Accounting. Number of transactions homed since + * activation. We only count transactions with log records. + */ + Blknum_t ZLB_LogBlockFilledInSinceCheckpointCount; + /* NSS_LOCK protected! Number of log blocks filled + * in since we took our last checkpoint. + */ + Blknum_t ZLB_LogBlockFilledInMaximum; + /* Number of log blocks that + * will be filled in prior to taking a new + * checkpoint. + */ + struct Buffer_s *ZLB_Buffer; + /* Current buffer that ZLOG is using. + ******** + * Because Zlog_FlushBlockStartSignalHandler accesses + * this item without latching the ZLOG's beast beastLatch + * we have special access rules. + * 1) Signal Handler will have shared latch on buffer + * and a NSS_LOCK. + * 2) ZLOG_ObtainRecord will NSS_LOCK when R/W if it + * does not have a exclusive latch on the buffer. + ******** + */ + Blknum_t ZLB_NumberOfLogBlocks; + /* Number of log blocks (originals and + * duplicates) in the pool log file. + */ + DQhead_t ZLB_SeniorityListHead; + /* DQ of all active transactions order by oldest + * to youngest. Used to determine when the home pointer + * and home pointer LSN can be moved forward. Transactions + * get placed on list by ZLOG_ObtainRecord() and removed + * by ZLOG_TransactionHomed(). + */ + DQhead_t ZLB_CachedBufferListHead; + /* DQ of all ZLOG buffers that need to be flushed. Ordered + * by oldest to youngest. Used to determine when signal + * to the bound DATA buffers can be passed through. + * Buffers get placed on list by ZLOG_ObtainRecord() and + * removed by Zlog_FlushBlockEndSignalHandler(). This + * link list implements the ZLOG specification requirement + * that NO DATA buffers be flushed before ALL log buffers + * less than the last log buffer the DATA is bond to have + * been flushed. + */ + ZfsXasRecovery_s *ZLB_ZfsXasRecovery; + /* Return value from ZLOG_ObtainRecord(). */ + Latch_s ZLB_FileFullLatch; + /* Used to block threads that are doing ZLOG_ObtainRecord + * when the ZLOG file is full. Under normal use, the ZLOG + * file should never become full. + */ + Latch_s ZLB_RecoveryLatch; + /* Used by recovery system to protect recovery phase + * from re-entry. All items within + * the ZLOG beast that start with ZLB_Recovery are + * protected by this latch. + */ + Latch_s ZLB_CheckpointTakeLatch; + /* Used to serialize taking checkpoints. We do not skip + * taking a checkpoint because someone else is currently + * taking one, because the 'snapshot' of the ZLOG beast + * may not contain the information that the current + * checkpoint take requestor needs. + */ + + Blknum_t ZLB_RecoveryAreaFirstBlockNumber; + /* Logical number of first recovery block. This + * is the first block that is needed for recovery. + * The first logical block number of the pool + * log file is 0. + */ + + Blknum_t ZLB_RecoveryActivePointerBlockNumber; + /* The true active pointer of the ZLOG file at recovery + * time. This may be the active pointer stored in the + * checkpoint OR it could be further in the file. The + * Recover Active Pointer(RAP) code determines this value + * at recovery time by scanning the ZLOG file from + * the home pointer until it locates a block with a LESSER + * LSN. The value is used to determine where the end + * of the recovery area is. Also the current active + * pointer is set to this value. + */ + Lsn_t ZLB_RecoveryActivePointerLsn; + /* Used by Recover Active Pointer code to track what + * RAP has found as the active pointer. Initially set to + * the home pointer and then moved when the next blocks + * contains a higher LSN. This value is also used to know + * when to stop processing blocks during recovery. LSNs + * equal to or greater than must not be recovered (they + * are log records that we logged during the recovery + * phase.) + */ + + Blknum_t ZLB_RecoveryInitialActivePointerBlockNumber; + /* This is the value of the Active pointer Block number + * after the recoveryactivepointer has been founded and + * the active pointer has been updated to point to it + * before we start redo/undo. With logical undo the + * active pointer value can change, so we save the initial + * value + */ + + Lsn_t ZLB_RecoveryInitialActivePointerLsn; + /* This is the value of the Active pointer LSN + * after the recoveryactivepointer has been founded and + * the active pointer has been updated to point to it + * before we start redo/undo. With logical undo the + * active pointer value can change, so we save the initial + * value + */ + + Lsn_t ZLB_RecoveryCompensationPointerLsn; + /* During redo/undo of compensation records, this + * keeps track of which logical undo records were + * already played and committed. Pass 6 uses this + * value to determine which logical undo records were + * already committed and need not be copied. + */ + +// BOOL ZLB_ProcessCompensationRecords; +// /* This tells us whether we are doing redo/undo on normal +// * records or compensation records. If we are doing +// * redo/undo on compensation records, we force undo +// * all the records. +// */ + + NINT ZLB_Signature; + /* Debug - So when we do STRUCT magic we can verify + * that this really is a ZLOG beast. The ID is 615960 + */ + + LONG ZLB_State; + /* State bits + * 0x0001 - No more checkpoints should be taken. + * + */ +#if ZLOG_USE_SYSTEMS_WORK_TO_DO + zWorkProc_s ZLB_CheckpointTakeWorkToDoStructure; + /* Protected by ZLB_CheckpointTakeWorkToDoScheduled flag. + * WorkToDo for NSS Library schedule API - ScheduleWork(). + */ +#else + FsmLite_s ZLB_CheckpointTakeWorkToDoFsm; + /* Protected by ZLB_CheckpointTakeWorkToDoScheduled flag. + * Lite FSM to pass to WORK_Schedule(). + */ +#endif +#if NSS_DEBUG IS_ENABLED + Time_t ZLB_CheckpointTakeWorkToDoTiming; + /* Times how long it takes the schedule code to actually + * start the checkpoint routine. + */ +#endif + OneShot_s ZLB_CheckpointTakeWorkToDoTimer; + /* Protected by ZLB_CheckpointTakeWorkToDoScheduled flag. + * One Shot timer used to implement '30 second' checkpoint + * logic. + */ + + BYTE ZLB_CheckpointTakeWorkToDoScheduled; + /* NSS_LOCK() protection required! TRUE if we have + * scheduled a checkpoint via our work-to-do logic. We + * track this because we can only have (and want) one item + * scheduled at a time. + */ + + BYTE ZLB_DebugState; + /* Debug. State that ZLOG is in. Used to do some + * ASSERT code. + */ + + BYTE ZLB_ActiveHasBeenRead; + /* FALSE if we need to read the current active pointer + * block. TRUE if we already have read the current active + * pointer block. This item is normally set to TRUE. + */ + BYTE ZLB_FileFullWaiters; + /* 0 if no one is waiting for the ZLOG file to become + * un-full. 1 if the file is full and someone is waiting + * to use it. Under normal use, the ZLOG file should + * never become full. + */ +#if LOG_TEST IS_ENABLED + LogTest_s ZLB_LT[LOG_TEST_MAX]; +#endif + /* Our persistent items are required to be on a QUAD + * boundary so add some padding. Our constructor has + * ASSERT code to verify that this is correct. + */ + LONG ZLB_WorkToDoParameter1; +#if NSS_DEBUG IS_ENABLED + /* Track the thread that is doing the current checkpoint. + */ + LONG ZLB_CheckpointThreadId; + LONG ZLB_CheckpointThreadIdLast; + /* The times that the last 4 checkpoints where taken. + */ + Time_t ZLB_CheckpointTime[CHECKPOINT_NUMBER]; +#endif + /* Parameter passed to ZLOG's work-to-do checkpoint routine. + * This is currently the 'state' value that the function + * ZFSPOOL_CheckpointTake() requires. + */ + ZlogXactionStats_s ZLB_Ftest; // Currently 4 LONGs + STATUS ZLB_RedoUndoStatus; + char *ZLB_RedoUndoStatusSetter; + /* Set to zFAILURE when REDO/UNDO fails. Used to prevent + * a taking a checkpoint when we REDO/UNDO fails. + */ + + ZlssBarrier_s *ZLB_Barrier; + /* Current barrier that ZLOG is using. + ******** + * Because Zlog_BarrierFlushBlockStartSignalHandler accesses + * this item without latching the ZLOG's beast beastLatch + * we have special access rules. + * 1) Signal Handler will have shared latch on barrier + * and a NSS_LOCK. + * 2) ZLOG_ObtainRecord will NSS_LOCK when R/W if it + * does not have a exclusive latch on the barrier. + ******** + */ + BYTE ZLB_BarrierWorkToDoScheduled; + /* NSS_LOCK() protection required! TRUE if we have + * scheduled a barrier via our work-to-do logic. We + * track this because we can only have (and want) one item + * scheduled at a time. + */ + BYTE ZLB_Reserved2007[3]; + SQhead_t ZLB_BarrierListHead; + /* NSS_LOCK protected. List of all Barrier Agents that + have been signaled. These Barrier Agents need to do + a barrier flush so that their signal can be sent. */ + FsmLite_s ZLB_BarrierWorkToDoFsm; + /* FSM to use to schedule barrier agent writes. */ + + /* Histograms track all events. This is done by placing a + * event into one of many 'buckets'. + */ + ZlogHistogram_s ZLB_FunctionHistogram; + + ZlogHistogram_s ZLB_SizeHistogram; + + /* Historys track specific number of events. This is done + * by logging specific events. + */ + ZlogHistory_s ZLB_History[4]; +#define ZH16_RECOVERY_UTC 0 +#define ZH16_REBUILD_UTC 1 +#define ZH16_PENDING_IO_HIGH 2 +#define ZH16_LAST_USED 2 /* The index of the last used element + * in the ZLB_History arrary. + */ + + ZlogHistogram_s ZLB_ReferenceBlockCountHistogram; + ZlogHistory_s ZLB_ReferenceBlockCountHistory; + + ZlogHistogram_s ZLB_BlockInuseCountHistogram; + ZlogHistory_s ZLB_BlockInuseCountHistory; + + ZlogHistogram_s ZLB_RecoveryTimeHistogram; + ZlogHistory_s ZLB_RecoveryTimeHistory; + + ZlogHistogram_s ZLB_DeferredWritesHistogram; + ZlogHistory_s ZLB_DeferredWritesHistory; + +// BYTE ZLB_Reserved[4]; + /*** Our persistent items ***/ + ZlogBeastPersistent_s ZLB_P; +} ZlogBeast_s; + + /* Needed because documented for ZLOGObtainRecord API */ +#define ZLB_CommitAgent ZLB_Barrier->ZB_Agent + +/* + * + * Signature define. + * + */ + +#define ZLOG_ZLB_S_SIGNATURE (615960) + +/* + * + * State defines(ZLB_State). This is a bitmask. + * + */ +#define ZLOG_ZB_S_DEFAULT_STATE 0x00000000uL + /* State to use when pool is activated */ +#define ZLOG_ZB_S_NO_MORE_CHECKPOINTS 0x00000001uL + /* State to indicate that we must not take any more checkpoints */ +#define ZLOG_ZB_S_TAKING_CHECKPOINT 0x00000004uL + /* FYI - Currently in the process of taking a checkpoint */ +#define ZLOG_ZB_S_DOING_COMPENSATION 0x00000010uL + /* We are processing logical undo records, and the log records + * being written at this time are compensation records + */ +#define ZLOG_ZB_S_NEEDTODO_COMPENSATION 0x00000020uL + /* We have finished the physical redo/undo passes and there are + * some records that were copied and we need to do logical + * undo resulting in generation of compensation records + */ + +/* + * + * State defines(ZLB_DebugState) - relative values are important. + * + */ +#define ZLOG_ZB_DS_CONSTRUCT_PRE 0 + /* The code assumes this is zero and an ASSERT + * verifies it in our constructor. + */ +#define ZLOG_ZB_DS_CONSTRUCT_START 1 /* In constructor */ +#define ZLOG_ZB_DS_CONSTRUCT_ERROR 2 /* Error from constructor. */ +#define ZLOG_ZB_DS_CONSTRUCT_END 3 /* Success form constructor. */ + /* Have made it through our constructor successfully. */ +#define ZLOG_ZB_DS_RECOVERY_START 4 + #define ZLOG_ZB_DS_RAP_START 5 /* Recover Active Pointer */ + #define ZLOG_ZB_DS_RAP_ERROR 6 /* Recover Active Pointer(error)*/ + #define ZLOG_ZB_DS_RAP_END 7 /* Recover Active Pointer */ + #define ZLOG_ZB_DS_PT_START 8 /* Process Transaction */ + #define ZLOG_ZB_DS_PT_ERROR 9 /* Process Transaction (error) */ + #define ZLOG_ZB_DS_PT_END 10 /* Process Transaction */ +#define ZLOG_ZB_DS_RECOVERY_ERROR 11 +#define ZLOG_ZB_DS_RECOVERY_END 12 + +#define ZLOG_ZB_DS_LOG_TEST 127 /* Doing a log record undo/redo + * or undo/redo test. + */ + +#define ZLOG_ZB_DS_DESTRUCT_START 253 +#define ZLOG_ZB_DS_DESTRUCT_ERROR 254 +#define ZLOG_ZB_DS_DESTRUCT_END 255 + + +#define ZFSLOGroot file.auth.named.root +#define ZFSLOGnamed file.auth.named +#define ZFSLOGauth file.auth +#define ZFSLOGfile file + +#define ZFSLOGblkSizeShift ZFSLOGroot.blkSizeShift +#define ZFSLOGmycache ZFSLOGroot.mycache +#define ZFSLOGvolLink ZFSLOGroot.volLink +#define ZFSLOGbstState ZFSLOGroot.bstState +#define ZFSLOGbeastLatch ZFSLOGroot.mycache.agent.latch +#define ZFSLOGzfsStInfo ZFSLOGroot.storage.zfsInfo +#define ZFSLOGstInfo ZFSLOGroot.storage.info +#define ZFSLOGzid ZFSLOGroot.zid +//#define ZFSLOGvolumeID ZFSLOGroot.vol.volume->p.volumeID +#define ZFSLOGrebuildCount ZFSLOGroot.vol.volume->p.rebuildCount + +typedef struct ZlogRecoveryKey_s { + ZfsXasRecovery_s *ZRK_ZfsXasRecovery; + /* External. Points to the Recovery information of + * current log record. Callers use to locate needed + * Memory pointed to can not be used after the next + * recovery find API call. + */ + Buffer_s *ZRK_Buffer; + /* Internal. Buffer_s that contains the recovery + * information. + */ + ZlogBeast_s *ZRK_ZlogBeast; + /* Internal. ZLOG beast that owns this key. */ + Blknum_t ZRK_LogBufferNumber; + /* Internal. Current file logical log buffer number. + * Zero relative to beginning of ZLOG file. Used to + * find the next or previous log buffer number. Also + * used to see when find has returned all of recovery + * log records. + */ + Lsn_t ZRK_LsnFirst; + /* Internal. The first LSN that can appear in the + * recovery area. + */ + Blknum_t ZRK_BlockFirst; + /* Internal. First block of the 'get' area. On a + * forward get this is the first block used. On a + * backwards get this is the last block used. + */ + Blknum_t ZRK_BlockLast; + /* Internal. Last block of the 'get' area. On a + * forward get this is the first block not used. On a + * backwards get this block is the first block not used. + */ + int ZRK_LogRecordNumber; + /* Internal. Current log record number. Zero relative + * to beginning of current log buffer. Used to find the + * next or previous log record. + */ +#if NSS_ASSERT IS_ENABLED + + /* These items are used to in ASSERTs only */ + unsigned int ZRK_Signature; +#define ZLOG_ZRK_S_SIGNATURE 801861 + unsigned int ZRK_Flag; +#define ZLOG_ZRK_F_KEY_VALID 8368742 + +#endif +} ZlogRecoveryKey_s; + + /* Flags for ZLOG_RecoveryOpen() */ +#define ZLOG_RECOVERY_BEGIN 0x0001 +#define ZLOG_RECOVERY_END 0x0000 // Begin or End must be selected +#define ZLOG_RECOVERY_EXPANDED 0x0004 +#define ZLOG_RECOVERY_LOGICAL 0x0008 +#define ZLOG_RECOVERY_NORMAL 0x0000 // Expanded or Normal or Logical + //must be selected + + + /* Direction flag for ZLOG_RecoveryGet() */ +#define ZLOG_RG_NEXT 1 +#define ZLOG_RG_PREVIOUS -1 + +#define ZLOG_ReleaseRecordAndLogEnd( _xaction ) \ +{ \ + if (DQ_EMPTY( &_xaction->ZX_deleteBlkQ)) \ + { \ + _xaction->xstate |= XAS_XR_TS_END; \ + } \ + ZLOG_ReleaseRecord( _xaction ); \ +} + + +/* + * The definition of the block information that follows the pool block count. + * The number of these structures is defined by the pool block count. + */ +typedef struct BlockInfo_s +{ + Blknum_t blkNum; /* the block number */ + WORD logState; /* state information used while logging */ + WORD replayState; /* state information used during playback */ + Lsn_t previousLsn; /* the previous log sequence number */ +} NSS_MEDIA_STRUCTURE(BlockInfo_s,previousLsn) BlockInfo_s; + +/* defines for logState */ +#define LOG_FREE_NODE 0x0001 /* Set deleted block bit */ +#define LOG_ALLOC_NODE 0x0002 /* Set allocated block bit */ + +/* defines for replay state */ +#define REPLAY_DONT_PROCESS 0x0001 + +/* macro to assign information to the block info structure */ +#if LOG_TEST IS_ENABLED +#define ZLOG_ASSIGN_BLOCK_INFO(_entry, _blknum, _prevLsn, \ + _buffer, _xaction, _index) \ + ((_entry).blkNum = (_blknum), \ + (_entry).previousLsn = (_prevLsn), \ + (_entry).logState = 0, \ + (_xaction)->ZX_Buffers[(_index)] = (_buffer), \ + ((_xaction)->ZX_Compare[(_index)]) = (LogTestCompareFunc_t)zlog_LogTestCompare, \ + zASSERT((_index) < LOG_TEST_MAX )) +#else +#define ZLOG_ASSIGN_BLOCK_INFO(_entry, _blknum, _prevLsn, \ + _notUsed1, _notUsed2, _notUsed3) \ + ((_entry).blkNum = (_blknum), \ + (_entry).previousLsn = (_prevLsn), \ + (_entry).logState = 0) +#endif + +/* macro to assign information to the block info structure AND supplies + a non-standard compare routine.*/ +#if LOG_TEST IS_ENABLED +#define ZLOG_ASSIGN_BLOCK_INFO2(_entry, _blknum, _prevLsn, \ + _buffer, _xaction, _index, _func) \ + ((_entry).blkNum = (_blknum), \ + (_entry).previousLsn = (_prevLsn), \ + (_entry).logState = 0, \ + (_xaction)->ZX_Buffers[(_index)] = (_buffer), \ + (_xaction)->ZX_Compare[(_index)] = ((LogTestCompareFunc_t)(_func)), \ + zASSERT((_index) < LOG_TEST_MAX )) +#else +#define ZLOG_ASSIGN_BLOCK_INFO2(_entry, _blknum, _prevLsn, \ + _notUsed1, _notUsed2, _notUsed3, _notUsed4) \ + ((_entry).blkNum = (_blknum), \ + (_entry).previousLsn = (_prevLsn), \ + (_entry).logState = 0) +#endif + + +#if LOG_TEST IS_ENABLED +#define ZLOG_TEST_REDO( _xaction ) \ + ((_xaction)->xstate |= X_REDO_THEN_UNDO) +#else +#define ZLOG_TEST_REDO( _xaction ) /* We do nothing */ +#endif +/* + * Set the bits and call the routines to indicate a block is deleted. + * Should only be used after ZLOG_ASSIGN_BLOCK_INFO. + */ +#define ZLOG_DELETE_BLOCK(_xaction, _entry) \ +{ \ + (_entry).logState = LOG_FREE_NODE; \ + XdeferPoolBlk((_xaction), (_entry).blkNum); \ +} + +/* + * Set the bits and call the routines to indicate a block has been allocated. + * Should only be used after ZLOG_ASSIGN_BLOCK_INFO. + */ + +#define ZLOG_ALLOC_BLOCK(_entry) \ +{ \ + (_entry).logState = LOG_ALLOC_NODE; \ +} + +/* macro to compute where the pool block section of the log record starts */ +#define ZLOG_START_OF_POOL_BLOCKS(_header) \ + (BlockInfo_s *)((ADDR)(_header) + sizeof(ZfsXasRecovery_s)) + +/* macro to compute where the logged information in the log record starts */ +#define ZLOG_START_OF_LOG_RECORD(_header) \ + (void *)((ADDR)(_header) + sizeof(ZfsXasRecovery_s) + \ + ((_header)->ZXR_PoolBlockCount * sizeof(BlockInfo_s))) + +/* macro to set the log sequence number during replay of the log */ +#define ZLOG_SET_LSN(_logBuf, _lsn, _entry, _action) \ + { \ + if ((_action) == X_REDO) \ + { \ + if (((_entry).blkNum != 0) && !((_entry).logState & \ + LOG_ALLOC_NODE)) \ + zASSERT((_lsn) == (_entry).previousLsn); \ + (_lsn) = (_logBuf)->ZXR_Lsn; \ + } \ + else \ + { \ + (_lsn) = (_entry).previousLsn; \ + } \ + } + + /* + * This macro determines if a Block already contains the information + * stored in the Log Record. It works for both REDO and UNDO. + * In addition, it 'tells' the xaction code if a REDO/UNDO is + * actually being done (via zp_stats.redid). + */ +#if NSS_DEBUG IS_ENABLED +#define ZLOG_ALREADY_DONE(_zfsPool, _logBuf, _lsn, _action) \ + ((((_action == X_REDO) && (_lsn) >= (_logBuf)->ZXR_Lsn) \ + || ((_action == X_UNDO) && (_lsn) < (_logBuf)->ZXR_Lsn)) \ + ? ( DBG_DebugPrintf(CYAN,"S"), TRUE ) \ + : ( DBG_DebugPrintf(RED,"P"), _zfsPool->zp_stats.redid++, FALSE) ) +#else +#define ZLOG_ALREADY_DONE(_zfsPool, _logBuf, _lsn, _action) \ + ((((_action == X_REDO) && (_lsn) >= (_logBuf)->ZXR_Lsn) \ + || ((_action == X_UNDO) && (_lsn) < (_logBuf)->ZXR_Lsn)) \ + ? TRUE : (_zfsPool->zp_stats.redid++, FALSE) ) +#endif + +/* macro to determine the size of the block info section of the log record */ +#define ZLOG_BLOCK_INFO_SIZE(_numblks) \ + ((_numblks) * sizeof(BlockInfo_s)) + + // This is the old bad name for the PLAY block test +#define ZLOG_VALID_BLOCK ZLOG_BLOCK_PROCESS + + // Should the log record be processed (REDO/UNDO) +#define ZLOG_BLOCK_PROCESS(_blkinfo) \ + ( ZLOG_BLOCK_VALID(_blkinfo) && !ZLOG_BLOCK_SKIP_FLAG(_blkinfo) ) + + // Is the block flagged as skip? +#define ZLOG_BLOCK_SKIP_FLAG(_blkinfo) \ + ((_blkinfo).replayState & REPLAY_DONT_PROCESS) + + // Does the block have a valid number? +#define ZLOG_BLOCK_VALID(_blkinfo) ((_blkinfo).blkNum != 0) + +/* macro to init information always needed after doing a ZLOG_ObtainRecord */ +#define ZLOG_INIT_LOG_RECORD(_operation, _xaction, _buffer, _numblks, _poolblks, _logrecord) \ + ((_buffer) = (_xaction)->ZX_zlogBeast->ZLB_ZfsXasRecovery, \ + (_buffer)->ZXR_PoolBlockCount = (_numblks), \ + (_buffer)->ZXR_FunctionIndex = (_operation), \ + (_poolblks) = ZLOG_START_OF_POOL_BLOCKS(_buffer), \ + (_logrecord) = ZLOG_START_OF_LOG_RECORD(_buffer)) + +/* macro to do binding for transactions */ + +#if NSS_DEBUG IS_ENABLED +#define ZLOG_BIND(_xaction, _data) \ +{ \ +/* extern NINT MaxXactionTicks; */\ +/* (bind(&(_data)->agent, &(_xaction)->ZX_zlogBeast->ZLB_Buffer->agent), */\ + (bind(&(_data)->agent, &(_xaction)->ZX_zlogBeast->ZLB_Barrier->ZB_Agent), \ + bind(&(_xaction)->xaction.agent, &(_data)->agent), \ + (_data)->state |= CACHE_DIRTY); \ +/* if ((Time.in - (_xaction)->timeStamp) >= (MaxXactionTicks >> 1)) */\ +/* zASSERT("Too much time has elasped since the begin of Xaction"== NULL);*/\ +} +#else +#define ZLOG_BIND(_xaction, _data) \ +/* (bind(&(_data)->agent, &(_xaction)->ZX_zlogBeast->ZLB_Buffer->agent), */\ + (bind(&(_data)->agent, &(_xaction)->ZX_zlogBeast->ZLB_Barrier->ZB_Agent), \ + bind(&(_xaction)->xaction.agent, &(_data)->agent), \ + (_data)->state |= CACHE_DIRTY) +#endif + + /* FixFixFix6(Future,If ZLOG mirror becomes a requirement) + * We may have lower layers do the cheap mirroring for us. If + * we must do then +2 is correct plus change code to do 2nd + * block write/read and modify asserts and errors on specific + * file size. + */ + + /* Get next log block */ + +#define ZLOG_NEXT_POOL_LOG_BLOCK( _zlogBeast, _blockNumber ) \ +{ \ + _blockNumber += 1; \ + zASSERT( _zlogBeast->ZLB_NumberOfLogBlocks > 0 ); \ + if ( _blockNumber >= _zlogBeast->ZLB_NumberOfLogBlocks ) \ + { \ + _blockNumber = 0; \ + } \ +} + + /* Get previous log block */ + +#define ZLOG_PREVIOUS_POOL_LOG_BLOCK( _zlogBeast, _blockNumber ) \ +{ \ + zASSERT( _zlogBeast->ZLB_NumberOfLogBlocks > 0 ); \ + if ( _blockNumber == 0 ) \ + { \ + _blockNumber = _zlogBeast->ZLB_NumberOfLogBlocks -1; \ + } \ + else \ + { \ + _blockNumber -= 1; \ + } \ +} + + +#if NSS_DEBUG IS_ENABLED + /* + * This is the header that is placed into '.ZLF' and '.ZLB' files + * so that ZAD can detect version/build information. + */ +typedef struct ZlogZadHeader_s { + LONG ZZH_VersionNumber; /* Version 2 supports ZHH_PoolState */ + LONG ZZH_ZSTOREMajorVersion; + LONG ZZH_ZSTOREMinorVersion; + LONG ZZH_ZSTORESubVersion; + LONG ZZH_ZSTOREBuildNumber; + char ZZH_Description[1000]; /* Area for descriptive user message. + * ZAD can let user fill in + */ + BYTE ZZH_PoolState; /* State of pool when Journal Read. + * Added in Version 2 because we + * can read Journal on an ACTIVE + * pool. + */ + BYTE ZZH_Reserved3; + WORD ZZH_Reserved2; + LONG ZZH_Reserved1[5]; +} ZlogZadHeader_s; +#endif + + /*** Global variables ***/ + +extern CommonBeastOps_s ZlogComnBeastOps; +extern LSSSpecificPackUnpackOps_s ZLOG_lssOps[]; + + + /*** Prototypes ***/ + + /** Public ZLOG functions (requirements of ZLOG specification) **/ + +void ZLOG_ObtainRecord( + ZfsXaction_s *zlogXaction, + NINT recordSize ); + +void ZLOG_ReleaseRecord( + ZfsXaction_s *zlogXaction ); + +void ZLOG_CopyLogicalUndoRecord( + struct ZlogBeast_s *zlogBeast, + struct ZfsXasRecovery_s *zxr); + +STATUS ZLOG_RecoveryPhase( + struct GeneralMsg_s *genMsg, + struct ZlogBeast_s *zlogBeast, + NINT mode); + +void ZLOG_TransactionHomed( + struct ZfsXaction_s *xaction ); + +void ZLOG_RecoveryClose( + ZlogRecoveryKey_s *zlogKey ); + +void ZLOG_RecoveryOpen( + NINT startingPosition, + struct ZfsPool_s *zfsPool, + ZlogRecoveryKey_s *zlogKey ); + +STATUS ZLOG_RecoveryGet( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey, + NINT direction ); + +STATUS ZLOG_RecoveryGetLogicalOnly( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey, + NINT direction ); + +STATUS ZLOG_InternalRecoveryGet( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey, + NINT direction ); + +Time_t ZLOG_RecoveryTimeGet( + ZlogRecoveryKey_s *zlogKey ); + + /** Public ZLOG functions (requirements of other components) **/ + +STATUS Zlog_Construct( struct GeneralMsg_s *genMsg, void *zlogBeast); +void Zlog_Destruct( void *zlogBeast ); +void Zlog_FlushBlockStartSignalHandler( struct Agent_s *agent ); +void Zlog_FlushBlockDoneSignalHandler( struct Agent_s *agent); +STATIC NINT Zlog_ZfsPackedSize( void *zlogBeast ); +STATIC BYTE *Zlog_ZfsPack( void *zlogBeast, BYTE *storeBuffer ); +STATIC BYTE *Zlog_ZfsUnpack( struct GeneralMsg_s *genMsg, + void *zlogBeast, BYTE *storeBuffer); +STATUS Zlog_PoolInitialize( struct GeneralMsg_s *genMsg, + struct ZlogBeast_s *zlogBeast, + BOOL rebuild ); +void Zlog_Throttle( Volume_s *volume, ZfsXaction_s *zlogXaction ); + + /** Internal functions **/ + +#if LOG_TEST IS_ENABLED +STATUS zlog_LogTestCompare( + BYTE *src1, + BYTE *src2, + NINT len); +#endif + +void zlog_CheckpointTakeSchedule( + ZlogBeast_s *zlogBeast, + NINT state ); + +void zlog_CheckpointTakeWorkToDoRoutine( +#if ZLOG_USE_SYSTEMS_WORK_TO_DO + zWorkProc_s *work); +#else + FsmLite_s *workToDoFsm ); +#endif + +void zlog_ORCommon( + NINT neededLongs, + ZlogBeast_s *zlogBeast, + ZLOGBlockHeader_s *logBlockHeader, + ZfsXaction_s *zlogXaction ); + +LONG zlog_CalculateChecksum( LONG *Buffer, NINT NumberOfLONGs ); + +STATUS zlog_CommonCreateAndOpen( struct GeneralMsg_s *genMsg, + struct ZlogBeast_s *zlogBeast ); + +NINT zlog_GetNewestCheckpointIndex( ZlogBeast_s *zlogBeast ); + +NINT zlog_GetOldestCheckpointIndex( ZlogBeast_s *zlogBeast ); + +void zlog_THSerialized( struct FsmLite_s *fsmLite ); + +STATUS zlog_RecoverActivePointer( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast ); + +STATUS zlog_RAPProcessSingleLogBlock( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + NINT *done ); + +void zlog_LogRecordDump( + ZLOGRecordHeader_s *logRecordHeader, + char *headerMsg, + NINT headerColor ); + +STATUS zlog_RecoveryVerifyBlock( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast ); + +STATUS zlog_RGNReal( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey ); + +STATUS zlog_RGPReal( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey ); + +STATUS zlog_RecoveryGet( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + ZlogRecoveryKey_s *zlogKey ); + + STATUS zlog_RGReal( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + ZlogRecoveryKey_s *zlogKey ); + + Buffer_s *zlog_RGReadAndVerifyBlock( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + Blknum_t blockToRead ); + + STATUS zlog_RGVerifyRecords( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + Buffer_s *buffer, + NINT recordNumber ); + +STATUS zlog_ProcessLogBlocks( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast ); +STATUS zlog_PLBSingle( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + NINT *done ); +STATUS zlog_PLBLogRecords( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + Buffer_s *buffer, + NINT recordNumber, + NINT *done ); + +void zlog_CopyLogFileToVolume( + GeneralMsg_s *genMsg, + ZlogBeast_s *zlogBeast, + char *volumeName, + int flags ); + +STATUS ZLOG_GenerateXML( + ZlogBeast_s *zlogBeast, + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen ); + +void zlog_HistogramEvent( + ZlogHistogram_s *histogram, + QUAD event); + +STATUS zlog_PoolSave( + GeneralMsg_s *genMsg, + struct ZfsPool_s *zfsPool ); + +STATUS zlog_PoolRestoreImage( + GeneralMsg_s *genMsg, + struct ZfsPool_s *zfsPool ); + +STATUS zlog_PoolRestoreScan( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool, + unicode_t *poolName, + unicode_t *sourceVolumeName ); + +STATUS zlog_PoolCompare( + GeneralMsg_s *genMsg, + struct ZfsPool_s *zfsPool ); + +STATUS zlog_RecoveryGetNextBlock( + GeneralMsg_s *genMsg, + ZlogRecoveryKey_s *zlogKey ); + + /** Testing functions **/ + +#if ZLOG_TEST IS_ENABLED +void ZLOG_TestMain( + ZlogBeast_s *, + GeneralMsg_s *, + RootBeast_s * ); + +void zlog_TestLoggingApi( + GeneralMsg_s *genMsg, + RootBeast_s *rootBeast, + LocalXid_t localXid, + NINT numberOfRecords ); + +STATUS zlog_TLAWriteSingleRecord( + GeneralMsg_s *genMsg, + RootBeast_s *rootBeast, + ZfsXaction_s *zlogXaction, + NINT recordLength, + WORD state ); + +void zlog_Seed(long seed); +NINT zlog_Rnd(NINT range); +NINT zlog_SizeofRecord(); +NINT zlog_NumberOfLogRecords(); +#endif + +void zlog_HistoryEvent(ZlogHistory_s *history, QUAD event); + +#endif /* _ZLOG_H_ */ diff --git a/src/nwnss/zlss/zlogFtest.h b/src/nwnss/zlss/zlogFtest.h new file mode 100644 index 0000000..f0ddd15 --- /dev/null +++ b/src/nwnss/zlss/zlogFtest.h @@ -0,0 +1,61 @@ +/**************************************************************************** + | + | (C) Copyright 1997 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | The ZFS Log (ZLOG) component of ZFS. + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Definitions used by ZLOG and FTEST. + | + +-------------------------------------------------------------------------*/ +#ifndef _ZLOGFTEST_H_ +#define _ZLOGFTEST_H_ +#include + +/* Pre-declare the following structure(s) */ +struct ZlogRecoveryInfo_s; + +NINT ZLOG_RecoveryInfoGet( + unicode_t *volumeName, + struct ZlogRecoveryInfo_s *info ); + +typedef struct ZlogXactionStats_s { + LONG ZRI_RedoMax; /* Maximum redo(s) that we could have done */ + LONG ZRI_RedoActual; /* Actual redo(s) that we did */ + LONG ZRI_UndoMax; /* Maximum undo(s) that we could have done */ + LONG ZRI_UndoActual; /* Actual undo(s) that we did */ +} ZlogXactionStats_s; + +typedef struct ZlogRecoveryInfo_s { + ZlogXactionStats_s ZRI_Zxs;/* Xaction stats */ + Time_t ZRI_ActivationTime; /* Time activation started (UTC) */ +} ZlogRecoveryInfo_s; + +#endif /* #ifndef _ZLOGFTEST_H_ */ diff --git a/src/nwnss/zlss/zlssConsumer.h b/src/nwnss/zlss/zlssConsumer.h new file mode 100644 index 0000000..4568ebf --- /dev/null +++ b/src/nwnss/zlss/zlssConsumer.h @@ -0,0 +1,251 @@ +/**************************************************************************** + | + | (C) Copyright 1995 - 2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (PSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2007-04-18 23:26:20 +0530 (Wed, 18 Apr 2007) $ + | + | $RCSfile$ + | $Revision: 1954 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | define all of the prototypes and globals. + | + | + +-------------------------------------------------------------------------*/ +#ifndef _ZLSSCONSUMER_H_ +#define _ZLSSCONSUMER_H_ + +#include + +#ifndef _OMNI_H_ +# include "omni.h" +#endif + +#ifndef _MAL_H_ +# include "mal.h" +#endif + +#ifndef _ZFS_H_ +# include "zfs.h" +#endif + +#ifndef _UTC_H_ +# include "utc.h" +#endif + +/*--------------------------------------------------------------------------- + | Global definitions + +-------------------------------------------------------------------------*/ +#define ZLSS_POOLINFOSIGNATURE MSGNot("ZLSSPoolStorInfo") +#define ZLSS_POOLINFOBLKOFFSET 0 +#define ZLSS_POOLINFOBLKCNT 2 + +#define ZLSS_CONFIGINFOSIGNATURE 0x5A434953 /* ZCIS */ + +#define ZLSS_MINPOOLSIZEINMEG 10 + +/*- pool operational status -*/ +#define POL_STAT_UNKNOWN 0 +#define POL_STAT_INCOMPLETE 1 +#define POL_STAT_FREE 2 +#define POL_STAT_READY 3 +#define POL_STAT_ORPHAN 4 +#define POL_STAT_NEW 5 +#define POL_STAT_NEW_SNAPSHOT 6 +#define POL_STAT_NEW_NAME 7 + +#define POL_INVALID_POOLID NSS_INVALIDMALID /*- 0 -*/ +#define POL_INVALID_DEPOSITID NSS_INVALIDDEPOSITID /*- 0x7fffffff -*/ + +/*- private area return codes -*/ +#define VERIFY_READONLY 1 +#define VERIFY_NOMEMORY 2 +#define VERIFY_NOREAD 3 +#define VERIFY_FOUNDINVALID 4 +#define VERIFY_NOTFOUND 5 +#define VERIFY_NOTCONSUMER 6 + +#define VERIFY_NONAME 7 +#define VERIFY_NEWNAME 8 +#define VERIFY_NAMEDIFF 9 + +#define VERIFY_RENAME 10 + +#define PRIVATEUNITSPERBLK 4 + +/*--------------------------------------------------------------------------- + | storage area information + +-------------------------------------------------------------------------*/ +typedef struct StorPhy_s +{ + LONG unitsize; /*- smallest IO unit size in bytes -*/ + QUAD sizeinunits; /*- number of units for this storage deposit -*/ + LONG sizeinmeg; /*- number of meg for this storage deposit -*/ + Time_t createtime; /*- utc time when storage was create -*/ + GUID_t guid; /*- GUID (128 bits) when storage was created -*/ +} StorPhy_s; + +/*--------------------------------------------------------------------------- + | Logical Information if assigned to a pool + +-------------------------------------------------------------------------*/ +typedef struct StorPool_s +{ + LONG poolstatus; /*- free, used, orphan - operational status of pool -*/ + LONG poolblocksize; /*- size of blocks used (cache block) for pool -*/ + LONG poolblkshift; /*- block shift factor for bytes -*/ + BOOL sharedStatus; + /* The SP_LoadStatus bits where added September 2003 to prevent multiple unloads, + * and unloads while loading. Mike Ohran and Rob Green where seeing these + * issues while testing their snapshot utilities. The end results where ABENDs. + */ + LONG SP_LoadStatus; /* Bit masks of load or unload of a pool */ +#define LS_LOADING 0x00000001 /* Someone is currently loading the pool */ +#define LS_UNLOADING 0x00000002 /* Someone is unloading a phypool (or waiting to unload if LS_LOADING is set) */ +#define LS_UNLOADED 0x00000004 /* Someone has unloaded the phypool */ + QUAD pooltotalblocks; /*- total number of blocks in storage -*/ + struct zConPool_s *phypool; /*- local storage element for this pool -*/ + ZfsPool_s *zfspool; /*- if member, memory pointer to zlss pool beast -*/ + unicode_t poolname[64]; /*- if member, name of pool -*/ +} StorPool_s; + + +// +// Used to track code that has a phypool PTR (a pointer to a zConPool_s). +// +typedef struct PhyCookie_s +{ + DQlink_t PC_CookieLink; /* Link use to track ALL cookies of a phypool. The + * head is ZCP_CookieHead in zConPool_s. + */ + LONG PC_Magic; /* Magic that indicate if the cookie is good */ +#define PC_MAGIC_GOOD 0x48465765 /* Cookie in use */ +#define PC_MAGIC_GOOD_SHARED 0x48465768 /* The SharedCookie */ +#define PC_MAGIC_GOOD_INIT 0x48466a6a /* Cookie has NEVER been used */ +#define PC_MAGIC_FREED 0x4a475866 /* Cookie no longer in use */ + ADDR PC_ObtainedThread; /* Thread ID of obtainer */ + char *PC_ObtainedWhere; /* WHERE of caller to phypool_Obtain */ + Time_t PC_ObtainedUTCTime; /* Time of phypool_Obtain call */ + ADDR PC_ReleasedThread; /* Thread ID of releaser */ + char *PC_ReleasedWhere; /* WHERE of caller to phypool_Obtain */ + Time_t PC_ReleasedUTCTime; /* Time of phypool_Release call */ + LONG PC_KeyValidCurrent; /* Current valid key. TheSharedCookie does not + * use to validate because it is shared. It does + * use to generate unique keys for each of its + * keys. This may help in debugging issues. + */ + struct zConPool_s *PC_Phypool; /* Use to validate release except in the + * case of TheSharedCookie. + */ +} PhyCookie_s; + +typedef struct PhyKey_s +{ + LONG pk_unique; /* The pk_unique is an unique count given to the cookie */ + ADDR pk_cookie; /* The pk_cookie is a PTR to a PhyCookie_s. */ +} PhyKey_s; + /* This allows us to detect when + * a key is released twice. + * We are assuming that our users are not trying to + * guess keys (we will abend in most cases as cookie + * will be an invalid address). + */ +typedef PhyKey_s PhyKey_t; + +#define PHYKEY_INVALID 0 + +/*--------------------------------------------------------------------------- + | Consumer Take information for deposit element owned by NSS + +-------------------------------------------------------------------------*/ +typedef struct zConPool_s +{ + DQlink_t stolink; /*- master link of owned storage deposits -*/ + DQlink_t pollink; /*- master link of created pools -*/ + struct block_device *ZCP_dev; /*- Linux Block Device ID -*/ + StorPhy_s phy; /*- description of storage deposit area -*/ + StorPool_s pol; /*- if member, pool information -*/ + + BOOL ZCP_BarrierWritesRequired; /* Current barrier setting. This may be + FALSE even if ZCP_BarrierCommandlineSetting + is TRUE. E.G. if device does not + support then we do not do barrier writes. */ + BOOL ZCP_BarrierCommandlineSetting; /* User request for barrier setting. */ + void *cp_inode; /* pointer to a root inode for the pool */ + DQhead_t ZCP_CookieHead; /* Head of link list of active cookies(users of a + * specific zConPool_s). + */ + PhyKey_t ZCP_LoadKey; /* Key that identifies our 'load' use count. */ + int ZCP_InUseCount; /* Number of threads using this phypool. */ + int ZCP_UnloadSpinners; /* Number of threads waiting for unload */ +} zConPool_s; + + +void ZLSSDoBarrierWriteIfRequired( struct zConPool_s *phyPool ); + +/*--------------------------------------------------------------------------- + | Data Prototypes needed + +-------------------------------------------------------------------------*/ +extern DQhead_t zlssConTakeList; +extern DQhead_t ZLSSMasterPoolList; + + +/*--------------------------------------------------------------------------- + | Function Prototypes needed + +-------------------------------------------------------------------------*/ + +extern STATUS CONSUMER_Startup(); + +extern void CONSUMER_Shutdown(); + +extern STATUS ZLSSCON_AutoReceiveDeposit(Deposit_s *info, LONG devFlags); + +extern STATUS ZLSSCON_AutoReturnDeposit(struct block_device *bdev, LONG reason); + +extern STATUS ZLSSCON_RetDepositInfo(struct block_device *bdev, zConPool_s **phypool); + +extern STATUS ZLSSPOOL_Startup(); + +extern void ZLSSPOOL_Shutdown(); + +extern STATUS ZLSSPOOL_Insert(zConPool_s *phypool); + +extern STATUS ZLSSPOOL_Remove(zConPool_s *phypool); + +extern STATUS zlssInsertPool(zConPool_s *phypool, unicode_t *oldname); +extern STATUS zlssRemovePool(zConPool_s *phypool); +extern STATUS zlssVerifyPool(zConPool_s *phypool); +extern STATUS zlssCompareName(Deposit_s *info); +extern STATUS zlssCmpInfoBlk(zConPool_s *phypool0, zConPool_s *phypool1); + +extern STATUS ZFSPOOL_CmpName(unicode_t *name); + +void Phypool_Shutdown( void ); +STATUS Phypool_Startup( void ); + +STATUS phypool_Release( PhyKey_t phyKey, zConPool_s *phypool, char *where ); +PhyKey_t phypool_Obtain( zConPool_s *phypool, char *where ); + +#endif /* _ZLSSCONSUMER_H_ */ diff --git a/src/nwnss/zlss/zlssIOPerformance.h b/src/nwnss/zlss/zlssIOPerformance.h new file mode 100644 index 0000000..6974895 --- /dev/null +++ b/src/nwnss/zlss/zlssIOPerformance.h @@ -0,0 +1,373 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1999 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | zfs.h defines information that affects the format of the data + | on the disk. This file needs to be referenced by utilities like + | install and diskedit. The classes used by ZFS are defined here too. + | + | WARNING: Data structures and QUADs should be designed to align + | on 64 bit boundries. So when we get a 64 bit processor things + | are aligned correctly. + +-------------------------------------------------------------------------*/ +#ifndef _ZLSSIOPERFORMANCE_H_ +#define _ZLSSIOPERFORMANCE_H_ + +#define ORDERED 300 +#define MTHREADS 0 +#define ASYNC_READ 1 + +#define VCF_BROWSE /* When defined then can use _ADMIN volume to + * gather browse information on ZLSS volumes. + */ +#define VCF_READTEST /* When defined then can use _ADMIN volume to + * gather Read performance figures of a pool. + */ + +#define GREG_SEQ FALSE +#define GREG_100 FALSE +#define GREG_112 FALSE +#define GREG_FULL FALSE + +typedef struct { + FsmLite_s BRP_WorkToDoFsm; + /* Protected by BRP_WorkToDoScheduled flag. + * Lite FSM to pass to WORK_Schedule(). + */ + Latch_s BRP_Latch; + Blknum_t BRP_Block; + ZfsPool_s *BRP_ZfsPool; + NINT BRP_WorkToDoScheduled; +} BlockReadParameters_s; + + +typedef struct { + /** Items needed for a readahead and current block **/ + Blknum_t ZR_BlockNext; /* Next block to be read. */ + Blknum_t ZR_BlockLeftSequential;/* Number of blocks left to read + * sequentially before next random read. + */ + Blknum_t ZR_SeeksLeftToDo; /* Number of seeks left to read */ + LONG ZR_Random; +} ZIOP_Random_s; + +typedef struct { + /** Passed in 'Construtor' items **/ + Blknum_t ZRRA_BlockStart; /* Beginning range of legal blocks + * to read. + */ + Blknum_t ZRRA_BlockEnd; /* End range of legal blocks + * to read. + */ + Blknum_t ZRRA_BlockSpaceing; /* Number of blocks to skip during + * sequential part of random reads. + * E.G. If 1 then all blocks will be + * read if 2 then every other block. + */ + Blknum_t ZRRA_BlockSequential;/* Number of blocks to read sequentially + * before next random read. + */ + Blknum_t ZRRA_SeeksToDo; /* Number of seeks to do */ + + /** Private items used by the read ahead object **/ + ZIOP_Random_s ZRRA_ReadAhead; + ZIOP_Random_s ZRRA_Read; +} ZIOP_Random_ReadAhead_s; + +typedef struct { + /** Passed in 'Construtor' items **/ + Blknum_t ZSRA_BlockStart; + Blknum_t ZSRA_BlockEnd; /* Last block to read */ + Blknum_t ZSRA_BlockSpaceing; /* Number of blocks add to get next block. + * E.G. If 1 then all blocks will be + * read if 2 then every other block. + */ + /** Private items used by the read ahead object **/ + Blknum_t ZSRA_BlockNext; /* Next block to be read ahead. When + * greater than ZRA_BlockEnd read ahead + * is done. Must never be less that + * ZRA_BlockStart. + */ +} ZIOP_Sequential_ReadAhead_s; + +typedef BOOL (*ZIOP_ReadAheadAlgoNextBlock_t)( void *data, BOOL readahead, Blknum_t *nextBlock ); + + +typedef struct { + /** Passed in 'Construtor' items **/ + ZfsPool_s *ZRA_ZfsPool; + ZIOP_ReadAheadAlgoNextBlock_t ZRA_ReadAheadAlgoNextBlock; + /* Pointer to read ahead specific algorithm + * 'next block' routine. + */ + void *ZRA_ReadAheadAlgo; /* Pointer to read ahead specific + * algorithm data. + */ +// Blknum_t ZRA_BlockStart; +// Blknum_t ZRA_BlockEnd; /* Last block to read */ + Blkcnt_t ZRA_ReadAheadMax; /* Maximum number of blocks to have in + * the I/O system. + */ + /** Private items used by the read ahead object **/ +// Blknum_t ZRA_BlockNext; /* Next block to be read ahead. When +// * greater than ZRA_BlockEnd read ahead +// * is done. Must never be less that +// * ZRA_BlockStart. +// */ + Blkcnt_t ZRA_ReadAheadCurrent; /* Current number of blocks that are + * in the I/O system. Must never be greater + * than ZRA_ReadAheadMax. + */ + Blkcnt_t ZRA_ReadAheadCurrentMax; /* Maximum blocks that we had + * in the I/O system. + */ + + /** Stats **/ + QUAD ZRA_ReadAttempts; /* Number of ASYNC reads we have attempted. + * This includes ASYNC reads that have not + * yet completed. + * + * + * + * ZRA_ReadFailure + ZRA_ReadSuccessful + * + ZRA_ReadCacheHit only WHEN + * ZRA_ReadAheadCurrent == 0 + */ + QUAD ZRA_ReadFailure; /* ASYNC Physical Read failed */ + QUAD ZRA_ReadSuccessful; /* ASYNC Physical Read succeeded */ + QUAD ZRA_ReadCacheHit; /* ASYNC Cache hit - did not need to do a + * physical read. + */ + NINT ZRA_TimeTicksStart; + NINT ZRA_TimeTicksEnd; + Time_t ZRA_TimeUTCStart; + Time_t ZRA_TimeUTCEnd; + QUAD ZRA_TimeMicroEnd; + QUAD ZRA_TimeMicroStart; +} ZIOP_ReadAhead_s; + +typedef struct +{ + Time_t ZR_CurrentTimeUTC; + Blknum_t ZR_CurrentBlock; + QUAD ZR_TotalTimeInUS; + QUAD ZR_TotalBlocks; + QUAD ZR_IncrementalTimeInUS; + QUAD ZR_IncrementalBlocks; +} ZIOP_Rate_s; + +typedef struct +{ + Time_t ZS_RecordNextTime; /* Next 'time' to record a rate. */ + Time_t ZS_RecordRate; /* How often to record a statistics. */ + Time_t ZS_DisplayNextTime; /* Next 'time' to display a rate. */ + Time_t ZS_DisplayRate; /* How often to display a statistics */ + QUAD ZS_ReadCountStart; + QUAD ZS_UsStart; + QUAD ZS_ReadCountEnd; + QUAD ZS_UsEnd; + QUAD ZS_ReadCountPrevious; + QUAD ZS_UsPrevious; /* Microseconds of previous rate stat */ + BOOL ZS_RecordTime; /* TRUE when rate stats should be displayed */ +} ZIOP_Statistics_s; + + +typedef struct ZIOP_ThreadInfo_s +{ + BOOL ZTI_scheduled; + LONG ZTI_numBlocks; + Blknum_t ZTI_bAreaStart; /* 1st block to read */ + Blknum_t ZTI_bAreaEnd; /* Last block to read */ + Blknum_t ZTI_bSpaceing; /* Must be > 0 */ + Blknum_t ZTI_bSequential; /* Must be > 0 */ + ZIOP_Rate_s *ZTI_rateObject; + NINT ZTI_rateObjectCount; + unicode_t ZTI_poolName[zMAX_COMPONENT_NAME]; + ZlssPool_s *ZTI_zlssPool; +} ZIOP_ThreadInfo_s; + + + +#ifdef VCF_READTEST + +typedef struct ZiopHighWatermarkBucket_s +{ + QUAD ZHWB_Event; +// time_t ZHWB_Time; + QUAD ZHWB_FileSize; + QUAD ZHWB_FATSize; + LONG ZHWB_Padding[1]; +} ZiopHighWatermarkBucket_s; + + +#define ZIOP_HWB_DEFAULT 10 + +typedef struct ZiopHighWatermark_s +{ + ZiopHighWatermarkBucket_s ZHW_Bucket[ZIOP_HWB_DEFAULT]; +} ZiopHighWatermark_s; + +#define ZIOP_HISTOGRAM_INIT(_hist,_bucketCount,_bucketSizeDetails,_flags,_buckets,_total,_fatTotal) \ + { \ + bzero( (_hist), sizeof( *(_hist ) ) ); \ + bzero( (_buckets), sizeof( *(_buckets ) ) ); \ + bzero( (_total), sizeof( *(_total ) ) ); \ + bzero( (_fatTotal), sizeof( *(_fatTotal ) ) ); \ + (_hist)->ZH_BucketCount = _bucketCount; \ + (_hist)->ZH_BucketSize = _bucketSizeDetails; \ + (_hist)->ZH_Flags = _flags; \ + (_hist)->ZH_Bucket = _buckets; \ + (_hist)->ZH_Total = _total; \ + (_hist)->ZH_FATTotal = _fatTotal; \ + } + +typedef struct ZiopHistogram_s +{ + ZiopHighWatermark_s ZH_Watermarks; /* Highest events */ + QUAD ZH_CurrentEvent; /* Current event */ + QUAD ZH_CurrentFileSize; /* Current file size of event */ + QUAD ZH_CurrentFATSize; /* Current FAT size of event */ + QUAD ZH_TotalEvent; /* Total of all events */ + QUAD ZH_TotalFileSize; /* Total of all file sizes */ + QUAD ZH_TotalFATSize; /* Total of all FAT sizes */ + QUAD ZH_EventCount; /* Total number of events */ + LONG ZH_BucketCount; /* Number of buckets */ + LONG ZH_Flags; /* Flags as follows */ +#define ZH_F_LONG 0x0001 /* Track with LONGs */ +#define ZH_F_QUAD 0x0002 /* Track with QUADs */ +#define ZH_F_HIGH_WATERMARK 0x8000 /* Track High Watermarks */ + unsigned long *ZH_BucketSize; /* 1st value that appears in bucket */ + void *ZH_Bucket; /* Pointer to bucket area */ + void *ZH_Total; /* Pointer to 'file size' total bucket area */ + void *ZH_FATTotal; /* Pointer to FAT total bucket area */ +// LONG ZH_Padding[1]; /* */ +} ZiopHistogram_s; +#endif + +//NINT doBrowseStatitics( +// struct PCLSwitchDef_s *switchDef, +// NINT options, +// void *userParm); +// +//NINT doRBPerfomance( +// struct PCLSwitchDef_s *switchDef, +// NINT options, +// void *userParm ); + +STATUS ZIOP_FMAP_AllUserObjects( + GeneralMsg_s *genMsg, + VirtInfo_s *virtInfo, + Volume_s *volume, + QUAD browseAmount, /* Number of files to do */ + LONG browseIncrement ); /* Number of ZIDs to get in one + * browse call. + */ +BOOL ZIOP_Random_Test( + struct VirtInfo_s *virtInfo, + LONG numBlocks, + Blknum_t bAreaStart, + Blknum_t bAreaEnd, + Blknum_t bSpaceing, /* Must be > 0 */ + Blknum_t bSequential, /* Must be > 0 */ + ZIOP_Rate_s *rateObject, + NINT rateObjectCount, + unicode_t *poolName, + ZlssPool_s *zlssPool ); + +BOOL ZIOP_ReadAheadNextReadAhead( + ZIOP_ReadAhead_s *rAO ); + +STATUS ZIOP_Sequential_Test( + struct VirtInfo_s *virtInfo, + LONG numBlocks, + Blknum_t bAreaStart, /* 1st block to read */ + Blknum_t bAreaEnd, /* Last block to read */ + Blknum_t bSpaceing, /* Must be > 0 */ + Blknum_t bSequential, /* Must be > 0 */ + ZIOP_Rate_s *rateObject, + NINT rateObjectCount, + unicode_t *poolName, + ZlssPool_s *zlssPool ); + +STATUS ZIOP_Sequential_Test2( + struct VirtInfo_s *virtInfo, + LONG numBlocks, + Blknum_t bAreaStart, /* 1st block to read */ + Blknum_t bAreaEnd, /* Last block to read */ + Blknum_t bSpaceing, /* Must be > 0 */ + Blknum_t bSequential, /* Must be > 0 */ + ZIOP_Rate_s *rateObject, + NINT rateObjectCount, + unicode_t *poolName, + ZlssPool_s *zlssPool ); + +STATUS ZIOP_Sequential_Test3( + LONG numBlocks, + Blknum_t bAreaStart, /* 1st block to read */ + Blknum_t bAreaEnd, /* Last block to read */ + Blknum_t bSpaceing, /* Must be > 0 */ + Blknum_t bSequential, /* Must be > 0 */ + ZIOP_Rate_s *rateObject, + NINT rateObjectCount, + unicode_t *poolName, + ZlssPool_s *zlssPool ); + +void ZIOP_Sequential_Thread( + THREAD threadID, + ZIOP_ThreadInfo_s *ti ); + +void zDisplayHistogram( + VirtInfo_s *virtInfo, + ZiopHistogram_s *hist, + void *buckets, + void *totals, + void *fatTotals ); + +void ziop_HistogramEvent( + ZiopHistogram_s *histogram, + QUAD event, + QUAD fileSize, + QUAD fatSize ); + +void zDisplayHistogramSpread( + VirtInfo_s *virtInfo, + ZiopHistogram_s *hist, + void *buckets, + void *totals, + void *fatTotals ); + +#define ZIOP_HISTOGRAM_EVENT( _histogram, _event, _fileSize, _fatSize ) \ + ziop_HistogramEvent( (_histogram), (_event), (_fileSize), (_fatSize) ) + + +#endif /* #ifndef _ZLSSIOPERFORMANCE_H_ */ diff --git a/src/nwnss/zlss/zlssLogicalVolume.h b/src/nwnss/zlss/zlssLogicalVolume.h new file mode 100644 index 0000000..e18b907 --- /dev/null +++ b/src/nwnss/zlss/zlssLogicalVolume.h @@ -0,0 +1,1335 @@ +/**************************************************************************** + | + | (C) Copyright 1999-2002 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | ZLSS - The 'Z' LSS code for Logical Volumes(LVs) + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2007-05-07 22:05:29 +0530 (Mon, 07 May 2007) $ + | + | $RCSfile$ + | $Revision: 1976 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define Logical Volume information that affects the format of the data + | on the disk. + +-------------------------------------------------------------------------*/ + +#ifndef _ZLSSLOGICALVOLUME_H_ +#define _ZLSSLOGICALVOLUME_H_ + +#ifndef _XCACHE_H_ +#include +#endif + +#ifndef _COMNBEASTS_H_ +#include "comnBeasts.h" +#endif + +#ifndef _VOLUME_H_ +#include "volume.h" +#endif + +#ifndef _PARSE_H_ +#include "parse.h" +#endif + +#ifndef _ZFS_H_ +#include +#endif + +/* Pre-declare the following structure(s) */ +struct ZfsXaction_s; +struct ZLSSVOL_ZVL_RenameInfo_t; +struct Node_s; +struct BeastTreeNode_s; + + /* Information about bitmaps used to ensure that the Purge Log + * is not hooked into itself. Used to prevent hangs. + */ +#ifndef HAVE_BLOCK_MAP_s +#define HAVE_BLOCK_MAP_s +typedef struct BlockMap_s { + char *BM_Startup; /* Who allocated (I.E. WHERE macro) */ + char *BM_Shutdown; /* Who allocated (I.E. WHERE macro) */ + Blkcnt_t BM_NumberOfBits; /* Number of bits in map */ + NINT *BM_Map; /* Actual bitmap */ +} BlockMap_s; + + // + // Caller must ensure that bitmap is legal and block is within + // range before using this MACROS. + // +#define BM_TST_BIT( _bitMap, _blockNum ) (TST_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_SET_BIT( _bitMap, _blockNum ) (SET_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_CLR_BIT( _bitMap, _blockNum ) (CLR_BIT( (_bitMap)->BM_Map, _blockNum )) +#define BM_XOR_BIT( _bitMap, _blockNum ) (XOR_BIT( (_bitMap)->BM_Map, _blockNum )) +#endif + + /* The zVOL_LV_DELETE_ACTION_xxx defines can not be redefined. This + * values are hard coded into the XML files used to export this + * API to clients. + */ +#define zVOL_LV_DELETE_ACTION_SALVAGE 1 +#define zVOL_LV_DELETE_ACTION_PAUSE 2 +#define zVOL_LV_DELETE_ACTION_CONTINUE 3 +#define zVOL_LV_DELETE_ACTION_PURGE 4 + + +#define AIPU_1ST_6PACK_MEDIA_VERSION 39 + + /* Major number that LV upgrade uses. */ +#define AIPU_LV_MEDIA_MAJOR 40 + /* Minor number that step finishes in */ +#define AIPU_LV_STEP_1_DONE 2 +#define AIPU_LV_STEP_2A_DONE 3 +#define AIPU_LV_STEP_2B_DONE 4 +#define AIPU_LV_STEP_3_DONE 5 +#define AIPU_LV_STEP_4_DONE 6 +#define AIPU_LV_STEP_5_DONE 7 +#define AIPU_LV_STEP_LAST_DONE AIPU_LV_STEP_5_DONE +#define AIPU_LV_STEP_PDB_DONE AIPU_LV_STEP_2A_DONE /* Pool Data Blocks created */ +#define AIPU_LV_STEP_PVPL_DONE AIPU_LV_STEP_2A_DONE /* Pool's Volume Purge Log exists */ + + + /* We start with LV version 35 because the first release of ZLSS + * used version 34.00 for the media version of the POOL/Volume. + * Note that the POOL media version and the LV media version + * are not the same. The POOL version is stored in the superblock + * and the Pool Data Block (PDB). The LV version is stored in + * the Volume Data Block(VDB). + */ +#define ZLSS_LV_MEDIA_MAJOR 35 /* The LOGICAL VOLUME media version */ +#define ZLSS_LV_MEDIA_MINOR 0 + +#if SUPERBLOCK_SB_VM_MEDIA_MAJOR != 43 +#error Has the LV media version also changed? +#endif + +#if SUPERBLOCK_SB_VM_MEDIA_MINOR != 3 +#error Has the LV media version also changed? +#endif + + + /* Postfix added to the name of a LV that is being + * deleted. We go with a short name so that it will + * not cause NSS /volumes or NSS /Pools a problem. + */ +#define ZLSSVOL_DELETE_NAME_UNICODE MSGNot(L"_DV") + + /* Directory name that all ZLSS Volume Locator beasts are stored. */ +#define ZLSSVOL_DIRECTORY_UNICODE MSGNot(L"LogicalVolumes") +#define ZLSSVOL_DIRECTORY_NAME_UNICODE MSGNot(L"LogicalVolumes/") + + /* Name used to create a temporary unique logical volume used + * when upgrading a ZfsPool_s into the Logical Volume world. We + * do not use the pool name because this would cause two volumes + * to have the same name during step 2 of AIPU. + */ +#define ZLSSVOL_IPU_NAME_UNIQUE MSGNot(L"_BIPHIUQVUNE_BIPHIUQVUNE_") + + +typedef struct PersistentZlssVolumeLocator_s { + LONG PZVL_signature; + /* Signature that identifies this is a ZLSS Volume + * locator beast. Can be used by zrepair and + * debug/ASSERT. The signature is 'ZVL ' on Little + * Endian CPUs. + */ + WORD PZVL_versionMajor; + /* The major version of the ZVL file. Changes when + * ZLV is no longer compatible with an older version + * of the ZLV file. The first release will have this + * set to 1. + */ + WORD PZVL_versionMinor; + /* The minor version of the ZVL file. Changes when + * old ZLSS are still compatible. This will be 0 in the + * first release. + */ + /* The next three items must match the values that are + * stored in the PersistentZfsVolume_s area of the + * ZfsVolume area. + */ + SQUAD PZVL_loggedVolumeDataBlk; + SQUAD PZVL_volumeDataBlk; + SQUAD PZVL_systemBeastBlkNum; + VolumeID_t PZVL_volumeID; + + LONG PZVL_state; +#define PZVL_S_CREATION_DELETE 0 /* Volume is being created, but if at load + * time we find such a Volume Locator + * beast we should not continue + * volume creation. + */ +#define PZVL_S_CREATION 1 /* Volume is being created. + * This will have to delete also because + * we may have gotten some wierd error + * and therefore should remove the LV + * as error may occur again and again. + */ +#define PZVL_S_CREATED 2 /* Volume is created (this is the normal + * state of a LV) + */ +#define PZVL_S_DELETION 3 /* Volume is being deleted */ + + LONG PZVL_subState; /* Sub-state of the state. */ +/* Sub-States of PZVL_S_DELETION */ + +#define PZVL_SS_DELETE_SALVAGEABLE 0 +#define PZVL_SS_DELETE_TRUNCATE_UST_DST_MFL_EFL 1 +#define PZVL_SS_DELETE_TRUNCATE_ALL_OBJECTS 2 +#define PZVL_SS_DELETE_TRUNCATE_NT 3 +#define PZVL_SS_DELETE_TRUNCATE_BT 4 +#define PZVL_SS_DELETE_STEP_PLOG_MOVE 5 +#define PZVL_SS_DELETE_STEP_PLOG_TRUNCATE 6 +#define PZVL_SS_DELETE_STEP_FREE_LAST_BLOCKS 7 +#define PZVL_SS_DELETE_STEP_DELETE_ZVLB 8 + +#define PZVL_SS_DELETE_STEP_ACTIVATE PZVL_SS_DELETE_STEP_PLOG_MOVE + /* The above define is used to determine if a LV in + * the PZVL_S_DELETION state should be left in the + * deactive state or activated. All sub states LESS THAN + * OR EQUAL must activate the volume EXCEPT for + * PZVL_SS_DELETE_SALVAGEABLE which is in its own world. + */ + + GUID_t PZVL_internalID; + /* This is the GUID that is written to every ZLSS + * system block. We no longer use the Volume's + * ID as it may change. For example, when a mirror + * is split apart into two pools. The internal + * ID is initially set to the volume ID, but it + * then never changes. + */ + VolumeID_t PZVL_volumeIDOriginal; + /* GUID of volume before it was deleted. */ + unicode_t PZVL_volumeName[64]; + /* By storing the name inside the Volume Location beast + * we do not need to worry if the volume location beast's + * name is the same as the LV. This allows the volume + * location beast to be renamed without effecting the + * name of the logical volume. Although, at LOAD time + * we will rename the ZVL Beast to agree with this + * item. This is REQUIRED because we use the volume + * name to lookup the ZVL Beast in LV rename and LV + * delete. + */ + + /*******************************************/ + /*** Information about DELETE of the LV ****/ + /*******************************************/ + Time_t PZVL_deleteTimeStart; /* When we initially started + * the LV delete. Used as FYI and + * to determine if LV is still SALVAGEABLE. + */ + + LONG PZVL_deleteState; +#define ZVL_DS_SALVAGEABLE 0 /* Waiting for purge time */ +#define ZVL_DS_PURGEING 1 /* LV is being purged. May not mean being + * activily purged as we only have 5 + * threads and the scan thread may have + * not seen in this new STATE. See + * ZVL_purgeThreadID for more information. + */ +#define ZVL_DS_PURGEING_PAUSED 2 /* Paused by user AFTER purge started */ +#define ZVL_DS_SALVAGEABLE_PAUSED 3 /* Paused by user BEFORE purge started */ +#define ZVL_DS_PURGE_ERROR 4 /* Last purge did not complete */ +#define ZVL_DS_UNDELETE 5 /* Thread actively undeleting LV. */ +#define ZVL_DS_UNDELETE_ERROR 6 /* Last undelete did not complete */ +#define ZVL_DS_SALVAGED 7 /* LV has been salvaged. This state is + * really brief, because as soon as + * we enter it we schedule a thread + * to remove LV for the dqi. + */ +#define ZVL_DS_UNKNOWN 8 /* Unknown state (should not happen + * but UI uses. + */ + + unicode_t PZVL_volumeNameOriginal[64]; + /* This is the name the volume had before we started + * to delete it. + */ + LONG PZVL_errno; + char PZVL_errnoSetter[48]; /* The LAST 48 characters of + * errno setter. Includes a NULL. + */ + + /*****************************************/ + /*** ***/ + /*** Information about PURGE of the LV ***/ + /*** ***/ + /*****************************************/ + Time_t PZVL_purgeTimeStart; /* When we initially started purgeing + * the LV. Used for FYI. + */ + Time_t PZVL_purgeTimeLastStart; + Time_t PZVL_purgeTimeLastEnd; + SQUAD PZVL_purgeLogBlocks; /* Used by LV delete to store + * the chain of purge log blocks so + * that they can be deleted AFTER + * the volume has been deactivated and + * destroyed for the last time. This + * is done so that we KNOWN that the + * purge log is not being used (I.E. + * deactivate waits for things to clean up). + */ + Zid_t PZVL_lastZidTruncated; + + /********************************************/ + /*** ***/ + /*** Information about SNAPSHOT of the LV ***/ + /*** ***/ + /*** Added in version 3.0 of ZVLBeast ***/ + /*** ***/ + /********************************************/ + + GUID_t PZVL_snapshotID; /* Unique ID given to a 'snapshot'. Used + * by ZLSS to see if a volume needs a + * snapshot. A snapshot is done if + * this GUID does not match the POOL's + * snapshot GUID. Ofcourse, the POOL + * must also have ZP_Snapshot set to + * TRUE. + */ + + /********************************************/ + /*** ***/ + /*** The below information is only valid ***/ + /*** if PZVL_snapshotID is the same as ***/ + /*** the pool's snapshot ID. ***/ + /*** ***/ + /********************************************/ + VolumeID_t PZVL_volumeIDSnapshot; + /* Volume ID of volume before 'snapshot' + * taken. This MAY be useful for + * user interfaces. If this is ZERO + * then volume was created after the + * snapshot was taken. + */ + VolumeID_t PZVL_volumeIDOriginalSnapshot; + /* Original volume ID of volume before + * 'snapshot' taken. This only applies + * to deleted volumes. + */ + + unicode_t PZVL_volumeNameSnapshot[64]; + /* Volume name of volume before 'snapshot' + * taken. This MAY be useful for + * user interfaces. + */ + + LONG PZVL_stateSnapshot; + /* PZVL_state at time the snapshot was + * taken. Useful in determining that + * PZVL_volumeNameSnapshot is a deleted + * name and that + * PZVL_volumeNameOriginalSnapshot is + * the name prior to deletion. + */ + unicode_t PZVL_volumeNameOriginalSnapshot[64]; + /* Original volume name of volume before + * 'snapshot' taken. This only applies + * to deleted volumes. + */ + /********************************************/ + /*** End OF ***/ + /*** Information about SNAPSHOT of the LV ***/ + /********************************************/ + + /*****************************************/ + /*** ***/ + /*** Information about auto LV rename ***/ + /*** Added in version 3.1 of ZVLBeast ***/ + /*** ***/ + /*****************************************/ + + Time_t PZVL_timeAutoRename; /* UTC of when last 'auto rename' was + * done. 0 would indicate no auto + * rename has ever beend done. + */ + Time_t PZVL_timeAutoRenameFirst; /* UTC of when first 'auto rename' was + * done. 0 would indicate no auto + * rename has ever been done. + */ + VolumeID_t PZVL_volumeIDAutoRename; + /* Volume ID of volume before FIRST 'auto rename' + * done. This MAY be useful for user interfaces. + */ + + unicode_t PZVL_volumeNameAutoRename[64]; + /* Volume name of volume before FIRST 'auto rename' + * done. This MAY be useful for user interfaces. + */ + + /*****************************************/ + /*** End OF ***/ + /*** Information about auto LV rename ***/ + /*** ***/ + /*****************************************/ + + /*** Added in version 3.02 of ZVLBeast by Craig ***/ + PersistentVolumeCrypt_s PZVL_volumeCryptData; + /*** Added in version 3.03 of ZVLBeast by Randy ***/ + LONG PZVL_authModelID; + /*** 3.04 versions have eof set to 0 (no new fields added) by Greg ***/ + + LONG PZVL_reserved[200-1-1-4-32-32-1]; + /* Was 32 in 2.0 version of beast. Made + * real big as if I need to add another + * unicode volume name I will have room. + */ + +} NSS_MEDIA_STRUCTURE(PersistentZlssVolumeLocator_s,PZVL_reserved[200-1-1-4-32-32-1]) PersistentZlssVolumeLocator_s; + + + +typedef struct ZlssVolumeLocator_s { + File_s ZVL_file; + PersistentZlssVolumeLocator_s ZVL_p; /* Persistent Information */ + Time_t ZVL_deleteStateChangeTime; + /* Time of last DELETE state change. + * One use is to prevent + * an immediate purge after a CONTINUE + * delete action causes us to re-enter + * SALVAGEABLE state. + */ + ADDR ZVL_purgeThreadID; /* Non-NULL value indicates that this + * LV is being activily purged by + * the thread specified. For a little + * period of time it is who is starting + * the thread. + */ + WORD ZVL_UnpackVersionMajor; /* Major version of beast on media */ + WORD ZVL_UnpackVersionMinor; /* Minor version of beast on media */ + +} ZlssVolumeLocator_s; + +typedef struct ZLSSVOL_LVD_PurgeThreadInfo_t { + ZfsVolume_s *DTI_zVolume; /* We inherit the use count */ + ZfsPool_s *DTI_poolVolume; + BOOL DTI_verbose; + FsmLite_s DTI_fsmLite; +} ZLSSVOL_LVD_PurgeThreadInfo_t; + + +/* Format of LV on the link list waiting to be deleted or + * undeleted? The items may be waiting but already started. + */ + + /*** The LV Delete Queue is used to store information about + *** ALL the LVs that are being deleted. The pool that the + *** volume resides on is found by looking at the pool that + *** the zvlBeast resides on. + *** The list is formed when the LVs are loaded. The + *** list is destroyed when the ZfsPool_s is deactivated. + *** This is required because I have elected to keep most of + *** the information we need in the zvlBeast which can only + *** be around if the ZfsPool_s is ACTIVE. Note that the + *** zvlBeast is stored in the ZfsPool_s. + ***/ +typedef struct ZLSSVOL_LVD_DeleteQueueInfo_t { + SETlink_t DQI_Link; + NINT DQI_useCount; /* Purge thread is only one + * that can set for a long time. All other + * users must be quick in their use + * of a DQI. + */ + ZfsVolume_s *DQI_zVolume; + /* We have a InUseCount on this beast. */ + ZlssVolumeLocator_s *DQI_zvlBeast; + /* We have a InUseCount on this beast. */ + BOOL DQI_activePurgeing; + /* TRUE when one of the 5 purgeing threads is activily + * purgeing the LV. Used to prevent assigning multiple + * purge threads to the same LV. + */ + ZLSSVOL_LVD_PurgeThreadInfo_t DQI_Dti; + /** Information about the thread that is purgeing the LV + * this information is only valid while the thread is + * running. + */ +} ZLSSVOL_LVD_DeleteQueueInfo_t; + + +#define ZLSS_DQI_INUSE( _dqi ) ( (_dqi)->DQI_useCount++ ) +#define ZLSS_DQI_UNUSE( _dqi ) \ + (_dqi)->DQI_useCount--; \ + if ( (dqi)->DQI_useCount == 0 ) \ + { \ + ZLSSVOL_LVD_DeleteListRemove( dqi ); \ + } + +#define ZVL_PZVL_S_SIGNATURE (0x204c565auL) /* 'ZVL ' on Little Endian */ +#define ZVL_PZVL_VM_MAJOR 3 /* On November 9, 1999 Greg changed + * from a 1 to a 2. This was done when + * all the persistent information for + * LV delete was added to the beast. All + * current users of LV will have to blow + * away there current volumes. + * On Jan 26, 2001 Greg changed from 2 to + * 3. This was done after BETA II of + * 6Pack. Change required for snapshot + * support that Product Management + * ask for. + */ +#define ZVL_PZVL_VM_MINOR 4 /* On Aug 6, 2005 Greg changed to 3.04 to + * indicate that EOF no longer contains + * the volume's persistent state. Needed + * to do so that COMN read-a-head code + * would not get confussed. Also made + * ZVL upgrade persistent see + * ZLSSVOL_LV_MakeZVLUpgradePersistent() + * + * + * On Jan 28, 2004 Randy changed to 3.03 to + * add the authorization model ID. This + * is the primary copy of the Auth ID. The + * VDB has a backup copy. + * + * On Dec 15, 2003 Craig changed to indicate + * that Locator Beast has a 'backup' copy + * of the Encryption Information. The primary + * copy is in the volume's VDB. Unencrypted + * volumes are also at 3.02. + * + * On May 9, 2002 Greg changed from 0 to 1. + * This was done when 'auto rename' fields + * where added. Not a major change as + * new fields from reserve area that is + * ZEROed. + */ + + +#define ZVLfile ZVL_file + + + +/* + * Volume items that are named ZLSSVOL and not ZFSVOL + */ + + +#define ZLSSVOLbookedInUseBlocks zv_bookedInUseBlocks +#define ZLSSVOLv_pool ZLSSVOLvol.v_pool +#define ZLSSVOLbeastTree beastTree +#define ZLSSVOLnameTree nameTree +#define ZLSSVOLuserTree userTree +#define ZLSSVOLdirTree dirTree +#define ZLSSVOLMFL mfl +#define ZLSSVOLEFL eflTree +#define ZLSSVOLvolumePurgeLog ZV_volumePurgeLog +#define ZLSSVOLlsn logged.LPZV_lsn + + + +#define ZLSSVOLroot vol.avfile.file.auth.named.root +#define ZLSSVOLnamed vol.avfile.file.auth.named +#define ZLSSVOLauth vol.avfile.file.auth +#define ZLSSVOLfile vol.avfile.file +#define ZLSSVOLavfile vol.avfile +#define ZLSSVOLvol vol + +#define ZLSSVOLrootdir ZLSSVOLvol.rootdir +#define ZLSSVOLstorageIndex ZLSSVOLvol.storageIndex +#define ZLSSVOLrootdir ZLSSVOLvol.rootdir +#define ZLSSVOLpool ZLSSVOLvol.v_pool +#define ZLSSVOLagent ZLSSVOLvol.agent +#define ZLSSVOLbeastList ZLSSVOLvol.beastList +#define ZLSSVOLstate ZLSSVOLvol.state +#define ZLSSVOLmaxBeastSize ZLSSVOLvol.maxBeastSize +#define ZLSSVOLfreeBlockAdjustment ZLSSVOLvol.freeBlockAdjustment + +#define ZLSSVOLpoolComnOps pool->ZFSPOOLbeastClass->comnOps +#define ZLSSVOLpurgeTree pool->purgeTree + +//#define ZfSVOLinUseBlocks ZFSVOLvol.logged.inUseBlocks +#define ZLSSVOLnextZid ZFSVOLvol.logged.nextZid +#define ZLSSVOLtotalBlocks ZLSSVOLvol.logged.totalBlocks +#define ZLSSVOLinUseBlocks ZLSSVOLvol.logged.inUseBlocks +#define ZLSSVOLnumFiles ZLSSVOLvol.logged.numFiles +#define ZLSSVOLnumObjects ZLSSVOLvol.logged.numObjects +#define ZLSSVOLpurgeableBlocks ZLSSVOLvol.logged.purgeableBlocks + +#define ZLSSVOLmycache ZLSSVOLroot.mycache + +#define ZLSSVOLmagic p.PZV_magic +#define ZLSSVOLversion p.PZV_version +#define ZLSSVOLloggedMagic logged.LPZV_magic +#define ZLSSVOLloggedVersion logged.LPZV_version +#define ZLSSVOLinternalID ZV_internalID +#define ZLSSVOLvolumeID ZLSSVOLvol.VOLvolumeID +#define ZLSSVOLnameSpaceMask ZLSSVOLvol.p.nameSpaceMask +#define ZLSSVOLvolAttributes ZLSSVOLvol.p.volAttributes +#define ZLSSVOLrebuildCount ZLSSVOLvol.p.rebuildCount +#define ZLSSVOLauthModelID ZLSSVOLvol.p.authModelID +#define ZLSSVOLbeastVersionMask ZLSSVOLvol.p.beastVersionMask +#define ZLSSVOLblockShift ZLSSVOLvol.p.blockShift +#define ZLSSVOLblockSize ZLSSVOLvol.p.blockSize +#define ZLSSVOLminKeepSeconds ZLSSVOLvol.p.minKeepSeconds +#define ZLSSVOLmaxKeepSeconds ZLSSVOLvol.p.maxKeepSeconds +#define ZLSSVOLlowWaterMark ZLSSVOLvol.p.lowWaterMark +#define ZLSSVOLhighWaterMark ZLSSVOLvol.p.highWaterMark + + +typedef struct ZLSSVolumeBeastCtrl_s +{ + NINT ZVBC_beastClass; /* class ID*/ + Zid_t ZVBC_zid; /* desired zid of the beast */ + NINT ZVBC_offset; /* offset into "ZfsVolume_s" beast where this goes*/ + unicode_t *ZVBC_name; + LONG ZVBC_flags; +} ZLSSVolumeBeastCtrl_s; + +/* Defines for ZVBC_flags */ +#define ZVBC_FLAG_NO_FLAGS 0 +#define ZVBC_FLAG_CREATE_BEAST 1 + +extern ZLSSVolumeBeastCtrl_s ZLSSVolumeSuperBeasts[]; +extern LSSSpecificPackUnpackOps_s ZVL_lssOps[]; +extern CommonBeastOps_s ZVL_ComnBeastOps; + + /** The link list of all LVs that are being deleted or purged. Must + ** be empty when all pools are deactive. I.E. if the pool an + ** LV is on is not ACTIVE then we do NOT have any information + ** about the LV in this list. + **/ +typedef struct ZLSSLVDeleteList_s { + SEThead_t ZDL_list; /* SYNC Non-Pre-emptive. Head of list of + * all items. Was a item has been located + * then a use count can must set on it if + * the user will be allowing blocking. + */ +// Latch_s ZDL_listLatch; /* Latch for sync of ZDL_list */ + Latch_s ZDL_beastLatch; /* Latch for default sync */ + SNINT ZDL_cnt; /* SYNC Non-Pre-emptive. Num of items in list */ + FsmLite_s ZDL_fsmLite; /* SYNC ZDL_scheduled flag. Thread to scan + * list to keep everything going. + */ + BOOL ZDL_stop; /* Used to tell scan thread that it needs to + * stop. + */ + BOOL ZDL_scheduled; + OneShot_s ZDL_timer; /* SYNC ZDL_scheduled flag. One Shot + * timer used to implement '60 second' + * LV Delete scanner logic. + */ + QUAD ZDL_timesRun; + ADDR ZDL_threadId; + ADDR ZDL_threadIdLast; + Time_t ZDL_scheduledTime; + Time_t ZDL_runTime; +} ZLSSLVDeleteList_s; + +extern ZLSSLVDeleteList_s ZLSSLVDeleteList; + +#define ZLSSVOL_LVD_SCAN_TICKS (18 * 6 * 1) +#define ZLSSVOL_LVD_SCAN_TICKS_FIRST (18 * 6 * 2) + + + + +/*** DO not modify ANY of the _2Dot0_ structures as they + *** MUST be defined as they were in MOAB/COBRA release + *** of ZLSS. + ***/ + +typedef struct PersistentZlssVolumeLocator_2Dot0_s { + LONG PZVL_2Dot0_signature; + WORD PZVL_2Dot0_versionMajor; + WORD PZVL_2Dot0_versionMinor; + SQUAD PZVL_2Dot0_loggedVolumeDataBlk; + SQUAD PZVL_2Dot0_volumeDataBlk; + SQUAD PZVL_2Dot0_systemBeastBlkNum; + VolumeID_t PZVL_2Dot0_volumeID; + LONG PZVL_2Dot0_state; + LONG PZVL_2Dot0_subState; /* Sub-state of the state. */ + GUID_t PZVL_2Dot0_internalID; + VolumeID_t PZVL_2Dot0_volumeIDOriginal; + LONG PZVL_2Dot0_reserved[32]; +#if zMAX_COMPONENT_NAME != 256 +#error This buffer is persistent so changes will be needed. +#endif + unicode_t PZVL_2Dot0_volumeName[zMAX_COMPONENT_NAME]; + Time_t PZVL_2Dot0_deleteTimeStart; + LONG PZVL_2Dot0_deleteState; +#if zMAX_COMPONENT_NAME != 256 +#error This buffer is persistent so changes will be needed. +#endif + unicode_t PZVL_2Dot0_volumeNameOriginal[zMAX_COMPONENT_NAME]; + LONG PZVL_2Dot0_errno; + char PZVL_2Dot0_errnoSetter[48]; + Time_t PZVL_2Dot0_purgeTimeStart; + Time_t PZVL_2Dot0_purgeTimeLastStart; + Time_t PZVL_2Dot0_purgeTimeLastEnd; + SQUAD PZVL_2Dot0_purgeLogBlocks; + Zid_t PZVL_2Dot0_lastZidTruncated; +} NSS_MEDIA_STRUCTURE(PersistentZlssVolumeLocator_2Dot0_s,PZVL_2Dot0_lastZidTruncated) PersistentZlssVolumeLocator_2Dot0_s; + + +void ZLSSVOL_LVD_DeleteScanThread( + FsmLite_s *fsmLite, + void *notUsed ); + +void ZLSSVOL_LVD_DeleteScanTimer( + OneShot_s *alarm); + +File_s *ZVL_Create( + GeneralMsg_s *genMsg, + unicode_t *fullName, + NINT fileType, + NINT fileAttributes, + NINT createFlags, + Key_t *retKey); + +void ZFSPOOL_ShutdownPool( + ZfsPool_s *poolVolume ); + +STATUS ZLSSVOL_PoolNameMangle( + CONST unicode_t *poolName, /* Current pool name */ + NINT *mangleKey, /* Mangle Key, must point to 0 on first call */ + NINT uniSize, /* Number of unicode newPoolName can hold */ + unicode_t *newPoolName ); /* New mangled name */ + + +STATUS ZLSSVOL_LoadPersistentPool( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + NINT mode, /* Must be VOLMODE_xxx define */ + NINT flags); /* Must be LPP_FLAGS_xxx define (or 0) */ + +STATUS ZLSSVOL_LoadSystemBeasts( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume); + +STATUS ZLSSVOL_LVD_DeleteActionAPI( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + unsigned long action ); + +STATUS ZLSSVOL_LV_GetInfoAPI( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + unsigned long action, + NINT offset, + NINT retBufLen, + BYTE *retBuf, + NINT *retLen ); + +void ZLSSVOL_LVD_DeleteListAddAndInit( + ZLSSVOL_LVD_DeleteQueueInfo_t *dqi, + ZlssVolumeLocator_s *zvlBeast, + ZfsVolume_s *zVolume ); + +void ZLSSVOL_LVD_DeleteListRemove( + ZLSSVOL_LVD_DeleteQueueInfo_t *dqi ); + +void ZLSSVOL_LVD_DeleteListRemoveAllFromPool( + Volume_s *volume ); + +ZfsVolume_s *ZLSSVOL_NewLVBeast( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + ZfsPool_s *pool, + unicode_t *zVolumeName); + + +ZfsVolume_s *ZLSSVOL_NewFakeLVBeast( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + ZfsPool_s *pool, + unicode_t *zVolumeName); + +STATUS ZLSSVOL_LV_AutoRename( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast); + +STATUS ZLSSVOL_LV_Snapshot( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast ); + + +STATUS ZLSSVOL_LV_Create( + GeneralMsg_s *genMsg, + Volume_s *pVolume, + unicode_t *zVolumeName, + QUAD zVolumeSize, + NINT authModelID, + const VolumeID_t *requestedVolumeID, + BOOL virtualFileFlag, + struct ZfsXaction_s *xactiom, + BOOL autoIPU ); + +STATUS ZLSSVOL_LVD_DeleteActionPause( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + ZfsVolume_s *zVolume ); + +STATUS ZLSSVOL_LVD_DeletePurge( + GeneralMsg_s *genMsg, + ZLSSVOL_LVD_DeleteQueueInfo_t *dqi, + ZlssVolumeLocator_s *zvlBeast, + ZfsVolume_s *zVolume, + ZfsPool_s *poolVolume, + BOOL verbose ); + +void ZLSSVOL_LVD_DeleteUndeleteThread( + FsmLite_s *fsmLite, + ZLSSVOL_LVD_DeleteQueueInfo_t *dqi ); + +void ZLSSVOL_LVD_DeletePurgeThread( + FsmLite_s *fsmLite, + ZLSSVOL_LVD_DeleteQueueInfo_t *dqi ); + +STATUS ZLSSVOL_LV_ZVLDeleteDirectory( + GeneralMsg_s *genMsg, + unicode_t *containerVolumeName ); + + File_s *ZLSSVOL_LV_ZVLCreateDirectory( + GeneralMsg_s *genMsg, + unicode_t *containerVolumeName, + struct ZfsXaction_s *xaction, + BOOL autoIPU ); + + ZlssVolumeLocator_s *ZLSSVOL_LV_ZVLCreate( + GeneralMsg_s *genMsg, + unicode_t *zVolumeName, + ZfsVolume_s *zVolume, + VolumeID_t zVolumeID, + unicode_t *containerVolumeName, + struct ZfsXaction_s *xaction, + BOOL autoIPU, + NINT authModelID ); + +#if NSS_DEBUG IS_ENABLED +STATUS doZLSSVOL_LV_NameCheck( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); +#endif + +Time_t ZLSSVOL_LVD_SalvageableTimeGet( + ZlssVolumeLocator_s *zvlBeast ); + +STATUS ZLSSVOL_LVD_NTTruncate( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + ZlssVolumeLocator_s *zvlBeast ); + +STATUS ZLSSVOL_LVD_NTNodeValidate( + GeneralMsg_s *genMsg, + struct ZfsNameTree_s *nameTree, + struct Node_s *node, + NINT level); + +STATIC STATUS ZLSSVOL_LVD_NTShrinkLeafOverflow( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + NINT eIndex, /* index of DUP LEAF entry */ + Buffer_s *eBuffer, + Blknum_t ovFlowBlk ); /* 1st LEAF OVERFLOW block */ + +STATIC STATUS ZLSSVOL_LVD_NTDepthRightVisit( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *parentBuffer, + NINT *depth ); + +STATIC STATUS ZLSSVOL_LVD_NTShrinkVisit( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *parentBuffer, + NINT *level, + NINT leafLevel ); + +STATIC STATUS ZLSSVOL_LVD_NTDepthRightBranchNode( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *brBuffer, + Buffer_s *ovBuffer, + NINT *depth ); + +STATIC STATUS ZLSSVOL_LVD_NTShrinkBranchNode( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *brBuffer, + Buffer_s *ovBuffer, + NINT *level, + NINT leafLevel ); + +STATIC STATUS ZLSSVOL_LVD_NTShrinkLast( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree ); + +STATIC STATUS ZLSSVOL_LVD_NTShrink( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + NINT leafLevel ); + +STATIC STATUS ZLSSVOL_LVD_NTDepthRightBranchChild( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *parentBuffer, + Blknum_t childBlock, + NINT *depth ); + +STATIC STATUS ZLSSVOL_LVD_NTShrinkBranchChild( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + Buffer_s *parentBuffer, + Blknum_t *childBlockPtr, + NINT *level, + NINT leafLevel ); + +STATIC STATUS ZLSSVOL_LVD_NTDepthRight( + GeneralMsg_s *genMsg, + ZfsNameTree_s *nameTree, + NINT *depth ); + +STATIC STATUS ZLSSVOL_LVD_BTShrinkLast( + GeneralMsg_s *genMsg, + ZfsBeastTreeBeast_s *beastTree ); + +STATIC STATUS ZLSSVOL_LVD_BTDepthRight( + GeneralMsg_s *genMsg, + struct ZfsBeastTreeBeast_s *beastTree, + SNINT *depth ); + +STATIC STATUS ZLSSVOL_LVD_BTDepthVisitRight( + GeneralMsg_s *genMsg, + SNINT *depth, + struct ZfsBeastTreeBeast_s *beastTree, + struct BeastTreeNode_s *node, + Blknum_t blknum ); + +STATUS ZLSSVOL_LVD_ShrinkRoot( + GeneralMsg_s *genMsg, + ZfsBtreeBeast_s *bTree ); + +STATIC STATUS ZLSSVOL_LVD_BTShrink( + GeneralMsg_s *genMsg, + struct ZfsBeastTreeBeast_s *beastTree, + SNINT leafLevel ); + +STATUS ZLSSVOL_LVD_BTTruncate( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + ZlssVolumeLocator_s *zvlBeast ); + +STATIC STATUS ZLSSVOL_LVD_BTShrinkVisit( + GeneralMsg_s *genMsg, + struct ZfsBeastTreeBeast_s *beastTree, + struct BeastTreeNode_s *nodeParent, + Buffer_s *bufferParent, + SNINT *level, + SNINT leafLevel, + Blknum_t blknum ); + +STATUS ZLSSVOL_LVD_BTNodeValidate( + GeneralMsg_s *genMsg, + struct ZfsBeastTreeBeast_s *beastTree, + struct BeastTreeNode_s *node, + SNINT level ); + +STATUS ZLSSVOL_LVD_MovePurgeLog( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + ZlssVolumeLocator_s *zvlBeast ); + +ZlssVolumeLocator_s *ZLSSVOL_LV_ZVLOpen2( + GeneralMsg_s *returnGenMsg, + ZfsVolume_s *zVolume, + Key_t *retKey ); + +void ZLSS_LV_DeleteAllUserObjectsThread( + FsmLite_s *fsmLite, + Volume_s *vol); + +STATUS ZLSSVOL_LV_TruncateABeast( + GeneralMsg_s *genMsg, + RootBeast_s *rootBeast ); + +STATUS ZLSSVOL_LV_CreateAPI( + GeneralMsg_s *genMsg, + unicode_t *poolName, + unicode_t *volumeName, + NINT authModelID, + QUAD diskQuota, + GUID_t *guid, + BOOL virtualFileFlag ); + +STATIC STATUS ZVL_ModifyInfo( + GeneralMsg_s *genMsg, + unicode_t *fullName, + NINT modifyInfoMask, + NINT modifyTypeInfoMask, + zInfo_s *modifyInfo, + void *modifyTypeInfo); + +STATUS ZLSSVOL_LV_AddRI( + GeneralMsg_s *genMsg, + unicode_t *fullName ); + +STATUS ZLSSVOL_LV_RemoveRI( + GeneralMsg_s *genMsg, + unicode_t *fullName ); + +STATUS ZLSSVOL_LV_RemoveDICIRI( + GeneralMsg_s *genMsg, + unicode_t *fullName ); + +STATUS ZVL_Delete( + GeneralMsg_s *genMsg, + unicode_t *fullName, + NINT deleteFlags); + +STATUS doZLSSVOL_LV_Scan( + PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +STATUS doZLSSVOL_LVD_UISalvageable( + PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +STATUS doZLSSVOL_LVD_UIBasic( + PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +STATUS doZLSSVOL_LV_Truncate( + PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +STATUS ZLSSVOL_LVD_TruncatePurgeLog( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + ZfsPool_s *poolVolume, + ZlssVolumeLocator_s *zvlBeast ); + +STATUS ZLSSVOL_LVD_FreeLastBlocks( + GeneralMsg_s *genMsg, + ZfsPool_s *poolVolume, + ZlssVolumeLocator_s *zvlBeast ); + +STATUS ZLSSVOL_LVD_DeleteZVLB( + GeneralMsg_s *genMsg, + ZfsPool_s *poolVolume, + ZlssVolumeLocator_s *zvlBeast ); + +STATUS ZLSSVOL_LVD_LoadModeDeletion( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + ZfsVolume_s *zVolume, + ZfsPool_s *poolVolume, + BOOL verbose ); + +STATUS ZLSSVOL_LVD_DeleteAPI( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + NINT mode ); + +STATUS ZLSSVOL_LVR_RenameAPI( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + unicode_t *newVolumeNam ); + +STATUS ZLSSVOL_LVD_SubStateUpdate( + GeneralMsg_s *genMsg, + struct ZfsXaction_s *xaction, + Volume_s *volume, + ZlssVolumeLocator_s *zvlBeast, + LONG newSubState ); + +STATUS ZVL_Rename( + GeneralMsg_s *genMsg, + unicode_t *oldFullName, + unicode_t *newFullName, + NINT renameFlags ); + +STATUS ZLSSVOL_LV_ZVLRename( + GeneralMsg_s *genMsg, + unicode_t *oldVolumeName, + unicode_t *newVolumeName, + unicode_t *containerVolumeName ); + +STATUS ZLSSVOL_LV_UnloadAll( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool ); + +STATUS ZLSSVOL_LV_Unload( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume ); + +ZfsVolume_s *ZLSSVOL_LV_LoadVerify( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + Volume_s *storageVolume, + BOOL verbose, + BOOL activate ); + +ZfsVolume_s *ZLSSVOL_LV_Load( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + Volume_s *storageVolume, + BOOL verbose, + BOOL activate ); + +STATUS ZLSSVOL_LV_LoadAll( + GeneralMsg_s *genMsg, + ZfsPool_s *pool, + BOOL verbose, + BOOL activate, + BOOL cvsLatched ); + +STATUS ZLSSVOL_LV_Scan( + GeneralMsg_s *genMsg, + NamingMsg_s *nameMsg, + SearchMsg_s *searchMsg, + ZfsPool_s *zlssPool, + ZlssVolumeLocator_s **ret_zvlBeast ); + +STATUS ZLSSVOL_DoFlushSystemBeasts( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + BOOL deactivating); /* if TRUE we are deactivating the volume, else flushing*/ + +void ZLSSVOL_UnloadPersistentPool( + ZfsVolume_s *zVolume, + NINT mode ); + +void ZLSSVOL_UnloadSystemBeasts( + ZfsVolume_s *zVolume); + +STATUS ZFSVOL_VOL_MakeVolumeFreeSpace( + GeneralMsg_s *genMsg, + void *volume_LX, + BOOL purgeAllDeletedFiles, + BOOL asyncPurge, + QUAD numberOfBlocks); + +STATUS doChangePoolState( + PCLSwitchDef_s *switchDef, + NINT options, + void *userParm); + +STATUS doChangePoolStateForce( + PCLSwitchDef_s *switchDef, + NINT options, + void *userParm); + +void ZFT_BlockFree( + ZfsVolume_s *zVolume, + struct ZfsXaction_s *xaction, + NINT blockCount, + Blknum_t *blockArray); /* in/out */ + +STATUS ZFT_BlockAlloc( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + Extent_s *request, + BOOL systemRequest, + struct ZfsXaction_s *xaction, + Blknum_t *blockArray); /* out */ + + +//STATUS ZLSSVOL_LV_Delete( +// GeneralMsg_s *genMsg, +// struct ZfsXaction_s *xaction, +// ZfsVolume_s *zVolume ); + +STATUS ZLSSVOL_LV_ZVLDelete( + GeneralMsg_s *genMsg, + unicode_t *zVolumeName, + unicode_t *containerVolumeName ); + +File_s *ZVL_Open( + GeneralMsg_s *genMsg, + unicode_t *fullName, + Key_t *retKey); + +ZfsVolume_s *ZLSSVOL_LV_LoadByName( + GeneralMsg_s *genMsg, + unicode_t *containerVolumeName, + unicode_t *zVolumeName, + ZlssPool_s *zlssPool, + Xaction_s *xation); + +void ZLSSVOL_LVD_ErrorRecordClear( + ZlssVolumeLocator_s *zvlBeast ); + + /*** ZLSS Logical Volume Auto In Place Upgrade Routines ***/ +STATUS ZLVAIPU_FTWalk( GeneralMsg_s *genMsg, ZfsPool_s *pool, Blknum_t *blockCount ); +STATUS ZLVAIPU_PLWalk( GeneralMsg_s *genMsg, ZfsPool_s *pool, Blknum_t *blockCount ); +STATUS ZLVAIPU_PTWalk( GeneralMsg_s *genMsg, ZfsPool_s *pool, Blknum_t *blockCount ); +STATUS ZLVAIPU_VolumePurgeLogCreate( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + struct ZfsXaction_s *xaction ); + +STATUS ZLVAIPU_TestAndSetBlock( + GeneralMsg_s *genMsg, + Blknum_t blockNum, + BlockMap_s *bitMap ); + +void ZLVAIPU_TestAndSetBlockShutdown( + char *where, + BlockMap_s *bitMap ); + +STATUS ZLVAIPU_TestAndSetBlockStartup( + GeneralMsg_s *genMsg, + char *where, + Blknum_t numberOfBlocks, + BlockMap_s *bitMap ); + +void ZLVAIPU_DisplayError( GeneralMsg_s *genMsg, char *where ); + +STATUS ZLSSPOOL_WriteInitialLPDB( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool, + struct ZfsXaction_s *xaction); + +STATUS ZLSSPOOL_WriteInitialPDB( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool, + struct ZfsXaction_s *xaction); + +STATUS ZLSSVOL_LV_ZVLRenameAsync( + GeneralMsg_s *genMsg, + unicode_t *oldName, + unicode_t *newName, + unicode_t *containerVolumeName ); + +void ZLSSVOL_LV_ZVLRenameThread( + FsmLite_s *fsmLite, + struct ZLSSVOL_ZVL_RenameInfo_t *ri ); + +STATUS ZLSSVOL_LV_GetInfoCreated( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + ZfsVolume_s *zVolume, + NINT offset, + NINT retBufLen, + BYTE *retBuf, + NINT *retLen ); + +STATUS ZLSSVOL_LV_GetInfoDeletion( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + ZfsVolume_s *zVolume, + NINT offset, + NINT retBufLen, + BYTE *retBuf, + NINT *retLen ); +void ZLSSVOL_InitLVDB( + ZfsVolume_s *zVolume, + QUAD totalBlocks, + Time_t epoch, + QUAD inUseBlocks, + BOOL resetCountsOnly ); + +void ZLSSVOL_InitVDB( + ZfsVolume_s *zVolume, + Blknum_t lvdb, + Blknum_t vdb, + Blknum_t btSpecialBlock, + Time_t createTime, + LONG rebuildCount, + Time_t rebuildTime, + BOOL virtualFileFlag ); + +void ZLSSPOOL_PoolVolDataInitialize( + ZfsPool_s *pool, + StorPool_s *storagepool); + +void ZLSSPOOL_InitLPDB( + ZlssPool_s *zlssPool, + Blknum_t totalBlocks, + BOOL repairFlag ); + +void ZLSSPOOL_InitPDB( + ZlssPool_s *zlssPool, + Blknum_t totalBlocks, + LONG blockShift, + QUAD persistentElsewhere, + BOOL repairFlag ); + +STATUS ZLVAIPU_FTValidate( + GeneralMsg_s *genMsg, + Buffer_s *parentBuffer ); + +STATUS ZLSSVOL_LV_ZVLDeleteAsync( + GeneralMsg_s *genMsg, + unicode_t *zVolumeName, + unicode_t *containerVolumeName ); + +STATUS ZLSSVOL_LVD_DeleteStateUpdate( + GeneralMsg_s *genMsg, + ZlssVolumeLocator_s *zvlBeast, + ZfsVolume_s *zVolume, + LONG newDeleteState ); + +STATUS ZLSSVOL_LVD_DeleteActionPurgeInternal( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + ZfsVolume_s *zVolume ); + +STATUS ZLSSVOL_LVD_DeleteActionSalvageInternal( + GeneralMsg_s *genMsg, + unicode_t *volumeName, + ZfsVolume_s *zVolume ); + +STATUS ZLSSVOL_LVD_ChangeVolumeStateWhenPoolLockedActive( + GeneralMsg_s *genMsg, + ZfsVolume_s *zVolume, + NINT destState, + NINT mode ); + +STATUS ZLSSVOL_LVD_DeleteAPIInternal( + GeneralMsg_s *genMsg, + unicode_t *oldVolumeName, + NINT mode, + VolumeID_t *retVolumeID); + +STATUS ZLSSVOL_LV_ZVLRenameInternal( + GeneralMsg_s *genMsg, + unicode_t *oldVolumeName, + unicode_t *newVolumeName, + unicode_t *containerVolumeName ); + +void ZLSSVOL_LVD_UIBasic( void ); + +void ZLSSVOL_LVD_UISalvageable( void ); + +STATUS ZLVAIPU_Step5_Async( + GeneralMsg_s *genMsg, + ZlssPool_s *zlssPool ); + +void ZLVAIPU_AbortXLocal( + GeneralMsg_s *genMsg, + ZfsPool_s *zfsPool ); + +#endif /* #ifndef _ZLSSLOGICALVOLUME_H_ */ diff --git a/src/nwnss/zlss/zlssMSAP.h b/src/nwnss/zlss/zlssMSAP.h new file mode 100644 index 0000000..2c71946 --- /dev/null +++ b/src/nwnss/zlss/zlssMSAP.h @@ -0,0 +1,306 @@ +/**************************************************************************** + | + | (C) Copyright 1999-2002 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | ZLSS - The 'Z' LSS code for Logical Volumes(LVs) + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2005-04-27 21:31:30 +0530 (Wed, 27 Apr 2005) $ + | + | $RCSfile$ + | $Revision: 961 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define MSAP information + +-------------------------------------------------------------------------*/ + +#ifndef _ZLSSMSAP_H_ +#define _ZLSSMSAP_H_ + +#define MSAP_BW_DEFAULT 0x0000000 +#define MSAP_BW_IGNORE_DISABLE 0x0000001 /* Do the write even though pool is disabled */ + + + +#define MSAP_RESPONSE_CHECK_SECONDS 2 /* Check for a probe response every 2 seconds */ +#define MAX_IO_RETRY_COUNT_ALLEN 3 /* Allens says three is the most we should retry */ +#define MSAP_IO_DELAY 15 /* Amount of time that a read and then a write + * must be able to complete in. Used by servers + * waiting for a probe request to ensure that they + * have given a 'owner' enough time to respond. + */ + +typedef struct MSAP_Block_s +{ + LONG MSAP_SignatureMinor; +#define MSAP_SIGNATURE 0x4d534150 /* "MSAP" */ + LONG MSAP_SignatureMajor; /* By having second; scan can use current logic and + * if not a known match can find unknown blocks + * by looking at 2nd long of block. + */ + Lsn_t MSAP_LsnNotUsed; /* Not currently used as block is not transactioned. */ + GUID_t MSAP_InternalID; /* Must be at offset 16. This is set to the pool's + * internal ID at init time. This value is never + * changed. + */ + GUID_t MSAP_ServerID; /* This indicates the server that currently owns + * access to the pool. See specification for + * details. The server calls this field the pool id. + */ + GUID_t MSAP_ClusterID; /* This indicates the cluster that we are active in. + * The value zZERO_GUID indicates we are not part + * of a cluster at this time. I.E. if we are part + * of a cluster, but not running cluster software + * then this field has zZERO_GUID in it. + */ + GUID_t MSAP_ProbeRequestID; /* If non-zero then the Server ID of the server that + * is doing a probe. When doing a probe set this field + * to the Server ID and the MSAP_ProbeResponse field + * to zero. Also update all other MSAP_ProbeRequestxxx fields. + */ + GUID_t MSAP_ProbeResponseID; /* If non-zero then the Server ID of the server that + * did the probe response. When responding to a probe + * this field is set to MSAP_ProbeRequestID and then + * MSAP_ProbeRequestID is set to 0. All other + * MSAP_ProbeResponsexxx fields are set. + */ + LONG MSAP_InitialUTC; /* UTC of time that block was initialized */ + LONG MSAP_WroteUTC; /* UTC of time that last write occurred */ + WORD MSAP_VersionMajor; +#define MSAP_VERSION_MAJOR 1 + WORD MSAP_VersionMinor; +#define MSAP_VERSION_MINOR 0 + WORD MSAP_ProbeRequestIDListSlot; /* 0 to 7. SLot to use next in Probe request ID list */ + WORD MSAP_ProbeResponseIDListSlot; /* 0 to 7. SLot to use next in Probe response ID list */ + WORD MSAP_ServerIDListSlot; /* 0 to 19. Slot to use next in Owner ID list */ + WORD MSAP_ProbeSeconds; /* Amount of time that owner lets go by before doing a + * check for porbe requests. + */ +#define MSAP_PROBE_SECONDS_DEFAULT (14) /* Originally 45 in specification */ + WORD MSAP_ProbeSecondsMinimum; /* Minimum value for above */ +#define MSAP_PROBE_SECONDS_MINIMUM (1) + WORD MSAP_ProbeSecondsMaximum; /* Maximum value for above */ +#define MSAP_PROBE_SECONDS_MAXIMUM (5*60) + QUAD MSAP_ServerIDCount; /* Total number of owner updates that have ever been done. */ + QUAD MSAP_ProbeRequestCount; /* Total number of probe request ever done. */ + QUAD MSAP_ProbeResponseCount; /* Total number of probe response ever done. */ +#define MSAP_REQUEST_COUNT 12 + GUID_t MSAP_ProbeRequestIDList[MSAP_REQUEST_COUNT]; /* Last z probe requestors. If items + * are in this list then either someone has their SAN set up + * wrong (I.E. allowing mulitple servers to access a POOL + * without clustering software) OR the Server ID has changed. + */ + GUID_t MSAP_ProbeRequestIDClusterList[MSAP_REQUEST_COUNT]; + LONG MSAP_ProbeRequestIDListUTC[MSAP_REQUEST_COUNT]; /* UTC of above probes ID List */ +#define MSAP_RESPONSE_COUNT 12 + GUID_t MSAP_ProbeResponseIDList[MSAP_RESPONSE_COUNT]; /* Last x probe responders (owner who did response). */ + GUID_t MSAP_ProbeResponseIDTargetList[MSAP_RESPONSE_COUNT]; /* Last x probe responders targets (who reponse was directed to). */ + LONG MSAP_ProbeResponseIDListUTC[MSAP_RESPONSE_COUNT]; /* UTC of above probe responses ID List */ +#define MSAP_POOL_COUNT 24 + GUID_t MSAP_ServerIDList[MSAP_POOL_COUNT]; /* Last y pool owners. This is updated every time + * a pool is activated. + */ + GUID_t MSAP_ClusterIDList[MSAP_POOL_COUNT]; /* The cluster that the above owners are part of */ + LONG MSAP_ServerIDListUTC[MSAP_POOL_COUNT]; /* UTC of when above took ownership */ + BYTE MSAP_ServerIDListFlags[MSAP_POOL_COUNT];/* 0x01 indicates that the owner is not running revalidate + * logic. Either the pool is marked as no MSAP or MSAP + * is turned off at the server. This information is + * useful on scanned pools to detect if the pool should + * have had MSAP enabled. + */ + BYTE MSAP_ServerIDFlags; +#define MSAP_FLAGS_DEFAULT MSAP_FLAGS_MSAP +#define MSAP_FLAGS_MSAP 0x01 +#define MSAP_FLAGS_STEAL 0x02 /* Set when owner steals back a stolen pool */ +#define MSAP_FLAGS_INIT 0x04 /* Block initialized/rebuilt */ + BYTE MSAP_Reserver4[1]; + WORD MSAP_ProbeReponseSeconds; +#define MSAP_PROBE_RESPONSE_SECONDS_DEFAULT (MSAP_PROBE_SECONDS_DEFAULT+MSAP_IO_DELAY) + LONG MSAP_Reserved3[36]; + LONG MSAP_SignatureMinor2; + /* MSAP block is only 2K - Went to 4K in Feb 2004 for NSS 4.x as Paul + * is requiring all I/O to be 4K. */ + BYTE MSAP_Junk[2048]; /* Since block was 2K at some point this part of block + * will have random data in it. + */ +} NSS_MEDIA_STRUCTURE(MSAP_Block_s,MSAP_Junk[2048]) MSAP_Block_s; + + +#define MSAP_SECTOR_COUNT 8 /* Number of sectors in a MSAP block */ + +/* + * MSAP_PoolStateInfo_s - + * This data structure exists for each ZLSS POOL that is being watched + * by the MSAP code. This means when a qualified pool is in the pool + * state of ACTIVE or MAINTENANCE. ZlssPool_s->ZP_MSAPInfo points + * to this allocated structure. + */ +typedef struct MSAP_PoolStateInfo_s { + LONG MPSI_signature; +#define MSAP_MPSI_SIGNATURE 0x49586378 + ZlssPool_s *MPSI_zlssPool; + Time_t MPSI_scheduledUTC; /* Last time scheduled */ + /* In December 2003, I saw that MSAP would not + * destruct because MPSI_scheduled never went FALSE. The + * MPSI_scheduledUTC was about 6 hours before curent time. + * I only saw this on my Nakoma SP1 server. + */ + Time_t MPSI_lastDoubleScheduledUTC; /* Debug */ + Time_t MPSI_lastTerminateUTC; /* Debug */ + Time_t MPSI_lastOneShotUTC; /* Debug */ + Time_t MPSI_lastPreOwnerUTC; /* Debug */ + Time_t MPSI_lastPostOwnerUTC; /* Debug */ + + BOOL MPSI_scheduled; /* TRUE if our thread is running */ + BOOL MPSI_terminate; /* Someone wishes for the thread to terminate. + * The thread must not schedule a new timer + * pop when a terminate is requested. + */ + LONG MPSI_reserved; + GUID_t MPSI_serverID; /* Server ID at time of Pool Activate Logic. + * We store and use because if the real + * server ID changes on us while the pool + * is active we will disable it. + */ + GUID_t MPSI_clusterID; /* Cluster ID at time of Pool Activate Logic. + */ + OneShot_s MPSI_timer; + FsmLite_s MPSI_fsmLite; + MSAP_Block_s MPSI_mSAP; +} MSAP_PoolStateInfo_s; + + +STATUS MSAP_OwnershipRevalidate( + ZlssPool_s *zlssPool ); +STATUS MSAP_OwnershipPoolDisable( + ZlssPool_s *zlssPool ); +void MSAP_OwnershipFatal( + ZlssPool_s *zlssPool, + STATUS fatalStatus ); +STATUS MSAP_ProbeResponseNeeded( + ZlssPool_s *zlssPool ); +void MSAP_OwnershipRevalidateAsync( + ZlssPool_s *zlssPool, + NINT seconds ); +void MSAP_WorkScheduleTimer( + OneShot_s *alarm); +void MSAP_OwnerThread( + FsmLite_s *fsmLite, + MSAP_PoolStateInfo_s *pSI ); +STATUS MSAP_ProbeResponsePhysical( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP, + GUID_t *serverID ); +void MSAP_ProbeResponse( + MSAP_Block_s *mSAP, + GUID_t *serverID ); +STATUS MSAP_PoolOwnerLogic( + ZlssPool_s *zlssPool ); +STATUS MSAP_ClusterIDUpdate( + ZlssPool_s *zlssPool ); +BOOL MSAP_PoolInhibitorLogicRequired( + ZlssPool_s *zlssPool ); +STATUS MSAP_PoolActivateLogic( + ZlssPool_s *zlssPool, + GeneralMsg_s *genMsg ); +void MSAP_PoolStateInfoZlssPoolFree( + ZlssPool_s *zlssPool ); +STATUS MSAP_OwnershipValidateProbe( + ZlssPool_s *zlssPool ); +STATUS MSAP_ProbeRequestPhysical( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID ); +void MSAP_ProbeRequest( + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID ); +STATUS MSAP_OwnerStatsUpdatePhysical( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID ); +void MSAP_OwnerStatsUpdate( + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID, + BYTE mSAPFlags ); +STATUS MSAP_OwnershipTakeBackPhysical( + ZlssPool_s *zlssPool ); +STATUS MSAP_ClusterIDPhysical( + ZlssPool_s *zlssPool ); +STATUS MSAP_OwnershipTakePhysical( + ZlssPool_s *zlssPool, + BYTE mSAPFlags ); +void MSAP_OwnershipTake( + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID, + BYTE mSAPFlags ); +BOOL MSAP_AreWeOwner( + MSAP_Block_s *mSAP, + GUID_t *serverID ); +BOOL MSAP_AreWeClearOwner( + MSAP_Block_s *mSAP, + GUID_t *serverID ); +BOOL MSAP_AreWeClearOwnerCluster( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP, + GUID_t *serverID, + GUID_t *clusterID ); +MSAP_PoolStateInfo_s *MSAP_PoolStateInfoNew( + ZlssPool_s *zlssPool, + GUID_t *serverID, + GUID_t *clusterID ); +void MSAP_PoolStateInfoFree( + MSAP_PoolStateInfo_s *pSI ); +void MSAP_PoolStateInfoDestruct( + MSAP_PoolStateInfo_s *pSI ); +void MSAP_PoolStateInfoConstruct( + MSAP_PoolStateInfo_s *pSI, + ZlssPool_s *zlssPool, + GUID_t *serverID, + GUID_t *clusterID ); +STATUS MSAP_SectorRead( + ZlssPool_s *zlssPool, + void *ioBuffer ); /* Must be at least 512*4 in size */ +STATUS MSAP_BlockReadAndValidate( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP ); +STATUS MSAP_BlockRead( + ZlssPool_s *zlssPool, + void *ioBuffer ); +STATUS MSAP_SectorWrite( + ZlssPool_s *zlssPool, + void *ioBuffer, /* Must be at least 512*4 in size */ + NINT flags ); +STATUS MSAP_BlockWrite( + ZlssPool_s *zlssPool, + MSAP_Block_s *mSAP, + NINT flags ); + +extern BOOL MSAP_Enabled; + +#endif /* #ifndef _ZLSSMSAP_H_ */ diff --git a/src/nwnss/zlss/zlssManage.h b/src/nwnss/zlss/zlssManage.h new file mode 100644 index 0000000..7dbc550 --- /dev/null +++ b/src/nwnss/zlss/zlssManage.h @@ -0,0 +1,151 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1999 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Structures, defines and proto-types used by ZLSS manage code. + +-------------------------------------------------------------------------*/ +#ifndef _ZLSSMANAGE_H_ +#define _ZLSSMANAGE_H_ + +#include "zlog.h" +#include "zlssIOPerformance.h" /* Need VCF_BROWSE */ + +STATUS ZLSS_ErrNoAndErrNoSetterSet( + VirtInfo_s *virtInfo, + GeneralMsg_s *genMsg ); + +void ZLSS_DebugHexDump( + void *userArea, + int length, + int size, + VirtInfo_s *virtInfo ); + +void ZLSS_DebugHexDumpNoASCII( + void *userArea, + int length, + int size, + VirtInfo_s *virtInfo ); + +STATUS ZLSS_VF_ReadBlock( + GeneralMsg_s *genMsg, + NINT parmLen, + utf8_t *parm, + NINT dataLen, + BYTE *data, + NINT offset, + VirtInfo_s *virtInfo ); + +STATUS ZLSS_VF_ReadTest( + GeneralMsg_s *genMsg, + NINT parmLen, + utf8_t *parm, + NINT dataLen, + BYTE *data, + NINT offset, + VirtInfo_s *virtInfo ); + +STATUS ZLSS_XML_Head( + VirtInfo_s *virtInfo, + GeneralMsg_s *genMsg ); + +STATUS ZLSS_XML_Tail( + VirtInfo_s *virtInfo, + GeneralMsg_s *genMsg ); + +STATUS sDisplayHistogram( + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen, + ZlogHistogram_s *hist ); + +STATUS ZLOG_DisplayHistograms( + ZlogBeast_s *zlogBeast, + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen ); + +STATUS ZLSS_XML_HeadReadBlock( + unicode_t *poolName, + Blknum_t blockNumber, + VirtInfo_s *virtInfo ); + +STATUS ZLSS_XML_TailReadBlock( + VirtInfo_s *virtInfo ); + +#ifdef VCF_BROWSE +STATUS ZLSS_VF_Browse( + GeneralMsg_s *genMsg, + NINT parmLen, + utf8_t *parm, + NINT dataLen, + BYTE *data, + NINT offset, + VirtInfo_s *virtInfo ); +#endif + +STATUS ZLSS_RebuildFileDetails( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_RebuildFileStatus( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_VerifyFileDetails( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_VerifyFileStatus( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_RebuildFileStatistics( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_VerifyFileStatistics( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_RebuildFileDebug( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_RebuildFileLog( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_VerifyFileLog( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); +STATUS ZLSS_VerifyFileDebug( NINT parmLen, utf8_t *parm, struct VirtInfo_s *virtInfo ); + +STATUS ZLSS_ZLogReadMetadata2( + GeneralMsg_s *genMsg, + NINT parmLen, + utf8_t *parm, + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen, + VirtInfo_s *virtInfo); + +STATUS ZLSS_ZLogReadMetadata2XML( + GeneralMsg_s *genMsg, + NINT parmLen, + utf8_t *parm, + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen, + VirtInfo_s *virtInfo); + +STATUS sDisplayHistory( + NINT bufferLength, + BYTE **bufferAddress, + NINT *retLen, + ZlogHistory_s *hist ); + +#endif /* _ZLSSMANAGE_H_ */ diff --git a/src/nwnss/zlss/zlssStartup.h b/src/nwnss/zlss/zlssStartup.h new file mode 100644 index 0000000..d1390f1 --- /dev/null +++ b/src/nwnss/zlss/zlssStartup.h @@ -0,0 +1,203 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Command Line Support module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | command line options for all input action + | + +-------------------------------------------------------------------------*/ +#ifndef _ZSTORESTARTUP_H_ +#define _ZSTORESTARTUP_H_ + +#ifndef _OMNI_H_ +# include +#endif + +#ifndef _DISPLAYVERSION_H_ +# include +#endif + +#define MODULE_NAME MSGNot("ZLSS") +extern const char Module[]; + +/*------------------------------------------------------------------------- + * Global variables + *-------------------------------------------------------------------------*/ +#ifdef __linux__ +extern void *ZSTORE_ModuleHandle; +#else +extern struct LoadDefinitionStructure *ZSTORE_ModuleHandle; +#endif +extern VersionInformation_s ZSTORE_VersionInfo; +extern struct PCLSwitchDef_s ZSTORE_CommandLineSwitches[]; + +#if NSS_DEBUG IS_ENABLED + extern BOOL ResetPools; + extern BOOL SkipCheckpoints; + extern BOOL SkipRecovery; + extern NINT CrashPools; /* Prevents shutdown code from being called + * at ZSTORE /EXIT time. */ + extern NINT zfsDebugBtree; + extern BOOL gZCL_SkipWrites; + extern BOOL GenerateOutOfDiskSpaceErrors; + extern NINT GenerateOutOfDiskSpaceErrorsBreakCount; + +#ifndef __linux__ // LINUX_ZlogDebug + /* These items are to supply the Netware Volume to commands */ + extern char GCL_ZlogFileCopy[16]; /* GCL_ Global Command Line */ + extern char GCL_ZlogBeastCopy[16]; /* GCL_ Global Command Line */ + extern char PoolSave[16]; + extern char PoolRestoreImage[16]; + extern char PoolCompare[16]; +#endif //__linux__ + +#if LOG_TEST IS_ENABLED + extern BOOL LogTest; +#endif + +#if FMAP_TEST IS_ENABLED + extern BOOL FmapTest; + extern BOOL OneBlockExtents; +#endif + +#if ZLOG_TEST IS_ENABLED + extern BOOL ZlogUnitTest; +#endif + +#endif + + +/*--------------------------------------------------------------------------- + * Global startup + *---------------------------------------------------------------------------*/ +extern STATUS ZSTORE_GlobalStartup(void); +extern void ZSTORE_GlobalShutdown(void); + +/*------------------------------------------------------------------------- + * Commandline function prototypes + *-------------------------------------------------------------------------*/ +//extern STATUS ZSTORE_CommandLineStartup(void); +//extern void ZSTORE_CommandLineShutdown(void); + +//extern STATUS ZSTORE_ParseCommandLine( +// char *cmdline, +// NINT fromLoadCmdline, +// NINT *didHelp); + +extern STATUS ZSTORE_DisplayVersion(void); + +/*------------------------------------------------------------------------- + * ZFSPOOL commands + *-------------------------------------------------------------------------*/ +extern STATUS ZFSPOOL_Startup( + struct GeneralMsg_s *genMsg); + +extern void ZFSPOOL_Shutdown(void); + +void EFL_DisplayEFLTree( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +void EFL_DisplayEFLLog( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +#if NSS_DEBUG IS_ENABLED + +void ZFSPOOL_Layout32( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +void ZFSVOL_CorruptLVDB( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +#ifndef __linux__ // LINUX_ZlogDebug +void ZFSVOL_CorruptToggle( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); +#endif + +void ZfsDisplayBeastTree( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +void DisplayPurgeLogInfo( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +void DBT_DisplayDirTree( + struct PCLSwitchDef_s *switchDef, + NINT index, + void *userParm); + +STATUS doPoolRestoreScan( + struct PCLSwitchDef_s *switchDef, + NINT options, + void *userParm); + +extern unicode_t *ReadBlkVolumeName; /* Generic volume name used by \RB + * commands and \PoolRestoreScan and etc. + */ + +#endif + +/*--------------------------------------------------------------------------- + * ZFS + * + * Routines INIT/UNINIT the memory storage system code + *---------------------------------------------------------------------------*/ +extern STATUS ZSTORE_Startup( + struct GeneralMsg_s *genMsg); + +extern void ZSTORE_Shutdown(void); + +extern STATUS ZSTORE_RegisterLSSOperations( + struct GeneralMsg_s *genMsg); + +extern void ZSTORE_ClearLSSOperations(void); + + +/*--------------------------------------------------------------------------- + * MENU + *---------------------------------------------------------------------------*/ +void NSSMenuMain(void); +void NSSMenuExit(void); + +#endif diff --git a/src/nwnss/zlss/zlssUpgrade.h b/src/nwnss/zlss/zlssUpgrade.h new file mode 100644 index 0000000..5be96ad --- /dev/null +++ b/src/nwnss/zlss/zlssUpgrade.h @@ -0,0 +1,277 @@ +/**************************************************************************** + | + | (C) Copyright 1995 - 2000, 2003 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | + +-------------------------------------------------------------------------*/ +#ifndef _ZLSSUPGRADE_H_ +#define _ZLSSUPGRADE_H_ + +#ifndef _OMNI_H_ +# include +#endif + +/*--------------------------------------------------------------------------- + | Global definitions + +-------------------------------------------------------------------------*/ + + /* + * **** VOLUME verson of media. **** + * + * Media 00.00 - Internal Volumes created in 6Pack FCS, SP1, SP2 + * or SP3. Bug was fixed in Nakoma and 6Pack SP4. The following + * VDB items where not inited correctly in these IVs. + * beastVersionMask Should be 2 was 0. + * beastVersion Should be 2 was 0. + * PV_mediaFormatMajor Should be 35 was 0. + * PV_mediaFormatMajorCreate Should be 35 was 0. + * PV_shredCount Should be 1 was 0. + * + * Media 35.00 - Original LV version. + * + * Media 36.00 - EFL Tree blocks can exist on volume. New COMP beasts + * can exist on volume. + * + * Media 36.01 - No old COMP beasts exist on volume (not true due to a bug). + * + * From the end of 2004 (to fix the above bug): + * Media 36.02, 37.02 - Old style COMP beasts may exist on volume. + * + * Media 36.03, 37.03 (encrypted volume), or 40.03 (auth unix) - + * No old style COMP beasts exist on volume. + * + * **** VOLUME verson of media. **** + * + * **** POOL verson of media. **** + * + * Media 43.01 - All volumes have upgraded to 36.01, 37.00, 40.00 + * + * Media 43.02 - All volumes have upgraded to 36.03, 37.03, 40.03 + * **** POOL verson of media. **** + */ + +#define AIPU_NAKOMA_MEDIA_MAJOR 43 + +#define ZLSS_LV_MEDIA_MAJOR_CURRENT 36 +#define ZLSS_LV_MEDIA_MINOR_CURRENT 03 + +#define ZLSS_LV_MEDIA_MAJOR_NAKOMA 36 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA 01 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_COMP 03 +#define ZLSS_LV_MEDIA_MAJOR_NAKOMA_ENCRYPTED 37 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_ENCRYPTED 00 /* This was released to public, but is not used anymore */ +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_ENCRYPTED_COMP 03 + +#define ZLSS_LV_MEDIA_MAJOR_NAKOMA_HARDLINK 38 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_HARDLINK_START 03 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_HARDLINK_INPROGRESS 04 +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_HARDLINK_DONE 05 + +#define ZLSS_LV_MEDIA_MAJOR_NAKOMA_AUTH_UNIX 40 +//#define ZLSS_LV_MEDIA_MINOR_NAKOMA_AUTH_UNIX 00 /* This minor number is never released to public */ +#define ZLSS_LV_MEDIA_MINOR_NAKOMA_AUTH_UNIX_COMP 03 + +#define ZLSS_MEDIA_VERSION_4006 0x2806 +#define ZLSS_MEDIA_VERSION_4007 0x2807 +#define ZLSS_MEDIA_VERSION_4008 0x2808 +#define ZLSS_MEDIA_VERSION_4009 0x2809 +#define ZLSS_MEDIA_VERSION_4010 0x280a +#define ZLSS_MEDIA_VERSION_4011 0x280b +#define ZLSS_MEDIA_VERSION_4012 0x280c +#define ZLSS_MEDIA_VERSION_4013 0x280d +#define ZLSS_MEDIA_VERSION_4014 0x280e +#define ZLSS_MEDIA_VERSION_4015 0x280f +#define ZLSS_MEDIA_VERSION_4016 0x2810 +#define ZLSS_MEDIA_VERSION_4017 0x2811 +#define ZLSS_MEDIA_VERSION_4018 0x2812 +#define ZLSS_MEDIA_VERSION_4019 0x2813 +#define ZLSS_MEDIA_VERSION_4020 0x2814 +#define ZLSS_MEDIA_VERSION_4021 0x2815 +#define ZLSS_MEDIA_VERSION_4022 0x2816 +#define ZLSS_MEDIA_VERSION_4023 0x2817 +#define ZLSS_MEDIA_VERSION_4024 0x2818 +#define ZLSS_MEDIA_VERSION_4025 0x2819 +#define ZLSS_MEDIA_VERSION_4026 0x281a +#define ZLSS_MEDIA_VERSION_4027 0x281b +#define ZLSS_MEDIA_VERSION_4028 0x281c +#define ZLSS_MEDIA_VERSION_4029 0x281d +#define ZLSS_MEDIA_VERSION_4030 0x281e +#define ZLSS_MEDIA_VERSION_4031 0x281f +#define ZLSS_MEDIA_VERSION_4032 0x2820 +#define ZLSS_MEDIA_VERSION_4033 0x2821 +#define ZLSS_MEDIA_VERSION_4034 0x2822 +#define ZLSS_MEDIA_VERSION_4035 0x2823 +#define ZLSS_MEDIA_VERSION_4036 0x2824 +#define ZLSS_MEDIA_VERSION_4037 0x2825 +#define ZLSS_MEDIA_VERSION_4038 0x2826 +#define ZLSS_MEDIA_VERSION_4039 0x2827 +#define ZLSS_MEDIA_VERSION_4040 0x2828 +#define ZLSS_MEDIA_VERSION_4041 0x2829 +#define ZLSS_MEDIA_VERSION_4042 0x282a +#define ZLSS_MEDIA_VERSION_4043 0x282b +#define ZLSS_MEDIA_VERSION_4044 0x282c +#define ZLSS_MEDIA_VERSION_4045 0x282d +#define ZLSS_MEDIA_VERSION_4046 0x282e +#define ZLSS_MEDIA_VERSION_4047 0x282f +#define ZLSS_MEDIA_VERSION_4048 0x2830 +#define ZLSS_MEDIA_VERSION_4049 0x2831 + +#define ZLSS_MEDIA_VERSION_4084 0x2854 +#define ZLSS_MEDIA_VERSION_4085 0x2855 +#define ZLSS_MEDIA_VERSION_4086 0x2856 +#define ZLSS_MEDIA_VERSION_4087 0x2857 +#define ZLSS_MEDIA_VERSION_4088 0x2858 +#define ZLSS_MEDIA_VERSION_4300 0x2b00 +#define ZLSS_MEDIA_VERSION_4301 0x2b01 +#define ZLSS_MEDIA_VERSION_4302 0x2b02 +#define ZLSS_MEDIA_VERSION_4303 0x2b03 + + +#define ZLSS_VOLUME_MEDIA_VERSION_0000 0x0000 /* A bug in NetWare 6.0 ZLSS causes ALL internal + * volumes create by ZLSS to have their version + * inited to 0. Upgraded pools from 5.x do not + * have this bug. + */ +#define ZLSS_VOLUME_MEDIA_VERSION_3500 0x2300 +#define ZLSS_VOLUME_MEDIA_VERSION_3501 0x2301 +#define ZLSS_VOLUME_MEDIA_VERSION_3502 0x2302 +#define ZLSS_VOLUME_MEDIA_VERSION_3503 0x2303 +#define ZLSS_VOLUME_MEDIA_VERSION_3504 0x2304 +#define ZLSS_VOLUME_MEDIA_VERSION_3505 0x2305 +#define ZLSS_VOLUME_MEDIA_VERSION_3506 0x2306 +#define ZLSS_VOLUME_MEDIA_VERSION_3507 0x2307 +#define ZLSS_VOLUME_MEDIA_VERSION_3508 0x2308 +#define ZLSS_VOLUME_MEDIA_VERSION_3509 0x2309 +#define ZLSS_VOLUME_MEDIA_VERSION_3510 0x230a +#define ZLSS_VOLUME_MEDIA_VERSION_3511 0x230b +#define ZLSS_VOLUME_MEDIA_VERSION_3512 0x230c +#define ZLSS_VOLUME_MEDIA_VERSION_3513 0x230d +#define ZLSS_VOLUME_MEDIA_VERSION_3514 0x230e +#define ZLSS_VOLUME_MEDIA_VERSION_3515 0x230f +#define ZLSS_VOLUME_MEDIA_VERSION_3516 0x2310 +#define ZLSS_VOLUME_MEDIA_VERSION_3517 0x2311 +#define ZLSS_VOLUME_MEDIA_VERSION_3518 0x2312 +#define ZLSS_VOLUME_MEDIA_VERSION_3519 0x2313 +#define ZLSS_VOLUME_MEDIA_VERSION_3520 0x2314 +#define ZLSS_VOLUME_MEDIA_VERSION_3521 0x2315 +#define ZLSS_VOLUME_MEDIA_VERSION_3522 0x2316 +#define ZLSS_VOLUME_MEDIA_VERSION_3523 0x2317 +#define ZLSS_VOLUME_MEDIA_VERSION_3524 0x2318 +#define ZLSS_VOLUME_MEDIA_VERSION_3525 0x2319 +#define ZLSS_VOLUME_MEDIA_VERSION_3526 0x231a +#define ZLSS_VOLUME_MEDIA_VERSION_3527 0x231b +#define ZLSS_VOLUME_MEDIA_VERSION_3528 0x231c +#define ZLSS_VOLUME_MEDIA_VERSION_3529 0x231d +#define ZLSS_VOLUME_MEDIA_VERSION_3530 0x231e +#define ZLSS_VOLUME_MEDIA_VERSION_3531 0x231f +#define ZLSS_VOLUME_MEDIA_VERSION_3532 0x2320 +#define ZLSS_VOLUME_MEDIA_VERSION_3533 0x2321 +#define ZLSS_VOLUME_MEDIA_VERSION_3534 0x2322 +#define ZLSS_VOLUME_MEDIA_VERSION_3535 0x2323 +#define ZLSS_VOLUME_MEDIA_VERSION_3536 0x2324 +#define ZLSS_VOLUME_MEDIA_VERSION_3537 0x2325 +#define ZLSS_VOLUME_MEDIA_VERSION_3538 0x2326 +#define ZLSS_VOLUME_MEDIA_VERSION_3539 0x2327 +#define ZLSS_VOLUME_MEDIA_VERSION_3540 0x2328 +#define ZLSS_VOLUME_MEDIA_VERSION_3541 0x2329 +#define ZLSS_VOLUME_MEDIA_VERSION_3542 0x232a +#define ZLSS_VOLUME_MEDIA_VERSION_3543 0x232b +#define ZLSS_VOLUME_MEDIA_VERSION_3544 0x232c +#define ZLSS_VOLUME_MEDIA_VERSION_3545 0x232d +#define ZLSS_VOLUME_MEDIA_VERSION_3546 0x232e +#define ZLSS_VOLUME_MEDIA_VERSION_3547 0x232f +#define ZLSS_VOLUME_MEDIA_VERSION_3548 0x2330 +#define ZLSS_VOLUME_MEDIA_VERSION_3549 0x2331 + +#define ZLSS_VOLUME_MEDIA_VERSION_3600 0x2400 +#define ZLSS_VOLUME_MEDIA_VERSION_3601 0x2401 +#define ZLSS_VOLUME_MEDIA_VERSION_3602 0x2402 +#define ZLSS_VOLUME_MEDIA_VERSION_3603 0x2403 + +#define ZLSS_VOLUME_MEDIA_VERSION_3700 0x2500 +#define ZLSS_VOLUME_MEDIA_VERSION_3702 0x2502 +#define ZLSS_VOLUME_MEDIA_VERSION_3703 0x2503 + +#define ZLSS_VOLUME_MEDIA_VERSION_3800 0x2600 +#define ZLSS_VOLUME_MEDIA_VERSION_3804 0x2604 +#define ZLSS_VOLUME_MEDIA_VERSION_3805 0x2605 + + + +/*--------------------------------------------------------------------------- + | Data Prototypes needed + +-------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- + | Function Prototypes needed + +-------------------------------------------------------------------------*/ +#ifdef NW5X_UPGRADE +extern STATUS ZFSPOOL_AutoInPlaceUpgradeNoXactions( + GeneralMsg_s *genMsg, + ZfsPool_s *pool ); +#endif +extern STATUS ZFSPOOL_AutoInPlaceUpgrade( + GeneralMsg_s *genMsg, + ZfsPool_s *pool ); + +STATUS ZFSPOOL_AIPU4008Through4049To4084( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +BOOL ZLSS_ClusterReadyForNakoma( ); +STATUS ZFSPOOL_AIPU4084To4085( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); + +BOOL ZFSPOOL_AIPU4006To4007Nakoma_Ready( ZlssPool_s *zlssPool ); +BOOL ZFSPOOL_AIPU4084To4085_Ready( ZlssPool_s *zlssPool ); +BOOL ZFSPOOL_AIPU4085To4086_Ready( ZlssPool_s *zlssPool ); +BOOL ZFSPOOL_AIPU4086To4087_Ready( ZlssPool_s *zlssPool ); +BOOL ZFSPOOL_AIPU4087To4088_Ready( ZlssPool_s *zlssPool ); +BOOL ZFSPOOL_AIPU4088To4300_Ready( ZlssPool_s *zlssPool ); +BOOL ZLSSVOL_AIPU3500Through3549To3600_Ready( ZfsVolume_s *zVolume ); +BOOL ZLSSVOL_AIPU3600To3601_Ready( ZfsVolume_s *zVolume ); +BOOL ZLSS_AIPUNakomaPool_Ready( ZlssPool_s *zlssPool ); +BOOL ZLSS_AIPUNakomaVolume_Ready( ZfsVolume_s *zVolume ); + +STATUS ZFSPOOL_AIPU4006To4007Nakoma( ZlssPool_s *zlssPool, GeneralMsg_s *genMsg ); +STATUS ZFSPOOL_AIPU4085To4086( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +STATUS ZFSPOOL_AIPU4086To4087( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +STATUS ZFSPOOL_AIPU4087To4088( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +STATUS ZLSSVOL_AIPU3500Through3549To3600( GeneralMsg_s *genMsg, ZfsVolume_s *zVolume ); +STATUS ZLSSVOL_AIPU3600To3601( GeneralMsg_s *genMsg, ZfsVolume_s *zVolume ); +STATUS ZFSPOOL_AIPU4088To4300( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +STATUS ZFSPOOL_AIPU4085_4086_4087_4088To4300( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); +STATUS ZLSS_AIPUNakomaPool( GeneralMsg_s *genMsg, ZlssPool_s *zlssPool ); + +void ZLSS_UpgradeShutdownNakoma(); +void ZLSS_UpgradeStartupNakoma(); + + +#endif /* _ZLSSUPGRADE_H_ */ diff --git a/src/nwnss/zlss/zstoreConfig.h b/src/nwnss/zlss/zstoreConfig.h new file mode 100644 index 0000000..c43bec5 --- /dev/null +++ b/src/nwnss/zlss/zstoreConfig.h @@ -0,0 +1,177 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) Initialization module + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2007-06-07 02:25:28 +0530 (Thu, 07 Jun 2007) $ + | + | $RCSfile$ + | $Revision: 2044 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define configuration values for the Z file system + +-------------------------------------------------------------------------*/ +#ifndef _ZSTORECONFIG_H_ +#define _ZSTORECONFIG_H_ + +#ifndef _OMNI_H_ +#include +#endif + +/** Set Maximum value to zero if there is no Maximum limit for the variable **/ +/** Set Minimum value to zero if the variable can be set to zero **/ + +/* Range definitions*/ +//#define MIN_NUM_BUFFERS 8 +//#define MAX_NUM_BUFFERS 262144 +// +//#define MIN_NUM_ASYNCIOS 4 +//#define MAX_NUM_ASYNCIOS 65536 +// +//#define MIN_NUM_BONDS (2 * MIN_NUM_BUFFERS) +//#define MAX_NUM_BONDS (2 * MAX_NUM_BUFFERS) +// +//#define MIN_CACHE_HASH_SHIFT 8 +//#define MAX_CACHE_HASH_SHIFT 20 +// +//#define MIN_NOT_IN_USE_BEASTS 1 +//#define MAX_NOT_IN_USE_BEASTS 0 +// +//#define MIN_BEAST_HASH_SHIFT 8 +//#define MAX_BEAST_HASH_SHIFT 20 +// +//#define MIN_SIZE_MAILBOX 64 +//#define MAX_SIZE_MAILBOX 256 +// +//#define MIN_SEC 1 +//#define MAX_SEC 1000 +// +//#define MIN_WORK_LIMIT 5 +//#define MAX_WORK_LIMIT 100 +// +//#define MIN_NUM_XACTIONS 4 +//#define MAX_NUM_XACTIONS 65536 +// +//#define MIN_NUM_XDELETES 4 +//#define MAX_NUM_XDELETES 65536 +// +// +//#if NSS_DEBUG IS_ENABLED /* debug default values*/ +//#define DEFAULT_NUM_BONDS 5000 /*(2 * DEFAULT_NUM_BUFFERS)*/ +//#define DEFAULT_NUM_BUFFERS 1024 +//#define DEFAULT_NUM_ASYNCIOS 2048 +//#define DEFAULT_NUM_DELAYED_BEASTS 40 +//#define DEFAULT_CACHE_HASH_SHIFT 10 +//#define DEFAULT_NOT_IN_USE_BEASTS 256 +//#define DEFAULT_BEAST_HASH_SHIFT 10 +//#define DEFAULT_SIZE_MAILBOX 64 +//#define DEFAULT_SEC_BEAST 10 +//#define DEFAULT_SEC_XACTION 5 +//#define DEFAULT_SEC_CHKPT 30 +//#define DEFAULT_SEC_BUFFER 1 +//#define DEFAULT_WORK_LIMIT 30 +//#define DEFAULT_NUM_XACTIONS 5000 +//#define DEFAULT_NUM_XDELETES 100 +//#else /* PRODUCTION default values*/ +//#define DEFAULT_NUM_BONDS 5000 /*(2 * DEFAULT_NUM_BUFFERS)*/ +//#define DEFAULT_NUM_BUFFERS 2048 +//#define DEFAULT_NUM_ASYNCIOS 2048 +#define DEFAULT_NUM_DELAYED_BEASTS 40 +//#define DEFAULT_CACHE_HASH_SHIFT 13 +//#define DEFAULT_NOT_IN_USE_BEASTS 512 +//#define DEFAULT_BEAST_HASH_SHIFT 11 +//#define DEFAULT_SIZE_MAILBOX 128 +//#define DEFAULT_SEC_BEAST 10 +#define DEFAULT_SEC_XACTION 20 +#define DEFAULT_SEC_CHKPT 30 +//#define DEFAULT_SEC_BUFFER 1 +//#define DEFAULT_WORK_LIMIT 40 +#define DEFAULT_NUM_XACTIONS 5000 +#define ZLSS_DEFAULT_NUM_XDELETES 100 +//#endif +// +//#define DEFAULT_WORK_DELAY_CNT 100 +//#define DEFAULT_MSEC_WORK_WAIT 100 + + +typedef struct ZstoreConfig_s +{ +// struct Cache_s +// { +// NINT numBuffers; +// NINT numBonds; +// NINT numAsyncios; +// NINT hashShift; +// NINT hashSize; +// NINT hashMask; +// } cache; +// struct Os_s +// { +// NINT sizeMailbox; +// NINT workLimit; +// NINT workDelayCnt; +// } os; +// struct Bst_s +// { +// NINT notInUseMax; +// NINT hashShift; +// NINT hashSize; +// NINT hashMask; +// } bst; + struct zSec_s + { +// NINT beast; + NINT xaction; + NINT chkpt; +// NINT buffer; + } sec; +// struct Msec_s +// { +// NINT workWait; +// } msec_s; + struct zTick_s + { +// NINT beast; + NINT xaction; + NINT chkpt; +// NINT buffer; + } tick; + struct zXact_s + { + NINT numDelayed; + } xact; + struct zZfs_s + { + NINT numXactions; + NINT numXdeletes; + } zfs; +} ZstoreConfig_s; + +extern ZstoreConfig_s ZstoreConfig; + +extern void ZstoreConfigStartup(void); + +#endif