hrev56194 adds 1 changeset to branch 'master'
old head: ac2215ca09fa6683037d5ce3c603090d71b82642
new head: 9c4a46b3183bd1ee5b510ee35cd81df11dfdc834
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=9c4a46b3183b+%5Eac2215ca09fa
----------------------------------------------------------------------------
9c4a46b3183b: xfs : version 5 superblock, checksum header file
- Implemented version 5 superblock fields and necessary macros.
- Checksum functions are implemented which will be used for crc verification
and crc updates.
- fssh_kernal_priv.h ROUNDDOWN macro definition is consistent with kernal.h
definition.
Change-Id: I49b7c939bfd3ea1bffc85b3db42bc678dcce75cd
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5350
Tested-by: Commit checker robot <no-reply+buildbot@xxxxxxxxxxxx>
Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
[ Mashijams <raghavself28@xxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev56194
Commit: 9c4a46b3183bd1ee5b510ee35cd81df11dfdc834
URL: https://git.haiku-os.org/haiku/commit/?id=9c4a46b3183b
Author: Mashijams <raghavself28@xxxxxxxxx>
Date: Tue May 31 11:47:41 2022 UTC
Committer: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Commit-Date: Sat Jun 18 08:32:18 2022 UTC
----------------------------------------------------------------------------
13 files changed, 460 insertions(+), 97 deletions(-)
headers/private/fs_shell/fssh_kernel_priv.h | 2 +-
src/add-ons/kernel/file_systems/ext2/Jamfile | 4 +-
.../kernel/file_systems/shared/CRCTable.h | 4 +-
.../file_systems/shared/{crc32.c => crc32.cpp} | 86 ++++----
src/add-ons/kernel/file_systems/xfs/Checksum.h | 85 ++++++++
src/add-ons/kernel/file_systems/xfs/Inode.cpp | 4 +-
src/add-ons/kernel/file_systems/xfs/Jamfile | 12 +-
src/add-ons/kernel/file_systems/xfs/Volume.cpp | 32 ++-
src/add-ons/kernel/file_systems/xfs/Volume.h | 2 +-
src/add-ons/kernel/file_systems/xfs/xfs.cpp | 215 +++++++++++++++----
src/add-ons/kernel/file_systems/xfs/xfs.h | 98 ++++++++-
src/add-ons/kernel/file_systems/xfs/xfs_types.h | 1 +
.../kernel/file_systems/xfs/xfs_shell/Jamfile | 12 +-
----------------------------------------------------------------------------
diff --git a/headers/private/fs_shell/fssh_kernel_priv.h
b/headers/private/fs_shell/fssh_kernel_priv.h
index 0892102864..db7df042af 100644
--- a/headers/private/fs_shell/fssh_kernel_priv.h
+++ b/headers/private/fs_shell/fssh_kernel_priv.h
@@ -45,7 +45,7 @@
#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
-#define ROUNDOWN(a, b) (((a) / (b)) * (b))
+#define ROUNDDOWN(a, b) (((a) / (b)) * (b))
#define CHECK_BIT(a, b) ((a) & (1 << (b)))
diff --git a/src/add-ons/kernel/file_systems/ext2/Jamfile
b/src/add-ons/kernel/file_systems/ext2/Jamfile
index 7d9c8f8ed6..ab8dc4c8b6 100644
--- a/src/add-ons/kernel/file_systems/ext2/Jamfile
+++ b/src/add-ons/kernel/file_systems/ext2/Jamfile
@@ -11,7 +11,7 @@ KernelAddon ext2 :
Attribute.cpp
BitmapBlock.cpp
BlockAllocator.cpp
- crc32.c
+ crc32.cpp
CRCTable.cpp
DataStream.cpp
DeviceOpener.cpp
@@ -34,7 +34,7 @@ KernelAddon ext2 :
SEARCH on [ FGristFiles DeviceOpener.cpp ]
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
-SEARCH on [ FGristFiles crc32.c ]
+SEARCH on [ FGristFiles crc32.cpp ]
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
SEARCH on [ FGristFiles CRCTable.cpp ]
diff --git a/src/add-ons/kernel/file_systems/shared/CRCTable.h
b/src/add-ons/kernel/file_systems/shared/CRCTable.h
index 04d802d2aa..bdaada97f0 100644
--- a/src/add-ons/kernel/file_systems/shared/CRCTable.h
+++ b/src/add-ons/kernel/file_systems/shared/CRCTable.h
@@ -12,8 +12,8 @@
uint16 calculate_crc(uint16 crc, uint8 *data, uint16 length);
-__BEGIN_DECLS
+
uint32 calculate_crc32c(uint32 crc32c, const unsigned char *buffer,
unsigned int length);
-__END_DECLS
+
diff --git a/src/add-ons/kernel/file_systems/shared/crc32.c
b/src/add-ons/kernel/file_systems/shared/crc32.cpp
similarity index 96%
rename from src/add-ons/kernel/file_systems/shared/crc32.c
rename to src/add-ons/kernel/file_systems/shared/crc32.cpp
index 944c154892..f4d6c0c42d 100644
--- a/src/add-ons/kernel/file_systems/shared/crc32.c
+++ b/src/add-ons/kernel/file_systems/shared/crc32.cpp
@@ -42,18 +42,32 @@
* CRC32 code derived from work by Gary S. Brown.
*/
+#ifndef FS_SHELL
+
#include <sys/cdefs.h>
#include <sys/param.h>
#ifdef __HAIKU__
-#define rounddown(x, y) (((x)/(y))*(y))
#include <endian.h>
+#include <kernel.h>
#include <size_t.h>
#include <stdint.h>
-uint32_t calculate_crc32c(uint32_t crc32c, const unsigned char *buffer,
+uint32 calculate_crc32c(uint32 crc32c, const unsigned char *buffer,
+ unsigned int length);
+#endif
+
+#else
+
+#include "fssh_api_wrapper.h"
+#include "fssh_auto_deleter.h"
+#include "fssh_kernel_priv.h"
+#include "Debug.h"
+uint32 calculate_crc32c(uint32 crc32c, const unsigned char *buffer,
unsigned int length);
+
#endif
-const uint32_t crc32_tab[] = {
+
+const uint32 crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -105,11 +119,11 @@ const uint32_t crc32_tab[] = {
* of this function that's actually used in the kernel can be found
* in sys/libkern.h, where it can be inlined.
*
- * uint32_t
+ * uint32
* crc32(const void *buf, size_t size)
* {
* const uint8_t *p = buf;
- * uint32_t crc;
+ * uint32 crc;
*
* crc = ~0U;
* while (size--)
@@ -139,7 +153,7 @@ const uint32_t crc32_tab[] = {
/* */
/*****************************************************************/
-static const uint32_t crc32Table[256] = {
+static const uint32 crc32Table[256] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
@@ -206,10 +220,10 @@ static const uint32_t crc32Table[256] = {
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
};
-static uint32_t
-singletable_crc32c(uint32_t crc, const void *buf, size_t size)
+static uint32
+singletable_crc32c(uint32 crc, const void *buf, size_t size)
{
- const uint8_t *p = buf;
+ const uint8_t *p = (const uint8_t *)buf;
while (size--)
@@ -245,7 +259,7 @@ singletable_crc32c(uint32_t crc, const void *buf, size_t
size)
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o32[256] =
+static const uint32 sctp_crc_tableil8_o32[256] =
{
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C,
0x26A1E7E8, 0xD4CA64EB,
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3,
0xAC78BF27, 0x5E133C24,
@@ -301,7 +315,7 @@ static const uint32_t sctp_crc_tableil8_o32[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o40[256] =
+static const uint32 sctp_crc_tableil8_o40[256] =
{
0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB,
0x69CF5132, 0x7A6DC945,
0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13,
0xF4DB928A, 0xE7790AFD,
@@ -357,7 +371,7 @@ static const uint32_t sctp_crc_tableil8_o40[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o48[256] =
+static const uint32 sctp_crc_tableil8_o48[256] =
{
0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664,
0xD1B1F617, 0x74F06469,
0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1,
0xE9E0C8D2, 0x4CA15AAC,
@@ -413,7 +427,7 @@ static const uint32_t sctp_crc_tableil8_o48[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o56[256] =
+static const uint32 sctp_crc_tableil8_o56[256] =
{
0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B,
0xC4451272, 0x1900B8CA,
0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD,
0x32017194, 0xEF44DB2C,
@@ -469,7 +483,7 @@ static const uint32_t sctp_crc_tableil8_o56[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o64[256] =
+static const uint32 sctp_crc_tableil8_o64[256] =
{
0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C,
0x906761E8, 0xA8760E44,
0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D,
0x55006A79, 0x6D1105D5,
@@ -525,7 +539,7 @@ static const uint32_t sctp_crc_tableil8_o64[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o72[256] =
+static const uint32 sctp_crc_tableil8_o72[256] =
{
0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E,
0x697997B4, 0x8649FCAD,
0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471,
0x097F8FAB, 0xE64FE4B2,
@@ -581,7 +595,7 @@ static const uint32_t sctp_crc_tableil8_o72[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o80[256] =
+static const uint32 sctp_crc_tableil8_o80[256] =
{
0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919,
0x75E69C41, 0x1DE5B089,
0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A,
0x3BCB6112, 0x53C84DDA,
@@ -637,7 +651,7 @@ static const uint32_t sctp_crc_tableil8_o80[256] =
* File Name = ............................ 8x256_tables.c
*/
-static const uint32_t sctp_crc_tableil8_o88[256] =
+static const uint32 sctp_crc_tableil8_o88[256] =
{
0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A,
0xB3657823, 0xFA590504,
0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90,
0xF15E7CF9, 0xB86201DE,
@@ -678,20 +692,19 @@ static const uint32_t sctp_crc_tableil8_o88[256] =
*/
-static uint32_t
-crc32c_sb8_64_bit(uint32_t crc,
+static uint32
+crc32c_sb8_64_bit(uint32 crc,
const unsigned char *p_buf,
- uint32_t length,
- uint32_t init_bytes)
+ uint32 length,
+ uint32 init_bytes)
{
- uint32_t li;
- uint32_t term1, term2;
- uint32_t running_length;
- uint32_t end_bytes;
+ uint32 li;
+ uint32 term1, term2;
+ uint32 running_length;
+ uint32 end_bytes;
- running_length = rounddown(length - init_bytes, 8);
+ running_length = ROUNDDOWN(length - init_bytes, 8);
end_bytes = length - init_bytes - running_length;
-
for (li = 0; li < init_bytes; li++)
crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^
(crc >> 8);
@@ -702,7 +715,7 @@ crc32c_sb8_64_bit(uint32_t crc,
crc ^= (*p_buf++) << 16;
crc ^= (*p_buf++) << 24;
#else
- crc ^= *(const uint32_t *) p_buf;
+ crc ^= *(const uint32 *) p_buf;
p_buf += 4;
#endif
term1 = sctp_crc_tableil8_o88[crc & 0x000000FF] ^
@@ -718,10 +731,9 @@ crc32c_sb8_64_bit(uint32_t crc,
crc ^= sctp_crc_tableil8_o40[*p_buf++];
crc ^= sctp_crc_tableil8_o32[*p_buf++];
#else
- term1 = sctp_crc_tableil8_o56[(*(const uint32_t *) p_buf) &
0x000000FF] ^
- sctp_crc_tableil8_o48[((*(const uint32_t *) p_buf) >> 8) &
0x000000FF];
-
- term2 = (*(const uint32_t *) p_buf) >> 16;
+ term1 = sctp_crc_tableil8_o56[(*(const uint32 *) p_buf) &
0x000000FF] ^
+ sctp_crc_tableil8_o48[((*(const uint32 *) p_buf) >> 8) &
0x000000FF];
+ term2 = (*(const uint32 *) p_buf) >> 16;
crc = crc ^
term1 ^
sctp_crc_tableil8_o40[term2 & 0x000000FF] ^
@@ -735,12 +747,12 @@ crc32c_sb8_64_bit(uint32_t crc,
return crc;
}
-static uint32_t
-multitable_crc32c(uint32_t crc32c,
+static uint32
+multitable_crc32c(uint32 crc32c,
const unsigned char *buffer,
unsigned int length)
{
- uint32_t to_even_word;
+ uint32 to_even_word;
if (length == 0) {
return (crc32c);
@@ -749,8 +761,8 @@ multitable_crc32c(uint32_t crc32c,
return (crc32c_sb8_64_bit(crc32c, buffer, length, to_even_word));
}
-uint32_t
-calculate_crc32c(uint32_t crc32c,
+uint32
+calculate_crc32c(uint32 crc32c,
const unsigned char *buffer,
unsigned int length)
{
diff --git a/src/add-ons/kernel/file_systems/xfs/Checksum.h
b/src/add-ons/kernel/file_systems/xfs/Checksum.h
new file mode 100644
index 0000000000..8aa1f1c6c9
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/xfs/Checksum.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2022, Raghav Sharma, raghavself28@xxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _XFS_CKSUM_H
+#define _XFS_CKSUM_H
+
+#include "CRCTable.h"
+#include "xfs_types.h"
+#include "system_dependencies.h"
+
+
+#define XFS_CRC_SEED (~(uint32)0)
+
+
+/*
+ Calculate the intermediate checksum for a buffer that has the CRC field
+ inside it. The offset of the 32bit crc fields is passed as the
+ cksum_offset parameter. We do not modify the buffer during verification,
+ hence we have to split the CRC calculation across the cksum_offset.
+*/
+static inline uint32
+xfs_start_cksum_safe(const char *buffer, size_t length, uint32 cksum_offset)
+{
+ uint32 zero = 0;
+ uint32 crc;
+
+ // Calculate CRC up to the checksum.
+ crc = calculate_crc32c(XFS_CRC_SEED, (uint8*)buffer, cksum_offset);
+
+ // Skip checksum field
+ crc = calculate_crc32c(crc, (uint8*)&zero, sizeof(uint32));
+
+ // Calculate the rest of the CRC.
+ return calculate_crc32c(crc, (uint8*)buffer + cksum_offset +
sizeof(uint32),
+ length - (cksum_offset + sizeof(uint32)));
+}
+
+
+/*
+ Fast CRC method where the buffer is modified. Callers must have exclusive
+ access to the buffer while the calculation takes place.
+*/
+static inline uint32
+xfs_start_cksum_update(char *buffer, size_t length, uint32 cksum_offset)
+{
+ // zero the CRC field
+ *(uint32 *)(buffer + cksum_offset) = 0;
+
+ // single pass CRC calculation for the entire buffer
+ return calculate_crc32c(XFS_CRC_SEED, (uint8*)buffer, length);
+}
+
+
+/*
+ Helper to generate the checksum for a buffer.
+
+ This modifies the buffer temporarily - callers must have exclusive
+ access to the buffer while the calculation takes place.
+*/
+static inline void
+xfs_update_cksum(char *buffer, size_t length, uint32 cksum_offset)
+{
+ uint32 crc = xfs_start_cksum_update(buffer, length, cksum_offset);
+
+ *(uint32 *)(buffer + cksum_offset) = ~crc;
+}
+
+
+/*
+ Helper to verify the checksum for a buffer.
+*/
+static inline int
+xfs_verify_cksum(char *buffer, size_t length, uint32 cksum_offset)
+{
+ uint32 crc = xfs_start_cksum_safe(buffer, length, cksum_offset);
+
+ TRACE("calculated crc: (%" B_PRIu32 ")\n", ~crc);
+
+ TRACE("buffer = %s, cksum_offset: (%" B_PRIu32 ")\n", buffer,
cksum_offset);
+
+ return *(uint32 *)(buffer + cksum_offset) == (~crc);
+}
+
+#endif
\ No newline at end of file
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
index 65895da7b8..a99d89ae1b 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -543,7 +543,7 @@ Inode::GetFromDisk()
xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(),
((uint64)(agNo * numberOfBlocksInAg) + agBlock));
- xfs_daddr_t readPos = blockToRead * BASICBLOCKSIZE + offset * len;
+ xfs_daddr_t readPos = blockToRead * XFS_MIN_BLOCKSIZE + offset * len;
if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) {
ERROR("Inode::Inode(): IO Error");
@@ -570,7 +570,7 @@ Inode::FileSystemBlockToAddr(uint64 block)
((uint64)(agNo * numberOfBlocksInAg) + agBlockNo));
TRACE("blockToRead:(%" B_PRIu64 ")\n", actualBlockToRead);
- uint64 readPos = actualBlockToRead * (BASICBLOCKSIZE);
+ uint64 readPos = actualBlockToRead * (XFS_MIN_BLOCKSIZE);
return readPos;
}
diff --git a/src/add-ons/kernel/file_systems/xfs/Jamfile
b/src/add-ons/kernel/file_systems/xfs/Jamfile
index 54fc1dab5f..03e5e312b3 100644
--- a/src/add-ons/kernel/file_systems/xfs/Jamfile
+++ b/src/add-ons/kernel/file_systems/xfs/Jamfile
@@ -18,10 +18,10 @@ UsePrivateKernelHeaders ;
DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
+UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] :
true ;
local xfsSources =
BPlusTree.cpp
- DeviceOpener.cpp
Directory.cpp
Extent.cpp
Inode.cpp
@@ -33,8 +33,14 @@ local xfsSources =
Volume.cpp
xfs.cpp
;
+local sharedSources =
+ crc32.cpp
+ CRCTable.cpp
+ DeviceOpener.cpp
+ ;
KernelAddon xfs :
$(xfsSources)
+ $(sharedSources)
:
libuuid_kernel.a
;
@@ -42,8 +48,10 @@ KernelAddon xfs :
SEARCH on [ FGristFiles $(xfsSources) ]
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems xfs ] ;
-SEARCH on [ FGristFiles DeviceOpener.cpp ]
+SEARCH on [ FGristFiles $(sharedSources) ]
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
SEARCH on [ FGristFiles kernel_cpp.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
+
+
diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.cpp
b/src/add-ons/kernel/file_systems/xfs/Volume.cpp
index e63bd5164f..cd655530f1 100644
--- a/src/add-ons/kernel/file_systems/xfs/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Volume.cpp
@@ -7,6 +7,7 @@
#include "Volume.h"
+#include "Checksum.h"
#include "Inode.h"
@@ -39,9 +40,28 @@ Volume::Identify(int fd, XfsSuperBlock *superBlock)
TRACE("Volume::Identify() : Identifying Volume in progress");
- if (read_pos(fd, 0, superBlock, sizeof(XfsSuperBlock))
- != sizeof(XfsSuperBlock))
- return B_IO_ERROR;
+ //Create a buffer of 512 bytes for Crc verification
+ char buf[512];
+
+ if(read_pos(fd, 0, buf, 512) != 512)
+ return B_IO_ERROR;
+
+ memcpy(superBlock, buf, sizeof(XfsSuperBlock));
+
+ int version = B_BENDIAN_TO_HOST_INT16(superBlock->Version()) &
XFS_SB_VERSION_NUMBITS;
+
+ // if its V5 filesystem check for superblock checksum
+ if (superBlock->MagicNum() == B_HOST_TO_BENDIAN_INT32(XFS_SB_MAGIC)
+ && (version == 5 || superBlock->Crc() != 0)) {
+
+ TRACE("Superblock Crc: (%" B_PRIu32 ")\n", superBlock->Crc());
+
+ if(!xfs_verify_cksum(buf, 512, offsetof(XfsSuperBlock,
sb_crc))) {
+ ERROR("Filesystem is corrupted");
+ return B_BAD_VALUE;
+ }
+
+ }
superBlock->SwapEndian();
@@ -85,7 +105,11 @@ Volume::Mount(const char *deviceName, uint32 flags)
return B_BAD_VALUE;
}
- TRACE("Volume::Mount(): Valid SuperBlock.\n");
+ if ((fSuperBlock.Version() & XFS_SB_VERSION_NUMBITS) == 5)
+ TRACE("Volume::Mount(): Valid Version 5 SuperBlock.\n");
+ else
+ TRACE("Volume::Mount(): Valid Version 4 SuperBlock.\n");
+
// check if the device size is large enough to hold the file system
off_t diskSize;
diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h
b/src/add-ons/kernel/file_systems/xfs/Volume.h
index 408d68eb98..a213451ff0 100644
--- a/src/add-ons/kernel/file_systems/xfs/Volume.h
+++ b/src/add-ons/kernel/file_systems/xfs/Volume.h
@@ -11,7 +11,7 @@
#include "xfs.h"
-#define FSBLOCK_SHIFT(fsBlockLog) (fsBlockLog - BASICBLOCKLOG);
+#define FSBLOCK_SHIFT(fsBlockLog) (fsBlockLog - XFS_MIN_BLOCKSIZE_LOG);
#define FSBLOCKS_TO_BASICBLOCKS(fsBlockLog, x) x << FSBLOCK_SHIFT(fsBlockLog);
// Converting the FS Blocks to Basic Blocks
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
index da59c446bd..2f43f882c8 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
@@ -13,23 +13,143 @@ XfsSuperBlock::Flags() const
}
+bool
+XfsSuperBlock::IsValidVersion() const
+{
+ // Version 5 is supported
+ if ((Version() & XFS_SB_VERSION_NUMBITS) == 5) {
+ return true;
+ }
+
+ // Version below 4 are not supported
+ if ((Version() & XFS_SB_VERSION_NUMBITS) < 4) {
+ ERROR("xfs version below 4 is not supported");
+ return false;
+ }
+
+ // V4 filesystems need v2 directories and unwritten extents
+ if (!(Version() & XFS_SB_VERSION_DIRV2BIT)) {
+ ERROR("xfs version 4 uses version 2 directories");
+ return false;
+ }
+ if (!(Version() & XFS_SB_VERSION_EXTFLGBIT)) {
+ ERROR("xfs version 4 uses unwritten extents");
+ return false;
+ }
+
+ // V4 should not have any unknown v4 feature bits set
+ if ((Version() & ~XFS_SB_VERSION_OKBITS) ||
+ ((Version() & XFS_SB_VERSION_MOREBITSBIT) &&
+ (Features2() & ~XFS_SB_VERSION2_OKBITS))) {
+ ERROR("xfs version 4 unknown feature bit detected");
+ return false;
+ }
+
+ // Valid V4 filesytem
+ return true;
+}
+
+
+bool
+XfsSuperBlock::IsValidFeatureMask() const
+{
+ // Version 5 superblock feature mask validation
+ if(sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN) {
+ ERROR("Superblock has unknown compatible features enabled");
+ ERROR("Use more recent kernal");
+ }
+
+ // We cannot have write support if this is set
+ if(sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_UNKNOWN) {
+ ERROR("Superblock has unknown read-only compatible features
enabled");
+ ERROR("Filesystem is read-only");
+ }
+
+ // check for incompatible features
+ if(sb_features_incompat & XFS_SB_FEAT_INCOMPAT_UNKNOWN) {
+ ERROR("Superblock has unknown incompatible features enabled");
+ return false;
+ }
+
+ return true;
+}
+
bool
XfsSuperBlock::IsValid() const
{
- if (sb_magicnum != XFS_SB_MAGIC)
+ if (sb_magicnum != XFS_SB_MAGIC) {
+ ERROR("Invalid Superblock");
return false;
+ }
- if (BASICBLOCKSIZE > sb_blocksize) {
+ // For version 4
+ if (XFS_MIN_BLOCKSIZE > sb_blocksize) {
ERROR("Basic block is less than 512 bytes!");
return false;
}
- // Checking version 4 file system
- if ((Version() & 0x000f) > 4) {
- ERROR("XFS version 5 or later is not yet supported");
+ // Checking correct version of filesystem
+ if(!(IsValidVersion())) {
+ return false;
+ }
+
+ if ((Version() & XFS_SB_VERSION_NUMBITS) == 4) {
+
+ if(sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
+ XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
+ ERROR("V4 Superblock has XFS_{P|G}QUOTA_{ENFD|CHKD}
bits");
+ return false;
+ }
+
+ return true;
+ }
+
+ if(!(IsValidFeatureMask())) {
+ return false;
+ }
+
+ // For V5
+ if (XFS_MIN_CRC_BLOCKSIZE > sb_blocksize) {
+ ERROR("Basic block is less than 1024 bytes!");
+ return false;
+ }
+
+ // V5 has a separate project quota inode
+ if (sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
+ ERROR("Version 5 of Super block has XFS_OQUOTA bits");
return false;
}
+ /*TODO: check if full Inode chunks are aligned to
+ inode chunk size when sparse inodes are
+ enabled to support the sparse chunk allocation
+ algorithm and prevent overlapping inode record.
+ */
+
+ // Sanity Checking
+ if( sb_agcount <= 0
||
+ sb_sectsize < XFS_MIN_SECTORSIZE
||
+ sb_sectsize > XFS_MAX_SECTORSIZE
||
+ sb_sectlog < XFS_MIN_SECTORSIZE_LOG
||
+ sb_sectlog > XFS_MAX_SECTORSIZE_LOG
||
+ sb_sectsize != (1 << sb_sectlog)
||
+ sb_blocksize < XFS_MIN_BLOCKSIZE
||
+ sb_blocksize > XFS_MAX_BLOCKSIZE
||
+ sb_blocklog < XFS_MIN_BLOCKSIZE_LOG
||
+ sb_blocklog > XFS_MAX_BLOCKSIZE_LOG
||
+ sb_blocksize != (uint32)(1 << sb_blocklog)
||
+ sb_dirblklog + sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
+ sb_inodesize < XFS_DINODE_MIN_SIZE
||
+ sb_inodesize > XFS_DINODE_MAX_SIZE
||
+ sb_inodelog < XFS_DINODE_MIN_LOG
||
+ sb_inodelog > XFS_DINODE_MAX_LOG
||
+ sb_inodesize != (1 << sb_inodelog)
) {
+
+ ERROR("Sanity checking failed");
+ return false;
+ }
+
+ // Valid V5 Superblock
return true;
}
@@ -167,38 +287,61 @@ XfsSuperBlock::AgBlocks() const
}
+uint32
+XfsSuperBlock::Crc() const
+{
+ return sb_crc;
+}
+
+uint32
+XfsSuperBlock::MagicNum() const
+{
+ return sb_magicnum;
+}
+
+
void
XfsSuperBlock::SwapEndian()
{
- sb_magicnum = B_BENDIAN_TO_HOST_INT32(sb_magicnum);
- sb_blocksize = B_BENDIAN_TO_HOST_INT32(sb_blocksize);
- sb_dblocks = B_BENDIAN_TO_HOST_INT64(sb_dblocks);
- sb_rblocks = B_BENDIAN_TO_HOST_INT64(sb_rblocks);
- sb_rextents = B_BENDIAN_TO_HOST_INT64(sb_rextents);
- sb_logstart = B_BENDIAN_TO_HOST_INT64(sb_logstart);
- sb_rootino = B_BENDIAN_TO_HOST_INT64(sb_rootino);
- sb_rbmino = B_BENDIAN_TO_HOST_INT64(sb_rbmino);
- sb_rsumino = B_BENDIAN_TO_HOST_INT64(sb_rsumino);
- sb_rextsize = B_BENDIAN_TO_HOST_INT32(sb_rextsize);
- sb_agblocks = B_BENDIAN_TO_HOST_INT32(sb_agblocks);
- sb_agcount = B_BENDIAN_TO_HOST_INT32(sb_agcount);
- sb_rbmblocks = B_BENDIAN_TO_HOST_INT32(sb_rbmblocks);
- sb_logblocks = B_BENDIAN_TO_HOST_INT32(sb_logblocks);
- sb_versionnum = B_BENDIAN_TO_HOST_INT16(sb_versionnum);
- sb_sectsize = B_BENDIAN_TO_HOST_INT16(sb_sectsize);
- sb_inodesize = B_BENDIAN_TO_HOST_INT16(sb_inodesize);
- sb_inopblock = B_BENDIAN_TO_HOST_INT16(sb_inopblock);
- sb_icount = B_BENDIAN_TO_HOST_INT64(sb_icount);
- sb_ifree = B_BENDIAN_TO_HOST_INT64(sb_ifree);
- sb_fdblocks = B_BENDIAN_TO_HOST_INT64(sb_fdblocks);
- sb_frextents = B_BENDIAN_TO_HOST_INT64(sb_frextents);
- sb_uquotino = B_BENDIAN_TO_HOST_INT64(sb_uquotino);
- sb_gquotino = B_BENDIAN_TO_HOST_INT64(sb_gquotino);
- sb_qflags = B_BENDIAN_TO_HOST_INT16(sb_qflags);
- sb_inoalignmt = B_BENDIAN_TO_HOST_INT32(sb_inoalignmt);
- sb_unit = B_BENDIAN_TO_HOST_INT32(sb_unit);
- sb_width = B_BENDIAN_TO_HOST_INT32(sb_width);
- sb_logsectsize = B_BENDIAN_TO_HOST_INT16(sb_logsectsize);
- sb_logsunit = B_BENDIAN_TO_HOST_INT32(sb_logsunit);
- sb_features2 = B_BENDIAN_TO_HOST_INT32(sb_features2);
+ sb_magicnum =
B_BENDIAN_TO_HOST_INT32(sb_magicnum);
+ sb_blocksize =
B_BENDIAN_TO_HOST_INT32(sb_blocksize);
+ sb_dblocks =
B_BENDIAN_TO_HOST_INT64(sb_dblocks);
+ sb_rblocks =
B_BENDIAN_TO_HOST_INT64(sb_rblocks);
+ sb_rextents =
B_BENDIAN_TO_HOST_INT64(sb_rextents);
+ sb_logstart =
B_BENDIAN_TO_HOST_INT64(sb_logstart);
+ sb_rootino =
B_BENDIAN_TO_HOST_INT64(sb_rootino);
+ sb_rbmino =
B_BENDIAN_TO_HOST_INT64(sb_rbmino);
+ sb_rsumino =
B_BENDIAN_TO_HOST_INT64(sb_rsumino);
+ sb_rextsize =
B_BENDIAN_TO_HOST_INT32(sb_rextsize);
+ sb_agblocks =
B_BENDIAN_TO_HOST_INT32(sb_agblocks);
+ sb_agcount =
B_BENDIAN_TO_HOST_INT32(sb_agcount);
+ sb_rbmblocks =
B_BENDIAN_TO_HOST_INT32(sb_rbmblocks);
+ sb_logblocks =
B_BENDIAN_TO_HOST_INT32(sb_logblocks);
+ sb_versionnum =
B_BENDIAN_TO_HOST_INT16(sb_versionnum);
+ sb_sectsize =
B_BENDIAN_TO_HOST_INT16(sb_sectsize);
+ sb_inodesize =
B_BENDIAN_TO_HOST_INT16(sb_inodesize);
+ sb_inopblock =
B_BENDIAN_TO_HOST_INT16(sb_inopblock);
+ sb_icount =
B_BENDIAN_TO_HOST_INT64(sb_icount);
+ sb_ifree =
B_BENDIAN_TO_HOST_INT64(sb_ifree);
+ sb_fdblocks =
B_BENDIAN_TO_HOST_INT64(sb_fdblocks);
+ sb_frextents =
B_BENDIAN_TO_HOST_INT64(sb_frextents);
+ sb_uquotino =
B_BENDIAN_TO_HOST_INT64(sb_uquotino);
+ sb_gquotino =
B_BENDIAN_TO_HOST_INT64(sb_gquotino);
+ sb_qflags =
B_BENDIAN_TO_HOST_INT16(sb_qflags);
+ sb_inoalignmt =
B_BENDIAN_TO_HOST_INT32(sb_inoalignmt);
+ sb_unit =
B_BENDIAN_TO_HOST_INT32(sb_unit);
+ sb_width =
B_BENDIAN_TO_HOST_INT32(sb_width);
+ sb_logsectsize =
B_BENDIAN_TO_HOST_INT16(sb_logsectsize);
+ sb_logsunit =
B_BENDIAN_TO_HOST_INT32(sb_logsunit);
+ sb_features2 =
B_BENDIAN_TO_HOST_INT32(sb_features2);
+ sb_bad_features2 =
B_BENDIAN_TO_HOST_INT32(sb_bad_features2);
+ sb_features_compat =
B_BENDIAN_TO_HOST_INT32(sb_features_compat);
+ sb_features_ro_compat =
B_BENDIAN_TO_HOST_INT32(sb_features_ro_compat);
+ sb_features_incompat =
B_BENDIAN_TO_HOST_INT32(sb_features_incompat);
+ sb_features_log_incompat =
B_BENDIAN_TO_HOST_INT32(sb_features_log_incompat);
+ // crc is only used on disk, not in memory; just init to 0 here
+ sb_crc = 0;
+ sb_spino_align =
B_BENDIAN_TO_HOST_INT32(sb_spino_align);
+ sb_pquotino =
B_BENDIAN_TO_HOST_INT64(sb_pquotino);
+ sb_lsn =
B_BENDIAN_TO_HOST_INT64(sb_lsn);
}
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h
b/src/add-ons/kernel/file_systems/xfs/xfs.h
index 3c6a904d89..e132fe65e4 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.h
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.h
@@ -24,13 +24,30 @@ extern fs_volume_ops gxfsVolumeOps;
#define XFS_SB_MAGIC 0x58465342
- // Identifies XFS. "XFSB"
+#define XFS_MIN_BLOCKSIZE_LOG 9
+#define XFS_MAX_BLOCKSIZE_LOG 16
+#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
+#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
+#define XFS_MIN_CRC_BLOCKSIZE (1 << (XFS_MIN_BLOCKSIZE_LOG + 1))
+#define XFS_MIN_SECTORSIZE_LOG 9
+#define XFS_MAX_SECTORSIZE_LOG 15
+#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
+#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
#define XFS_SB_MAXSIZE 512
-#define BASICBLOCKLOG 9
- // Log of block size should be 9
-#define BASICBLOCKSIZE (1 << BASICBLOCKLOG)
- // The size of a basic block should be 512
+
+
#define XFS_OPEN_MODE_USER_MASK 0x7fffffff
+#define XFS_SB_VERSION_NUMBITS 0x000f
+#define XFS_SB_VERSION_ALLFBITS 0xfff0
+#define XFS_SB_VERSION_NUM(sb) ((sb)->sb_versionnum &
XFS_SB_VERSION_NUMBITS)
+
+/*
+ Inode minimum and maximum sizes.
+*/
+#define XFS_DINODE_MIN_LOG 8
+#define XFS_DINODE_MAX_LOG 11
+#define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG)
+#define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG)
/* B+Tree related macros
*/
@@ -50,11 +67,12 @@ struct file_cookie {
};
-/* Version 4 superblock definition */
class XfsSuperBlock {
public:
bool IsValid() const;
+ bool IsValidVersion() const;
+ bool IsValidFeatureMask()
const;
const char* Name() const;
uint32 BlockSize() const;
uint8 BlockLog() const;
@@ -77,6 +95,8 @@ public:
uint8 Flags() const;
uint16 Version() const;
uint32 Features2() const;
+ uint32 Crc() const;
+ uint32 MagicNum() const;
private:
uint32 sb_magicnum;
@@ -124,6 +144,22 @@ private:
uint16 sb_logsectsize;
uint32 sb_logsunit;
uint32 sb_features2;
+ uint32 sb_bad_features2;
+
+ // version 5
+
+ uint32 sb_features_compat;
+ uint32 sb_features_ro_compat;
+ uint32 sb_features_incompat;
+ uint32
sb_features_log_incompat;
+public:
+ uint32 sb_crc;
+private:
+ xfs_extlen_t sb_spino_align;
+
+ xfs_ino_t sb_pquotino;
+ xfs_lsn_t sb_lsn;
+ uuid_t sb_meta_uuid;
};
@@ -146,6 +182,9 @@ private:
#define XFS_SB_VERSION_DIRV2BIT 0x2000
#define XFS_SB_VERSION_MOREBITSBIT 0x4000
+#define XFS_SB_VERSION_OKBITS \
+ ((XFS_SB_VERSION_NUMBITS | XFS_SB_VERSION_ALLFBITS) & \
+ ~XFS_SB_VERSION_SHAREDBIT)
/*
Superblock quota flags - sb_qflags
@@ -182,4 +221,51 @@ Superblock quota flags - sb_qflags
#define XFS_SB_VERSION2_CRCBIT 0x00000100 /* Metadata
checksumming */
#define XFS_SB_VERSION2_FTYPE 0x00000200
+#define XFS_SB_VERSION2_OKBITS \
+ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
+ XFS_SB_VERSION2_ATTR2BIT | \
+ XFS_SB_VERSION2_PROJID32BIT | \
+ XFS_SB_VERSION2_FTYPE)
+
+/*
+ Extended Version 5 Superblock Read-Only compatibility flags
+*/
+
+#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode
btree */
+#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map
btree */
+#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked
files */
+#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block
counts */
+
+/*
+ Extended Version 5 Superblock Read-Write incompatibility flags
+*/
+
+#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
+#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks
*/
+#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
+#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
+
+/*
+ Extended v5 superblock feature masks. These are to be used for new v5
+ superblock features only.
+*/
+
+#define XFS_SB_FEAT_COMPAT_ALL 0
+#define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALL
+
+#define XFS_SB_FEAT_RO_COMPAT_ALL \
+ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \
+ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
+ XFS_SB_FEAT_RO_COMPAT_REFLINK| \
+ XFS_SB_FEAT_RO_COMPAT_INOBTCNT)
+#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
+
+#define XFS_SB_FEAT_INCOMPAT_ALL \
+ (XFS_SB_FEAT_INCOMPAT_FTYPE| \
+ XFS_SB_FEAT_INCOMPAT_SPINODES| \
+ XFS_SB_FEAT_INCOMPAT_META_UUID| \
+ XFS_SB_FEAT_INCOMPAT_BIGTIME)
+
+#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
+
#endif
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs_types.h
b/src/add-ons/kernel/file_systems/xfs/xfs_types.h
index 3892894264..5e8a8279d9 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs_types.h
+++ b/src/add-ons/kernel/file_systems/xfs/xfs_types.h
@@ -36,6 +36,7 @@ typedef uint64 xfs_rtblock_t; // extent number in the
real-time sub-volume
typedef uint64 xfs_fileoff_t; // block offset into a file
typedef uint64 xfs_filblks_t; // block count for a file
typedef int64 xfs_fsize_t; // byte size of a file
+typedef int64 xfs_lsn_t; // log sequence number
typedef xfs_fileoff_t TreeKey;
typedef xfs_fsblock_t TreePointer;
diff --git a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile
b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile
index c2eb14ac16..1dee2f14f3 100644
--- a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile
+++ b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src tests add-ons kernel file_systems xfs xfs_shell ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems xfs ]
;
+SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems
shared ] ;
# prevent inclusion of HaikuBuildCompatibility.h and _BSD_SOURCE headers
DEFINES += HAIKU_BUILD_COMPATIBILITY_H __STRICT_ANSI__ ;
@@ -37,10 +38,10 @@ UsePrivateHeaders fs_shell ;
UsePrivateHeaders file_systems ;
UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
+UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] :
true ;
local xfsSource =
BPlusTree.cpp
- DeviceOpener.cpp
Directory.cpp
Extent.cpp
Inode.cpp
@@ -51,8 +52,13 @@ local xfsSource =
Volume.cpp
xfs.cpp
;
+local sharedSources =
+ crc32.cpp
+ CRCTable.cpp
+ DeviceOpener.cpp
+;
-BuildPlatformMergeObject <build>xfs_shell.o : $(xfsSource) ;
+BuildPlatformMergeObject <build>xfs_shell.o : $(xfsSource) $(sharedSources) ;
BuildPlatformMain <build>xfs_shell
:
@@ -74,5 +80,3 @@ BuildPlatformMain <build>xfs_fuse
SEARCH on [ FGristFiles QueryParserUtils.cpp ]
+= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
-SEARCH on [ FGristFiles DeviceOpener.cpp ]
- += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;