/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos72Q src/bos/kernel/j2/include/j2_snapshot.h 1.36.1.2 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 2002,2019 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /* @(#)76 1.36.1.2 src/bos/kernel/j2/include/j2_snapshot.h, sysj2, bos72Q, q2019_13A4 2/4/19 06:29:05 */ #ifndef _H_J2_SNAPSHOT #define _H_J2_SNAPSHOT /* * j2_snapshot.h */ #include #include #ifdef __cplusplus extern "C" { #endif #define _J2_SNAPSHOT 1 /* external filesystem snapshot: * snapshot superblock * (at fixed offset of 4 Kbyte in snapshotStorage) */ #define J2SNAPSHOT "J2SS" /* magic */ #define J2SNAPSHOTVERSION 1 /* version 1 */ #define SNAPSHOT_NONPERSISTENT J2SNAPSHOTVERSION #define SNAPSHOT_PERSISTENT 2 /* version 2: Persistent snapshots */ typedef struct snapSuperblock { /* self descriptor */ char snapshotMagic[4]; /* 4: J2SS */ int32 rsrvd1; /* 4: */ int32 snapshotVersion; /* 4: */ int32 snapshotGeneration; /* 4: snapshotSeries generation number */ uint32 snapshotAttribute; /* 4: */ uint32 snapshotState; /* 4: */ dev64_t snapshotDevice; /* 8: */ ino64_t snapshotInumber; /* 8: */ uint32 snapshotIgeneration; /* 4: */ uint32 snapshotType; /* 4: */ j2time_t snapshotTimestamp; /* 16: creation time */ int64 snapshotStorageSize; /* 8: current storageObject size in fsBlock */ int64 maxSnapshotStorage; /* 8: max/limit storageObject size in fsBlock */ /* base file system descriptor; */ dev64_t fileSystemDevice; /* 8: */ ino64_t fileSystemInumber; /* 8: */ uint32 fileSystemIgeneration; /* 4: */ int32 fileSystemL2BlockSize; /* 4: */ int64 fileSystemSize; /* 8: */ /* bMapMap descriptor */ int64 bMapMap; /* 8: bMapMap start address */ /* ssTable descriptor; */ int64 ssTable; /* 8: ssTable start address */ int32 ssTableSize; /* 4: */ int32 sTableGroupSize;/* 4: */ /* sTable descriptor; */ /* sSegment descriptor; */ int64 segmentListHead; /* 8: segment list head address */ int64 segmentListTail; /* 8: segment list tail address */ int32 segmentSize; /* 4: */ int32 trackSize; /* 4: */ int64 nBID; /* 8: number of beforeImage extents */ } snapshotSuperblock_t; #define SNAPSHOT_SUPERBLOCK_OFFSET BPSIZE #define SNAPSHOT_ITABLE_OFFSET SNAPSHOT_SUPERBLOCK_OFFSET + BPSIZE /* snapshot attribute */ #define SS_SSLV 0x00000001 /* External file system snapshot */ #define SS_SSVDF 0x00000002 /* Internal file system snapshot */ #define SS_SSDS 0x00000004 /* Dataset snapshot */ /* snapshot state */ #define SNAPSHOT_DIP 0x00000001 /* delete-in-progress */ #define SNAPSHOT_PIP 0x00000002 /* This value has different meanings * dependent on the base file system * superblock s_snapshotVersion field * value: * SNAPSHOT_NONPERSISTENT: indicates an * invalid snapshot, the only * action allowed should be to * delete the snapshot. * SNAPSHOT_PERSISTENT: indicates a * normal snapshot which is * recoverable, the snapshot should * only be deleted on prior * releases that don't support * recoverable snapshots */ #define SNAPSHOT_CUR 0x00000004 /* current snapshot */ #define SNAPSHOT_AIP 0x00000008 /* abort-in-progress: * s_snapshotState has this bit set when current snapshot * is aborted. When current snapshot is aborted * all snapshots are aborted. * state in sSeries has this bit set for each snapshot * which is aborted. */ #define SNAPSHOT_NODEV 0x00000010 /* No device: If the snapshot device is not available, or the * snapshot superblock doesn't match, then the snapshot is * marked as SNAPSHOT_AIP and SNAPSHOT_NODEV. This allows * snapshots which follow the unavailable one to still remain * available. */ /* SNAPGENOK: Validate the generation number for an external snapshot with the * snappedFS superblock. The generation number must be in the range of * in-use snapshots owned by the snappedFS and its device must match. */ #define SNAPGENOK(SNAPSB, FSSB, RC) \ {\ int32 first, last, sGen;\ first = (FSSB).s_snapshotSeries.first;\ last = (FSSB).s_snapshotSeries.last;\ sGen = (SNAPSB).snapshotGeneration;\ /* Device should match and generation should be in use */\ RC = (((FSSB).s_snapshotSeries.generation[sGen].device ==\ (SNAPSB).snapshotDevice)\ && ((first <= last && sGen >= first && sGen <= last)\ || (first > last &&\ (sGen >= first || sGen <= last))));\ } /* internal snapshot: * snapshot superblock * (at logical offset of INTSNAPSUPER_OFFSET in snapshotObject) */ #define J2INTSNAPSHOT "J2IS" /* magic */ #define J2INTSNAPSHOTVERSION 3 /* version 3: Internal snapshot */ typedef struct isnapSuperblock { /* self descriptor */ char ssb_snapshotMagic[4]; /* 4: J2IS */ int32 ssb_rsrvd1; /* 4: */ int32 ssb_snapshotVersion; /* 4: J2INTSNAPSHOTVERSION */ uint32 ssb_snapshotGeneration; /* 4: snapshot generation number. * Snapshot generation numbers continue to increase * while a file system remains mounted. This allows * buffers to be marked with the snapshot generation * that copied them to prevent siCOW again on the same * generation. Use the last snapshot generation number * (persistently maintained in imap) to determine next * generation number even if this is the first snapshot * for the file system. generation % MAXINTSNAPSHOT * gives index into pSeries table in imap. */ uint32 ssb_snapshotAttribute; /* 4: SS_SSVDF */ uint32 ssb_snapshotState; /* 4: see above */ int64 ssb_maxSnapshotStorage; /* 8: rsrvd: max/limit snapshot size in fsBlock */ /* base file system descriptor; */ ino64_t ssb_rootInumber; /* 8: Datasets: root inum of dataset */ ino64_t ssb_fileSystemInumber; /* 8: Datasets: datasetObject*/ uint32 ssb_fileSystemIgeneration; /* 4: Datasets: */ uint32:32; /* 4: pad */ int64 ssb_fileSystemSize; /* 8: Size of filesystem when * snapshot was created */ char ssb_snapName[J2_NAME_MAX]; /* 256: snapshotName */ int32 padding[48]; /* 192: pad to 512 boundary */ struct dinode ssb_dsinode; /* 512: For datasets, PIT copy of dsiMap * inode */ int32 padding2[768]; /* pad to 4096 */ } iSnapshotSuperblock_t; /* 4096: */ RAS_FILE_ASSERT(isnapSuperblock, (sizeof(struct isnapSuperblock) == PSIZE)); /* INTSNAPSUPER_OFFSET: Logical offset of internal snapshot superblock */ #define INTSNAPSUPER_OFFSET 0 /* ISNAPGENOK: Validate the generation number for an internal snapshot with the * pSeries. The generation number must be in the range of in-use * snapshots owned by the pSeries. */ #define ISNAPGENOK(SNAPSB, PSERIES, RCP) \ {\ uint32 first, last, sGen;\ first = (PSERIES)->is_first % (PSERIES)->is_maxnumsnap;\ last = (PSERIES)->is_last % (PSERIES)->is_maxnumsnap;\ sGen = (SNAPSB)->ssb_snapshotGeneration % (PSERIES)->is_maxnumsnap;\ /* generation should be in use */\ *RCP = (((first <= last && sGen >= first && sGen <= last)\ || (first > last && (sGen >= first || sGen <= last))));\ } /* external filesystem snapshot: * snapshotSeries generation summary * (defined in base file system superblock) */ typedef struct snapshotSummary { uint32 attribute; /* 4: */ uint32 state; /* 4: */ j2time_t timestamp; /* 16: */ dev64_t device; /* 8: */ ino64_t iNumber; /* 8: */ uint32 gNumber; /* 4: */ uint32 type; /* 4: */ /* transient binding */ union { uint64 storageObject; struct file *fpDevice; struct inode *ipVDF; } snapshotStorageObject; /* 8: */ union { uint64 snapshotObject; struct inode *ipSnapshot; } snapshotObject; /* 8: */ } sSummary_t; /* 64: */ /* external filesystem snapshot: * snapshot series table * (defined in base file system superblock) */ typedef struct snapshotSeries { int32 nSnapshot; /* 4: */ int32 first; /* 4: */ int32 last; /* 4: */ int32 rsrvd[5]; /* 20: */ struct snapshotSummary generation[MAXNUMSNAPSHOT]; /* 64 * 15 */ } sSeries_t; /* 992 */ #define MAXINTSNAPSHOT 64 /* Max # of internal snapshots per data space */ /* internal snapshot: * snapshotSeries table * (persistent snapshot series information: defined in ipimap control page) */ typedef struct isSeries { uint32 is_maxnumsnap; /* 4: Maximum # internal snapshots */ uint32 is_nSnapshot; /* 4: Number of active snapshots */ uint32 is_first; /* 4: Generation of oldest snapshot */ uint32 is_last; /* 4: Generation of current snapshot */ ino64_t is_generation[MAXINTSNAPSHOT]; /* 8 * 64: Aggregate inum snapshotObject */ } isSeries_t; /* 528: */ /* NUMSNAP: Calculate number of snapshots in series range from SI to SN, where * series has MAX number of snapshots. */ #define NUMSNAP(SI, SN, MAX) (((SN) >= (SI)) ? (SN) - (SI) + 1 \ : (MAX) - (SI) + (SN) + 1) #ifdef _KERNEL /* internal snapshot: * working/in-memory snapshotSeries generation summary */ typedef struct wisSummary { struct inode *is_ipSnapshot; /* 8: in-memory snapshotObject */ uint32 is_attribute; /* 4: Snapshot attribute from snapSuper */ uint32 is_state; /* 4: Snapshot state from snapSuper */ } wisSummary_t; /* 16: */ /* internal snapshot: * working/in-memory snapshotSeries */ typedef struct wisSeries { wisSummary_t wis_generation[MAXINTSNAPSHOT]; /* 64 * 16: */ } wisSeries_t; /* 1024: */ #include /* * snapshotObject * (wrapped as an ipmnt aka ipSnapshot: ref. j2_inode.h) * per active snapshot writer and/or reader; */ struct snapshotObject { /* bfs binding */ struct inode *so_ipFileSystem; /* 8: primary ipmnt */ struct inode *so_ipIMap; /* 8: primary/current iMap */ int64 so_fsSize; /* 8: baseFileSystem size */ /* snapshot attributes */ uint32 so_version; /* 4: */ uint32 so_generation; /* 4: * External: sSeries index in PFS superblock * Internal: generation number; * generation % MAXINTSNAPSHOT for pSeries * index in PDS imap control page */ uint32 so_attribute; /* 4: */ uint32 so_state; /* 4: */ dev_t so_device; /* 8: storageObject */ uint32 so_type; /* 4: storageObject */ int32 so_segmentSize; /* 4: */ j2time_t so_timestamp; /* 16: */ struct snapshotSegmentDescriptor *so_wipSegment; /* 8: */ union { struct { int64 so_size; /* 8: current storageObject size in fsBlock */ int64 so_maxSize; /* 8: max/limit storageObject size in fsBlock */ int64 so_ssTable; /* 8: ssTable start address */ int64 so_segmentListHead; /* 8: segmentList head address */ int64 so_segmentListTail; /* 8: segmentList tail address */ struct snapshotSeries *so_series; /* 8: */ struct file *so_fpDevice; /* 8: storageObject */ struct inode *so_ipBMapMap; /* 8: */ event_t so_freeWait; /* 8: event wait for free segment space */ int64 so_nBID; /* 8: nummber of beforeImage extents */ }; /* External snapshot */ struct { struct inode *so_ipSMap; /* 8: sMap object */ struct wisSeries *so_wisSeries; /* 8: */ struct inode *so_ipPITIMap; /* 8: PIT generation ipimap */ int64 so_nBIblks; /* 8: # before-image blocks used for quota of * snapshot */ }; /* Internal snapshot */ }; MUTEXLOCK_T so_lock; /* 8: */ event_t so_liWait; /* 8: event wait for lazy initialization */ }; #endif /* _KERNEL */ #define SNAPSHOTDIR ".snapshot" #define SNAPSHOTDIRLEN 9 /* * sMap/ssMap (sMap_t) * * For external snapshot: * ssMap is statically allocated at snapshot creation time; * a single ssMap entry covers 32 sMap pages of 4 Kbyte each * (as allocated by a snapshotSegment), * For internal snapshot: * the snapshotObject's xtree points to sMap pages; * sMap is allocated/initialized lazily; * where each sMap page covers 512 blocks of snapshot; */ #define L2SMAPENTRYSIZE 3 typedef struct { unsigned sxd_flag:8; /* 1: flags; see below */ unsigned sxd_rsrvd:8; /* 1: composite level (index) */ unsigned sxd_generation:8; /* 1: snapshot index with copy */ unsigned sxd_addr1:8; /* 1: address in unit of fsblksize */ uint32 sxd_addr2; /* 4: address in unit of fsblksize */ } sxd_t; /* - 8 - */ typedef sxd_t sMap_t; #define SXDaddress(xd, address64)\ {\ (xd)->sxd_addr1 = (address64) >> 32;\ (xd)->sxd_addr2 = (address64) & 0xffffffff;\ } #define addressSXD(xd)\ ( ((int64)((xd)->sxd_addr1)) << 32 | (xd)->sxd_addr2 ) /* sMap extent descriptor (sxd) flag */ #define SXD_UNUSED 0x01 /* IS: Deprecated: To reuse this bit * must change the snapshot version */ #define SXD_INUSE 0x01 /* ES: block inuse at PIT */ #define SXD_COW 0x02 /* Block copied; address is location */ #define SXD_IOD 0x04 /* Inherit-on-Delete */ #define SXD_COD 0x08 /* Copy-on-Delete */ #define SXD_COPIED (SXD_COW | SXD_COD) /* Before-image copied to snapshot */ #define SXD_SAVED (SXD_COW | SXD_IOD | SXD_COD) /* Before-image preserved by snapshot */ #define SXD_FINALIZED (SXD_RON | SXD_COW | SXD_IOD | SXD_COD) /* State for block known */ #define SXD_INITIALIZED 0x10 /* ES: ssMap entry, sMapGroup initialized */ #define SXD_RON 0x10 /* Register-on-New */ #define SXD_LOCKED 0x20 /* ES: ssMap entry being initialized */ #define SXD_FOD 0x20 /* IS: Free-On-Delete */ #define SXD_XXX 0x40 /* reserved */ #define SXD_COMPOSITE 0x80 /* Map is composite of multiple * generations; in-memory only */ typedef struct { unsigned flag:8; /* 1: flags */ unsigned rsrvd:8; /* 1: */ unsigned generation:8; /* 1: snapshot generation with copy */ unsigned addr1:8; /* 1: address in unit of fsblksize */ uint32 addr2; /* 4: address in unit of fsblksize */ uint64 summary; /* 8: */ } ssxd_t; /* 16 */ typedef ssxd_t ssMap_t; #define sgInUseMask 0x8000000000000000LL #define sgCopiedMask 0x4000000000000000LL #define nBitPerSGPage 2 #define nSMapPagePerBMapPage 16 /* * block address to sMap page/entry */ #define nBlockPerSMapPage 512 #define maskBlockPerSMapPage 511 #define nEntryInSMapPage nBlockPerSMapPage #define l2nEntryInSMapPage 9 #define l2nBlockPerSMapPage l2nEntryInSMapPage #define l2nSMapPagePerSSMapEntry 5 #define l2nEntryPerSMapGroup 14 #define l2nBlockPerSMapGroup l2nEntryPerSMapGroup #define l2nBlockPerSSMapEntry l2nEntryPerSMapGroup #define maskBlockPerSSMapEntry ((1 << 14) - 1) #define l2nEntryInSSMapPage 8 #define l2nBlockPerSSMapPage 22 #define maskEntryPerSSMapPage 255 /* blockAddress to ssMapPage address */ #define Block2SSMapPage(baddr, l2nBlockPerPage) \ (((baddr) >> l2nBlockPerSSMapPage) << l2nBlockPerPage) /* blockAddress to index in ssMapPage */ #define Block2IndexInSSMapPage(baddr) \ (((baddr) >> l2nBlockPerSSMapEntry) & 255) /* blockAddress to sMap page in sMap group */ #define Block2SMapGroupPageOffset(baddr, l2nBlockPerPage) \ ((((baddr) & maskBlockPerSSMapEntry) >> 9) << l2nBlockPerPage) #define Block2SMapGroupPage(baddr) \ (((baddr) & maskBlockPerSSMapEntry) >> 9) /* blockAddress to index in sMapPage */ #define Block2IndexInSMapPage(baddr) ((baddr) & 511) /* * snapshotSegment layout */ /* before image descriptor in segment log */ typedef struct { unsigned flag:8; /* 1: flags */ unsigned rsrvd:8; /* 1: */ unsigned len:8; /* 1: length in unit of fsblksize */ unsigned addr1:8; /* 1: bfs address in unit of fsblksize */ uint32 addr2; /* 4: bfs address in unit of fsblksize */ #ifdef __cplusplus uint64 crc; /* 8: */ #else uint64 xor; /* 8: */ #endif } bid_t; /* - 16 - */ #define XDaddress(xd, address64)\ {\ (xd)->addr1 = (address64) >> 32;\ (xd)->addr2 = (address64) & 0xffffffff;\ } #define addressXD(xd)\ ( ((int64)((xd)->addr1)) << 32 | (xd)->addr2 ) #define BID_BID 0x80 /* page of bid_t */ /* * NAME: GETXOR * * FUNCTION: Compute checksum of specified snapshot segment * * PARAMETERS: * XOR - Set to checksum * SSD - Snapshot segment descriptor with extent to get checksum * BCOUNT - Byte offset into segment of start to compute * FCOUNT - Number of bytes in this segment */ #define GETXOR(XOR, SSD, BCOUNT, FCOUNT) {\ uint64 *XORPTR;\ int32 IDX;\ XORPTR = (uint64 *)((SSD)->ssd_segment + (BCOUNT));\ for (IDX = 0, (XOR) = 0;\ IDX < ((FCOUNT) / sizeof(uint64));\ IDX++, XORPTR++)\ (XOR) ^= *XORPTR;\ } /* snapshotSegment log: 4 Kbyte */ typedef struct snapshotSegmentLog { int64 next; /* 8: */ int64 self; /* 8: */ int32 nBID; /* 4: */ int32 crc; /* 4: */ int32 rsrvd[26]; /* 104: */ bid_t bidList[248]; /* 3968: 16*248 */ } sSegmentLog_t; /* snapshot segment layout: 128 Kbyte */ #define J2SNAPSHOTSEGMENTSIZE (1 << 17) typedef struct snapshotSegment { sSegmentLog_t log; /* 4Kbyte: */ uint8 segmentData[4096*31]; /* 124KByte: */ } sSegment_t; #ifdef _KERNEL enum pbtype; /* * prototypes for snapshot manager services. */ int32 j2_snapshot(struct vfs *vfsp, int32 cmd, caddr_t arg, size_t argsize, struct ucred *crp); reg_t seCOW(struct bufx *iobpList, uint32 flag); reg_t smCOD(struct inode *ipSnapshot, int64 xaddr, int32 xlen, uint32 flag); reg_t smRead(struct bufx *bpList, uint32 flag); reg_t smRIORead(struct vnode *pvp, struct uio *uiop, struct ucred *crp); reg_t smPager(struct bufx *iobpList, uint32 flag); reg_t smClose(struct vnode *vp, struct ucred *crp); reg_t smCreate(struct inode *ipmnt, char *snapshotName, struct inode *ipimap, struct ucred *crp, struct vfs *vfsp); reg_t seMount(struct vfs *vfsp, struct vnode *vpStorage, struct vnode *vpCovered); reg_t smUnmount(uint32 snapshotType, uint32 flag, struct inode *ipimap, struct inode *ipSnapshot, struct inode *ipmnt); #define smUnmountPHASE1 0x00000001 #define smUnmountPHASE2 0x00000002 #define smUnmountESNAP 0x00000004 #define smUnmountFORCE 0x00000008 reg_t seOpen(struct vnode *vpStorage, struct ucred *crp); reg_t seCOD(struct inode *ipSnapshot, int64 xaddr, int32 xlen, uint32 flag); reg_t smReadBMap( struct inode *ipSnapshot, int64 xaddr, struct pagerBuffer **, int64 xoff, enum pbtype buftype ); reg_t siAttach(struct inode *ipimap, ino64_t iSMap, struct inode **pitIPimap, struct ucred *crp); reg_t siRON(struct inode *ip, int64 xaddr, int32 xlen); reg_t siGCZombie(struct inode *ipimap); reg_t siCOWFilter(struct inode *ip, void *vbp, uint32 flag, struct inode **ipSnapshotp); reg_t siCOW(struct bufx *iobpList, uint32 flag); /* siCOW() flags */ #define siCOW_TMP 0x00000001 /* Convert IOD to COD for tmp file */ #define siCOW_WRITE 0x00000002 /* Buffer contains PIT image */ #define siCOW_COPY 0x00000004 /* Page-in PIT block to segment */ #define siCOW_SYNC 0x00000008 /* Commit COW synchronously */ void siCOWUpdateMap(struct inode *ip, struct txLock *tlck, struct txBlock *tblk); int siIODFilter(struct inode *ip, struct inode **ipSnapshotp); reg_t siIODUpdateMap(struct inode *ipSnapshot, struct txBlock *tblk, struct inode *ip, int64 xaddr, int32 xlen, uint32 mapType); int32 siIOD(struct inode *ipSnapshot, int32 tid, struct lrd *lrd, int64 *xaddr, int32 xlen); void siIOD_COD(struct inode *ip); void siAbort(struct inode *ipSnapshot, int32 rc); reg_t siOpen(struct vnode *vp, struct ucred *crp); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /*_H_J2_SNAPSHOT */