462 lines
13 KiB
C
462 lines
13 KiB
C
/*
|
|
* linux/include/linux/jbd.h
|
|
*
|
|
* Written by Stephen C. Tweedie <sct@redhat.com>
|
|
*
|
|
* 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 */
|