From a7725a42a965fd7906b313fbb7efdd0686e692e6 Mon Sep 17 00:00:00 2001 From: SuhelMehta9 Date: Fri, 20 Mar 2020 23:58:28 +0530 Subject: [PATCH] ufs2: Add superblock, volume, identify() and mount() Change-Id: I27a492145fe1a365ceea6d172e332167513f5c3b Reviewed-on: https://review.haiku-os.org/c/haiku/+/2381 Reviewed-by: Adrien Destugues --- src/add-ons/kernel/file_systems/ufs2/Jamfile | 1 + .../kernel/file_systems/ufs2/Volume.cpp | 67 ++++++++++ src/add-ons/kernel/file_systems/ufs2/Volume.h | 33 +++++ .../file_systems/ufs2/kernel_interface.cpp | 17 ++- src/add-ons/kernel/file_systems/ufs2/ufs2.h | 117 ++++++++++++++++++ .../file_systems/ufs2/ufs2_shell/Jamfile | 1 + 6 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/ufs2/Volume.cpp create mode 100644 src/add-ons/kernel/file_systems/ufs2/Volume.h create mode 100644 src/add-ons/kernel/file_systems/ufs2/ufs2.h diff --git a/src/add-ons/kernel/file_systems/ufs2/Jamfile b/src/add-ons/kernel/file_systems/ufs2/Jamfile index 34791f4261..2724386e72 100644 --- a/src/add-ons/kernel/file_systems/ufs2/Jamfile +++ b/src/add-ons/kernel/file_systems/ufs2/Jamfile @@ -18,6 +18,7 @@ UsePrivateKernelHeaders ; DEFINES += DEBUG_APP="\\\"ufs2\\\"" ; local ufs2Sources = + Volume.cpp kernel_cpp.cpp kernel_interface.cpp ; diff --git a/src/add-ons/kernel/file_systems/ufs2/Volume.cpp b/src/add-ons/kernel/file_systems/ufs2/Volume.cpp new file mode 100644 index 0000000000..bf63bf8901 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ufs2/Volume.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#include "Volume.h" + +//#define TRACE_UFS2 +#ifdef TRACE_UFS2 +# define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) +#else +# define TRACE(x...) ; +#endif +# define ERROR(x...) dprintf("\33[34mexfat:\33[0m " x) + +class DeviceOpner { + public: + DeviceOpner(int fd, int mode); + DeviceOpner(const char* device, int mode); + ~DeviceOpner(); + + 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; +}; + +bool +ufs2_super_block::IsValid() +{ + if (ufs2_magic != UFS2_SUPER_BLOCK_MAGIC) + return false; + + return true; +} + +status_t +Volume::Identify(int fd, ufs2_super_block *superBlock) +{ + if (read_pos(fd, UFS2_SUPER_BLOCK_OFFSET, superBlock, + sizeof(ufs2_super_block)) != sizeof(ufs2_super_block)) + return B_IO_ERROR; + + if (!superBlock->IsValid()) { + ERROR("invalid superblock! Identify failed!!\n"); + return B_BAD_VALUE; + } + + return B_OK; +} diff --git a/src/add-ons/kernel/file_systems/ufs2/Volume.h b/src/add-ons/kernel/file_systems/ufs2/Volume.h new file mode 100644 index 0000000000..ab35fb8150 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ufs2/Volume.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef VOLUME_H +#define VOLUME_H + +#include "ufs2.h" + +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* name, + uint32 blockSize, uint32 flags); + + bool IsValidSuperBlock(); + bool IsValidInodeBlock(off_t block) const; + bool IsReadOnly() const; + fs_volume* FSVolume() const { return fFSVolume; } + ufs2_super_block& SuperBlock() { return fSuperBlock; } + status_t LoadSuperBlock(); + static status_t Identify(int fd, ufs2_super_block* superBlock); + + private: + fs_volume* fFSVolume; + ufs2_super_block fSuperBlock; +}; + +#endif // VOLUME_H diff --git a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp index e53d93d826..5e0adc1df6 100644 --- a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp @@ -3,6 +3,8 @@ * All rights reserved. Distributed under the terms of the MIT License. */ #include "system_dependencies.h" +#include "ufs2.h" +#include "Volume.h" #ifdef TRACE_ufs2 #define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) @@ -13,9 +15,7 @@ struct identify_cookie { - /* super_block_struct super_block; - * No structure yet implemented. - */ + ufs2_super_block super_block; int cookie; }; @@ -42,7 +42,16 @@ iterative_io_finished_hook(void *cookie, io_request *request, status_t status, static float ufs2_identify_partition(int fd, partition_data *partition, void **_cookie) { - return B_NOT_SUPPORTED; + ufs2_super_block superBlock; + status_t status = Volume::Identify(fd, &superBlock); + if (status != B_OK) + return -1; + + identify_cookie* cookie = new identify_cookie; + memcpy(&cookie->super_block, &superBlock, sizeof(ufs2_super_block)); + *_cookie = cookie; + + return 0.8f; } diff --git a/src/add-ons/kernel/file_systems/ufs2/ufs2.h b/src/add-ons/kernel/file_systems/ufs2/ufs2.h new file mode 100644 index 0000000000..142f98d851 --- /dev/null +++ b/src/add-ons/kernel/file_systems/ufs2/ufs2.h @@ -0,0 +1,117 @@ +/* + * Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef UFS2_H +#define UFS2_H + +#include "system_dependencies.h" + +#define UFS2_SUPER_BLOCK_MAGIC 0x19540119 +#define UFS2_SUPER_BLOCK_OFFSET 65536 +#define MAXMNTLEN 512 +#define MAXCSBUFS 32 + +struct ufs2_super_block { + uint32 ufs2_link; /* linked list of file systems */ + uint32 ufs2_rolled; /* logging only: fs fully rolled */ + uint32 ufs2_sblkno; /* addr of super-block in filesys */ + uint32 ufs2_cblkno; /* offset of cyl-block in filesys */ + uint32 ufs2_iblkno; /* offset of inode-blocks in filesys */ + uint32 ufs2_dblkno; /* offset of first data after cg */ + uint32 ufs2_cgoffset; /* cylinder group offset in cylinder */ + uint32 ufs2_cgmask; /* used to calc mod ufs2_ntrak */ + uint64 ufs2_time; /* last time written */ + uint64 ufs2_size; /* number of blocks in fs */ + uint64 ufs2_dsize; /* number of data blocks in fs */ + uint32 ufs2_ncg; /* number of cylinder groups */ + uint32 ufs2_bsize; /* size of basic blocks in fs */ + uint32 ufs2_fsize; /* size of frag blocks in fs */ + uint32 ufs2_frag; /* number of frags in a block in fs */ + uint32 ufs2_minfree; /* minimum percentage of free blocks */ + uint32 ufs2_rotdelay; /* num of ms for optimal next block */ + uint32 ufs2_rps; /* disk revolutions per second */ + /* these fields can be computed from the others */ + uint32 ufs2_bmask; /* ``blkoff'' calc of blk offsets */ + uint32 ufs2_fmask; /* ``fragoff'' calc of frag offsets */ + uint32 ufs2_bshift; /* ``lblkno'' calc of logical blkno */ + uint32 ufs2_fshift; /* ``numfrags'' calc number of frags */ + /* these are configuration parameters */ + uint32 ufs2_maxcontig; /* max number of contiguous blks */ + uint32 ufs2_maxbpg; /* max number of blks per cyl group */ + /* these fields can be computed from the others */ + uint32 ufs2_fragshift; /* block to frag shift */ + uint32 ufs2_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + uint32 ufs2_sbsize; /* actual size of super block */ + uint32 ufs2_csmask; /* csum block offset */ + uint32 ufs2_csshift; /* csum block number */ + uint32 ufs2_nindir; /* value of NINDIR */ + uint32 ufs2_inopb; /* value of INOPB */ + uint32 ufs2_nspf; /* value of NSPF */ + /* yet another configuration parameter */ + uint32 ufs2_optim; /* optimization preference, see below */ + /* these fields are derived from the hardware */ + /* USL SVR4 compatibility */ +#ifdef _LITTLE_ENDIAN + /* + * * USL SVR4 compatibility + */ + uint32 ufs2_state; /* file system state time stamp */ +#else + uint32 ufs2_npsect; /* # sectors/track including spares */ +#endif + uint32 ufs2_si; /* summary info state - lufs only */ + uint32 ufs2_trackskew; /* sector 0 skew, per track */ + uint32 ufs2_id[2]; /* file system id */ + /* sizes determined by number of cylinder groups and their sizes */ + uint64 ufs2_csaddr; /* blk addr of cyl grp summary area */ + uint32 ufs2_cssize; /* size of cyl grp summary area */ + uint32 ufs2_cgsize; /* cylinder group size */ + /* these fields are derived from the hardware */ + uint32 ufs2_ntrak; /* tracks per cylinder */ + uint32 ufs2_nsect; /* sectors per track */ + uint32 ufs2_spc; /* sectors per cylinder */ + /* this comes from the disk driver partitioning */ + uint32 ufs2_ncyl; /* cylinders in file system */ + /* these fields can be computed from the others */ + uint32 ufs2_cpg; /* cylinders per group */ + uint32 ufs2_ipg; /* inodes per group */ + uint32 ufs2_fpg; /* blocks per group * ufs2_frag */ + /* these fields are cleared at mount time */ + uint32 ufs2_fmod; /* super block modified flag */ + uint32 ufs2_clean; /* file system state flag */ + uint32 ufs2_ronly; /* mounted read-only flag */ + uint32 ufs2_flags; /* largefiles flag, etc. */ + uint32 ufs2_fsmnt[MAXMNTLEN]; /* name mounted on */ + /* these fields retain the current block allocation info */ + uint32 ufs2_cgrotor; /* last cg searched */ + union { /* ufs2_cs (csum) info */ + uint32 ufs2_csp_pad[MAXCSBUFS]; + struct csum *ufs2_csp; + } ufs2_u; + uint32 ufs2_cpc; /* cyl per cycle in postbl */ + uint64 ufs2_opostbl[16][8]; /* old rotation block list head */ + uint32 ufs2_sparecon[51]; /* reserved for future constants */ + uint32 ufs2_version; /* minor version of ufs */ + uint32 ufs2_logbno; /* block # of embedded log */ + uint32 ufs2_reclaim; /* reclaim open, deleted files */ + uint32 ufs2_sparecon2; /* reserved for future constant */ +#ifdef _LITTLE_ENDIAN + /* USL SVR4 compatibility */ + uint32 ufs2_npsect; /* # sectors/track including spares */ +#else + uint32 ufs2_state; /* file system state time stamp */ +#endif + uint64 ufs2_qbmask; /* ~ufs2_bmask - for use with quad size */ + uint64 ufs2_qfmask; /* ~ufs2_fmask - for use with quad size */ + uint32 ufs2_postblformat; /* format of positional layout tables */ + uint32 ufs2_nrpos; /* number of rotaional positions */ + uint32 ufs2_postbloff; /* (short) rotation block list head */ + uint32 ufs2_rotbloff; /* (uchar_t) blocks for each rotation */ + uint32 ufs2_magic; /* magic number */ + uint32 ufs2_space[1]; /* list of blocks for each rotation */ + bool IsValid(); +}; + +#endif diff --git a/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile b/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile index fe7873bbf4..df68c9bb65 100644 --- a/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile @@ -38,6 +38,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ; UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ; local ufs2Source = + Volume.cpp kernel_interface.cpp ;