/* * linux/include/linux/jbd.h * * Written by Stephen C. Tweedie * * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * * Definitions for transaction data structures for the buffer cache * filesystem journaling support. */ #ifndef _LINUX_JBD_H #define _LINUX_JBD_H #include "jfs_compat.h" #define JFS_DEBUG #define jfs_debug jbd_debug #ifndef __GNUC__ #define __FUNCTION__ "" #endif #define journal_oom_retry 1 #ifdef __STDC__ #ifdef CONFIG_JBD_DEBUG /* * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal * consistency checks. By default we don't do this unless * CONFIG_JBD_DEBUG is on. */ #define JBD_EXPENSIVE_CHECKING extern int journal_enable_debug; #define jbd_debug(n, f, a...) \ do { \ if ((n) <= journal_enable_debug) { \ printk (KERN_DEBUG "(%s, %d): %s: ", \ __FILE__, __LINE__, __FUNCTION__); \ printk (f, ## a); \ } \ } while (0) #else #ifdef __GNUC__ #if defined(__KERNEL__) || !defined(CONFIG_JBD_DEBUG) #define jbd_debug(f, a...) /**/ #else extern int journal_enable_debug; #define jbd_debug(n, f, a...) \ do { \ if ((n) <= journal_enable_debug) { \ printf("(%s, %d): %s: ", \ __FILE__, __LINE__, __func__); \ printf(f, ## a); \ } \ } while (0) #endif /*__KERNEL__ */ #else #define jbd_debug(f, ...) /**/ #endif #endif #else #define jbd_debug(x) /* AIX doesn't do STDC */ #endif extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); #define jbd_kmalloc(size, flags) \ __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) #define jbd_rep_kmalloc(size, flags) \ __jbd_kmalloc(__FUNCTION__, (size), (flags), 1) #define JFS_MIN_JOURNAL_BLOCKS 1024 /* * Internal structures used by the logging mechanism: */ #define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ /* * On-disk structures */ /* * Descriptor block types: */ #define JFS_DESCRIPTOR_BLOCK 1 #define JFS_COMMIT_BLOCK 2 #define JFS_SUPERBLOCK_V1 3 #define JFS_SUPERBLOCK_V2 4 #define JFS_REVOKE_BLOCK 5 /* * Standard header for all descriptor blocks: */ typedef struct journal_header_s { __u32 h_magic; __u32 h_blocktype; __u32 h_sequence; } journal_header_t; /* * Checksum types. */ #define JBD2_CRC32_CHKSUM 1 #define JBD2_MD5_CHKSUM 2 #define JBD2_SHA1_CHKSUM 3 #define JBD2_CRC32C_CHKSUM 4 #define JBD2_CRC32_CHKSUM_SIZE 4 #define JBD2_CHECKSUM_BYTES (32 / sizeof(__u32)) /* * Commit block header for storing transactional checksums: * * NOTE: If FEATURE_COMPAT_CHECKSUM (checksum v1) is set, the h_chksum* * fields are used to store a checksum of the descriptor and data blocks. * * If FEATURE_INCOMPAT_CSUM_V2 (checksum v2) is set, then the h_chksum * field is used to store crc32c(uuid+commit_block). Each journal metadata * block gets its own checksum, and data block checksums are stored in * journal_block_tag (in the descriptor). The other h_chksum* fields are * not used. * * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses * journal_block_tag3_t to store a full 32-bit checksum. Everything else * is the same as v2. * * Checksum v1, v2, and v3 are mutually exclusive features. */ struct commit_header { __u32 h_magic; __u32 h_blocktype; __u32 h_sequence; unsigned char h_chksum_type; unsigned char h_chksum_size; unsigned char h_padding[2]; __u32 h_chksum[JBD2_CHECKSUM_BYTES]; __u64 h_commit_sec; __u32 h_commit_nsec; }; /* * The block tag: used to describe a single buffer in the journal */ typedef struct journal_block_tag3_s { __u32 t_blocknr; /* The on-disk block number */ __u32 t_flags; /* See below */ __u32 t_blocknr_high; /* most-significant high 32bits. */ __u32 t_checksum; /* crc32c(uuid+seq+block) */ } journal_block_tag3_t; typedef struct journal_block_tag_s { __u32 t_blocknr; /* The on-disk block number */ __u16 t_checksum; /* truncated crc32c(uuid+seq+block) */ __u16 t_flags; /* See below */ __u32 t_blocknr_high; /* most-significant high 32bits. */ } journal_block_tag_t; /* Tail of descriptor block, for checksumming */ struct journal_block_tail { __be32 t_checksum; }; /* * The revoke descriptor: used on disk to describe a series of blocks to * be revoked from the log */ typedef struct journal_revoke_header_s { journal_header_t r_header; int r_count; /* Count of bytes used in the block */ } journal_revoke_header_t; /* Tail of revoke block, for checksumming */ struct journal_revoke_tail { __be32 r_checksum; }; /* Definitions for the journal tag flags word: */ #define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ #define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ #define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ #define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ #define UUID_SIZE 16 #define JFS_USERS_MAX 48 #define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX) /* * The journal superblock. All fields are in big-endian byte order. */ typedef struct journal_superblock_s { /* 0x0000 */ journal_header_t s_header; /* 0x000C */ /* Static information describing the journal */ __u32 s_blocksize; /* journal device blocksize */ __u32 s_maxlen; /* total blocks in journal file */ __u32 s_first; /* first block of log information */ /* 0x0018 */ /* Dynamic information describing the current state of the log */ __u32 s_sequence; /* first commit ID expected in log */ __u32 s_start; /* blocknr of start of log */ /* 0x0020 */ /* Error value, as set by journal_abort(). */ __s32 s_errno; /* 0x0024 */ /* Remaining fields are only valid in a version-2 superblock */ __u32 s_feature_compat; /* compatible feature set */ __u32 s_feature_incompat; /* incompatible feature set */ __u32 s_feature_ro_compat; /* readonly-compatible feature set */ /* 0x0030 */ __u8 s_uuid[16]; /* 128-bit uuid for journal */ /* 0x0040 */ __u32 s_nr_users; /* Nr of filesystems sharing log */ __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ /* 0x0048 */ __u32 s_max_transaction; /* Limit of journal blocks per trans.*/ __u32 s_max_trans_data; /* Limit of data blocks per trans. */ /* 0x0050 */ __u8 s_checksum_type; /* checksum type */ __u8 s_padding2[3]; __u32 s_padding[42]; __u32 s_checksum; /* crc32c(superblock) */ /* 0x0100 */ __u8 s_users[JFS_USERS_SIZE]; /* ids of all fs'es sharing the log */ /* 0x0400 */ } journal_superblock_t; #define JFS_HAS_COMPAT_FEATURE(j,mask) \ ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask)))) #define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask)))) #define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask)))) #define JFS_FEATURE_COMPAT_CHECKSUM 0x00000001 #define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 #define JFS_FEATURE_INCOMPAT_64BIT 0x00000002 #define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 #define JFS_FEATURE_INCOMPAT_CSUM_V2 0x00000008 #define JFS_FEATURE_INCOMPAT_CSUM_V3 0x00000010 /* Features known to this kernel version: */ #define JFS_KNOWN_COMPAT_FEATURES 0 #define JFS_KNOWN_ROCOMPAT_FEATURES 0 #define JFS_KNOWN_INCOMPAT_FEATURES (JFS_FEATURE_INCOMPAT_REVOKE|\ JFS_FEATURE_INCOMPAT_ASYNC_COMMIT|\ JFS_FEATURE_INCOMPAT_64BIT|\ JFS_FEATURE_INCOMPAT_CSUM_V2|\ JFS_FEATURE_INCOMPAT_CSUM_V3) #ifdef NO_INLINE_FUNCS extern size_t journal_tag_bytes(journal_t *journal); extern int journal_has_csum_v2or3(journal_t *journal); extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused)); extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); #endif #if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) #ifdef E2FSCK_INCLUDE_INLINE_FUNCS #if (__STDC_VERSION__ >= 199901L) #define _INLINE_ extern inline #else #define _INLINE_ inline #endif #else /* !E2FSCK_INCLUDE_INLINE FUNCS */ #if (__STDC_VERSION__ >= 199901L) #define _INLINE_ inline #else /* not C99 */ #ifdef __GNUC__ #define _INLINE_ extern __inline__ #else /* For Watcom C */ #define _INLINE_ extern inline #endif /* __GNUC__ */ #endif /* __STDC_VERSION__ >= 199901L */ #endif /* INCLUDE_INLINE_FUNCS */ /* journal feature predicate functions */ #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ _INLINE_ int jfs_has_feature_##name(journal_t *j); \ _INLINE_ int jfs_has_feature_##name(journal_t *j) \ { \ return ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_compat & \ ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname)) != 0); \ } \ _INLINE_ void jfs_set_feature_##name(journal_t *j); \ _INLINE_ void jfs_set_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_compat |= \ ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \ } \ _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_compat &= \ ~ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \ } #define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ _INLINE_ int jfs_has_feature_##name(journal_t *j); \ _INLINE_ int jfs_has_feature_##name(journal_t *j) \ { \ return ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_ro_compat & \ ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname)) != 0); \ } \ _INLINE_ void jfs_set_feature_##name(journal_t *j); \ _INLINE_ void jfs_set_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_ro_compat |= \ ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \ } \ _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_ro_compat &= \ ~ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \ } #define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \ _INLINE_ int jfs_has_feature_##name(journal_t *j); \ _INLINE_ int jfs_has_feature_##name(journal_t *j) \ { \ return ((j)->j_format_version >= 2 && \ ((j)->j_superblock->s_feature_incompat & \ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname)) != 0); \ } \ _INLINE_ void jfs_set_feature_##name(journal_t *j); \ _INLINE_ void jfs_set_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_incompat |= \ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \ } \ _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ { \ (j)->j_superblock->s_feature_incompat &= \ ~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \ } #else #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ extern int jfs_has_feature_##name(journal_t *j); \ extern void jfs_set_feature_##name(journal_t *j); \ extern void jfs_clear_feature_##name(journal_t *j); #define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ extern int jfs_has_feature_##name(journal_t *j); \ extern void jfs_set_feature_##name(journal_t *j); \ extern void jfs_clear_feature_##name(journal_t *j); #define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \ extern int jfs_has_feature_##name(journal_t *j); \ extern void jfs_set_feature_##name(journal_t *j); \ extern void jfs_clear_feature_##name(journal_t *j); #endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ JFS_FEATURE_COMPAT_FUNCS(checksum, CHECKSUM) JFS_FEATURE_INCOMPAT_FUNCS(revoke, REVOKE) JFS_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT) JFS_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT) JFS_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2) JFS_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) #if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) /* * helper functions to deal with 32 or 64bit block numbers. */ _INLINE_ size_t journal_tag_bytes(journal_t *journal) { size_t sz; if (jfs_has_feature_csum3(journal)) return sizeof(journal_block_tag3_t); sz = sizeof(journal_block_tag_t); if (jfs_has_feature_csum2(journal)) sz += sizeof(__u16); if (jfs_has_feature_64bit(journal)) return sz; return sz - sizeof(__u32); } _INLINE_ int journal_has_csum_v2or3(journal_t *journal) { if (jfs_has_feature_csum2(journal) || jfs_has_feature_csum3(journal)) return 1; return 0; } /* Comparison functions for transaction IDs: perform comparisons using * modulo arithmetic so that they work over sequence number wraps. */ _INLINE_ int tid_gt(tid_t x, tid_t y) { int difference = (x - y); return (difference > 0); } _INLINE_ int tid_geq(tid_t x, tid_t y) { int difference = (x - y); return (difference >= 0); } #endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ #undef _INLINE_ extern int journal_blocks_per_page(struct inode *inode); /* * Definitions which augment the buffer_head layer */ /* journaling buffer types */ #define BJ_None 0 /* Not journaled */ #define BJ_SyncData 1 /* Normal data: flush before commit */ #define BJ_AsyncData 2 /* writepage data: wait on it before commit */ #define BJ_Metadata 3 /* Normal journaled metadata */ #define BJ_Forget 4 /* Buffer superceded by this transaction */ #define BJ_IO 5 /* Buffer is for temporary IO use */ #define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ #define BJ_LogCtl 7 /* Buffer contains log descriptors */ #define BJ_Reserved 8 /* Buffer is reserved for access by journal */ #define BJ_Types 9 extern int jbd_blocks_per_page(struct inode *inode); #endif /* _LINUX_JBD_H */