From f854decea14b87a5c19d2ccd8ab5a37a1d500561 Mon Sep 17 00:00:00 2001 From: logkos <65683493+logkos@users.noreply.github.com.> Date: Mon, 16 Sep 2024 23:07:28 +0300 Subject: [PATCH] Ext2FS: Replace Linux macros with homegrown Serenity-style definitions --- Kernel/FileSystem/Ext2FS/Definitions.h | 874 +++++------------------- Kernel/FileSystem/Ext2FS/FileSystem.cpp | 111 +-- Kernel/FileSystem/Ext2FS/FileSystem.h | 29 +- Kernel/FileSystem/Ext2FS/Inode.cpp | 110 +-- Kernel/FileSystem/Ext2FS/Inode.h | 11 +- Kernel/FileSystem/Ext2FS/ext2_types.h | 154 ----- 6 files changed, 308 insertions(+), 981 deletions(-) delete mode 100644 Kernel/FileSystem/Ext2FS/ext2_types.h diff --git a/Kernel/FileSystem/Ext2FS/Definitions.h b/Kernel/FileSystem/Ext2FS/Definitions.h index 47533a08d7b37a..bea208e12bc5d5 100644 --- a/Kernel/FileSystem/Ext2FS/Definitions.h +++ b/Kernel/FileSystem/Ext2FS/Definitions.h @@ -1,736 +1,228 @@ /* - * linux/include/linux/ext2_fs.h + * Copyright (c) 2024, the SerenityOS developers. * - * Copyright (C) 1992, 1993, 1994, 1995 - * Remy Card (card@masi.ibp.fr) - * Laboratoire MASI - Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * from - * - * linux/include/linux/minix_fs.h - * - * Copyright (C) 1991, 1992 Linus Torvalds + * SPDX-License-Identifier: BSD-2-Clause */ -#ifndef _LINUX_EXT2_FS_H -#define _LINUX_EXT2_FS_H - -static constexpr size_t max_block_size = 4096; -static constexpr size_t super_block_offset_on_device = 1024; - -#include "ext2_types.h" /* Changed from linux/types.h */ - -/* - * The second extended filesystem constants/structures - */ - -/* - * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files - */ -#define EXT2_PREALLOCATE -#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 - -/* - * The second extended file system version - */ -#define EXT2FS_DATE "95/08/09" -#define EXT2FS_VERSION "0.5b" - -/* - * Special inode numbers - */ -#define EXT2_BAD_INO 1 /* Bad blocks inode */ -#define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_ACL_IDX_INO 3 /* ACL inode */ -#define EXT2_ACL_DATA_INO 4 /* ACL inode */ -#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ -#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ -#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ -#define EXT2_JOURNAL_INO 8 /* Journal inode */ +#pragma once -/* First non-reserved inode for old ext2 filesystems */ -#define EXT2_GOOD_OLD_FIRST_INO 11 +#include +#include -/* - * The second extended file system magic number - */ -#define EXT2_SUPER_MAGIC 0xEF53 - -#ifdef __KERNEL__ -# define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -#else -/* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test - * macros from user land. */ -# define EXT2_SB(sb) (sb) -#endif - -/* - * Maximal count of links to a file - */ -#define EXT2_LINK_MAX 65000 - -/* - * Macro-instructions used to manage several block sizes - */ -#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ -#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ -#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) -#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) -#ifdef __KERNEL__ -# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) -# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -# define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits) -# define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) -# define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) -#else -# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) -# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) -# define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) -# define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) -#endif -#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32)) - -/* - * Macro-instructions used to manage fragments - */ -#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE -#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE -#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE -#ifdef __KERNEL__ -# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) -#else -# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) -#endif - -/* - * ACL structures - */ -struct ext2_acl_header /* Header of Access Control Lists */ -{ - __u32 aclh_size; - __u32 aclh_file_count; - __u32 aclh_acle_count; - __u32 aclh_first_acle; -}; - -struct ext2_acl_entry /* Access Control List Entry */ -{ - __u32 acle_size; - __u16 acle_perms; /* Access permissions */ - __u16 acle_type; /* Type of entry */ - __u16 acle_tag; /* User or group identity */ - __u16 acle_pad1; - __u32 acle_next; /* Pointer on next entry for the */ - /* same inode or on next free entry */ -}; +// NOTE: Using https://www.nongnu.org/ext2-doc/ext2.html -/* - * Structure of a blocks group descriptor - */ -struct ext2_group_desc { - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_flags; - __u32 bg_reserved[2]; - __u16 bg_itable_unused; /* Unused inodes count */ - __u16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/ +namespace Kernel::Ext2 { +static constexpr size_t max_block_size = 4096; +static constexpr size_t super_block_offset_on_device = 1024; +static constexpr size_t max_name_length = 255; +static constexpr size_t number_of_direct_blocks = 12; +static constexpr size_t single_indirect_block = 12; +static constexpr size_t double_indirect_blocks = 13; +static constexpr size_t trible_indirect_blocks = 14; +static constexpr size_t number_of_blocks = 15; +static constexpr size_t min_group_size = 32; +static constexpr size_t min_group_size64 = 64; +static constexpr size_t min_block_size = 1024; +static constexpr u16 ext2_magic_number = 0xEF53; + +enum InodeNumber { + Reserved, + EXT2_BAD_INO, + EXT2_ROOT_INO, + EXT2_ACL_IDX_INO, + EXT2_ACL_DATA_INO, + EXT2_BOOT_LOADER_INO, + EXT2_UNDEL_DIR_INO, + EXT2_RESIZE_INO, + EXT2_JOURNAL_INO }; -struct ext4_group_desc { - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_flags; - __u32 bg_reserved[2]; - __u16 bg_itable_unused; /* Unused inodes count */ - __u16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/ - __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ - __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ - __u32 bg_inode_table_hi; /* Inodes table block MSB */ - __u16 bg_free_blocks_count_hi; /* Free blocks count MSB */ - __u16 bg_free_inodes_count_hi; /* Free inodes count MSB */ - __u16 bg_used_dirs_count_hi; /* Directories count MSB */ - __u16 bg_pad; - __u32 bg_reserved2[3]; +enum class FeaturesOptional : u32 { + None = 0, + ExtendedAttributes = 0x0008, }; -#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */ -#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */ -#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */ - -/* - * Data structures used by the directory indexing feature - * - * Note: all of the multibyte integer fields are little endian. - */ +AK_ENUM_BITWISE_OPERATORS(FeaturesOptional); -/* - * Note: dx_root_info is laid out so that if it should somehow get - * overlaid by a dirent the two low bits of the hash version will be - * zero. Therefore, the hash version mod 4 should never be 0. - * Sincerely, the paranoia department. - */ -struct ext2_dx_root_info { - __u32 reserved_zero; - __u8 hash_version; /* 0 now, 1 at release */ - __u8 info_length; /* 8 */ - __u8 indirect_levels; - __u8 unused_flags; +enum class FeaturesReadOnly : u32 { + None = 0, + SparseSuperblock = 0x0001, + FileSize64bits = 0x0002, }; -#define EXT2_HASH_LEGACY 0 -#define EXT2_HASH_HALF_MD4 1 -#define EXT2_HASH_TEA 2 -#define EXT2_HASH_LEGACY_UNSIGNED 3 /* reserved for userspace lib */ -#define EXT2_HASH_HALF_MD4_UNSIGNED 4 /* reserved for userspace lib */ -#define EXT2_HASH_TEA_UNSIGNED 5 /* reserved for userspace lib */ +AK_ENUM_BITWISE_OPERATORS(FeaturesReadOnly); -#define EXT2_HASH_FLAG_INCOMPAT 0x1 - -struct ext2_dx_entry { - __u32 hash; - __u32 block; +enum class FeaturesIncompat : u32 { + None = 0, + EXT4_FEATURE_INCOMPAT_64BIT = 0x0080 }; -struct ext2_dx_countlimit { - __u16 limit; - __u16 count; +AK_ENUM_BITWISE_OPERATORS(FeaturesIncompat); + +enum FileType { + EXT2_FT_UNKNOWN, + EXT2_FT_REG_FILE, + EXT2_FT_DIR, + EXT2_FT_CHRDEV, + EXT2_FT_BLKDEV, + EXT2_FT_FIFO, + EXT2_FT_SOCK, + EXT2_FT_SYMLINK, + EXT2_FT_MAX }; -/* - * Macro-instructions used to manage group descriptors - */ -#define EXT2_MIN_DESC_SIZE 32 -#define EXT2_MIN_DESC_SIZE_64BIT 64 -#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE -#define EXT2_DESC_SIZE(s) \ - ((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? (s)->s_desc_size : EXT2_MIN_DESC_SIZE) - -#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) -#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) -#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_INODE_SIZE(s)) -/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ -#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) -#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) -#ifdef __KERNEL__ -# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) -# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) -#else -# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s)) -#endif - -/* - * Constants relative to the data blocks - */ -#define EXT2_NDIR_BLOCKS 12 -#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS -#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) -#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) -#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) - -/* - * Inode flags - */ -#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ -#define EXT2_UNRM_FL 0x00000002 /* Undelete */ -#define EXT2_COMPR_FL 0x00000004 /* Compress file */ -#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ -#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ -#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ -#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ -#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ -/* Reserved for compression usage... */ -#define EXT2_DIRTY_FL 0x00000100 -#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ -#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ -#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ -/* End compression flags --- maybe not all used */ -#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ -#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ -#define EXT2_IMAGIC_FL 0x00002000 -#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ -#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ -#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ -#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ -#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ -#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ -#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ - -#define EXT2_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ -#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ - -/* - * ioctl commands - */ - -/* Used for online resize */ -struct ext2_new_group_input { - __u32 group; /* Group number for this data */ - __u32 block_bitmap; /* Absolute block number of block bitmap */ - __u32 inode_bitmap; /* Absolute block number of inode bitmap */ - __u32 inode_table; /* Absolute block number of inode table start */ - __u32 blocks_count; /* Total number of blocks in this group */ - __u16 reserved_blocks; /* Number of reserved blocks in this group */ - __u16 unused; /* Number of reserved GDT blocks in group */ -}; - -struct ext4_new_group_input { - __u32 group; /* Group number for this data */ - __u64 block_bitmap; /* Absolute block number of block bitmap */ - __u64 inode_bitmap; /* Absolute block number of inode bitmap */ - __u64 inode_table; /* Absolute block number of inode table start */ - __u32 blocks_count; /* Total number of blocks in this group */ - __u16 reserved_blocks; /* Number of reserved blocks in this group */ - __u16 unused; +enum FileSystemState : u8 { + Valid = 0x0001, /* Unmounted cleanly */ + Error = 0x0002, /* Errors detected */ + Orphan = 0x0004 /* Orphans being recovered */ }; -#ifdef __GNU__ /* Needed for the Hurd */ -# define _IOT_ext2_new_group_input _IOT(_IOTS(__u32), 5, _IOTS(__u16), 2, 0, 0) -#endif - -#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) -#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) -#define EXT2_IOC_GETVERSION _IOR('v', 1, long) -#define EXT2_IOC_SETVERSION _IOW('v', 2, long) -#define EXT2_IOC_GETVERSION_NEW _IOR('f', 3, long) -#define EXT2_IOC_SETVERSION_NEW _IOW('f', 4, long) -#define EXT2_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long) -#define EXT2_IOC_GROUP_ADD _IOW('f', 8, struct ext2_new_group_input) -#define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input) - -/* - * Structure of an inode on the disk - */ -struct ext2_inode { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Low 16 bits of Owner Uid */ - __u32 i_size; /* Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Inode change time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u16 i_gid; /* Low 16 bits of Group Id */ - __u16 i_links_count; /* Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* File flags */ - union { - struct { - __u32 l_i_version; /* was l_i_reserved1 */ - } linux1; - struct { - __u32 h_i_translator; - } hurd1; - } osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */ - __u32 i_generation; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ - union { - struct { - __u16 l_i_blocks_hi; - __u16 l_i_file_acl_high; - __u16 l_i_uid_high; /* these 2 fields */ - __u16 l_i_gid_high; /* were reserved2[0] */ - __u32 l_i_reserved2; - } linux2; - struct { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; - } hurd2; - } osd2; /* OS dependent 2 */ +struct GroupDescriptor { + u32 bg_block_bitmap; /* Blocks bitmap block */ + u32 bg_inode_bitmap; /* Inodes bitmap block */ + u32 bg_inode_table; /* Inodes table block */ + u16 bg_free_blocks_count; /* Free blocks count */ + u16 bg_free_inodes_count; /* Free inodes count */ + u16 bg_used_dirs_count; /* Directories count */ + u16 bg_flags; + u32 bg_reserved[2]; + u16 bg_itable_unused; /* Unused inodes count */ + u16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/ }; -/* - * Permanent part of an large inode on the disk - */ -struct ext2_inode_large { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Low 16 bits of Owner Uid */ - __u32 i_size; /* Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Inode Change time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u16 i_gid; /* Low 16 bits of Group Id */ - __u16 i_links_count; /* Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* File flags */ +struct Ext2Inode { + u16 i_mode; /* File mode */ + u16 i_uid; /* Low 16 bits of Owner Uid */ + u32 i_size; /* Size in bytes */ + u32 i_atime; /* Access time */ + u32 i_ctime; /* Inode change time */ + u32 i_mtime; /* Modification time */ + u32 i_dtime; /* Deletion Time */ + u16 i_gid; /* Low 16 bits of Group Id */ + u16 i_links_count; /* Links count */ + u32 i_blocks; /* Blocks count */ + u32 i_flags; /* File flags */ union { struct { - __u32 l_i_version; /* was l_i_reserved1 */ + u32 l_i_version; /* was l_i_reserved1 */ } linux1; struct { - __u32 h_i_translator; + u32 h_i_translator; } hurd1; - } osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */ - __u32 i_generation; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ + } osd1; /* OS dependent 1 */ + u32 i_block[number_of_blocks]; /* Pointers to blocks */ + u32 i_generation; /* File version (for NFS) */ + u32 i_file_acl; /* File ACL */ + u32 i_dir_acl; /* Directory ACL */ + u32 i_faddr; /* Fragment address */ union { struct { - __u16 l_i_blocks_hi; - __u16 l_i_file_acl_high; - __u16 l_i_uid_high; /* these 2 fields */ - __u16 l_i_gid_high; /* were reserved2[0] */ - __u32 l_i_reserved2; + u16 l_i_blocks_hi; + u16 l_i_file_acl_high; + u16 l_i_uid_high; /* these 2 fields */ + u16 l_i_gid_high; /* were reserved2[0] */ + u32 l_i_reserved2; } linux2; struct { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; + u8 h_i_frag; /* Fragment number */ + u8 h_i_fsize; /* Fragment size */ + u16 h_i_mode_high; + u16 h_i_uid_high; + u16 h_i_gid_high; + u32 h_i_author; } hurd2; } osd2; /* OS dependent 2 */ - __u16 i_extra_isize; - __u16 i_pad1; - __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ - __u32 i_mtime_extra; /* extra Modification time (nsec << 2 | epoch) */ - __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ - __u32 i_crtime; /* File creation time */ - __u32 i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/ - __u32 i_version_hi; /* high 32 bits for 64-bit version */ }; -#define i_size_high i_dir_acl - -#if defined(__KERNEL__) || defined(__linux__) -# define i_reserved1 osd1.linux1.l_i_reserved1 -# define i_frag osd2.linux2.l_i_frag -# define i_fsize osd2.linux2.l_i_fsize -# define i_uid_low i_uid -# define i_gid_low i_gid -# define i_uid_high osd2.linux2.l_i_uid_high -# define i_gid_high osd2.linux2.l_i_gid_high -# define i_reserved2 osd2.linux2.l_i_reserved2 -#else -# if defined(__GNU__) - -# define i_translator osd1.hurd1.h_i_translator -# define i_frag osd2.hurd2.h_i_frag; -# define i_fsize osd2.hurd2.h_i_fsize; -# define i_uid_high osd2.hurd2.h_i_uid_high -# define i_gid_high osd2.hurd2.h_i_gid_high -# define i_author osd2.hurd2.h_i_author - -# endif /* __GNU__ */ -#endif /* defined(__KERNEL__) || defined(__linux__) */ - -#define inode_uid(inode) ((inode).i_uid | (inode).osd2.linux2.l_i_uid_high << 16) -#define inode_gid(inode) ((inode).i_gid | (inode).osd2.linux2.l_i_gid_high << 16) -#define ext2fs_set_i_uid_high(inode, x) ((inode).osd2.linux2.l_i_uid_high = (x)) -#define ext2fs_set_i_gid_high(inode, x) ((inode).osd2.linux2.l_i_gid_high = (x)) - -/* - * File system states - */ -#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ -#define EXT2_ERROR_FS 0x0002 /* Errors detected */ -#define EXT3_ORPHAN_FS 0x0004 /* Orphans being recovered */ - -/* - * Misc. filesystem flags - */ -#define EXT2_FLAGS_SIGNED_HASH 0x0001 /* Signed dirhash in use */ -#define EXT2_FLAGS_UNSIGNED_HASH 0x0002 /* Unsigned dirhash in use */ -#define EXT2_FLAGS_TEST_FILESYS 0x0004 /* OK for use on development code */ - -/* - * Mount flags - */ -#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ -#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ -#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ -#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ -#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ -#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ -#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ -#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ - -#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt -#define set_opt(o, opt) o |= EXT2_MOUNT_##opt -#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_##opt) -/* - * Maximal mount counts between two filesystem checks - */ -#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ -#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ - -/* - * Behavior when detecting errors - */ -#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ -#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ -#define EXT2_ERRORS_PANIC 3 /* Panic */ -#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE - -/* - * Structure of the super block - */ -struct ext2_super_block { - __u32 s_inodes_count; /* Inodes count */ - __u32 s_blocks_count; /* Blocks count */ - __u32 s_r_blocks_count; /* Reserved blocks count */ - __u32 s_free_blocks_count; /* Free blocks count */ - __u32 s_free_inodes_count; /* Free inodes count */ - __u32 s_first_data_block; /* First Data Block */ - __u32 s_log_block_size; /* Block size */ - __s32 s_log_frag_size; /* Fragment size */ - __u32 s_blocks_per_group; /* # Blocks per group */ - __u32 s_frags_per_group; /* # Fragments per group */ - __u32 s_inodes_per_group; /* # Inodes per group */ - __u32 s_mtime; /* Mount time */ - __u32 s_wtime; /* Write time */ - __u16 s_mnt_count; /* Mount count */ - __s16 s_max_mnt_count; /* Maximal mount count */ - __u16 s_magic; /* Magic signature */ - __u16 s_state; /* File system state */ - __u16 s_errors; /* Behavior when detecting errors */ - __u16 s_minor_rev_level; /* minor revision level */ - __u32 s_lastcheck; /* time of last check */ - __u32 s_checkinterval; /* max. time between checks */ - __u32 s_creator_os; /* OS */ - __u32 s_rev_level; /* Revision level */ - __u16 s_def_resuid; /* Default uid for reserved blocks */ - __u16 s_def_resgid; /* Default gid for reserved blocks */ - /* - * These fields are for EXT2_DYNAMIC_REV superblocks only. - * - * Note: the difference between the compatible feature set and - * the incompatible feature set is that if there is a bit set - * in the incompatible feature set that the kernel doesn't - * know about, it should refuse to mount the filesystem. - * - * e2fsck's requirements are more strict; if it doesn't know - * about a feature in either the compatible or incompatible - * feature set, it must abort and not try to meddle with - * things it doesn't understand... - */ - __u32 s_first_ino; /* First non-reserved inode */ - __u16 s_inode_size; /* size of inode structure */ - __u16 s_block_group_nr; /* block group # of this superblock */ - __u32 s_feature_compat; /* compatible feature set */ - __u32 s_feature_incompat; /* incompatible feature set */ - __u32 s_feature_ro_compat; /* readonly-compatible feature set */ - __u8 s_uuid[16]; /* 128-bit uuid for volume */ +struct SuperBlock { + u32 s_inodes_count; /* Inodes count */ + u32 s_blocks_count; /* Blocks count */ + u32 s_r_blocks_count; /* Reserved blocks count */ + u32 s_free_blocks_count; /* Free blocks count */ + u32 s_free_inodes_count; /* Free inodes count */ + u32 s_first_data_block; /* First Data Block */ + u32 s_log_block_size; /* Block size */ + unsigned short s_log_frag_size; /* Fragment size */ + u32 s_blocks_per_group; /* # Blocks per group */ + u32 s_frags_per_group; /* # Fragments per group */ + u32 s_inodes_per_group; /* # Inodes per group */ + u32 s_mtime; /* Mount time */ + u32 s_wtime; /* Write time */ + u16 s_mnt_count; /* Mount count */ + unsigned short s_max_mnt_count; /* Maximal mount count */ + u16 s_magic; /* Magic signature */ + u16 s_state; /* File system state */ + u16 s_errors; /* Behavior when detecting errors */ + u16 s_minor_rev_level; /* minor revision level */ + u32 s_lastcheck; /* time of last check */ + u32 s_checkinterval; /* max. time between checks */ + u32 s_creator_os; /* OS */ + u32 s_rev_level; /* Revision level */ + u16 s_def_resuid; /* Default uid for reserved blocks */ + u16 s_def_resgid; /* Default gid for reserved blocks */ + u32 s_first_ino; /* First non-reserved inode */ + u16 s_inode_size; /* size of inode structure */ + u16 s_block_group_nr; /* block group # of this superblock */ + u32 s_feature_compat; /* compatible feature set */ + u32 s_feature_incompat; /* incompatible feature set */ + u32 s_feature_ro_compat; /* readonly-compatible feature set */ + u8 s_uuid[16]; /* 128-bit uuid for volume */ char s_volume_name[16]; /* volume name */ char s_last_mounted[64]; /* directory where last mounted */ - __u32 s_algorithm_usage_bitmap; /* For compression */ - /* - * Performance hints. Directory preallocation should only - * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. - */ - __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ - __u16 s_reserved_gdt_blocks; /* Per group table for online growth */ - /* - * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. - */ - __u8 s_journal_uuid[16]; /* uuid of journal superblock */ - __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ - __u32 s_hash_seed[4]; /* HTREE hash seed */ - __u8 s_def_hash_version; /* Default hash version to use */ - __u8 s_jnl_backup_type; /* Default type of journal backup */ - __u16 s_desc_size; /* Group desc. size: INCOMPAT_64BIT */ - __u32 s_default_mount_opts; - __u32 s_first_meta_bg; /* First metablock group */ - __u32 s_mkfs_time; /* When the filesystem was created */ - __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ - __u32 s_blocks_count_hi; /* Blocks count high 32bits */ - __u32 s_r_blocks_count_hi; /* Reserved blocks count high 32 bits*/ - __u32 s_free_blocks_hi; /* Free blocks count */ - __u16 s_min_extra_isize; /* All inodes have at least # bytes */ - __u16 s_want_extra_isize; /* New inodes should reserve # bytes */ - __u32 s_flags; /* Miscellaneous flags */ - __u16 s_raid_stride; /* RAID stride */ - __u16 s_mmp_interval; /* # seconds to wait in MMP checking */ - __u64 s_mmp_block; /* Block for multi-mount protection */ - __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ - __u8 s_log_groups_per_flex; /* FLEX_BG group size */ - __u8 s_reserved_char_pad; - __u16 s_reserved_pad; /* Padding to next 32bits */ - __u32 s_reserved[162]; /* Padding to the end of the block */ -}; - -/* - * Codes for operating systems - */ -#define EXT2_OS_LINUX 0 -#define EXT2_OS_HURD 1 -#define EXT2_OBSO_OS_MASIX 2 -#define EXT2_OS_FREEBSD 3 -#define EXT2_OS_LITES 4 - -/* - * Revision levels - */ -#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ -#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ - -#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV -#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV - -#define EXT2_GOOD_OLD_INODE_SIZE 128 - -/* - * Journal inode backup types - */ -#define EXT3_JNL_BACKUP_BLOCKS 1 - -/* - * Feature set definitions - */ - -#define EXT2_HAS_COMPAT_FEATURE(sb, mask) \ - (EXT2_SB(sb)->s_feature_compat & (mask)) -#define EXT2_HAS_RO_COMPAT_FEATURE(sb, mask) \ - (EXT2_SB(sb)->s_feature_ro_compat & (mask)) -#define EXT2_HAS_INCOMPAT_FEATURE(sb, mask) \ - (EXT2_SB(sb)->s_feature_incompat & (mask)) - -#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 -#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 -#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 -#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 -#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 -#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 -#define EXT2_FEATURE_COMPAT_LAZY_BG 0x0040 - -#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 -#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 -/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ -#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 -#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 -#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 -#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 - -#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 -#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ -#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ -#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 -#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 -#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 -#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 - -#define EXT2_FEATURE_COMPAT_SUPP 0 -#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) -#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT2_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_DIR_NLINK | EXT2_FEATURE_RO_COMPAT_BTREE_DIR) - -/* - * Default values for user and/or group using reserved blocks - */ -#define EXT2_DEF_RESUID 0 -#define EXT2_DEF_RESGID 0 - -/* - * Default mount options - */ -#define EXT2_DEFM_DEBUG 0x0001 -#define EXT2_DEFM_BSDGROUPS 0x0002 -#define EXT2_DEFM_XATTR_USER 0x0004 -#define EXT2_DEFM_ACL 0x0008 -#define EXT2_DEFM_UID16 0x0010 -#define EXT3_DEFM_JMODE 0x0060 -#define EXT3_DEFM_JMODE_DATA 0x0020 -#define EXT3_DEFM_JMODE_ORDERED 0x0040 -#define EXT3_DEFM_JMODE_WBACK 0x0060 - -/* - * Structure of a directory entry - */ -#define EXT2_NAME_LEN 255 - -struct ext2_dir_entry { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u16 name_len; /* Name length */ - char name[EXT2_NAME_LEN]; /* Filename */ + u32 s_algorithm_usage_bitmap; /* For compression */ + u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + u16 s_reserved_gdt_blocks; /* Per group table for online growth */ + u8 s_journal_uuid[16]; /* uuid of journal superblock */ + u32 s_journal_inum; /* inode number of journal file */ + u32 s_journal_dev; /* device number of journal file */ + u32 s_last_orphan; /* start of list of inodes to delete */ + u32 s_hash_seed[4]; /* HTREE hash seed */ + u8 s_def_hash_version; /* Default hash version to use */ + u8 s_jnl_backup_type; /* Default type of journal backup */ + u16 s_desc_size; /* Group desc. size: INCOMPAT_64BIT */ + u32 s_default_mount_opts; + u32 s_first_meta_bg; /* First metablock group */ + u32 s_mkfs_time; /* When the filesystem was created */ + u32 s_jnl_blocks[17]; /* Backup of the journal inode */ + u32 s_blocks_count_hi; /* Blocks count high 32bits */ + u32 s_r_blocks_count_hi; /* Reserved blocks count high 32 bits*/ + u32 s_free_blocks_hi; /* Free blocks count */ + u16 s_min_extra_isize; /* All inodes have at least # bytes */ + u16 s_want_extra_isize; /* New inodes should reserve # bytes */ + u32 s_flags; /* Miscellaneous flags */ + u16 s_raid_stride; /* RAID stride */ + u16 s_mmp_interval; /* # seconds to wait in MMP checking */ + u64 s_mmp_block; /* Block for multi-mount protection */ + u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ + u8 s_log_groups_per_flex; /* FLEX_BG group size */ + u8 s_reserved_char_pad; + u16 s_reserved_pad; /* Padding to next 32bits */ + u32 s_reserved[162]; /* Padding to the end of the block */ }; -/* - * The new version of the directory entry. Since EXT2 structures are - * stored in intel byte order, and the name_len field could never be - * bigger than 255 chars, it's safe to reclaim the extra byte for the - * file_type field. - */ -struct ext2_dir_entry_2 { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u8 name_len; /* Name length */ - __u8 file_type; - char name[EXT2_NAME_LEN]; /* Filename */ +struct DirectoryEntry { + u32 inode; + u16 rec_len; + u8 name_len; + u8 file_type; + char name[max_name_length]; }; -/* - * Ext2 directory file types. Only the low 3 bits are used. The - * other bits are reserved for now. - */ -#define EXT2_FT_UNKNOWN 0 -#define EXT2_FT_REG_FILE 1 -#define EXT2_FT_DIR 2 -#define EXT2_FT_CHRDEV 3 -#define EXT2_FT_BLKDEV 4 -#define EXT2_FT_FIFO 5 -#define EXT2_FT_SOCK 6 -#define EXT2_FT_SYMLINK 7 - -#define EXT2_FT_MAX 8 - -/* - * EXT2_DIR_PAD defines the directory entries boundaries - * - * NOTE: It must be a multiple of 4 - */ -#define EXT2_DIR_PAD 4 -#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) -#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & ~EXT2_DIR_ROUND) +inline size_t superblock_size(SuperBlock sb) { return min_block_size << sb.s_log_block_size; } +inline size_t superblock_size_bits(SuperBlock sb) { return sb.s_log_block_size + 10; } -/* - * This structure will be used for multiple mount protection. It will be - * written into the block number saved in the s_mmp_block field in the - * superblock. - */ -#define EXT2_MMP_MAGIC 0x004D4D50 /* ASCII for MMP */ -#define EXT2_MMP_CLEAN 0xFF4D4D50 /* Value of mmp_seq for clean unmount */ -#define EXT2_MMP_FSCK_ON 0xE24D4D50 /* Value of mmp_seq when being fscked */ +inline size_t first_inode(SuperBlock sb) { return (sb.s_rev_level == 0) ? 11 : sb.s_first_ino; } +inline size_t address_per_block(SuperBlock sb) { return superblock_size(sb) / 4; } +inline size_t fragment_size(SuperBlock sb) { return super_block_offset_on_device << sb.s_log_frag_size; } +inline size_t descriptor_size(SuperBlock sb) { return (sb.s_feature_incompat & static_cast(FeaturesIncompat::EXT4_FEATURE_INCOMPAT_64BIT)) ? sb.s_desc_size : Ext2::min_group_size; } -struct mmp_struct { - __u32 mmp_magic; - __u32 mmp_seq; - __u64 mmp_time; - char mmp_nodename[64]; - char mmp_bdevname[32]; - __u16 mmp_interval; - __u16 mmp_pad1; - __u32 mmp_pad2; -}; - -/* - * Interval in number of seconds to update the MMP sequence number. - */ -#define EXT2_MMP_DEF_INTERVAL 5 +inline size_t descriptor_per_block(SuperBlock sb) { return superblock_size(sb) / descriptor_size(sb); } +// ^ Inode operations +inline size_t inode_uid(Ext2Inode inode) { return (inode.i_uid | inode.osd2.linux2.l_i_uid_high) << 16; } +inline size_t inode_gid(Ext2Inode inode) { return (inode.i_gid | inode.osd2.linux2.l_i_gid_high) << 16; } +inline size_t set_i_uid_high(Ext2Inode inode, unsigned uid) { return inode.osd2.linux2.l_i_uid_high = uid; } +inline size_t set_i_gid_high(Ext2Inode inode, unsigned uid) { return inode.osd2.linux2.l_i_gid_high = uid; } +inline size_t directory_record_length(size_t name_len) { return ((name_len + 11) & ~3); } -#endif /* _LINUX_EXT2_FS_H */ +} diff --git a/Kernel/FileSystem/Ext2FS/FileSystem.cpp b/Kernel/FileSystem/Ext2FS/FileSystem.cpp index 2e26574b9af24d..6ebe3cb8fa0d15 100644 --- a/Kernel/FileSystem/Ext2FS/FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FS/FileSystem.cpp @@ -13,6 +13,7 @@ #include namespace Kernel { +using namespace Ext2; ErrorOr> Ext2FS::try_create(OpenFileDescription& file_description, FileSystemSpecificOptions const&) { @@ -30,13 +31,13 @@ ErrorOr Ext2FS::flush_super_block() { MutexLocker locker(m_lock); auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block); - auto const superblock_physical_block_count = (sizeof(ext2_super_block) / device_block_size()); + auto const superblock_physical_block_count = (sizeof(Ext2::SuperBlock) / device_block_size()); // FIXME: We currently have no ability of writing within a device block, but the ability to do so would allow us to use device block sizes larger than 1024. - VERIFY((sizeof(ext2_super_block) % device_block_size()) == 0); - TRY(raw_write_blocks(super_block_offset_on_device / device_block_size(), superblock_physical_block_count, super_block_buffer)); + VERIFY((sizeof(Ext2::SuperBlock) % device_block_size()) == 0); + TRY(raw_write_blocks(Ext2::super_block_offset_on_device / device_block_size(), superblock_physical_block_count, super_block_buffer)); - auto is_sparse = has_flag(get_features_readonly(), FeaturesReadOnly::SparseSuperblock); + auto is_sparse = has_flag(get_features_readonly(), Ext2::FeaturesReadOnly::SparseSuperblock); for (auto group = 1u; group < m_block_group_count; ++group) { auto first_block_in_group = first_block_of_group(group); @@ -50,7 +51,7 @@ ErrorOr Ext2FS::flush_super_block() return {}; } -ext2_group_desc const& Ext2FS::group_descriptor(GroupIndex group_index) const +Ext2::GroupDescriptor const& Ext2FS::group_descriptor(GroupIndex group_index) const { // FIXME: Should this fail gracefully somehow? VERIFY(group_index <= m_block_group_count); @@ -69,40 +70,40 @@ ErrorOr Ext2FS::initialize_while_locked() VERIFY(m_lock.is_locked()); VERIFY(!is_initialized_while_locked()); - VERIFY((sizeof(ext2_super_block) % device_block_size()) == 0); + VERIFY((sizeof(Ext2::SuperBlock) % device_block_size()) == 0); auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block); - TRY(raw_read_blocks(super_block_offset_on_device / device_block_size(), (sizeof(ext2_super_block) / device_block_size()), super_block_buffer)); + TRY(raw_read_blocks(Ext2::super_block_offset_on_device / device_block_size(), (sizeof(Ext2::SuperBlock) / device_block_size()), super_block_buffer)); auto const& super_block = this->super_block(); if constexpr (EXT2_DEBUG) { - dmesgln("Ext2FS: super block magic: {:04x} (super block size: {})", super_block.s_magic, sizeof(ext2_super_block)); + dmesgln("Ext2FS: super block magic: {:04x} (super block size: {})", super_block.s_magic, sizeof(Ext2::SuperBlock)); } - if (super_block.s_magic != EXT2_SUPER_MAGIC) { + if (super_block.s_magic != ext2_magic_number) { dmesgln("Ext2FS: Bad super block magic"); return EINVAL; } - if (super_block.s_state == EXT2_ERROR_FS) + if (super_block.s_state == Error) dmesgln("Ext2FS: Was not unmounted cleanly, file system may be erroneous!"); if constexpr (EXT2_DEBUG) { dmesgln("Ext2FS: {} inodes, {} blocks", super_block.s_inodes_count, super_block.s_blocks_count); - dmesgln("Ext2FS: Block size: {}", EXT2_BLOCK_SIZE(&super_block)); + dmesgln("Ext2FS: Block size: {}", superblock_size(super_block)); dmesgln("Ext2FS: First data block: {}", super_block.s_first_data_block); dmesgln("Ext2FS: Inodes per block: {}", inodes_per_block()); dmesgln("Ext2FS: Inodes per group: {}", inodes_per_group()); dmesgln("Ext2FS: Free inodes: {}", super_block.s_free_inodes_count); - dmesgln("Ext2FS: Descriptors per block: {}", EXT2_DESC_PER_BLOCK(&super_block)); - dmesgln("Ext2FS: Descriptor size: {}", EXT2_DESC_SIZE(&super_block)); + dmesgln("Ext2FS: Descriptors per block: {}", descriptor_per_block(super_block)); + dmesgln("Ext2FS: Descriptor size: {}", descriptor_size(super_block)); } - set_logical_block_size(EXT2_BLOCK_SIZE(&super_block)); - set_fragment_size(EXT2_FRAG_SIZE(&super_block)); + set_logical_block_size(superblock_size(super_block)); + set_fragment_size(Ext2::fragment_size(super_block)); // Note: This depends on the block size being available. TRY(BlockBasedFileSystem::initialize_while_locked()); - VERIFY(logical_block_size() <= (int)max_block_size); + VERIFY(logical_block_size() <= Ext2::max_block_size); m_block_group_count = ceil_div(super_block.s_blocks_count, super_block.s_blocks_per_group); @@ -111,7 +112,7 @@ ErrorOr Ext2FS::initialize_while_locked() return EINVAL; } - auto blocks_to_read = ceil_div(m_block_group_count * sizeof(ext2_group_desc), logical_block_size()); + auto blocks_to_read = ceil_div(m_block_group_count * sizeof(GroupDescriptor), logical_block_size()); BlockIndex first_block_of_bgdt = first_block_of_block_group_descriptors(); m_cached_group_descriptor_table = TRY(KBuffer::try_create_with_size("Ext2FS: Block group descriptors"sv, logical_block_size() * blocks_to_read, Memory::Region::Access::ReadWrite)); auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_group_descriptor_table->data()); @@ -128,7 +129,7 @@ ErrorOr Ext2FS::initialize_while_locked() // Set filesystem to "error" state until we unmount cleanly. dmesgln("Ext2FS: Mount successful, setting superblock to error state."); - m_super_block.s_state = EXT2_ERROR_FS; + m_super_block.s_state = Ext2::Error; TRY(flush_super_block()); return {}; @@ -143,7 +144,7 @@ bool Ext2FS::find_block_containing_inode(InodeIndex inode, BlockIndex& block_ind { auto const& super_block = this->super_block(); - if (inode != EXT2_ROOT_INO && inode < EXT2_FIRST_INO(&super_block)) + if (inode != Ext2::EXT2_ROOT_INO && inode < first_inode(super_block)) return false; if (inode > super_block.s_inodes_count) @@ -152,7 +153,7 @@ bool Ext2FS::find_block_containing_inode(InodeIndex inode, BlockIndex& block_ind auto const& bgd = group_descriptor(group_index_from_inode(inode)); u64 full_offset = ((inode.value() - 1) % inodes_per_group()) * inode_size(); - block_index = bgd.bg_inode_table + (full_offset >> EXT2_BLOCK_SIZE_BITS(&super_block)); + block_index = bgd.bg_inode_table + (full_offset >> superblock_size_bits(super_block)); offset = full_offset & (logical_block_size() - 1); return true; @@ -161,59 +162,60 @@ bool Ext2FS::find_block_containing_inode(InodeIndex inode, BlockIndex& block_ind u8 Ext2FS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const { switch (entry.file_type) { - case EXT2_FT_REG_FILE: + case Ext2::EXT2_FT_REG_FILE: return DT_REG; - case EXT2_FT_DIR: + case Ext2::EXT2_FT_DIR: return DT_DIR; - case EXT2_FT_CHRDEV: + case Ext2::EXT2_FT_CHRDEV: return DT_CHR; - case EXT2_FT_BLKDEV: + case Ext2::EXT2_FT_BLKDEV: return DT_BLK; - case EXT2_FT_FIFO: + case Ext2::EXT2_FT_FIFO: return DT_FIFO; - case EXT2_FT_SOCK: + case Ext2::EXT2_FT_SOCK: return DT_SOCK; - case EXT2_FT_SYMLINK: + case Ext2::EXT2_FT_SYMLINK: return DT_LNK; default: return DT_UNKNOWN; } } -Ext2FS::FeaturesOptional Ext2FS::get_features_optional() const +Ext2::FeaturesOptional Ext2FS::get_features_optional() const { if (m_super_block.s_rev_level > 0) - return static_cast(m_super_block.s_feature_compat); - return Ext2FS::FeaturesOptional::None; + return static_cast(m_super_block.s_feature_compat); + return Ext2::FeaturesOptional::None; } -Ext2FS::FeaturesReadOnly Ext2FS::get_features_readonly() const +Ext2::FeaturesReadOnly Ext2FS::get_features_readonly() const { if (m_super_block.s_rev_level > 0) - return static_cast(m_super_block.s_feature_ro_compat); - return Ext2FS::FeaturesReadOnly::None; + return static_cast(m_super_block.s_feature_ro_compat); + return Ext2::FeaturesReadOnly::None; } u64 Ext2FS::inodes_per_block() const { - return EXT2_INODES_PER_BLOCK(&super_block()); + return superblock_size(super_block()) / inode_size(); } u64 Ext2FS::inodes_per_group() const { - return EXT2_INODES_PER_GROUP(&super_block()); + return super_block().s_inodes_per_group; } u64 Ext2FS::inode_size() const { - return EXT2_INODE_SIZE(&super_block()); + return (super_block().s_rev_level == 0) ? 128 : super_block().s_inode_size; } + u64 Ext2FS::blocks_per_group() const { - return EXT2_BLOCKS_PER_GROUP(&super_block()); + return super_block().s_blocks_per_group; } -ErrorOr Ext2FS::write_ext2_inode(InodeIndex inode, ext2_inode const& e2inode) +ErrorOr Ext2FS::write_ext2_inode(InodeIndex inode, Ext2::Ext2Inode const& e2inode) { BlockIndex block_index; unsigned offset; @@ -326,7 +328,7 @@ ErrorOr Ext2FS::allocate_inode(GroupIndex preferred_group) cached_bitmap->dirty = true; m_super_block.s_free_inodes_count--; m_super_block_dirty = true; - const_cast(bgd).bg_free_inodes_count--; + const_cast(bgd).bg_free_inodes_count--; m_block_group_descriptors_dirty = true; // In case the inode cache had this cached as "non-existent", uncache that info. @@ -409,7 +411,7 @@ ErrorOr Ext2FS::set_inode_allocation_state(InodeIndex inode_index, bool ne unsigned bit_index = (index_in_group - 1) % inodes_per_group(); dbgln_if(EXT2_DEBUG, "Ext2FS: set_inode_allocation_state: Inode {} -> {}", inode_index, new_state); - auto& bgd = const_cast(group_descriptor(group_index)); + auto& bgd = const_cast(group_descriptor(group_index)); return update_bitmap_block(bgd.bg_inode_bitmap, bit_index, new_state, m_super_block.s_free_inodes_count, bgd.bg_free_inodes_count); } @@ -441,7 +443,7 @@ ErrorOr Ext2FS::set_block_allocation_state(BlockIndex block_index, bool ne auto group_index = group_index_from_block_index(block_index); unsigned index_in_group = (block_index.value() - first_block_index().value()) - ((group_index.value() - 1) * blocks_per_group()); unsigned bit_index = index_in_group % blocks_per_group(); - auto& bgd = const_cast(group_descriptor(group_index)); + auto& bgd = const_cast(group_descriptor(group_index)); dbgln_if(EXT2_DEBUG, "Ext2FS: Block {} state -> {} (in bitmap block {})", block_index, new_state, bgd.bg_block_bitmap); return update_bitmap_block(bgd.bg_block_bitmap, bit_index, new_state, m_super_block.s_free_blocks_count, bgd.bg_free_blocks_count); @@ -465,7 +467,7 @@ ErrorOr> Ext2FS::create_directory(Ext2FSInode& parent_inode TRY(static_cast(*inode).write_directory(entries)); TRY(parent_inode.increment_link_count()); - auto& bgd = const_cast(group_descriptor(group_index_from_inode(inode->identifier().index()))); + auto& bgd = const_cast(group_descriptor(group_index_from_inode(inode->identifier().index()))); ++bgd.bg_used_dirs_count; m_block_group_descriptors_dirty = true; @@ -474,19 +476,19 @@ ErrorOr> Ext2FS::create_directory(Ext2FSInode& parent_inode ErrorOr> Ext2FS::create_inode(Ext2FSInode& parent_inode, StringView name, mode_t mode, dev_t dev, UserID uid, GroupID gid) { - if (name.length() > EXT2_NAME_LEN) + if (name.length() > max_name_length) return ENAMETOOLONG; if (parent_inode.m_raw_inode.i_links_count == 0) return ENOENT; - ext2_inode e2inode {}; + Ext2Inode e2inode {}; auto now = kgettimeofday().truncated_seconds_since_epoch(); e2inode.i_mode = mode; e2inode.i_uid = static_cast(uid.value()); - ext2fs_set_i_uid_high(e2inode, uid.value() >> 16); + set_i_uid_high(e2inode, uid.value() >> 16); e2inode.i_gid = static_cast(gid.value()); - ext2fs_set_i_gid_high(e2inode, gid.value() >> 16); + set_i_gid_high(e2inode, gid.value() >> 16); e2inode.i_size = 0; e2inode.i_atime = now; e2inode.i_ctime = now; @@ -569,7 +571,7 @@ ErrorOr Ext2FS::prepare_to_clear_last_mount(Inode& mount_guest_inode) // Mark filesystem as valid before unmount. dmesgln("Ext2FS: Clean unmount, setting superblock to valid state"); - m_super_block.s_state = EXT2_VALID_FS; + m_super_block.s_state = Valid; TRY(flush_super_block()); BlockBasedFileSystem::remove_disk_cache_before_last_unmount(); @@ -599,27 +601,26 @@ ErrorOr Ext2FS::free_inode(Ext2FSInode& inode) // If the inode being freed is a directory, update block group directory counter. if (inode.is_directory()) { - auto& bgd = const_cast(group_descriptor(group_index_from_inode(inode.index()))); + auto& bgd = const_cast(group_descriptor(group_index_from_inode(inode.index()))); --bgd.bg_used_dirs_count; dbgln_if(EXT2_DEBUG, "Ext2FS[{}]::free_inode(): Decremented bg_used_dirs_count to {} for inode {}", fsid(), bgd.bg_used_dirs_count, inode.index()); m_block_group_descriptors_dirty = true; } // NOTE: After this point, the inode metadata is wiped. - memset(&inode.m_raw_inode, 0, sizeof(ext2_inode)); + memset(&inode.m_raw_inode, 0, sizeof(Ext2::Ext2Inode)); inode.m_raw_inode.i_dtime = kgettimeofday().truncated_seconds_since_epoch(); TRY(write_ext2_inode(inode.index(), inode.m_raw_inode)); // Mark the inode as free. TRY(set_inode_allocation_state(inode.index(), false)); - return {}; } void Ext2FS::flush_block_group_descriptor_table() { MutexLocker locker(m_lock); - auto blocks_to_write = ceil_div(m_block_group_count * sizeof(ext2_group_desc), logical_block_size()); + auto blocks_to_write = ceil_div(m_block_group_count * sizeof(Ext2::GroupDescriptor), logical_block_size()); auto first_block_of_bgdt = first_block_of_block_group_descriptors(); auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)block_group_descriptors()); auto write_bgdt_to_block = [&](BlockIndex index) { @@ -629,7 +630,7 @@ void Ext2FS::flush_block_group_descriptor_table() write_bgdt_to_block(first_block_of_bgdt); - auto is_sparse = has_flag(get_features_readonly(), FeaturesReadOnly::SparseSuperblock); + auto is_sparse = has_flag(get_features_readonly(), Ext2::FeaturesReadOnly::SparseSuperblock); for (auto group = 1u; group < m_block_group_count; ++group) { // First block is occupied by the super block @@ -704,10 +705,10 @@ ErrorOr> Ext2FS::build_root_inode() const if (!find_block_containing_inode(EXT2_ROOT_INO, block_index, offset)) return EINVAL; - auto inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Ext2FSInode(const_cast(*this), EXT2_ROOT_INO))); + auto inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Ext2FSInode(const_cast(*this), Ext2::EXT2_ROOT_INO))); auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&inode->m_raw_inode)); - TRY(read_block(block_index, &buffer, sizeof(ext2_inode), offset)); + TRY(read_block(block_index, &buffer, sizeof(Ext2Inode), offset)); return inode; } @@ -744,7 +745,7 @@ ErrorOr> Ext2FS::get_inode(InodeIdentifier inode) const auto new_inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Ext2FSInode(const_cast(*this), inode.index()))); auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast(&new_inode->m_raw_inode)); - TRY(read_block(block_index, &buffer, sizeof(ext2_inode), offset)); + TRY(read_block(block_index, &buffer, sizeof(Ext2::Ext2Inode), offset)); TRY(m_inode_cache.try_set(inode.index(), new_inode)); return new_inode; diff --git a/Kernel/FileSystem/Ext2FS/FileSystem.h b/Kernel/FileSystem/Ext2FS/FileSystem.h index b101601a77f0d3..bc89b80f5c8066 100644 --- a/Kernel/FileSystem/Ext2FS/FileSystem.h +++ b/Kernel/FileSystem/Ext2FS/FileSystem.h @@ -16,28 +16,13 @@ #include namespace Kernel { - class Ext2FSInode; +using namespace Ext2; class Ext2FS final : public BlockBasedFileSystem { friend class Ext2FSInode; public: - // s_feature_compat - enum class FeaturesOptional : u32 { - None = 0, - ExtendedAttributes = EXT2_FEATURE_COMPAT_EXT_ATTR, - }; - AK_ENUM_BITWISE_FRIEND_OPERATORS(FeaturesOptional); - - // s_feature_ro_compat - enum class FeaturesReadOnly : u32 { - None = 0, - SparseSuperblock = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, - FileSize64bits = EXT2_FEATURE_RO_COMPAT_LARGE_FILE, - }; - AK_ENUM_BITWISE_FRIEND_OPERATORS(FeaturesReadOnly); - static ErrorOr> try_create(OpenFileDescription&, FileSystemSpecificOptions const&); virtual ~Ext2FS() override; @@ -63,10 +48,10 @@ class Ext2FS final : public BlockBasedFileSystem { explicit Ext2FS(OpenFileDescription&); - ext2_super_block const& super_block() const { return m_super_block; } - ext2_group_desc const& group_descriptor(GroupIndex) const; - ext2_group_desc* block_group_descriptors() { return (ext2_group_desc*)m_cached_group_descriptor_table->data(); } - ext2_group_desc const* block_group_descriptors() const { return (ext2_group_desc const*)m_cached_group_descriptor_table->data(); } + SuperBlock const& super_block() const { return m_super_block; } + GroupDescriptor const& group_descriptor(GroupIndex) const; + GroupDescriptor* block_group_descriptors() { return reinterpret_cast(m_cached_group_descriptor_table->data()); } + GroupDescriptor const* block_group_descriptors() const { return reinterpret_cast(m_cached_group_descriptor_table->data()); } void flush_block_group_descriptor_table(); u64 inodes_per_block() const; u64 inodes_per_group() const; @@ -75,7 +60,7 @@ class Ext2FS final : public BlockBasedFileSystem { ErrorOr> build_root_inode() const; - ErrorOr write_ext2_inode(InodeIndex, ext2_inode const&); + ErrorOr write_ext2_inode(InodeIndex, Ext2Inode const&); bool find_block_containing_inode(InodeIndex, BlockIndex& block_index, unsigned& offset) const; ErrorOr flush_super_block(); @@ -108,7 +93,7 @@ class Ext2FS final : public BlockBasedFileSystem { u64 m_block_group_count { 0 }; - mutable ext2_super_block m_super_block {}; + mutable SuperBlock m_super_block {}; mutable OwnPtr m_cached_group_descriptor_table; mutable HashMap> m_inode_cache; diff --git a/Kernel/FileSystem/Ext2FS/Inode.cpp b/Kernel/FileSystem/Ext2FS/Inode.cpp index cc680389e8c809..88c672f20e3658 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.cpp +++ b/Kernel/FileSystem/Ext2FS/Inode.cpp @@ -15,6 +15,7 @@ #include namespace Kernel { +using namespace Ext2; static constexpr size_t max_inline_symlink_length = 60; @@ -39,24 +40,24 @@ static u8 to_ext2_file_type(mode_t mode) ErrorOr Ext2FSInode::write_singly_indirect_block_pointer(BlockBasedFileSystem::BlockIndex logical_block_index, BlockBasedFileSystem::BlockIndex on_disk_index) { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); + auto const entries_per_block = address_per_block(fs().super_block()); auto const block_size = fs().logical_block_size(); - auto offset_in_block = logical_block_index.value() - EXT2_IND_BLOCK; + auto offset_in_block = logical_block_index.value() - single_indirect_block; auto singly_indirect_block_storage = TRY(ByteBuffer::create_zeroed(block_size)); auto singly_indirect_block_contents = Span { bit_cast(singly_indirect_block_storage.data()), entries_per_block }; auto singly_indirect_block_buffer = UserOrKernelBuffer::for_kernel_buffer(singly_indirect_block_storage.data()); - if (m_raw_inode.i_block[EXT2_IND_BLOCK] == 0) [[unlikely]] { - m_raw_inode.i_block[EXT2_IND_BLOCK] = TRY(allocate_and_zero_block()); + if (m_raw_inode.i_block[single_indirect_block] == 0) [[unlikely]] { + m_raw_inode.i_block[single_indirect_block] = TRY(allocate_and_zero_block()); set_metadata_dirty(true); } - TRY(fs().read_block(m_raw_inode.i_block[EXT2_IND_BLOCK], &singly_indirect_block_buffer, block_size, 0)); + TRY(fs().read_block(m_raw_inode.i_block[single_indirect_block], &singly_indirect_block_buffer, block_size, 0)); singly_indirect_block_contents[offset_in_block] = on_disk_index.value(); - TRY(fs().write_block(m_raw_inode.i_block[EXT2_IND_BLOCK], singly_indirect_block_buffer, block_size)); + TRY(fs().write_block(m_raw_inode.i_block[single_indirect_block], singly_indirect_block_buffer, block_size)); if (on_disk_index != 0) return {}; @@ -64,8 +65,8 @@ ErrorOr Ext2FSInode::write_singly_indirect_block_pointer(BlockBasedFileSys if (!singly_indirect_block_contents.filled_with(0)) return {}; - TRY(fs().set_block_allocation_state(m_raw_inode.i_block[EXT2_IND_BLOCK], false)); - m_raw_inode.i_block[EXT2_IND_BLOCK] = 0; + TRY(fs().set_block_allocation_state(m_raw_inode.i_block[single_indirect_block], false)); + m_raw_inode.i_block[single_indirect_block] = 0; set_metadata_dirty(true); return {}; @@ -73,7 +74,7 @@ ErrorOr Ext2FSInode::write_singly_indirect_block_pointer(BlockBasedFileSys ErrorOr Ext2FSInode::write_doubly_indirect_block_pointer(BlockBasedFileSystem::BlockIndex logical_block_index, BlockBasedFileSystem::BlockIndex on_disk_index) { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); + auto const entries_per_block = address_per_block(fs().super_block()); auto const block_size = fs().logical_block_size(); auto const offset = logical_block_index.value() - singly_indirect_block_capacity(); @@ -88,16 +89,16 @@ ErrorOr Ext2FSInode::write_doubly_indirect_block_pointer(BlockBasedFileSys auto singly_indirect_block_contents = Span { bit_cast(singly_indirect_block_storage.data()), entries_per_block }; auto singly_indirect_block_buffer = UserOrKernelBuffer::for_kernel_buffer(singly_indirect_block_storage.data()); - if (m_raw_inode.i_block[EXT2_DIND_BLOCK] == 0) [[unlikely]] { - m_raw_inode.i_block[EXT2_DIND_BLOCK] = TRY(allocate_and_zero_block()); + if (m_raw_inode.i_block[double_indirect_blocks] == 0) [[unlikely]] { + m_raw_inode.i_block[double_indirect_blocks] = TRY(allocate_and_zero_block()); set_metadata_dirty(true); } - TRY(fs().read_block(m_raw_inode.i_block[EXT2_DIND_BLOCK], &doubly_indirect_block_buffer, block_size, 0)); + TRY(fs().read_block(m_raw_inode.i_block[double_indirect_blocks], &doubly_indirect_block_buffer, block_size, 0)); if (doubly_indirect_block_contents[offset_in_doubly_indirect_block] == 0) [[unlikely]] { doubly_indirect_block_contents[offset_in_doubly_indirect_block] = TRY(allocate_and_zero_block()); - TRY(fs().write_block(m_raw_inode.i_block[EXT2_DIND_BLOCK], doubly_indirect_block_buffer, block_size)); + TRY(fs().write_block(m_raw_inode.i_block[double_indirect_blocks], doubly_indirect_block_buffer, block_size)); } TRY(fs().read_block(doubly_indirect_block_contents[offset_in_doubly_indirect_block], &singly_indirect_block_buffer, block_size, 0)); @@ -113,13 +114,13 @@ ErrorOr Ext2FSInode::write_doubly_indirect_block_pointer(BlockBasedFileSys TRY(fs().set_block_allocation_state(doubly_indirect_block_contents[offset_in_doubly_indirect_block], false)); doubly_indirect_block_contents[offset_in_doubly_indirect_block] = 0; - TRY(fs().write_block(m_raw_inode.i_block[EXT2_DIND_BLOCK], doubly_indirect_block_buffer, block_size)); + TRY(fs().write_block(m_raw_inode.i_block[double_indirect_blocks], doubly_indirect_block_buffer, block_size)); if (!doubly_indirect_block_contents.filled_with(0)) return {}; - TRY(fs().set_block_allocation_state(m_raw_inode.i_block[EXT2_DIND_BLOCK], false)); - m_raw_inode.i_block[EXT2_DIND_BLOCK] = 0; + TRY(fs().set_block_allocation_state(m_raw_inode.i_block[double_indirect_blocks], false)); + m_raw_inode.i_block[double_indirect_blocks] = 0; set_metadata_dirty(true); return {}; @@ -127,7 +128,7 @@ ErrorOr Ext2FSInode::write_doubly_indirect_block_pointer(BlockBasedFileSys ErrorOr Ext2FSInode::write_triply_indirect_block_pointer(BlockBasedFileSystem::BlockIndex logical_block_index, BlockBasedFileSystem::BlockIndex on_disk_index) { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); + auto const entries_per_block = address_per_block(fs().super_block()); auto const block_size = fs().logical_block_size(); auto const offset = logical_block_index.value() - doubly_indirect_block_capacity(); @@ -148,16 +149,16 @@ ErrorOr Ext2FSInode::write_triply_indirect_block_pointer(BlockBasedFileSys auto singly_indirect_block_contents = Span { bit_cast(singly_indirect_block_storage.data()), entries_per_block }; auto singly_indirect_block_buffer = UserOrKernelBuffer::for_kernel_buffer(singly_indirect_block_storage.data()); - if (m_raw_inode.i_block[EXT2_TIND_BLOCK] == 0) [[unlikely]] { - m_raw_inode.i_block[EXT2_TIND_BLOCK] = TRY(allocate_and_zero_block()); + if (m_raw_inode.i_block[trible_indirect_blocks] == 0) [[unlikely]] { + m_raw_inode.i_block[trible_indirect_blocks] = TRY(allocate_and_zero_block()); set_metadata_dirty(true); } - TRY(fs().read_block(m_raw_inode.i_block[EXT2_TIND_BLOCK], &triply_indirect_block_buffer, block_size, 0)); + TRY(fs().read_block(m_raw_inode.i_block[trible_indirect_blocks], &triply_indirect_block_buffer, block_size, 0)); if (triply_indirect_block_contents[offset_in_triply_indirect_block] == 0) [[unlikely]] { triply_indirect_block_contents[offset_in_triply_indirect_block] = TRY(allocate_and_zero_block()); - TRY(fs().write_block(m_raw_inode.i_block[EXT2_TIND_BLOCK], triply_indirect_block_buffer, block_size)); + TRY(fs().write_block(m_raw_inode.i_block[trible_indirect_blocks], triply_indirect_block_buffer, block_size)); } TRY(fs().read_block(triply_indirect_block_contents[offset_in_triply_indirect_block], &doubly_indirect_block_buffer, block_size, 0)); @@ -187,13 +188,13 @@ ErrorOr Ext2FSInode::write_triply_indirect_block_pointer(BlockBasedFileSys TRY(fs().set_block_allocation_state(triply_indirect_block_contents[offset_in_triply_indirect_block], false)); triply_indirect_block_contents[offset_in_triply_indirect_block] = 0; - TRY(fs().write_block(m_raw_inode.i_block[EXT2_TIND_BLOCK], triply_indirect_block_buffer, block_size)); + TRY(fs().write_block(m_raw_inode.i_block[trible_indirect_blocks], triply_indirect_block_buffer, block_size)); if (!triply_indirect_block_contents.filled_with(0)) return {}; - TRY(fs().set_block_allocation_state(m_raw_inode.i_block[EXT2_TIND_BLOCK], false)); - m_raw_inode.i_block[EXT2_TIND_BLOCK] = 0; + TRY(fs().set_block_allocation_state(m_raw_inode.i_block[trible_indirect_blocks], false)); + m_raw_inode.i_block[trible_indirect_blocks] = 0; set_metadata_dirty(true); return {}; @@ -214,7 +215,7 @@ ErrorOr Ext2FSInode::allocate_and_zero_block() ErrorOr Ext2FSInode::write_block_pointer(BlockBasedFileSystem::BlockIndex logical_block_index, BlockBasedFileSystem::BlockIndex on_disk_index) { VERIFY(m_inode_lock.is_locked()); - VERIFY(logical_block_index >= EXT2_NDIR_BLOCKS); + VERIFY(logical_block_index >= number_of_direct_blocks); if (logical_block_index < singly_indirect_block_capacity()) return write_singly_indirect_block_pointer(logical_block_index, on_disk_index); @@ -232,7 +233,7 @@ ErrorOr Ext2FSInode::flush_block_list(Ext2FS::BlockList const& old_block_l { MutexLocker locker(m_inode_lock); - for (unsigned i = 0; i < EXT2_NDIR_BLOCKS; ++i) { + for (unsigned i = 0; i < number_of_direct_blocks; ++i) { auto block = get_block(i); if (m_raw_inode.i_block[i] != block) { set_metadata_dirty(true); @@ -241,14 +242,14 @@ ErrorOr Ext2FSInode::flush_block_list(Ext2FS::BlockList const& old_block_l } for (auto const& [logical_block_index, _] : old_block_list) { - if (logical_block_index < EXT2_NDIR_BLOCKS) + if (logical_block_index < number_of_direct_blocks) continue; if (!m_block_list.contains(logical_block_index)) TRY(write_block_pointer(logical_block_index, 0)); } for (auto const& [logical_block_index, on_disk_index] : m_block_list) { - if (logical_block_index < EXT2_NDIR_BLOCKS) + if (logical_block_index < number_of_direct_blocks) continue; auto iterator = old_block_list.find(logical_block_index); if (iterator == old_block_list.end() || (*iterator).value != on_disk_index) @@ -287,7 +288,7 @@ ErrorOr Ext2FSInode::compute_block_list_impl(Vector ErrorOr { TRY(list.try_set(logical_index, on_disk_index)); @@ -309,29 +310,29 @@ ErrorOr Ext2FSInode::compute_block_list_impl(Vector ErrorOr { + if (m_raw_inode.i_block[single_indirect_block]) { + TRY(process_block_array(number_of_direct_blocks, 1, m_raw_inode.i_block[single_indirect_block], block_storage[0], [&](auto logical_block_index, auto on_disk_index) -> ErrorOr { return set_block(logical_block_index, on_disk_index); })); } - if (m_raw_inode.i_block[EXT2_DIND_BLOCK]) { - TRY(process_block_array(singly_indirect_block_capacity(), 2, m_raw_inode.i_block[EXT2_DIND_BLOCK], block_storage[1], [&](auto logical_block_index, auto on_disk_index) -> ErrorOr { + if (m_raw_inode.i_block[double_indirect_blocks]) { + TRY(process_block_array(singly_indirect_block_capacity(), 2, m_raw_inode.i_block[double_indirect_blocks], block_storage[1], [&](auto logical_block_index, auto on_disk_index) -> ErrorOr { return process_block_array(logical_block_index, 1, on_disk_index, block_storage[0], [&](auto logical_block_index2, auto on_disk_index2) -> ErrorOr { return set_block(logical_block_index2, on_disk_index2); }); })); } - if (m_raw_inode.i_block[EXT2_TIND_BLOCK]) { - TRY(process_block_array(doubly_indirect_block_capacity(), 3, m_raw_inode.i_block[EXT2_TIND_BLOCK], block_storage[2], [&](auto logical_block_index, auto on_disk_index) -> ErrorOr { + if (m_raw_inode.i_block[trible_indirect_blocks]) { + TRY(process_block_array(doubly_indirect_block_capacity(), 3, m_raw_inode.i_block[trible_indirect_blocks], block_storage[2], [&](auto logical_block_index, auto on_disk_index) -> ErrorOr { return process_block_array(logical_block_index, 2, on_disk_index, block_storage[1], [&](auto logical_block_index2, auto on_disk_index2) -> ErrorOr { return process_block_array(logical_block_index2, 1, on_disk_index2, block_storage[0], [&](auto logical_block_index3, auto on_disk_index3) -> ErrorOr { return set_block(logical_block_index3, on_disk_index3); @@ -358,7 +359,7 @@ Ext2FSInode::~Ext2FSInode() u64 Ext2FSInode::size() const { - if (Kernel::is_regular_file(m_raw_inode.i_mode) && ((u32)fs().get_features_readonly() & (u32)Ext2FS::FeaturesReadOnly::FileSize64bits)) + if (Kernel::is_regular_file(m_raw_inode.i_mode) && ((u32)fs().get_features_readonly() & (u32)Ext2::FeaturesReadOnly::FileSize64bits)) return static_cast(m_raw_inode.i_dir_acl) << 32 | m_raw_inode.i_size; return m_raw_inode.i_size; } @@ -490,7 +491,7 @@ ErrorOr Ext2FSInode::resize(u64 new_size) if (size() == new_size) return {}; - if (!((u32)fs().get_features_readonly() & (u32)Ext2FS::FeaturesReadOnly::FileSize64bits) && (new_size >= static_cast(-1))) + if (!((u32)fs().get_features_readonly() & (u32)Ext2::FeaturesReadOnly::FileSize64bits) && (new_size >= static_cast(-1))) return ENOSPC; if (new_size < size()) { @@ -599,7 +600,7 @@ ErrorOr Ext2FSInode::traverse_as_directory(Function(FileSyst auto block_size = fs().logical_block_size(); auto file_size = size(); - bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2::FeaturesOptional::ExtendedAttributes); // Directory entries are guaranteed not to span multiple blocks, // so we can iterate over blocks separately. @@ -607,15 +608,15 @@ ErrorOr Ext2FSInode::traverse_as_directory(Function(FileSyst for (u64 offset = 0; offset < file_size; offset += block_size) { TRY(read_bytes(offset, block_size, buf, nullptr)); - using ext2_extended_dir_entry = ext2_dir_entry_2; - auto* entry = reinterpret_cast(buffer); - auto* entries_end = reinterpret_cast(buffer + block_size); + //using ext2_extended_dir_entry = DirectoryEntry; + auto* entry = reinterpret_cast(buffer); + auto* entries_end = reinterpret_cast(buffer + block_size); while (entry < entries_end) { if (entry->inode != 0) { dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::traverse_as_directory(): inode {}, name_len: {}, rec_len: {}, file_type: {}, name: {}", identifier(), entry->inode, entry->name_len, entry->rec_len, entry->file_type, StringView(entry->name, entry->name_len)); TRY(callback({ { entry->name, entry->name_len }, { fsid(), entry->inode }, has_file_type_attribute ? entry->file_type : (u8)EXT2_FT_UNKNOWN })); } - entry = (ext2_extended_dir_entry*)((char*)entry + entry->rec_len); + entry = reinterpret_cast(entry + entry->rec_len); } } @@ -636,10 +637,10 @@ ErrorOr Ext2FSInode::write_directory(Vector& entries size_t space_in_block = block_size; for (size_t i = 0; i < entries.size(); ++i) { auto& entry = entries[i]; - entry.record_length = EXT2_DIR_REC_LEN(entry.name->length()); + entry.record_length = directory_record_length(entry.name->length()); space_in_block -= entry.record_length; if (i + 1 < entries.size()) { - if (EXT2_DIR_REC_LEN(entries[i + 1].name->length()) > space_in_block) { + if (directory_record_length(entries[i + 1].name->length()) > space_in_block) { entry.record_length += space_in_block; space_in_block = block_size; } @@ -653,7 +654,8 @@ ErrorOr Ext2FSInode::write_directory(Vector& entries auto directory_data = TRY(ByteBuffer::create_uninitialized(directory_size)); FixedMemoryStream stream { directory_data.bytes() }; - bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); + + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2::FeaturesOptional::ExtendedAttributes); for (auto& entry : entries) { dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): Writing inode: {}, name_len: {}, rec_len: {}, file_type: {}, name: {}", identifier(), entry.inode_index, u16(entry.name->length()), u16(entry.record_length), u8(entry.file_type), entry.name); @@ -661,7 +663,7 @@ ErrorOr Ext2FSInode::write_directory(Vector& entries MUST(stream.write_value(entry.inode_index.value())); MUST(stream.write_value(entry.record_length)); MUST(stream.write_value(entry.name->length())); - MUST(stream.write_value(has_file_type_attribute ? entry.file_type : EXT2_FT_UNKNOWN)); + MUST(stream.write_value(has_file_type_attribute ? entry.file_type : static_cast(EXT2_FT_UNKNOWN))); MUST(stream.write_until_depleted(entry.name->bytes())); int padding = entry.record_length - entry.name->length() - 8; for (int j = 0; j < padding; ++j) @@ -729,11 +731,11 @@ ErrorOr Ext2FSInode::add_child(Inode& child, StringView name, mode_t mode) MutexLocker locker(m_inode_lock); VERIFY(is_directory()); - if (name.length() > EXT2_NAME_LEN) + if (name.length() > Ext2::max_name_length) return ENAMETOOLONG; dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::add_child(): Adding inode {} with name '{}' and mode {:o} to directory {}", identifier(), child.index(), name, mode, index()); - bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2::FeaturesOptional::ExtendedAttributes); Vector entries; TRY(traverse_as_directory([&](auto& entry) -> ErrorOr { @@ -772,7 +774,7 @@ ErrorOr Ext2FSInode::remove_child(StringView name) auto child_inode_index = (*it).value; InodeIdentifier child_id { fsid(), child_inode_index }; - bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2::FeaturesOptional::ExtendedAttributes); Vector entries; TRY(traverse_as_directory([&](auto& entry) -> ErrorOr { @@ -802,11 +804,11 @@ ErrorOr Ext2FSInode::replace_child(StringView name, Inode& child) TRY(populate_lookup_cache()); - if (name.length() > EXT2_NAME_LEN) + if (name.length() > Ext2::max_name_length) return ENAMETOOLONG; Vector entries; - bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2::FeaturesOptional::ExtendedAttributes); Optional old_child_index; TRY(traverse_as_directory([&](auto& entry) -> ErrorOr { @@ -958,9 +960,9 @@ ErrorOr Ext2FSInode::chown(UserID uid, GroupID gid) if (inode_uid(m_raw_inode) == uid && inode_gid(m_raw_inode) == gid) return {}; m_raw_inode.i_uid = static_cast(uid.value()); - ext2fs_set_i_uid_high(m_raw_inode, uid.value() >> 16); + set_i_uid_high(m_raw_inode, uid.value() >> 16); m_raw_inode.i_gid = static_cast(gid.value()); - ext2fs_set_i_gid_high(m_raw_inode, gid.value() >> 16); + set_i_gid_high(m_raw_inode, gid.value() >> 16); set_metadata_dirty(true); return {}; } diff --git a/Kernel/FileSystem/Ext2FS/Inode.h b/Kernel/FileSystem/Ext2FS/Inode.h index 827fc6637a856d..f2d76b031c92f9 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.h +++ b/Kernel/FileSystem/Ext2FS/Inode.h @@ -14,6 +14,7 @@ #include namespace Kernel { +using namespace Ext2; class Ext2FSInode final : public Inode { friend class Ext2FS; @@ -65,19 +66,19 @@ class Ext2FSInode final : public Inode { u64 singly_indirect_block_capacity() const { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); - return EXT2_NDIR_BLOCKS + entries_per_block; + auto const entries_per_block = address_per_block(fs().super_block()); + return number_of_direct_blocks + entries_per_block; } u64 doubly_indirect_block_capacity() const { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); + auto const entries_per_block = address_per_block(fs().super_block()); return singly_indirect_block_capacity() + entries_per_block * entries_per_block; } u64 triply_indirect_block_capacity() const { - auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block()); + auto const entries_per_block = address_per_block(fs().super_block()); return doubly_indirect_block_capacity() + entries_per_block * entries_per_block * entries_per_block; } @@ -87,7 +88,7 @@ class Ext2FSInode final : public Inode { Ext2FS::BlockList m_block_list; HashMap, InodeIndex> m_lookup_cache; - ext2_inode m_raw_inode {}; + Ext2Inode m_raw_inode {}; Mutex m_block_list_lock { "BlockList"sv }; }; diff --git a/Kernel/FileSystem/Ext2FS/ext2_types.h b/Kernel/FileSystem/Ext2FS/ext2_types.h deleted file mode 100644 index 420e6236fb66ec..00000000000000 --- a/Kernel/FileSystem/Ext2FS/ext2_types.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -/* - * If linux/types.h is already been included, assume it has defined - * everything we need. (cross fingers) Other header files may have - * also defined the types that we need. - */ -#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && !defined(_EXT2_TYPES_H)) -# define _EXT2_TYPES_H - -# define __S8_TYPEDEF __signed__ char -# define __U8_TYPEDEF unsigned char -# define __S16_TYPEDEF __signed__ short -# define __U16_TYPEDEF unsigned short -# define __S32_TYPEDEF __signed__ int -# define __U32_TYPEDEF unsigned int -# define __S64_TYPEDEF __signed__ long long -# define __U64_TYPEDEF unsigned long long - -# ifdef __U8_TYPEDEF -typedef __U8_TYPEDEF __u8; -# else -typedef unsigned char __u8; -# endif - -# ifdef __S8_TYPEDEF -typedef __S8_TYPEDEF __s8; -# else -typedef signed char __s8; -# endif - -# ifdef __U16_TYPEDEF -typedef __U16_TYPEDEF __u16; -# else -# if (4 == 2) -typedef unsigned int __u16; -# else -# if (2 == 2) -typedef unsigned short __u16; -# else -? == error : undefined 16 bit type -# endif /* SIZEOF_SHORT == 2 */ -# endif /* SIZEOF_INT == 2 */ -# endif /* __U16_TYPEDEF */ - -# ifdef __S16_TYPEDEF -typedef __S16_TYPEDEF __s16; -# else -# if (4 == 2) -typedef int __s16; -# else -# if (2 == 2) -typedef short __s16; -# else - ? == error - : undefined 16 bit type -# endif /* SIZEOF_SHORT == 2 */ -# endif /* SIZEOF_INT == 2 */ -# endif /* __S16_TYPEDEF */ - -# ifdef __U32_TYPEDEF -typedef __U32_TYPEDEF __u32; -# else -# if (4 == 4) -typedef unsigned int __u32; -# else -# if (4 == 4) -typedef unsigned long __u32; -# else -# if (2 == 4) - typedef unsigned short __u32; -# else - ? == error - : undefined 32 bit type -# endif /* SIZEOF_SHORT == 4 */ -# endif /* SIZEOF_LONG == 4 */ -# endif /* SIZEOF_INT == 4 */ -# endif /* __U32_TYPEDEF */ - -# ifdef __S32_TYPEDEF -typedef __S32_TYPEDEF __s32; -# else -# if (4 == 4) -typedef int __s32; -# else -# if (4 == 4) -typedef long __s32; -# else -# if (2 == 4) -typedef short __s32; -# else - ? == error - : undefined 32 bit type -# endif /* SIZEOF_SHORT == 4 */ -# endif /* SIZEOF_LONG == 4 */ -# endif /* SIZEOF_INT == 4 */ -# endif /* __S32_TYPEDEF */ - -# ifdef __U64_TYPEDEF -typedef __U64_TYPEDEF __u64; -# else -# if (4 == 8) -typedef unsigned int __u64; -# else -# if (4 == 8) -typedef unsigned long __u64; -# else -# if (8 == 8) -typedef unsigned long long __u64; -# endif /* SIZEOF_LONG_LONG == 8 */ -# endif /* SIZEOF_LONG == 8 */ -# endif /* SIZEOF_INT == 8 */ -# endif /* __U64_TYPEDEF */ - -# ifdef __S64_TYPEDEF -typedef __S64_TYPEDEF __s64; -# else -# if (4 == 8) -typedef int __s64; -# else -# if (4 == 8) -typedef long __s64; -# else -# if (8 == 8) -# if defined(__GNUC__) -typedef __signed__ long long __s64; -# else -typedef signed long long __s64; -# endif /* __GNUC__ */ -# endif /* SIZEOF_LONG_LONG == 8 */ -# endif /* SIZEOF_LONG == 8 */ -# endif /* SIZEOF_INT == 8 */ -# endif /* __S64_TYPEDEF */ - -# undef __S8_TYPEDEF -# undef __U8_TYPEDEF -# undef __S16_TYPEDEF -# undef __U16_TYPEDEF -# undef __S32_TYPEDEF -# undef __U32_TYPEDEF -# undef __S64_TYPEDEF -# undef __U64_TYPEDEF - -#endif /* _*_TYPES_H */ - -/* These defines are needed for the public ext2fs.h header file */ -#define HAVE_SYS_TYPES_H 1 -#undef WORDS_BIGENDIAN