diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h b/src/add-ons/kernel/file_systems/xfs/Debug.h new file mode 100644 index 0000000000..6ab16012bc --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Debug.h @@ -0,0 +1,16 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#define TRACE_XFS +#ifdef TRACE_XFS +#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x) +#else +#define TRACE(x...) ; +#endif +#define ERROR(x...) dprintf("\n\33[34mxfs:\33[0m " x) + +#endif \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/xfs/Jamfile b/src/add-ons/kernel/file_systems/xfs/Jamfile index edf605bb98..79c72ddc19 100644 --- a/src/add-ons/kernel/file_systems/xfs/Jamfile +++ b/src/add-ons/kernel/file_systems/xfs/Jamfile @@ -20,6 +20,8 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ; UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ; local xfsSources = + xfs.cpp + Volume.cpp kernel_cpp.cpp kernel_interface.cpp ; diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.cpp b/src/add-ons/kernel/file_systems/xfs/Volume.cpp new file mode 100644 index 0000000000..0c24307d5e --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Volume.cpp @@ -0,0 +1,267 @@ +/* + * Copyright 2001 - 2017, Axel Dörfler, axeld @pinc - software.de. + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#include "Volume.h" + + +class DeviceOpener +{ +public: + DeviceOpener(int fd, int mode); + DeviceOpener(const char *device, int mode); + ~DeviceOpener(); + + int Open(const char *device, int mode); + int Open(int fd, int mode); + void* InitCache(off_t numBlocks, uint32 blockSize); + void RemoveCache(bool allowWrites); + + void Keep(); + + int Device() const { return fDevice; } + int Mode() const { return fMode; } + bool IsReadOnly() const + { return _IsReadOnly(fMode); } + + status_t GetSize(off_t* _size, uint32* _blockSize = NULL); + +private: + static bool _IsReadOnly(int mode) + { return (mode & O_RWMASK) == O_RDONLY; } + static bool _IsReadWrite(int mode) + { return (mode & O_RWMASK) == O_RDWR; } + + int fDevice; + int fMode; + void* fBlockCache; +}; + + +DeviceOpener::DeviceOpener(const char *device, int mode) + : fBlockCache(NULL) +{ + Open(device, mode); +} + + +DeviceOpener::DeviceOpener(int fd, int mode) + : fBlockCache(NULL) +{ + Open(fd, mode); +} + + +DeviceOpener::~DeviceOpener() +{ + if (fDevice >= 0) { + RemoveCache(false); + close(fDevice); + } +} + + +int +DeviceOpener::Open(const char *device, int mode) +{ + fDevice = open(device, mode | O_NOCACHE); + if (fDevice < 0) + fDevice = errno; + + if (fDevice < 0 && _IsReadWrite(mode)){ + // try again to open read-only (don't rely on a specific error code) + return Open(device, O_RDONLY | O_NOCACHE); + } + + if (fDevice >= 0) { + // opening succeeded + fMode = mode; + if (_IsReadWrite(mode)) { + // check out if the device really allows for read/write access + device_geometry geometry; + if (!ioctl(fDevice, B_GET_GEOMETRY, &geometry)) { + + if (geometry.read_only) { + // reopen device read-only + close(fDevice); + return Open(device, O_RDONLY | O_NOCACHE); + } + } + } + } + + return fDevice; +} + + +int +DeviceOpener::Open(int fd, int mode) +{ + fDevice = dup(fd); + if (fDevice < 0) + return errno; + + fMode = mode; + + return fDevice; +} + + +void* +DeviceOpener::InitCache(off_t numBlocks, uint32 blockSize) +{ + return fBlockCache = block_cache_create(fDevice, numBlocks, blockSize, + IsReadOnly()); +} + + +void +DeviceOpener::RemoveCache(bool allowWrites) +{ + if (fBlockCache == NULL) + return; + + block_cache_delete(fBlockCache, allowWrites); + fBlockCache = NULL; +} + + +void +DeviceOpener::Keep() +{ + fDevice = -1; +} + + +/*! Returns the size of the device in bytes. It uses B_GET_GEOMETRY + to compute the size, or fstat() if that failed. +*/ +status_t +DeviceOpener::GetSize(off_t *_size, uint32 *_blockSize) +{ + device_geometry geometry; + if (ioctl(fDevice, B_GET_GEOMETRY, &geometry) < 0) { + // maybe it's just a file + struct stat stat; + if (fstat(fDevice, &stat) < 0) + return B_ERROR; + + if (_size) + *_size = stat.st_size; + if (_blockSize) // that shouldn't cause us any problems + *_blockSize = 512; + + return B_OK; + } + + if (_size) { + *_size = 1LL * geometry.head_count * geometry.cylinder_count + * geometry.sectors_per_track * geometry.bytes_per_sector; + } + if (_blockSize) + *_blockSize = geometry.bytes_per_sector; + + return B_OK; +} + + +Volume::Volume(fs_volume *volume) + : fFSVolume(volume) +{ + fFlags = 0; + mutex_init(&fLock, "xfs volume"); + TRACE("Volume::Volume() : Initialising volume"); +} + + +Volume::~Volume() +{ + mutex_destroy(&fLock); + TRACE("Volume::Destructor : Removing Volume"); +} + + +bool +Volume::IsValidSuperBlock() +{ + return fSuperBlock.IsValid(); +} + + +status_t +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; + + superBlock->SwapEndian(); + + if (!superBlock->IsValid()) { + ERROR("Volume::Identify(): Invalid Superblock!\n"); + return B_BAD_VALUE; + } + return B_OK; +} + + +status_t +Volume::Mount(const char *deviceName, uint32 flags) +{ + TRACE("Volume::Mount() : Mounting in progress"); + + flags |= B_MOUNT_READ_ONLY; + + if ((flags & B_MOUNT_READ_ONLY) != 0) { + TRACE("Volume::Mount(): Read only\n"); + } else { + TRACE("Volume::Mount(): Read write\n"); + } + + DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0 + ? O_RDONLY + : O_RDWR); + fDevice = opener.Device(); + if (fDevice < B_OK) { + ERROR("Volume::Mount(): couldn't open device\n"); + return fDevice; + } + + if (opener.IsReadOnly()) + fFlags |= VOLUME_READ_ONLY; + + // read the superblock + status_t status = Identify(fDevice, &fSuperBlock); + if (status != B_OK) { + ERROR("Volume::Mount(): Invalid super block!\n"); + return B_BAD_VALUE; + } + + TRACE("Volume::Mount(): Valid SuperBlock.\n"); + + // check if the device size is large enough to hold the file system + off_t diskSize; + if (opener.GetSize(&diskSize) != B_OK) { + ERROR("Volume:Mount() Unable to get diskSize"); + return B_ERROR; + } + + opener.Keep(); + return B_OK; +} + + +status_t +Volume::Unmount() +{ + TRACE("Volume::Unmount(): Unmounting"); + + TRACE("Volume::Unmount(): Closing device"); + close(fDevice); + + return B_OK; +} diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h b/src/add-ons/kernel/file_systems/xfs/Volume.h new file mode 100644 index 0000000000..748eb10329 --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Volume.h @@ -0,0 +1,64 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef _VOLUME_H_ +#define _VOLUME_H_ + +#include "xfs.h" + +extern fs_volume_ops gxfsVolumeOps; +enum volume_flags { + VOLUME_READ_ONLY = 0x0001 +}; + + +class Volume { +public: + Volume(fs_volume *volume); + ~Volume(); + + status_t Mount(const char *device, uint32 flags); + status_t Unmount(); + status_t Initialize(int fd, const char *label, + uint32 blockSize, uint32 sectorSize); + + bool IsValidSuperBlock(); + bool IsReadOnly() const + { return (fFlags & VOLUME_READ_ONLY) != 0; } + + dev_t ID() const + { return fFSVolume ? fFSVolume->id : -1; } + fs_volume* FSVolume() const + { return fFSVolume; } + char* Name() + { return fSuperBlock.Name(); } + + XfsSuperBlock& SuperBlock() { return fSuperBlock; } + int Device() const { return fDevice; } + + static status_t Identify(int fd, XfsSuperBlock *superBlock); + + #if 0 + off_t NumBlocks() const + { return fSuperBlock.NumBlocks(); } + + off_t Root() const { return fSuperBlock.rootino; } + + static status_t Identify(int fd, SuperBlock *superBlock); + #endif + +protected: + fs_volume* fFSVolume; + int fDevice; + XfsSuperBlock fSuperBlock; + char fName[32]; /* filesystem name */ + + uint32 fDeviceBlockSize; + mutex fLock; + + uint32 fFlags; +}; + +#endif \ No newline at end of file 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 905ad2752d..012e0806ce 100644 --- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp @@ -1,14 +1,10 @@ /* - * Copyright 2020 Shubham Bhagat, shubhambhagat111@yahoo.com + * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com * All rights reserved. Distributed under the terms of the MIT License. */ #include "system_dependencies.h" - -#ifdef TRACE_XFS -#define TRACE(x...) dprintf("\33[34mxfs:\33[0m " x) -#else -#define TRACE(x...) ; -#endif +#include "Volume.h" struct identify_cookie @@ -23,7 +19,7 @@ struct identify_cookie //! xfs_io() callback hook static status_t iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset, - size_t size, struct file_io_vec *vecs, size_t *_count) + size_t size, struct file_io_vec *vecs, size_t *_count) { return B_NOT_SUPPORTED; } @@ -32,13 +28,15 @@ iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset, //! xfs_io() callback hook static status_t iterative_io_finished_hook(void *cookie, io_request *request, status_t status, - bool partialTransfer, size_t bytesTransferred) + bool partialTransfer, size_t bytesTransferred) { return B_NOT_SUPPORTED; } // #pragma mark - Scanning + + static float xfs_identify_partition(int fd, partition_data *partition, void **_cookie) { @@ -62,18 +60,48 @@ xfs_free_identify_partition_cookie(partition_data *partition, void *_cookie) // #pragma mark - + + static status_t xfs_mount(fs_volume *_volume, const char *device, uint32 flags, - const char *args, ino_t *_rootID) + const char *args, ino_t *_rootID) { - return B_NOT_SUPPORTED; + TRACE("xfs_mount(): Trying to mount\n"); + + Volume *volume = new (std::nothrow) Volume(_volume); + if (volume == NULL) + return B_NO_MEMORY; + + _volume->private_volume = volume; + _volume->ops = &gxfsVolumeOps; + + status_t status = volume->Mount(device, flags); + if (status != B_OK) { + ERROR("Failed mounting the volume. Error: %s\n", strerror(status)); + delete volume; + _volume->private_volume = NULL; + return status; + } + +/* Don't have Inodes yet */ +#if 0 + *_rootID = volume->Root()->ID(); +#endif + + return B_OK; } static status_t xfs_unmount(fs_volume *_volume) { - return B_NOT_SUPPORTED; + Volume* volume = (Volume*) _volume->private_volume; + + status_t status = volume->Unmount(); + delete volume; + + TRACE("xfs_unmount(): Deleted volume"); + return status; } @@ -86,9 +114,10 @@ xfs_read_fs_info(fs_volume *_volume, struct fs_info *info) // #pragma mark - + static status_t xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, - uint32 *_flags, bool reenter) + uint32 *_flags, bool reenter) { return B_NOT_SUPPORTED; } @@ -110,7 +139,7 @@ xfs_can_page(fs_volume *_volume, fs_vnode *_node, void *_cookie) static status_t xfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie, - off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) + off_t pos, const iovec *vecs, size_t count, size_t *_numBytes) { return B_NOT_SUPPORTED; } @@ -118,7 +147,7 @@ xfs_read_pages(fs_volume *_volume, fs_vnode *_node, void *_cookie, static status_t xfs_io(fs_volume *_volume, fs_vnode *_node, void *_cookie, - io_request *request) + io_request *request) { return B_NOT_SUPPORTED; } @@ -126,7 +155,7 @@ xfs_io(fs_volume *_volume, fs_vnode *_node, void *_cookie, static status_t xfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset, - size_t size, struct file_io_vec *vecs, size_t *_count) + size_t size, struct file_io_vec *vecs, size_t *_count) { return B_NOT_SUPPORTED; } @@ -134,9 +163,10 @@ xfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset, // #pragma mark - + static status_t xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, - ino_t *_vnodeID) + ino_t *_vnodeID) { return B_NOT_SUPPORTED; } @@ -144,7 +174,7 @@ xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, static status_t xfs_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd, - void *buffer, size_t bufferLength) + void *buffer, size_t bufferLength) { return B_NOT_SUPPORTED; } @@ -159,7 +189,7 @@ xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) static status_t xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode, - void **_cookie) + void **_cookie) { return B_NOT_SUPPORTED; } @@ -167,7 +197,7 @@ xfs_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode, static status_t xfs_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, - void *buffer, size_t *_length) + void *buffer, size_t *_length) { return B_NOT_SUPPORTED; } @@ -186,6 +216,7 @@ xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) return B_NOT_SUPPORTED; } + static status_t xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode) { @@ -195,7 +226,7 @@ xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode) static status_t xfs_read_link(fs_volume *_volume, fs_vnode *_node, char *buffer, - size_t *_bufferSize) + size_t *_bufferSize) { return B_NOT_SUPPORTED; } @@ -210,9 +241,10 @@ xfs_unlink(fs_volume *_volume, fs_vnode *_directory, const char *name) // #pragma mark - Directory functions + static status_t xfs_create_dir(fs_volume *_volume, fs_vnode *_directory, const char *name, - int mode) + int mode) { return B_NOT_SUPPORTED; } @@ -234,7 +266,7 @@ xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie) static status_t xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, - struct dirent *dirent, size_t bufferSize, uint32 *_num) + struct dirent *dirent, size_t bufferSize, uint32 *_num) { return B_NOT_SUPPORTED; } @@ -249,7 +281,7 @@ xfs_rewind_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, void *_cookie) static status_t xfs_close_dir(fs_volume * /*_volume*/, fs_vnode * /*node*/, - void * /*_cookie*/) + void * /*_cookie*/) { return B_NOT_SUPPORTED; } @@ -285,7 +317,7 @@ xfs_free_attr_dir_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) static status_t xfs_read_attr_dir(fs_volume *_volume, fs_vnode *_node, - void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) + void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { return B_NOT_SUPPORTED; } @@ -301,7 +333,7 @@ xfs_rewind_attr_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie) /* attribute operations */ static status_t xfs_create_attr(fs_volume *_volume, fs_vnode *_node, - const char *name, uint32 type, int openMode, void **_cookie) + const char *name, uint32 type, int openMode, void **_cookie) { return B_NOT_SUPPORTED; } @@ -309,7 +341,7 @@ xfs_create_attr(fs_volume *_volume, fs_vnode *_node, static status_t xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name, - int openMode, void **_cookie) + int openMode, void **_cookie) { return B_NOT_SUPPORTED; } @@ -317,15 +349,14 @@ xfs_open_attr(fs_volume *_volume, fs_vnode *_node, const char *name, static status_t xfs_close_attr(fs_volume *_volume, fs_vnode *_node, - void *cookie) + void *cookie) { return B_NOT_SUPPORTED; } static status_t -xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, - void *cookie) +xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, void *cookie) { return B_NOT_SUPPORTED; } @@ -333,7 +364,7 @@ xfs_free_attr_cookie(fs_volume *_volume, fs_vnode *_node, static status_t xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie, - off_t pos, void *buffer, size_t *_length) + off_t pos, void *buffer, size_t *_length) { return B_NOT_SUPPORTED; } @@ -341,7 +372,7 @@ xfs_read_attr(fs_volume *_volume, fs_vnode *_node, void *_cookie, static status_t xfs_write_attr(fs_volume *_volume, fs_vnode *_node, void *cookie, - off_t pos, const void *buffer, size_t *length) + off_t pos, const void *buffer, size_t *length) { return B_NOT_SUPPORTED; } @@ -349,7 +380,7 @@ xfs_write_attr(fs_volume *_volume, fs_vnode *_node, void *cookie, static status_t xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node, - void *_cookie, struct stat *stat) + void *_cookie, struct stat *stat) { return B_NOT_SUPPORTED; } @@ -357,7 +388,7 @@ xfs_read_attr_stat(fs_volume *_volume, fs_vnode *_node, static status_t xfs_write_attr_stat(fs_volume *_volume, fs_vnode *_node, - void *cookie, const struct stat *stat, int statMask) + void *cookie, const struct stat *stat, int statMask) { return B_NOT_SUPPORTED; } @@ -365,7 +396,7 @@ xfs_write_attr_stat(fs_volume *_volume, fs_vnode *_node, static status_t xfs_rename_attr(fs_volume *_volume, fs_vnode *fromVnode, - const char *fromName, fs_vnode *toVnode, const char *toName) + const char *fromName, fs_vnode *toVnode, const char *toName) { return B_NOT_SUPPORTED; } @@ -373,7 +404,7 @@ xfs_rename_attr(fs_volume *_volume, fs_vnode *fromVnode, static status_t xfs_remove_attr(fs_volume *_volume, fs_vnode *vnode, - const char *name) + const char *name) { return B_NOT_SUPPORTED; } @@ -388,7 +419,7 @@ xfs_get_supported_operations(partition_data *partition, uint32 mask) static status_t xfs_initialize(int fd, partition_id partitionID, const char *name, - const char *parameterString, off_t partitionSize, disk_job_id job) + const char *parameterString, off_t partitionSize, disk_job_id job) { return B_NOT_SUPPORTED; } @@ -396,7 +427,7 @@ xfs_initialize(int fd, partition_id partitionID, const char *name, static status_t xfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize, - uint32 blockSize, disk_job_id job) + uint32 blockSize, disk_job_id job) { return B_NOT_SUPPORTED; } @@ -404,6 +435,7 @@ xfs_uninitialize(int fd, partition_id partitionID, off_t partitionSize, // #pragma mark - + static status_t xfs_std_ops(int32 op, ...) { @@ -427,57 +459,59 @@ xfs_std_ops(int32 op, ...) } } + fs_volume_ops gxfsVolumeOps = { &xfs_unmount, &xfs_read_fs_info, - NULL, // write_fs_info() - NULL, // fs_sync, + NULL, // write_fs_info() + NULL, // fs_sync, &xfs_get_vnode, }; + fs_vnode_ops gxfsVnodeOps = { /* vnode operations */ &xfs_lookup, - NULL, // xfs_get_vnode_name - optional, and we can't do better than the - // fallback implementation, so leave as NULL. + NULL, // xfs_get_vnode_name- optional, and we can't do better + // than the fallback implementation, so leave as NULL. &xfs_put_vnode, - NULL, // xfs_remove_vnode, + NULL, // xfs_remove_vnode, /* VM file access */ &xfs_can_page, &xfs_read_pages, - NULL, // xfs_write_pages, + NULL, // xfs_write_pages, - &xfs_io, // io() - NULL, // cancel_io() + &xfs_io, // io() + NULL, // cancel_io() &xfs_get_file_map, &xfs_ioctl, NULL, - NULL, // fs_select - NULL, // fs_deselect - NULL, // fs_fsync, + NULL, // fs_select + NULL, // fs_deselect + NULL, // fs_fsync, &xfs_read_link, - NULL, // fs_create_symlink, + NULL, // fs_create_symlink, - NULL, // fs_link, + NULL, // fs_link, &xfs_unlink, - NULL, // fs_rename, + NULL, // fs_rename, &xfs_access, &xfs_read_stat, - NULL, // fs_write_stat, - NULL, // fs_preallocate + NULL, // fs_write_stat, + NULL, // fs_preallocate /* file operations */ - NULL, // fs_create, + NULL, // fs_create, &xfs_open, &xfs_close, &xfs_free_cookie, &xfs_read, - NULL, // fs_write, + NULL, // fs_write, /* directory operations */ &xfs_create_dir, @@ -509,18 +543,19 @@ fs_vnode_ops gxfsVnodeOps = { }; -static file_system_module_info sxfsFileSystem = { +static +file_system_module_info sxfsFileSystem = { { "file_systems/xfs" B_CURRENT_FS_API_VERSION, 0, xfs_std_ops, }, - "xfs", // short_name - "XFS File System", // pretty_name + "xfs", // short_name + "XFS File System", // pretty_name // DDM flags - 0| B_DISK_SYSTEM_SUPPORTS_INITIALIZING |B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME + 0 |B_DISK_SYSTEM_SUPPORTS_INITIALIZING |B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME // | B_DISK_SYSTEM_SUPPORTS_WRITING , @@ -528,29 +563,29 @@ static file_system_module_info sxfsFileSystem = { xfs_identify_partition, xfs_scan_partition, xfs_free_identify_partition_cookie, - NULL, // free_partition_content_cookie() + NULL, // free_partition_content_cookie() &xfs_mount, /* capability querying operations */ &xfs_get_supported_operations, - NULL, // validate_resize - NULL, // validate_move - NULL, // validate_set_content_name - NULL, // validate_set_content_parameters - NULL, // validate_initialize, + NULL, // validate_resize + NULL, // validate_move + NULL, // validate_set_content_name + NULL, // validate_set_content_parameters + NULL, // validate_initialize, /* shadow partition modification */ - NULL, // shadow_changed + NULL, // shadow_changed /* writing */ - NULL, // defragment - NULL, // repair - NULL, // resize - NULL, // move - NULL, // set_content_name - NULL, // set_content_parameters + NULL, // defragment + NULL, // repair + NULL, // resize + NULL, // move + NULL, // set_content_name + NULL, // set_content_parameters xfs_initialize, xfs_uninitialize}; diff --git a/src/add-ons/kernel/file_systems/xfs/system_dependencies.h b/src/add-ons/kernel/file_systems/xfs/system_dependencies.h index cb49f9f164..a42dc02a51 100644 --- a/src/add-ons/kernel/file_systems/xfs/system_dependencies.h +++ b/src/add-ons/kernel/file_systems/xfs/system_dependencies.h @@ -1,29 +1,30 @@ /* - * Copyright 2020 Shubham Bhagat, shubhambhagat111@yahoo.com + * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com * All rights reserved. Distributed under the terms of the MIT License. */ -#ifndef _SYSTE_DEPENDENCIES_H -#define _SYSTEM_DEPENDENCIES_H +#ifndef _SYSTEM_DEPENDENCIES_H_ +#define _SYSTEM_DEPENDENCIES_H_ #ifdef FS_SHELL // This needs to be included before the fs_shell wrapper #include "fssh_api_wrapper.h" #include "fssh_auto_deleter.h" -#include +#include "Debug.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef unsigned char uuid_t[16]; + typedef unsigned char uuid_t[16]; -void uuid_generate(uuid_t out); + void uuid_generate(uuid_t out); #ifdef __cplusplus } #endif - #else // !FS_SHELL #include @@ -44,6 +45,7 @@ void uuid_generate(uuid_t out); #include #include #include +#include "Debug.h" #include #include #include diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.cpp b/src/add-ons/kernel/file_systems/xfs/xfs.cpp new file mode 100644 index 0000000000..616290c070 --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp @@ -0,0 +1,73 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "xfs.h" + + +bool +XfsSuperBlock::IsValid() +{ + if (sb_magicnum != XFS_SB_MAGIC) return false; + + return true; +} + + +uint32 +XfsSuperBlock::BlockSize() +{ + return sb_blocksize; +} + + +uint32 +XfsSuperBlock::Size() +{ + return XFS_SB_MAXSIZE; +} + + +char* +XfsSuperBlock::Name() +{ + return sb_fname; +} + + +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); +} diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h b/src/add-ons/kernel/file_systems/xfs/xfs.h new file mode 100644 index 0000000000..a1d6e6fabc --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/xfs.h @@ -0,0 +1,129 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef _XFS_SB_H_ +#define _XFS_SB_H_ + +#include "system_dependencies.h" +#include "xfs_types.h" + +#define XFS_SB_MAGIC 0x58465342 /* Identifies XFS. "XFSB" */ +#define XFS_SB_MAXSIZE 512 + + + +/* Version 4 superblock definition */ +class XfsSuperBlock +{ +public: + + bool IsValid(); + char* Name(); + uint32 BlockSize(); + uint32 Size(); + void SwapEndian(); + +private: + + uint32 sb_magicnum; + uint32 sb_blocksize; + xfs_rfsblock_t sb_dblocks; + xfs_rfsblock_t sb_rblocks; + xfs_rtblock_t sb_rextents; + uuid_t sb_uuid; + xfs_fsblock_t sb_logstart; + xfs_ino_t sb_rootino; + xfs_ino_t sb_rbmino; + xfs_ino_t sb_rsumino; + xfs_agblock_t sb_rextsize; + xfs_agblock_t sb_agblocks; + xfs_agnumber_t sb_agcount; + xfs_extlen_t sb_rbmblocks; + xfs_extlen_t sb_logblocks; + uint16 sb_versionnum; + uint16 sb_sectsize; + uint16 sb_inodesize; + uint16 sb_inopblock; + char sb_fname[12]; + uint8 sb_blocklog; + uint8 sb_sectlog; + uint8 sb_inodelog; + uint8 sb_inopblog; + uint8 sb_agblklog; + uint8 sb_rextslog; + uint8 sb_inprogress; + uint8 sb_imax_pct; + uint64 sb_icount; + uint64 sb_ifree; + uint64 sb_fdblocks; + uint64 sb_frextents; + xfs_ino_t sb_uquotino; + xfs_ino_t sb_gquotino; + uint16 sb_qflags; + uint8 sb_flags; + uint8 sb_shared_vn; + xfs_extlen_t sb_inoalignmt; + uint32 sb_unit; + uint32 sb_width; + uint8 sb_dirblklog; + uint8 sb_logsectlog; + uint16 sb_logsectsize; + uint32 sb_logsunit; + uint32 sb_features2; +}; + +/* + These flags indicate features introduced over time. + + If the lower nibble of sb_versionnum >=4 then the following features are + checked. If it's equal to 5, it's version 5. +*/ + +#define XFS_SB_VERSION_ATTRBIT 0x0010 +#define XFS_SB_VERSION_NLINKBIT 0x0020 +#define XFS_SB_VERSION_QUOTABIT 0x0040 +#define XFS_SB_VERSION_ALIGNBIT 0x0080 +#define XFS_SB_VERSION_DALIGNBIT 0x0100 +#define XFS_SB_VERSION_SHAREDBIT 0x0200 +#define XFS_SB_VERSION_LOGV2BIT 0x0400 +#define XFS_SB_VERSION_SECTORBIT 0x0800 +#define XFS_SB_VERSION_EXTFLGBIT 0x1000 +#define XFS_SB_VERSION_DIRV2BIT 0x2000 +#define XFS_SB_VERSION_MOREBITSBIT 0x4000 + +/* +Superblock quota flags - sb_qflags +*/ +#define XFS_UQUOTA_ACCT 0x0001 +#define XFS_UQUOTA_ENFD 0x0002 +#define XFS_UQUOTA_CHKD 0x0004 +#define XFS_PQUOTA_ACCT 0x0008 +#define XFS_OQUOTA_ENFD 0x0010 +#define XFS_OQUOTA_CHKD 0x0020 +#define XFS_GQUOTA_ACCT 0x0040 +#define XFS_GQUOTA_ENFD 0x0080 +#define XFS_GQUOTA_CHKD 0x0100 +#define XFS_PQUOTA_ENFD 0x0200 +#define XFS_PQUOTA_CHKD 0x0400 + +/* + Superblock flags - sb_flags +*/ +#define XFS_SBF_READONLY 0x1 + +/* + Extended v4 Superblock flags - sb_features2 +*/ + +#define XFS_SB_VERSION2_LAZYSBCOUNTBIT \ + 0x0001 /*update global free space \ + and inode on clean unmount*/ +#define XFS_SB_VERSION2_ATTR2BIT \ + 0x0002 /* 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 +#endif \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/xfs/xfs_types.h b/src/add-ons/kernel/file_systems/xfs/xfs_types.h new file mode 100644 index 0000000000..a2940bfcfc --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/xfs_types.h @@ -0,0 +1,41 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * Distributed under the terms of the MIT License. + */ +#ifndef _XFS_TYPES_H_ +#define _XFS_TYPES_H_ + +#include "system_dependencies.h" + +/* +Reference documentation: +https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs +/xfs_filesystem_structure.pdf + +Chapter 5: Common XFS types (Page 8) +*/ + + +typedef uint64 xfs_ino_t; // absolute inode number +typedef int64 xfs_off_t; // file offset +typedef int64 xfs_daddr_t; // device address +typedef uint32 xfs_agnumber_t; // Allocation Group (AG) number +typedef uint32 xfs_agblock_t; // AG relative block number +typedef uint32 xfs_extlen_t; // extent length in blocks +typedef int32 xfs_extnum_t; // number of extends in a file +typedef int16 xfs_aextnum_t; // number of extents in an attribute fork +typedef uint32 xfs_dablk_t; // block number for directories + // and extended attributes +typedef uint32 xfs_dahash_t; // hash of a directory file name + // or extended attribute name +typedef uint64 xfs_fsblock_t; // filesystem block number combining AG number + // and block offset into the AG +typedef uint64 xfs_rfsblock_t; // raw filesystem block number +typedef uint64 xfs_rtblock_t; // extent number in the real-time sub-volume +typedef uint64 xfs_filoff_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 unsigned char uuid_t[16]; + +#endif \ No newline at end of file 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 cefcc77947..93db59e162 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 @@ -38,15 +38,17 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ; UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ; local xfsSource = + xfs.cpp + Volume.cpp kernel_interface.cpp ; -BuildPlatformMergeObject xfs.o : $(xfsSource) ; +BuildPlatformMergeObject xfs_shell.o : $(xfsSource) ; BuildPlatformMain xfs_shell : : - xfs.o + xfs_shell.o fs_shell.a $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) $(HOST_LIBROOT) $(fsShellCommandLibs) ; @@ -54,7 +56,7 @@ BuildPlatformMain xfs_shell BuildPlatformMain xfs_fuse : : - xfs.o + xfs_shell.o fuse_module.a $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) $(HOST_STATIC_LIBROOT) $(fsShellCommandLibs) fuse