#include "ext4_config.h"
#include "ext4_blockdev.h"
-#include "tree.h"
+#include "misc/tree.h"
#include <stddef.h>
#include <stdint.h>
#define UUID_SIZE 16
+#pragma pack(push, 1)
+
/*
* Structure of the super block
*/
uint32_t lpf_ino; /* Location of the lost+found inode */
uint32_t padding[100]; /* Padding to the end of the block */
uint32_t checksum; /* crc32c(superblock) */
-} __attribute__((packed));
+};
+
+#pragma pack(pop)
#define EXT4_SUPERBLOCK_MAGIC 0xEF53
#define EXT4_SUPERBLOCK_SIZE 1024
uint64_t inode_blocks_per_level[4];
uint32_t last_inode_bg_id;
+
+ struct jbd_fs *jbd_fs;
+ struct jbd_journal *jbd_journal;
+ struct jbd_trans *curr_trans;
};
/* Inode table/bitmap not in use */
#define EXT4_INODE_INDIRECT_BLOCK_COUNT \
(EXT4_INODE_BLOCKS - EXT4_INODE_DIRECT_BLOCK_COUNT)
+#pragma pack(push, 1)
+
/*
* Structure of an inode on the disk
*/
uint16_t gid_high;
uint32_t author;
} hurd2;
- } __attribute__((packed)) osd2;
+ } osd2;
uint16_t extra_isize;
uint16_t checksum_hi; /* crc32c(uuid+inum+inode) BE */
uint32_t
crtime_extra; /* Extra file creation time (nsec << 2 | epoch) */
uint32_t version_hi; /* High 32 bits for 64-bit version */
-} __attribute__((packed));
+};
+
+#pragma pack(pop)
#define EXT4_INODE_MODE_FIFO 0x1000
#define EXT4_INODE_MODE_CHARDEV 0x2000
#define EXT4_DIRENTRY_DIR_CSUM 0xDE
+#pragma pack(push, 1)
+
union ext4_dir_en_internal {
uint8_t name_length_high; /* Higher 8 bits of name length */
uint8_t inode_type; /* Type of referenced inode (in rev >= 0.5) */
-} __attribute__((packed));
+};
/**
* Linked list directory entry structure
union ext4_dir_en_internal in;
uint8_t name[EXT4_DIRECTORY_FILENAME_LEN]; /* Entry name */
-} __attribute__((packed));
+};
struct ext4_dir_iter {
struct ext4_inode_ref *inode_ref;
uint32_t checksum; /* crc32c(uuid+inum+dirblock) */
};
+#pragma pack(pop)
+
#define EXT4_DIRENT_TAIL(block, blocksize) \
((struct ext4_dir_entry_tail *)(((char *)(block)) + ((blocksize) - \
sizeof(struct ext4_dir_entry_tail))))
((ex)->block_count |= to_le16(EXT4_EXT_UNWRITTEN_MASK))
#define EXT4_EXT_SET_WRITTEN(ex) \
((ex)->block_count &= ~(to_le16(EXT4_EXT_UNWRITTEN_MASK)))
+
+#pragma pack(push, 1)
+
/*
* This is the extent tail on-disk structure.
* All other extent structures are 12 bytes long. It turns out that
uint32_t generation; /* generation of the tree */
};
+#pragma pack(pop)
+
/*
* Types of blocks.
#define EXT4_XATTR_INDEX_RICHACL 8
#define EXT4_XATTR_INDEX_ENCRYPTION 9
+#pragma pack(push, 1)
+
struct ext4_xattr_header {
uint32_t h_magic; /* magic number for identification */
uint32_t h_refcount; /* reference count */
uint32_t h_checksum; /* crc32c(uuid+id+xattrblock) */
/* id = inum if refcount=1, blknum otherwise */
uint32_t h_reserved[3]; /* zero right now */
-} __attribute__((packed));
+};
struct ext4_xattr_ibody_header {
uint32_t h_magic; /* magic number for identification */
-} __attribute__((packed));
+};
struct ext4_xattr_entry {
uint8_t e_name_len; /* length of name */
uint32_t e_value_block; /* disk block attribute is stored on (n/i) */
uint32_t e_value_size; /* size of attribute value */
uint32_t e_hash; /* hash value of name and value */
-} __attribute__((packed));
+};
+
+#pragma pack(pop)
struct ext4_xattr_item {
/* This attribute should be stored in inode body */
#define JBD_SUPERBLOCK_V2 4
#define JBD_REVOKE_BLOCK 5
+#pragma pack(push, 1)
+
/*
* Standard header for all descriptor blocks:
*/
uint32_t sequence;
};
+#pragma pack(pop)
+
/*
* Checksum types.
*/
#define JBD_CRC32_CHKSUM_SIZE 4
#define JBD_CHECKSUM_BYTES (32 / sizeof(uint32_t))
+
+#pragma pack(push, 1)
+
/*
* Commit block header for storing transactional checksums:
*
*
* Checksum v1, v2, and v3 are mutually exclusive features.
*/
+
struct jbd_commit_header {
struct jbd_bhdr header;
uint8_t chksum_type;
uint32_t blocknr_high; /* most-significant high 32bits. */
};
+#pragma pack(pop)
+
+/* Definitions for the journal tag flags word: */
+#define JBD_FLAG_ESCAPE 1 /* on-disk block is escaped */
+#define JBD_FLAG_SAME_UUID 2 /* block has same uuid as previous */
+#define JBD_FLAG_DELETED 4 /* block deleted by this transaction */
+#define JBD_FLAG_LAST_TAG 8 /* last tag in this descriptor block */
+
+#pragma pack(push, 1)
+
/* Tail of descriptor block, for checksumming */
struct jbd_block_tail {
uint32_t checksum;
uint32_t checksum;
};
+#pragma pack(pop)
+
#define JBD_USERS_MAX 48
#define JBD_USERS_SIZE (UUID_SIZE * JBD_USERS_MAX)
+#pragma pack(push, 1)
+
/*
* The journal superblock. All fields are in big-endian byte order.
*/
/* 0x0400 */
};
+#pragma pack(pop)
+
+#define JBD_SUPERBLOCK_SIZE sizeof(struct jbd_sb)
+
#define JBD_HAS_COMPAT_FEATURE(jsb,mask) \
((jsb)->header.blocktype >= to_be32(2) && \
((jsb)->feature_compat & to_be32((mask))))
struct ext4_blockdev *bdev;
struct ext4_inode_ref inode_ref;
struct jbd_sb sb;
+
+ bool dirty;
+};
+
+struct jbd_buf {
+ uint64_t jbd_lba;
+ struct ext4_block block;
+ struct jbd_trans *trans;
+ struct jbd_block_rec *block_rec;
+ TAILQ_ENTRY(jbd_buf) buf_node;
+ TAILQ_ENTRY(jbd_buf) dirty_buf_node;
+};
+
+struct jbd_revoke_rec {
+ ext4_fsblk_t lba;
+ LIST_ENTRY(jbd_revoke_rec) revoke_node;
+};
+
+struct jbd_block_rec {
+ ext4_fsblk_t lba;
+ struct ext4_buf *buf;
+ struct jbd_trans *trans;
+ RB_ENTRY(jbd_block_rec) block_rec_node;
+ LIST_ENTRY(jbd_block_rec) tbrec_node;
+ TAILQ_HEAD(jbd_buf_dirty, jbd_buf) dirty_buf_queue;
+};
+
+struct jbd_trans {
+ uint32_t trans_id;
+
+ uint32_t start_iblock;
+ int alloc_blocks;
+ int data_cnt;
+ uint32_t data_csum;
+ int written_cnt;
+ int error;
+
+ struct jbd_journal *journal;
+
+ TAILQ_HEAD(jbd_trans_buf, jbd_buf) buf_queue;
+ LIST_HEAD(jbd_revoke_list, jbd_revoke_rec) revoke_list;
+ LIST_HEAD(jbd_trans_block_rec, jbd_block_rec) tbrec_list;
+ TAILQ_ENTRY(jbd_trans) trans_node;
+};
+
+struct jbd_journal {
+ uint32_t first;
+ uint32_t start;
+ uint32_t last;
+ uint32_t trans_id;
+ uint32_t alloc_trans_id;
+
+ uint32_t block_size;
+
+ TAILQ_HEAD(jbd_trans_queue, jbd_trans) trans_queue;
+ TAILQ_HEAD(jbd_cp_queue, jbd_trans) cp_queue;
+ RB_HEAD(jbd_block, jbd_block_rec) block_rec_root;
+
+ struct jbd_fs *jbd_fs;
};
/*****************************************************************************/
#define EXT4_CRC32_INIT (0xFFFFFFFFUL)
/*****************************************************************************/
-#ifdef CONFIG_BIG_ENDIAN
-static inline uint64_t to_le64(uint64_t n)
+
+static inline uint64_t reorder64(uint64_t n)
{
- return ((n & 0xff) << 56) | ((n & 0xff00) << 40) |
- ((n & 0xff0000) << 24) | ((n & 0xff000000LL) << 8) |
- ((n & 0xff00000000LL) >> 8) | ((n & 0xff0000000000LL) >> 24) |
+ return ((n & 0xff) << 56) |
+ ((n & 0xff00) << 40) |
+ ((n & 0xff0000) << 24) |
+ ((n & 0xff000000LL) << 8) |
+ ((n & 0xff00000000LL) >> 8) |
+ ((n & 0xff0000000000LL) >> 24) |
((n & 0xff000000000000LL) >> 40) |
((n & 0xff00000000000000LL) >> 56);
}
-static inline uint32_t to_le32(uint32_t n)
+static inline uint32_t reorder32(uint32_t n)
{
- return ((n & 0xff) << 24) | ((n & 0xff00) << 8) |
- ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
+ return ((n & 0xff) << 24) |
+ ((n & 0xff00) << 8) |
+ ((n & 0xff0000) >> 8) |
+ ((n & 0xff000000) >> 24);
}
-static inline uint16_t to_le16(uint16_t n)
+static inline uint16_t reorder16(uint16_t n)
{
- return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
+ return ((n & 0xff) << 8) |
+ ((n & 0xff00) >> 8);
}
+#ifdef CONFIG_BIG_ENDIAN
+#define to_le64(_n) reorder64(_n)
+#define to_le32(_n) reorder32(_n)
+#define to_le16(_n) reorder16(_n)
+
#define to_be64(_n) _n
#define to_be32(_n) _n
#define to_be16(_n) _n
#define to_le32(_n) _n
#define to_le16(_n) _n
-static inline uint64_t to_be64(uint64_t n)
-{
- return ((n & 0xff) << 56) | ((n & 0xff00) << 40) |
- ((n & 0xff0000) << 24) | ((n & 0xff000000LL) << 8) |
- ((n & 0xff00000000LL) >> 8) | ((n & 0xff0000000000LL) >> 24) |
- ((n & 0xff000000000000LL) >> 40) |
- ((n & 0xff00000000000000LL) >> 56);
-}
-
-static inline uint32_t to_be32(uint32_t n)
-{
- return ((n & 0xff) << 24) | ((n & 0xff00) << 8) |
- ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
-}
-
-static inline uint16_t to_be16(uint16_t n)
-{
- return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
-}
-
+#define to_be64(_n) reorder64(_n)
+#define to_be32(_n) reorder32(_n)
+#define to_be16(_n) reorder16(_n)
#endif
/****************************Access macros to ext4 structures*****************/
(s, f, v) do { (s)->f = (v); } \
while (0)
+/****************************Access macros to jbd2 structures*****************/
+
+#define jbd_get32(s, f) to_be32((s)->f)
+#define jbd_get16(s, f) to_be16((s)->f)
+#define jbd_get8(s, f) (s)->f
+
+#define jbd_set32(s, f, v) \
+ do { \
+ (s)->f = to_be32(v); \
+ } while (0)
+#define jbd_set16(s, f, v) \
+ do { \
+ (s)->f = to_be16(v); \
+ } while (0)
+#define jbd_set8 \
+ (s, f, v) do { (s)->f = (v); } \
+ while (0)
#ifdef __GNUC__
-#ifndef __unused
-#define __unused __attribute__ ((__unused__))
-#endif
+ #ifndef __unused
+ #define __unused __attribute__ ((__unused__))
+ #endif
+#else
+ #define __unused
#endif
#ifndef offsetof