From Shubham Bhagat <shubhambhagat111@xxxxxxxxx>:
Shubham Bhagat has uploaded this change for review. (
https://review.haiku-os.org/c/haiku/+/2952 ;)
Change subject: xfs: Read Short Form Directories
......................................................................
xfs: Read Short Form Directories
We can now read short form directories.
---
M src/add-ons/kernel/file_systems/xfs/Debug.h
M src/add-ons/kernel/file_systems/xfs/Inode.cpp
M src/add-ons/kernel/file_systems/xfs/Inode.h
M src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
M src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
M src/add-ons/kernel/file_systems/xfs/Volume.h
M src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
M src/add-ons/kernel/file_systems/xfs/xfs.cpp
M src/add-ons/kernel/file_systems/xfs/xfs.h
9 files changed, 194 insertions(+), 52 deletions(-)
git pull ssh://git.haiku-os.org:22/haiku refs/changes/52/2952/1
diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h
b/src/add-ons/kernel/file_systems/xfs/Debug.h
index bc41c80..51b5f70 100644
--- a/src/add-ons/kernel/file_systems/xfs/Debug.h
+++ b/src/add-ons/kernel/file_systems/xfs/Debug.h
@@ -1,6 +1,10 @@
/*
+ * Copyright 2017, Chế Vũ Gia Hy, cvghy116@xxxxxxxxx.
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2005-2007, Ingo Weinhold, bonefish@xxxxxxxxxxxxxxx.
* Copyright 2020, Shubham Bhagat, shubhambhagat111@xxxxxxxxx
- * All rights reserved. Distributed under the terms of the MIT License.
+ * This file may be used under the terms of the MIT License.
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
@@ -8,8 +12,10 @@
// #define TRACE_XFS
#ifdef TRACE_XFS
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
+#define ASSERT(x) { if (!(x)) kernel_debugger("btrfs: assert failed: " #x
"\n"); }
#else
#define TRACE(x...) ;
+#define ASSERT(x) ;
#endif
#define ERROR(x...) dprintf("\n\33[34mxfs:\33[0m " x)
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
index a73cdd8..c653c87 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -174,6 +174,9 @@
// Inode len to read (size of inode)
int fd = fVolume->Device();
+ TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d),
Offset: (%d), len: (%d)\n",
+ agNo, agInodeNo, agBlock, offset, len);
+
if (agNo > fVolume->AgCount()) {
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
return B_ENTRY_NOT_FOUND;
@@ -184,7 +187,7 @@
xfs_fsblock_t blockToRead = FSB_TO_BB(fVolume->BlockLog(),
((uint64)(agNo * agBlocks) + agBlock));
- xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset;
+ xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset*len;
if (read_pos(fd, readPos, fBuffer, len) != len) {
ERROR("Inode::Inode(): IO Error");
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h
b/src/add-ons/kernel/file_systems/xfs/Inode.h
index 948be5d..4b4757d 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.h
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.h
@@ -28,9 +28,9 @@
// Gets the AG relative block number that contains inode
#define INO_TO_OFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog()))
// Gets the offset into the block from the inode number
-#define DIR_DFORK_PTR(dir_ino_ptr) (char*) dir_ino_ptr + DATA_FORK_OFFSET
+#define DIR_DFORK_PTR(dir_ino_ptr) (void*)((char*) dir_ino_ptr +
DATA_FORK_OFFSET)
#define DIR_AFORK_PTR(dir_ino_ptr) \
- (XFS_DFORK_PTR + \
+ (void*)((char*)XFS_DFORK_PTR + \
((uint32)dir_ino_ptr->di_forkoff<<3))
#define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
index 63c912e..b69a972 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
@@ -12,7 +12,7 @@
fInode(inode),
fTrack(0)
{
- memcpy(&fHeader, DIR_DFORK_PTR(fInode->Buffer()),
sizeof(xfs_dir2_sf_hdr_t));
+ fHeader = (xfs_dir2_sf_hdr_t*)(DIR_DFORK_PTR(fInode->Buffer()));
}
@@ -22,33 +22,121 @@
}
-xfs_ino_t
-ShortDirectory::GetParentIno()
+bool
+ShortDirectory::HasFileTypeField()
{
- TRACE("GetParentIno: \n");
- if (fHeader.i8count)
- return B_BENDIAN_TO_HOST_INT64(fHeader.parent.i8);
+ if (fInode->GetVolume()->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE)
+ return true;
else
- return B_BENDIAN_TO_HOST_INT32(fHeader.parent.i4);
+ return false;
+}
+
+
+uint8
+ShortDirectory::GetFileType(xfs_dir2_sf_entry_t* entry)
+{
+ ASSERT(HasFileTypeField() == true);
+ return entry->name[entry->namelen];
+}
+
+
+xfs_dir2_sf_entry_t*
+ShortDirectory::FirstEntry()
+{
+ return (xfs_dir2_sf_entry_t*) ((char*) fHeader + HeaderSize());
+}
+
+
+size_t
+ShortDirectory::HeaderSize()
+{
+ if (fHeader->i8count)
+ return sizeof(xfs_dir2_sf_hdr_t);
+ else
+ return sizeof(xfs_dir2_sf_hdr_t) - sizeof(uint32);
+}
+
+
+xfs_ino_t
+ShortDirectory::GetIno(xfs_dir2_inou_t* inum)
+{
+ if (fHeader->i8count)
+ return B_BENDIAN_TO_HOST_INT64(inum->i8);
+ else
+ return B_BENDIAN_TO_HOST_INT32(inum->i4);
+}
+
+
+xfs_ino_t
+ShortDirectory::GetEntryIno(xfs_dir2_sf_entry_t* entry)
+{
+ if(HasFileTypeField())
+ return GetIno((xfs_dir2_inou_t*)(entry->name
+ + entry->namelen + sizeof(uint8)));
+ else
+ return GetIno((xfs_dir2_inou_t*)(entry->name + entry->namelen));
+}
+
+
+size_t
+ShortDirectory::EntrySize(int namelen)
+{
+ return sizeof(xfs_dir2_sf_entry_t) + namelen
+ + (HasFileTypeField()? sizeof(uint8) : 0)
+ + (fHeader->i8count? sizeof(uint64):sizeof(uint32));
+}
+
+
+bool
+ShortDirectory::CompareName(const char* name, size_t length,
+ xfs_dir2_sf_entry_t* entry)
+{
+ if (length != entry->namelen)
+ return false;
+
+ bool status = true;
+ for (int i = 0; i < length; i++)
+ {
+ if(name[i] == entry->name[i])
+ continue;
+ status = false;
+ }
+
+ return status;
}
status_t
ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino)
{
- if (strcmp(name, ".") == 0 || strcmp(name, "..")) {
+ TRACE("ShortDirectory::Lookup\n");
+
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
xfs_ino_t rootIno = fInode->GetVolume()->Root();
- if (strcmp(name, ".") || (rootIno == fInode->ID())) {
+ if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) {
*ino = fInode->ID();
TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n",
*ino);
return B_OK;
}
- *ino = GetParentIno();
+ *ino = GetIno(&fHeader->parent);
TRACE("Parent: (%d)\n", *ino);
return B_OK;
}
- //TODO: Other entries
- return B_NOT_SUPPORTED;
+
+ xfs_dir2_sf_entry_t* entry = FirstEntry();
+ TRACE("Length of first entry: (%d), offset of first entry: (%d)\n",
entry->namelen,
+ B_BENDIAN_TO_HOST_INT16(entry->offset.i));
+
+ for (int i = 0; i < fHeader->count; i++) {
+ bool status = CompareName(name, length, entry);
+ if (status) {
+ *ino = GetEntryIno(entry);
+ return B_OK;
+ }
+ entry = (xfs_dir2_sf_entry_t*)((char*) entry +
EntrySize(entry->namelen));
+ }
+
+ return B_ENTRY_NOT_FOUND;
}
@@ -70,12 +158,35 @@
return B_BUFFER_OVERFLOW;
*length = 3;
strlcpy(name, "..", *length + 1);
- *ino = GetParentIno();
+ *ino = GetIno(&fHeader->parent);
fTrack = 2;
- TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino);
+ // TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n",
*ino);
return B_OK;
}
- // TODO: Now iterate through sf entries
- return B_NOT_SUPPORTED;
+ xfs_dir2_sf_entry_t* entry = FirstEntry();
+ TRACE("Length of first entry: (%d), offset of first entry: (%d)\n",
entry->namelen,
+ B_BENDIAN_TO_HOST_INT16(entry->offset.i));
+
+ for(int i = 0; i < fHeader->count; i++)
+ {
+ uint16 curOffset = B_BENDIAN_TO_HOST_INT16(entry->offset.i);
+ if (curOffset > fLastEntryOffset) {
+
+ if (entry->namelen > *length)
+ return B_BUFFER_OVERFLOW;
+
+ fLastEntryOffset = curOffset;
+ memcpy(name, entry->name, entry->namelen);
+ name[entry->namelen] = '\0';
+ *length = entry->namelen + 1;
+ *ino = GetEntryIno(entry);
+
+ TRACE("Entry found. Name: (%s), Length: (%ld), ino:
(%ld)\n", name, *length, *ino);
+ return B_OK;
+ }
+ entry = (xfs_dir2_sf_entry_t*)((char*)entry +
EntrySize(entry->namelen));
+ }
+
+ return B_ENTRY_NOT_FOUND;
}
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
index a6f47b5..635c2e1 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
@@ -8,41 +8,33 @@
#include "Inode.h"
-typedef struct { uint8 i[2]; } xfs_dir2_sf_off_t; //offset into the literal
area
-typedef union {
+struct xfs_dir2_sf_off_t{
+ uint16 i;
+} __attribute__((packed)); //offset into the literal area
+
+union xfs_dir2_inou_t{
uint64 i8;
uint32 i4;
-} xfs_dir2_inou_t;
+} __attribute__((packed));
// Short form directory header
-typedef struct xfs_dir2_sf_hdr{
+struct xfs_dir2_sf_hdr_t{
uint8 count; // number of entries
uint8 i8count; // # of 64bit inode entries
xfs_dir2_inou_t parent; // absolute inode # of parent
-} xfs_dir2_sf_hdr_t;
+} __attribute__((packed));
-/*
- *The xfs_dir2_sf_entry is split into
- * two parts because the entries size is variable
- */
-typedef struct xfs_dir2_sf_entry {
+struct xfs_dir2_sf_entry_t {
uint8 namelen; // length of the name, in bytes
xfs_dir2_sf_off_t offset; // offset tag, for directory iteration
uint8 name[]; // name of directory entry
-} xfs_dir2_sf_entry_t;
-
-
-typedef union xfs_dir2_sf_entry_inum {
- struct xfs_ftype_inum{
- uint8 ftype;
- xfs_dir2_inou_t inumber;
- };
- struct xfs_inum{
- xfs_dir2_inou_t inumber;
- };
-} xfs_dir2_sf_entry_inum_t;
+ /*
+ * Following will be a single byte file type variable
+ * and inode number (64bits or 32 bits)
+ */
+} __attribute__((packed));
class ShortDirectory
@@ -50,16 +42,24 @@
public:
ShortDirectory(Inode* inode);
~ShortDirectory();
+ size_t HeaderSize();
+ bool HasFileTypeField();
+ uint8
GetFileType(xfs_dir2_sf_entry_t* entry);
+ xfs_dir2_sf_entry_t* FirstEntry();
+ xfs_ino_t GetIno(xfs_dir2_inou_t*
inum);
+ xfs_ino_t
GetEntryIno(xfs_dir2_sf_entry_t* entry);
+ size_t EntrySize(int namelen);
+ bool CompareName(const char*
name, size_t length,
+
xfs_dir2_sf_entry_t* entry);
status_t GetNext(char* name,
size_t* length,
xfs_ino_t* ino);
- xfs_ino_t GetParentIno();
status_t Lookup(const char*
name, size_t length,
xfs_ino_t* id);
private:
Inode* fInode;
- xfs_dir2_sf_hdr_t fHeader;
- xfs_dir2_sf_off_t fLastEntryOffset;
+ xfs_dir2_sf_hdr_t* fHeader;
+ uint16 fLastEntryOffset;
// offset into the literal area
uint8 fTrack;
// Takes the values 0, 1 or 2
diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h
b/src/add-ons/kernel/file_systems/xfs/Volume.h
index 5683bc5..85abcbb 100644
--- a/src/add-ons/kernel/file_systems/xfs/Volume.h
+++ b/src/add-ons/kernel/file_systems/xfs/Volume.h
@@ -77,6 +77,9 @@
uint8 SuperBlockFlags() const
{
return fSuperBlock.Flags(); }
+ uint32 SuperBlockFeatures2()
const
+ {
return fSuperBlock.Features2(); }
+
#if 0
off_t NumBlocks() const
{
return fSuperBlock.NumBlocks(); }
diff --git a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
index ecbe4e5..6ea60d7 100644
--- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
@@ -235,7 +235,7 @@
xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
{
Inode* inode = (Inode*)_node->private_node;
- TRACE("XFS_READ_STAT: root_id: (%d)\n", inode->ID());
+ // TRACE("XFS_READ_STAT: id: (%d)\n", inode->ID());
stat->st_dev = inode->GetVolume()->ID();
stat->st_ino = inode->ID();
stat->st_nlink = 1;
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
index 9a3f207..6391392 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
@@ -24,10 +24,27 @@
return false;
}
+ // Checking version 4 file system
+ ASSERT((Version() & 0x000f) == 4)
+
return true;
}
+uint16
+XfsSuperBlock::Version() const
+{
+ return sb_versionnum;
+}
+
+
+uint32
+XfsSuperBlock::Features2() const
+{
+ return sb_features2;
+}
+
+
uint32
XfsSuperBlock::BlockSize() const
{
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h
b/src/add-ons/kernel/file_systems/xfs/xfs.h
index b72a600..08e3d21 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.h
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.h
@@ -55,6 +55,8 @@
xfs_agnumber_t AgCount() const;
xfs_agblock_t AgBlocks() const;
uint8 Flags() const;
+ uint16 Version() const;
+ uint32 Features2() const;
private:
uint32 sb_magicnum;
@@ -151,13 +153,13 @@
Extended v4 Superblock flags - sb_features2
*/
-#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x0001
+#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000001
// update global free space and inode on clean unmount
-#define XFS_SB_VERSION2_ATTR2BIT 0x0002
+#define XFS_SB_VERSION2_ATTR2BIT 0x00000002
// optimises the inode layout of ext-attr
-#define XFS_SB_VERSION2_PARENTBIT 0x0004 /* Parent pointers */
-#define XFS_SB_VERSION2_PROJID32BIT 0x0008 /* 32-bit project id */
-#define XFS_SB_VERSION2_CRCBIT 0x0010 /* Metadata checksumming */
-#define XFS_SB_VERSION2_FTYPE 0x0020
+#define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* Parent pointers */
+#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project id */
+#define XFS_SB_VERSION2_CRCBIT 0x00000100 /* Metadata
checksumming */
+#define XFS_SB_VERSION2_FTYPE 0x00000200
#endif
--
To view, visit https://review.haiku-os.org/c/haiku/+/2952
To unsubscribe, or for help writing mail filters, visit
https://review.haiku-os.org/settings
Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I23eb6ef52e8bb07643213e603ed0185f536c649f
Gerrit-Change-Number: 2952
Gerrit-PatchSet: 1
Gerrit-Owner: Shubham Bhagat <shubhambhagat111@xxxxxxxxx>
Gerrit-MessageType: newchange