Anonymous user
Ext2: Difference between revisions
no edit summary
[unchecked revision] | [unchecked revision] |
mNo edit summary |
No edit summary |
||
Line 1:
{{Filesystems}}
The '''Second Extended Filesystem''' ('''ext2fs''')
'''Important Note: All values are little-endian unless otherwise specified'''
==
=== What is a Block? ===
The Ext2 file system divides up disk space into logical blocks of contiguous space. The size of blocks need not be the same size as the sector size of the disk the file system resides on. The size of blocks can be determined by reading the field starting at byte 24 in the [[#Superblock|Superblock]].
===
Blocks, along with inodes, are divvied up into "block groups." These are nothing more than contiguous groups of blocks.
Each block group reserves a few of its blocks for special purposes such as:
* A bitmap of free/allocated blocks within the group
* A bitmap of allocated inodes within the group
* A table of inode structures that belong to the group
* Depending upon the revision of Ext2 used, some or all block groups may also contain a backup copy of the [[#Superblock|Superblock]] and the [[#Block_Group_Descriptor_Table|Block Group Descriptor Table]].
===
An inode is a structure on the disk (in an inode table of a block group) that represents a file, directory, symbolic link, etc.
== Superblock ==
The first step in implementing an Ext2 driver is to find, extract, and parse the superblock. The Superblock contains all information about the layout of the file system and possibly contains other important information like what optional features were used to create the file system. Once you have finished with the Superblock, the next step is to look at the [[#Block_Group_Descriptor_Table|Block Group Descriptor Table]]
===
The Superblock is always located at byte 1024 from the beginning of the volume and is exactly 1024 bytes in length. For example, if the disk uses 512 byte sectors, the Superblock will begin at LBA 2 and will occupy all of sector 2 and 3.
=== Determining the Number of Block Groups ===
From the Superblock, extract the size of each block, the total number of inodes, the total number of blocks, the number of blocks per block group, and the number of inodes in each block group. From this information we can infer the number of block groups there are by:
* Rounding up the total number of blocks divided by the number of blocks per block group
* Rounding up the total number of inodes divided by the number of inodes per block group
* Both (and check them against each other)
=== Base Superblock Fields ===
These fields are present in all versions of Ext2
{| {{wikitable}}
! Starting
Byte
! Ending
Byte
! Size
in Bytes
! Field Description
|-
| 0 || 3 || 4 || Total number of inodes in file system
|-
|
|-
|
|-
| 12 || 15 || 4 || Total number of unallocated blocks
|-
|
|-
| 20 || 23 || 4 || Block number of the block containing the superblock
|-
| 24 || 27 || 4 || ''log''<sub>2</sub> (block size) - 10. (In other words, the number to shift 1,024 to the left by to obtain the block size)
|-
|
|-
| 32 || 35 || 4 || Number of blocks in each block group
|-
|
|-
|
|-
| 44 || 47 || 4 || Last mount time (in [http://en.wikipedia.org/wiki/Unix_time POSIX time])
|-
| 48 || 51 || 4 || Last written time (in [http://en.wikipedia.org/wiki/Unix_time POSIX time])
|-
| 52 || 53 || 2 || Number of times the volume has been mounted since its last consistency check ([http://en.wikipedia.org/wiki/Fsck fsck])
|-
| 54 || 55 || 2 || Number of mounts allowed before a consistency check ([http://en.wikipedia.org/wiki/Fsck fsck]) must be done
|-
| 56 || 57 || 2 || Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a volume
|-
| 58 || 59 || 2 || File system state ([[#File_System_States|see below]])
|-
| 60 || 61 || 2 || What to do when an error is detected ([[#Error_Handling_Methods|see below]])
|-
| 62 || 63 || 2 || Minor portion of version (combine with Major portion below to construct full version field)
|-
| 64 || 67 || 4 || [http://en.wikipedia.org/wiki/Unix_time POSIX time] of last consistency check ([http://en.wikipedia.org/wiki/Fsck fsck])
|-
| 68 || 71 || 4 || Interval (in [http://en.wikipedia.org/wiki/Unix_time POSIX time]) between forced consistency checks ([http://en.wikipedia.org/wiki/Fsck fsck])
|-
| 72 || 75 || 4 || Operating system ID from which the filesystem on this volume was created ([[#Creator_Operating_System_IDs|see below]])
|-
| 76 || 79 || 4 || Major portion of version (combine with Minor portion above to construct full version field)
|-
| 80 || 81 || 2 || User ID that can use reserved blocks
|-
|
|}
==== File System States ====
{| {{Wikitable}}
! Value
! State Description
|-
| 1 || File system is clean
|-
| 2 || File system has errors
|}
==== Error Handling Methods ====
{| {{Wikitable}}
! Value
! Action to Take
|-
| 1 || Ignore the error (continue on)
|-
| 2 || Remount file system as read-only
|-
| 3 || Kernel panic
|}
==== Creator Operating System IDs ====
{| {{Wikitable}}
! Value
! Operating System
|-
| 0 || [http://kernel.org/ Linux]
|-
| 1 || [http://www.gnu.org/software/hurd/hurd.html GNU HURD]
|-
| 2 || MASIX (an operating system developed by Rémy Card, one of the developers of ext2)
|-
| 3 || [http://www.freebsd.org/ FreeBSD]
|-
| 4 || Other "Lites" (BSD4.4-Lite derivatives such as [http://www.netbsd.org/ NetBSD], [http://www.openbsd.org/ OpenBSD], [http://www.opensource.apple.com/source/xnu/ XNU/Darwin], etc.)
|}
=== Extended Superblock Fields ===
These fields are only present if Major version (specified in the base superblock fields), is greater than 1.
{| {{Wikitable}}
! Starting
Byte
! Ending
Byte
! Size
in Bytes
! Field Description
|-
| 84 || 87 || 4 || First non-reserved inode in file system. (In versions < 1.0, this is fixed as 11)
|-
| 88 || 89 || 2 || Size of each inode structure in bytes. (In versions < 1.0, this is fixed as 128)
|-
| 90 || 91 || 2 || Block group that this superblock is part of (if backup copy)
|-
| 92 || 95 || 4 || Optional features present (features that are not required to read or write, but usually result in a performance increase. [[#Optional_Feature_Flags|see below]])
|-
| 96 || 99 || 4 || Required features present (features that are required to be supported to read or write. [[#Required_Feature_Flags|see below]])
|-
| 100 || 103 || 4 || Features that if not supported, the volume must be mounted read-only [[#Read-Only_Feature_Flags|see below]])
|-
| 104 || 119 || 16 || File system ID (what is output by blkid)
|-
| 120 || 135 || 16 || Volume name (C-style string: characters terminated by a 0 byte)
|-
| 136 || 199 || 64 || Path volume was last mounted to (C-style string: characters terminated by a 0 byte)
|-
| 200 || 203 || 4 || Compression algorithms used (see Required features above)
|-
| 204 || 204 || 1 || Number of blocks to preallocate for files
|-
| 205 || 205 || 1 || Number of blocks to preallocate for directories
|-
|
|-
| 208 || 223 || 16 || Journal ID (same style as the File system ID above)
|-
| 224 || 227 || 4 || Journal inode
|-
| 228 || 231 || 4 || Journal device
|-
|
|-
| 236 || 1023 || X || (Unused)
|}
==== Optional Feature Flags ====
These are optional features for an implementation to support, but offer performance or reliability gains to implementations that do support them.
{| {{Wikitable}}
|-
Line 224 ⟶ 185:
! Description
|-
| 0x0001 || Preallocate
|-
| 0x0002 || AFS server inodes exist
Line 237 ⟶ 198:
|}
====
These features if present on a file system are required to be supported by an implementation in order to correctly read from or write to the file system.
{| {{Wikitable}}
|-
Line 243 ⟶ 205:
! Description
|-
| 0x0001 || Compression is used
|-
| 0x0002 || Directory entries contain a
|-
| 0x0004 || File system needs recovery
Line 252 ⟶ 214:
|}
==== Read
These features, if present on a file system, are required in order for an implementation to write to the file system, but are not required to read from the file system.
{| {{Wikitable}}
|-
Line 260 ⟶ 223:
| 0x0001 || Sparse superblocks and group descriptor tables
|-
| 0x0002 || File system
|-
| 0x0004 || Directory contents are stored in the form of a [http://en.wikipedia.org/wiki/Binary_tree Binary Tree]
|}
The Group Descriptor Table contains an entry for each block group within the file system.
=== Locating the Block Group Descriptor Table ===
The table is located in the block immediately following the Superblock. Each Descriptor contains information regarding where important data structures for that group are located.
=== Block Group Descriptor ===
{| {{Wikitable}}
! Starting
Byte
! Ending
Byte
! Size
in Bytes
! Field Description
|-
| 0 || 3 || 4 || Block address of block usage bitmap
|-
|
|-
|
|-
| 12 || 13 || 2 || Number of unallocated blocks in group
|-
|
|-
|
|-
|
|}
Like blocks, each inode has a numerical address. It is extremely important to note that unlike block addresses, '''inode addresses start at 1'''.
With Ext2 versions prior to Major version 1, inodes 1 to 10 are reserved and should be in an allocated state. Starting with version 1, the first non-reserved inode is indicated via a field in the Superblock. Of the reserved inodes, number 2 has subjectively has the most significance as it is used for the root directory. Inode 1 keeps track of bad blocks, but it does
not have any special status in the Linux kernel.
=== Determining which Block Group contains an Inode ===
From an inode address (remember that they start at 1), we can determine which group the inode is in, by using the formula:
group = (inode – 1) / INODES_PER_GROUP
=== Inode Data Structure ===
{| {{Wikitable}}
Line 348 ⟶ 329:
| 124–127 || Unused
|}
Each inode has a static number of fields, and additional information might be stored in extended attributes and indirect block pointers. The allocation status of an inode is determined using the inode bitmap, whose location is given in the group descriptor.
Ext2, like UFS, was designed for efficiency of small files. Therefore, each inode can store the addresses of the first 12 blocks that a file has allocated. These are called direct pointers. If
a file needs more than 12 blocks, a block is allocated to store the remaining addresses. The pointer to the block is called an indirect block pointer. The addresses in the block are all four
bytes, and the total number in each block is based on the block size. The indirect block pointer is stored in the inode.
If a file has more blocks than can fit in the 12 direct pointers and the indirect block, a double indirect block is used. A double indirect block is when the inode points to a block that
contains a list of single indirect block pointers, each of which point to blocks that contain a
list of direct pointers. Lastly, if a file needs still more space, it can use a triple indirect block
pointer. A triple indirect block contains addresses of double indirect blocks, which contain
addresses of single indirect blocks. Each inode contains 12 direct pointers, one single
indirect pointer, one double indirect block pointer, and one triple indirect pointer.
An inode also contains the file's size, ownership, and temporal information. The size value in
newer versions of ExtX is 64 bits, but older versions had only 32 bits and therefore could not
handle files over 4GB. Newer versions utilize an unused field for the upper 32 bits of the size
value and set a read-only compatible feature flag when a large file exists.
"Ownership" information is stored using the user and group ID.
=== Directories ===
Directories are files which contains information needed to find files within the filesystem. The root directory is Inode 2.
==== Filemode flags ====
Line 485 ⟶ 493:
|EXT2_FT_MAX ||8
|}
== Putting it all together ==
=== How To Read A File ===
# Read the superblock to find the size of each block, the number of blocks per group, number Inodes per group, the starting block of the first group.
# Read the first entry of the Group Descriptor Table, to find the location of the Inode table. get Inode 2, this will be the root directory.
# The directory information is located within the data blocks that the Inode points to, read all the data blocks associated within the Inode.
# Interate through the directory information to find the directory/file.
# Read the inode bitmap to find out weather the inode pointed to by the directory structure is allocated.
# if Allocated and is a directory go to step 3. If not allocated continue with step 4.
# Read the inode the block information, to get where the directory information is located.
# Read the first 12 blocks, (if file is less then 12 blocks, only read the number of blocks needed specified by the inode (i.e to get the number of block the file takes, divide the size of the file by the size of each block).
# If is larger than 12 blocks.
## Read indirect block.
## foreach block larger than 12 blocks, read the pointer from the block. (i.e if reading block 13, pointer 1 from the block should be read).
## if the file needs more blocks. then read the double pointer will be a pointer to a block containing pointers to blocks of data.
## if the file still need more blocks, than read the triple indirect pointer.
== Links ==
|