From ef6028c523d7e3d1768806a6d0e5cf468826111a Mon Sep 17 00:00:00 2001 From: 6902140 <3356142450@qq.com> Date: Sat, 27 May 2023 22:23:56 +0800 Subject: [PATCH] add fs and vfs --- include/constrains.h | 3 + include/fs/bio.h | 62 ++++++ include/fs/ext2/ext2_disk.h | 0 include/fs/ext2/ext2_file.h | 0 include/fs/ext2/ext2_mem.h | 0 include/fs/fat/fat32_disk.h | 414 +++++++++++++++++++++++++++++++++++ include/fs/fat/fat32_file.h | 49 +++++ include/fs/fat/fat32_mem.h | 181 +++++++++++++++ include/fs/fat/fat32_stack.h | 36 +++ include/fs/fcntl.h | 32 +++ include/fs/fdtable.h | 24 ++ include/fs/stat.h | 53 +++++ include/fs/vfs/fs.h | 155 +++++++++++++ include/fs/vfs/fs_macro.h | 7 + include/fs/vfs/ops.h | 13 ++ include/kernel/options.h | 28 +++ include/vfs/fs.h | 155 +++++++++++++ include/vfs/fs_macro.h | 7 + include/vfs/ops.h | 13 ++ kernel/pcb_life.c | 119 ++++++++++ 20 files changed, 1351 insertions(+) create mode 100644 include/fs/bio.h create mode 100644 include/fs/ext2/ext2_disk.h create mode 100644 include/fs/ext2/ext2_file.h create mode 100644 include/fs/ext2/ext2_mem.h create mode 100644 include/fs/fat/fat32_disk.h create mode 100644 include/fs/fat/fat32_file.h create mode 100644 include/fs/fat/fat32_mem.h create mode 100644 include/fs/fat/fat32_stack.h create mode 100644 include/fs/fcntl.h create mode 100644 include/fs/fdtable.h create mode 100644 include/fs/stat.h create mode 100644 include/fs/vfs/fs.h create mode 100644 include/fs/vfs/fs_macro.h create mode 100644 include/fs/vfs/ops.h create mode 100644 include/kernel/options.h create mode 100644 include/vfs/fs.h create mode 100644 include/vfs/fs_macro.h create mode 100644 include/vfs/ops.h diff --git a/include/constrains.h b/include/constrains.h index 9b8ca5c..9654943 100644 --- a/include/constrains.h +++ b/include/constrains.h @@ -88,4 +88,7 @@ #define NOFILE 128 // open files per process + + +#define NFILE 100 // open files per system #endif \ No newline at end of file diff --git a/include/fs/bio.h b/include/fs/bio.h new file mode 100644 index 0000000..dbcceaa --- /dev/null +++ b/include/fs/bio.h @@ -0,0 +1,62 @@ +#ifndef __BIO_H__ +#define __BIO_H__ + +#include "common.h" +#include "list.h" +#include "atomic/atomic.h" +#include "atomic/semaphore.h" +#include "fs/vfs/fs_macro.h" + +enum bh_state_bits { + BH_Uptodate, /* Contains valid data */ + BH_Dirty, /* Is dirty */ + BH_Lock, /* Is locked */ + BH_Req, /* Has been submitted for I/O */ +}; + +struct buffer_head { + struct semaphore sem_lock; + struct semaphore sem_disk_done; + uint64 b_state; // buffer state + int valid; // has data been read from disk? + int disk; // does disk "own" buf? + uint dev; + uint blockno; + atomic_t refcnt; + // struct buffer_head *prev; // LRU cache list + // struct buffer_head *next; + list_head_t lru; + uchar data[BSIZE]; + int dirty; // dirty +}; + +struct bio_vec { + // <page,offset,len> + struct page *bv_page; + uint bv_len; + uint bv_offset; +}; + +struct bio { + atomic_t bi_cnt; // ref + ushort bi_idx; // current idx + struct bio_vec *bi_io_vec; // bio vecs list + uint64 bi_rw; // read or write + uint bi_bdev; // device no + ushort bi_vcnt; // total number +}; + +// bio.c +void binit(void); +struct buffer_head *bread(uint, uint); +void brelse(struct buffer_head *); +void bwrite(struct buffer_head *); +int bpin(struct buffer_head *); +int bunpin(struct buffer_head *); + +int init_bio(void); +int submit_bio(int, struct bio *); +int free_bio(struct bio *); + +void fat32_bzero(int, int); +#endif // __BIO_H__ \ No newline at end of file diff --git a/include/fs/ext2/ext2_disk.h b/include/fs/ext2/ext2_disk.h new file mode 100644 index 0000000..e69de29 diff --git a/include/fs/ext2/ext2_file.h b/include/fs/ext2/ext2_file.h new file mode 100644 index 0000000..e69de29 diff --git a/include/fs/ext2/ext2_mem.h b/include/fs/ext2/ext2_mem.h new file mode 100644 index 0000000..e69de29 diff --git a/include/fs/fat/fat32_disk.h b/include/fs/fat/fat32_disk.h new file mode 100644 index 0000000..1f3481e --- /dev/null +++ b/include/fs/fat/fat32_disk.h @@ -0,0 +1,414 @@ +#ifndef __FAT32_DISK_H__ +#define __FAT32_DISK_H__ + +#include "common.h" + +/* + FAT32 + +---------------------------+ + | 0: Boot Sector | + +---------------------------+ + | 1: FsInfo | + +---------------------------+ + | 6: Backup BPB Structure | + +---------------------------+ + | 7: Backup FsInfo Structure| + +---------------------------+ + | FAT Region (FAT1) | + +---------------------------+ + | FAT Region (FAT2) | + +---------------------------+ + | Data Region (Cluster 2)| + +---------------------------+ + | Data Region (Cluster 3)| + +---------------------------+ + | ... | + +---------------------------+ + | Data Region (Cluster n)| + +---------------------------+ +*/ +// /*BPB (BIOS Parameter Block)*/ +// #define BS_JmpBoot 0 /* jump instruction (3-byte) */ +// #define BS_OEMName 3 /* OEM name (8-byte) */ +// #define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +// #define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +// #define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +// #define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +// #define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ +// #define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +// #define BPB_Media 21 /* Media descriptor byte (BYTE) */ +// #define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +// #define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ +// #define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +// #define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +// #define BPB_TotSec 32 /* Volume size (32-bit) [sector] (DWORD) */ + +// /*Extended Boot Record*/ +// #define BPB_FATSz 36 /* FAT32: FAT size [sector] (DWORD) */ +// #define BPB_ExtFlags 40 /* FAT32: Extended flags (WORD) */ +// #define BPB_FSVer 42 /* FAT32: Filesystem version (WORD) */ +// #define BPB_RootClus 44 /* FAT32: Root directory cluster (DWORD) */ +// #define BPB_FSInfo 48 /* FAT32: Offset of FSINFO sector (WORD) */ +// #define BPB_BkBootSec 50 /* FAT32: Offset of backup boot sector (WORD) */ +// #define BPB_Reserved 52 /* FAT32: Reserved. Must be set to 0x0.*/ + +// #define BS_DrvNum 64 /* FAT32: Physical drive number for int13h (BYTE) */ +// #define BS_NTres 65 /* FAT32: Error flag (BYTE) */ +// #define BS_BootSig 66 /* FAT32: Extended boot signature (BYTE) */ +// #define BS_VolID 67 /* FAT32: Volume serial number (DWORD) */ +// #define BS_VolLab 71 /* FAT32: Volume label string (8-byte) */ +// #define BS_FilSysType 82 /* FAT32: Filesystem type string (8-byte) */ +// #define BS_BootCode 90 /* FAT32: Boot code (420-byte) */ +// #define BS_BootSign 510 /* Signature word (WORD) */ + +// /*FSInfo Structure (FAT32 only)*/ +// #define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +// #define FSI_Reserved1 4 /* FAT32 FSI: Reserved1. This field should be always initialized to zero.*/ +// #define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +// #define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +// #define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ +// #define FSI_Reserved2 496 /* FAT32 FSI: Reserved. This field should be always initialized to zero.*/ +// #define FSI_TrailSig 512 /* FAT32 FSI: */ +// /*reserved, may be used in the future*/ +// #define ClnShutBitMask 0x08000000 +// // If bit is 1, volume is "clean".If bit is 0, volume is "dirty". +// #define HrdErrBitMask 0x04000000 +// // If this bit is 1, no disk read/write errors were encountered. +// // If this bit is 0, the file system driver encountered a disk I/O error on theVolume the last time it was mounted, +// // which is an indicator that some sectorsmay have gone bad on the volume. +// #define NAME0_NOT_VALID(x) (x == 0x20) +// #define NAME_CHAR_NOT_VALID(x) ((x < 0x20 && x != 0x05) || (x == 0x22) || (x >= 0x2A && x <= 0x2C) || (x >= 0x2E && x <= 0x2F) || (x >= 0x3A || x <= 0x3F) || (x >= 0x5B && x <= 0x5D) || (x == 0x7C)) +// // " * + , . / : ; < = > ? [ \ ] | +// #define FCB_NUM(x) (sizeof(x) / sizeof(dirent_s_t)) +extern struct _superblock fat32_sb; + +// the sector of bpb and fsinfo +#define SECTOR_BPB 0 +#define SECTOR_FSINFO 1 +#define SECTOR_BPB_BACKUP 6 +#define SECTOR_FSINFO_BACKUP 7 + +// some useful field of fat32 super block +#define __BPB_RootEntCnt 0 +#define __BPB_BytsPerSec (fat32_sb.sector_size) +#define __TotSec (fat32_sb.n_sectors) +#define __BPB_ResvdSecCnt (fat32_sb.fat32_sb_info.fatbase) +#define __BPB_NumFATs (fat32_sb.fat32_sb_info.n_fats) +#define __FATSz (fat32_sb.fat32_sb_info.n_sectors_fat) +#define __BPB_SecPerClus (fat32_sb.sectors_per_block) +#define __Free_Count (fat32_sb.fat32_sb_info.free_count) +#define __Nxt_Free (fat32_sb.fat32_sb_info.nxt_free) +#define __CLUSTER_SIZE (fat32_sb.cluster_size) +#define FAT_BASE __BPB_ResvdSecCnt + +#define FAT_SFN_LENGTH 11 // çŸæ–‡ä»¶å长度 +#define FAT_LFN_LENGTH 13 // 长文件å长度 + +/* some useful macro from manual */ +// 1. number of root directory sectors (not important in fat32 file system) +// (0*32+512-1)/512 FAT32 没有Root Directory 的概念,所以一直是0 +#define RootDirSectors (((__BPB_RootEntCnt * 32) + (__BPB_BytsPerSec - 1)) / __BPB_BytsPerSec) + +// 2. the first data sector num(sector number index from 0) +// å‡è®¾ä¸€ä¸ªFAT32区域å 2017个扇区: 32 + (2 * 2017) + 0 +#define FirstDataSector ((__BPB_ResvdSecCnt) + ((__BPB_NumFATs) * (__FATSz)) + (RootDirSectors)) + +// 3. the first sector number of cluster N +// å‡è®¾ä¸€ä¸ªç°‡ä¸¤ä¸ªæ‰‡åŒº,ä¿ç•™åŒºæœ‰32个扇区,一个fat区域å 2017个扇区,有两个fat区域:(N-2)*2+32+(2*2017)+0 +#define FirstSectorofCluster(N) (((N)-2) * (__BPB_SecPerClus) + (FirstDataSector)) + +// 4. the number of sectors in data region +// 就是用总的数é‡å‡åŽ»ä¿ç•™æ‰‡åŒºï¼Œç„¶åŽå‡åŽ»FAT的扇区 +// remeber, RootDirSectors is always 0 +#define DataSec ((__TotSec) - ((__BPB_ResvdSecCnt) + ((__BPB_NumFATs) * (__FATSz)) + (RootDirSectors))) + +// 5. the count of clusters in data region +// remeber, cluster 0 and cluster 1 can not used!!! +#define CountofClusters ((DataSec) / (__BPB_SecPerClus)) + +// 6. the maxium of FAT entry +// 最åŽä¸€ä¸ªç°‡ +#define FAT_CLUSTER_MAX ((CountofClusters) + 1) + +// 7. æ¯ä¸ªBLOCKæ¯ä¸ªFCBçš„æ•°é‡ +#define FCB_PER_BLOCK ((__BPB_BytsPerSec) / sizeof(dirent_s_t)) + +// 8. bytes of (FAT32 entry) +#define FATOffset(N) ((N)*4) + +// 9. the sector number of fat entry +// ä¿ç•™åŒºåŸŸçš„æ‰‡åŒºä¸ªæ•°+一个扇区对应4å—节的FAT表项的åç§»/一个扇区多少个å—节,就å¯ä»¥ç®—出这个FAT表项在那个扇区 +#define ThisFATEntSecNum(N) ((__BPB_ResvdSecCnt) + ((FATOffset(N)) / (__BPB_BytsPerSec))) + +// 10. the offset of an entry within a sector +// 算出FAT表项在对应扇区的具体多少å移的ä½ç½® +#define ThisFATEntOffset(N) ((FATOffset(N)) % (__BPB_BytsPerSec)) + +// remember ,the valid number of bits of the FAT32 entry is 28 +#define FAT_VALID_MASK 0x0FFFFFFF + +// 11. read the FAT32 cluster entry value +// 读FAT32 çš„entry +#define FAT32ClusEntryVal(SectorBuf, N) ((*((DWORD *)&((char *)SectorBuf)[(ThisFATEntOffset(N))])) & FAT_VALID_MASK) + +// 12. set the FAT32 cluster entry value +// 写FAT32 çš„entry +#define SetFAT32ClusEntryVal(SecBuff, N, Val) \ + do { \ + int fat_entry_val = Val & FAT_VALID_MASK; \ + *((DWORD *)&SecBuff[ThisFATEntOffset(N)]) = (*((DWORD *)&SecBuff[ThisFATEntOffset(N)])) & 0xF0000000; \ + *((DWORD *)&SecBuff[ThisFATEntOffset(N)]) = (*((DWORD *)&SecBuff[ThisFATEntOffset(N)])) | fat_entry_val; \ + } while (0); + +// FAT[0] and FAT[1] is reserved !!! +// FAT[0]: 0FFF FFF8 +// FAT[1]: 0FFF FFFF + +/*some useful macro for fat chain travel*/ +// 1. reach the end of fat32 chain? +#define ISEOF(FATContent) ((FATContent) >= 0x0FFFFFF8) + +// 2. EOC and FREE +#define EOC 0xFFFFFFFF +#define FREE_MASK 0x00000000 + +// 3. NAME0 flag +#define NAME0_FREE_ONLY(x) (x == 0xE5) +#define NAME0_FREE_ALL(x) (x == 0x00) +#define NAME0_FREE_BOOL(x) (NAME0_FREE_ONLY(x) || NAME0_FREE_ALL(x)) +#define NAME0_SPECIAL(x) (x == 0x05) // 0xE5伪装->0x05 + +/* File attribute bits for directory entry*/ +// 1. some attrs definition +#define ATTR_READ_ONLY 0x01 // Read only 0000_0001 +#define ATTR_HIDDEN 0x02 // Hidden 0000_0010 +#define ATTR_SYSTEM 0x04 // System 0000_0100 +#define ATTR_VOLUME_ID 0x08 // VOLUME_ID 0000_1000 +#define ATTR_ARCHIVE 0x20 // Archive 0010_0000 +#define ATTR_DIRECTORY 0x10 // Directory 0001_0000 +// 2. long directory attr +#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) +#define ATTR_LONG_NAME_MASK (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY | ATTR_ARCHIVE) + +// 3. is dir? and is long dir entry? +#define DIR_BOOL(x) ((x)&ATTR_DIRECTORY) + +// 4. set attr to dir and set attr to none dir +#define DIR_SET(x) ((x) = ((x)&FREE_MASK) | ATTR_DIRECTORY) +// we suppose it is archive if a file is not a directory when initialized +#define NONE_DIR_SET(x) ((x) = ((x)&FREE_MASK) | ATTR_ARCHIVE) + +// 5. read only ? +#define READONLY_GET(x) ((x)&ATTR_READ_ONLY) + +// first cluster number +#define DIR_FIRST_CLUS(high, low) ((high << 16) | (low)) +#define DIR_FIRST_HIGH(x) ((x) >> 16) +#define DIR_FIRST_LOW(x) ((x)&0x0000FFFF) + +// The maximum length of the name and the maximum length of the path +// 1. short +#define NAME_SHORT_MAX 8 +#define PATH_SHORT_MAX 80 +// 2. long +// $ % ' - _ @ ~ ` ! ( ) { } ^ # & is allowed for fat32 file system allowed long directory +#define NAME_LONG_MAX 255 +#define PATH_LONG_MAX 260 + +// some useful macro related to long dirent +#define FIRST_LONG_ENTRY 0x01 +#define LAST_LONG_ENTRY 0x40 +#define LONG_DIRENT_CNT 20 + +#define LONG_NAME_BOOL(x) (((x) ^ ATTR_LONG_NAME) == 0) +#define LAST_LONG_ENTRY_BOOL(x) ((x)&LAST_LONG_ENTRY) +#define LAST_LONG_ENTRY_SET(x) ((x) = ((x) | LAST_LONG_ENTRY)) + +// long name char macro +#define LONG_NAME_CHAR_MASK(x) ((x)&0xFF) +#define LONG_NAME_CHAR_VALID(x) (((x) != 0x0000) && ((x) != 0xFFFF)) +#define LONG_NAME_CHAR_SET(x) (((ushort)(x)) & 0x00FF) + +// NOTE: inum index from 0 (root is 0) +// allocate an ino for each fat32 short entry +#define FCB_PER_BLOCK ((__BPB_BytsPerSec) / sizeof(dirent_s_t)) +#define SECTOR_TO_FATINUM(s, offset) (((s)-FirstDataSector) * (FCB_PER_BLOCK) + (offset) + 1) +#define INUM_TRANSFER(ino) ((ino == 0) ? 0 : ino - 1) +#define FATINUM_TO_SECTOR(ino) (INUM_TRANSFER(ino) / (FCB_PER_BLOCK) + FirstDataSector) +#define FATINUM_TO_OFFSET(ino) (INUM_TRANSFER(ino) % (FCB_PER_BLOCK)) + +// the logistic number of cluster for position : off +// start from 0 +#define LOGISTIC_C_NUM(off) ((off) / (__BPB_SecPerClus * __BPB_BytsPerSec)) +#define LOGISTIC_C_OFFSET(off) ((off) % (__BPB_SecPerClus * __BPB_BytsPerSec)) +// the logistic number of sector for position : off +// start form 0 +#define LOGISTIC_S_NUM(off) (LOGISTIC_C_OFFSET(off) / __BPB_BytsPerSec) +#define LOGISTIC_S_OFFSET(off) (LOGISTIC_C_OFFSET(off) % __BPB_BytsPerSec) + +// misc +// 1. the length of a dir file +#define DIRLENGTH(ip) ((ip->fat32_i.cluster_cnt) * __CLUSTER_SIZE) +// 2. the fat32 entry number of a sector +#define FAT_PER_SECTOR ((__BPB_BytsPerSec) / 4) +// 3. the maxium of FCB (short and long entry) +#define FCB_MAX_LENGTH 672 // (20+1)*32 +// 4. first long directory in the data region ? +#define first_long_dir(ip) (ip == fat32_sb.fat32_sb_info.root_entry && off == 0) + +// for debug: the start addr of the cluster in the fat32.img +#define FSIMG_STARTADDR (FirstDataSector * __BPB_BytsPerSec) + +// compare the s and t +#define fat32_namecmp(s, t) (strncmp(s, t, PATH_LONG_MAX)) + +// FAT32 Boot Record +typedef struct FAT32_BootRecord { + /*FAT common field*/ + + uchar Jmpboot[3]; // Jump instruction to boot code. + // 0xEB 0x?? 0x?? + uchar OEMName[8]; // OEM Name Identifier. + // Can be set by a FAT implementation to any desired value. + uint16 BytsPerSec; // Count of bytes per sector(*) + // 512 1024 2048 4096 + uint8 SecPerClus; // Number of sectors per allocation unit. + // 1 2 4 8 16 32 64 128 + uint16 RsvdSecCnt; // Number of reserved sectors in the reserved region + // of the volume starting at the first sector of the volume. + uint8 NumFATs; // The count of file allocation tables (FATs) on the volume. + // 1 or 2 + uchar RootEntCnt[2]; // for FAT32 , set to 0 + uint16 TotSec16; // the count of all sectors in all four regions of the volume + uchar Media; // For removable media, 0xF0 is frequently used. + uchar FATSz16[2]; // On FAT32 volumes this field must be 0, and BPB_FATSz32 contains the FAT size count. + uint16 SecPerTrk; // Sectors per track for interrupt 0x13. + uint16 NumHeads; // Number of heads for interrupt 0x13. + uint32 HiddSec; // Count of hidden sectors preceding the partition that contains this FAT volume. + uint32 TotSec32; // the count of all sectors in all four regions of the volume. + + /*special for FAT32*/ + uint32 FATSz32; // 32-bit count of sectors occupied by ONE FAT + uchar ExtFlags[2]; // 0-3 : Zero-based number of active FAT + // 4-6 : Reserved + // 7 : 0 means the FAT is mirrored at runtime into all FATs + // 1 means only one FAT is active; it is the one referenced in bits 0-3 + // 8-15 : Reserved + uchar FSVer[2]; + // High byte is major revision number + // Low byte is minor revision number + uint32 RootClus; + // cluster number of the first cluster of the root directory, + // usually 2 but not required to be 2 + uint16 FSInfo; + // Sector number of FSINFO structure + // in the reserved area of the FAT32 volume. Usually 1. + uint16 BkBootSec; + // If non-zero, indicates the sector number + // in the reserved area of the volume of a copy of the boot record. + // Usually 6. No value other than 6 is recommended. + uchar Reserved1[12]; + // Reserved for future expansion + uint8 DrvNum; + // driver number + uchar Reserved2; + uchar BootSig; + // Signature (must be 0x28 or 0x29). + uchar VolID[4]; // Volume ID 'Serial' number + uchar VolLab[11]; + // Volume label string. + uchar FilSysType[8]; + // System identifier string "FAT32 " + uchar BootCode[420]; + // Boot code. + uchar BootSign[2]; + // Bootable partition signature 0xAA55. +} __attribute__((packed)) fat_bpb_t; + +// FAT32 Fsinfo +typedef struct FAT32_Fsinfo { + uchar LeadSig[4]; // validate that this is in fact an FSInfo sector + // Value 0x41615252 + uchar Reserved1[480]; // is currently reserved for future expansion + uchar StrucSig[4]; // is more localized in the sector to the location of the fields that are used + // Value 0x61417272 + uint32 Free_Count; // the last known free cluster count on the volume. + // If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. + uint32 Nxt_Free; + // the cluster number at which the driver should start looking for free clusters + uchar Reserved2[12]; + uchar TrailSig[4]; // validate that this is in fact an FSInfo sector + // Value 0xAA550000 +} __attribute__((packed)) fsinfo_t; + +// Date +// typedef struct __date_t { +// uchar day : 5; // 0~31 +// uchar month : 4; // Jan ~ Dec +// uchar year : 7; // form 1980 (1980~2107) +// } __attribute__((packed)) uint16; + +// // Time +// typedef struct __time_t { +// uchar second_per_2 : 5; // 2-second increments 0~59 +// uchar minute : 6; // number of minutes 0~59 +// uchar hour : 5; // hours 0~23 +// } __attribute__((packed)) uint16; + +// typedef struct __date_t { +// uchar day; // 0~31 +// uchar month; // Jan ~ Dec +// uchar year; // form 1980 (1980~2107) +// } __attribute__((packed)) uint16; + +// // Time +// typedef struct __time_t { +// uchar second_per_2; // 2-second increments 0~59 +// uchar minute; // number of minutes 0~59 +// uchar hour; // hours 0~23 +// } __attribute__((packed)) uint16; + +// Directory Structure (short name) +typedef struct Short_Dir_t { + uchar DIR_Name[FAT_SFN_LENGTH]; // directory name + uchar DIR_Attr; // directory attribute + uchar DIR_Dev; // reserved, but we use it as DEVICE + // DIR_NTRes + uchar DIR_CrtTimeTenth; // create time + // Count of tenths of a second + // 0 <= DIR_CrtTimeTenth <= 199 + // uint16 DIR_CrtTime; // create time, 2 bytes + uint16 DIR_CrtTime; // create time, 2 bytes + uint16 DIR_CrtDate; // create date, 2 bytes + uint16 DIR_LstAccDate; // last access date, 2 bytes + uint16 DIR_FstClusHI; // High word of first data cluster number + uint16 DIR_WrtTime; // Last modification (write) time. + uint16 DIR_WrtDate; // Last modification (write) date. + uint16 DIR_FstClusLO; // Low word of first data cluster number + uint32 DIR_FileSize; // 32-bit quantity containing size +} __attribute__((packed)) dirent_s_t; + +// Directory Structure (long name) +typedef struct Long_Dir_t { + uchar LDIR_Ord; // The order of this entry in the sequence + uint16 LDIR_Name1[5]; // characters 1 through 5 + uchar LDIR_Attr; // Attributes + uchar LDIR_Type; // Must be set to 0. + uchar LDIR_Chksum; // Checksum of name + uint16 LDIR_Name2[6]; // characters 6 through 11 + uint16 LDIR_Nlinks; // (Must be set to 0, but we use it as nlinks) + // LDIR_FstClusLO + uint16 LDIR_Name3[2]; // characters 12 and 13 +} __attribute__((packed)) dirent_l_t; + +typedef uint32 FAT_entry_t; + +// 1. mount fat32 file system +int fat32_fs_mount(int, struct _superblock *); + +// 2. bpb parser +int fat32_boot_sector_parser(struct _superblock *, fat_bpb_t *); + +// 3. fsinfo parser +int fat32_fsinfo_parser(struct _superblock *, fsinfo_t *); +#endif \ No newline at end of file diff --git a/include/fs/fat/fat32_file.h b/include/fs/fat/fat32_file.h new file mode 100644 index 0000000..2d40eee --- /dev/null +++ b/include/fs/fat/fat32_file.h @@ -0,0 +1,49 @@ +#ifndef __FAT32_FILE_H__ +#define __FAT32_FILE_H__ + +#include "common.h" + +extern struct devsw devsw[]; + +void fat32_fileinit(void); +struct file *fat32_filedup(struct file *); +ssize_t fat32_fileread(struct file *, uint64, int n); +int fat32_filestat(struct file *, uint64 addr); +ssize_t fat32_filewrite(struct file *, uint64, int n); +void fat32_getcwd(char *buf); +ssize_t fat32_getdents(struct inode *dp, char *buf, size_t len); +// implement file_operations( ==ignore== ) +// char *fat32_getcwd(char *__user buf, size_t size); +// int fat32_pipe2(int fd[2], int flags); +// int fat32_dup(int fd); +// int fat32_dup3(int oldfd, int newfd, int flags); +// int fat32_chdir(const char *path); +// int fat32_openat(int dirfd, const char *pathname, int flags, mode_t mode); +// int fat32_close(int fd); +// ssize_t fat32_getdents64(int fd, void *dirp, size_t count); +// ssize_t fat32_read(int fd, void *buf, size_t count); +// ssize_t fat32_write(int fd, const void *buf, size_t count); +// int fat32_linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags); +// int fat32_unlinkat(int dirfd, const char *pathname, int flags); +// int fat32_mkdirat(int dirfd, const char *pathname, mode_t mode); +// int fat32_umount2(const char *target, int flags); +// int fat32_mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); +// int fat32_fstat(int fd, struct kstat *statbuf); + +// inline const struct file_operations *get_fat32_fops() { +// const static struct file_operations fat32_file_operations = { +// .chdir = fat32_chdir, +// .close = fat32_close, +// .dup3 = fat32_dup3, +// // .fstat = fat32_fstat, +// .getcwd = fat32_getcwd, +// .getdents64 = fat32_getdents64, +// .linkat = fat32_linkat, +// .mkdirat = fat32_mkdirat, +// .mount = fat32_mount, +// .write = fat32_write, +// }; + +// return &fat32_file_operations; +// } +#endif \ No newline at end of file diff --git a/include/fs/fat/fat32_mem.h b/include/fs/fat/fat32_mem.h new file mode 100644 index 0000000..a4de40b --- /dev/null +++ b/include/fs/fat/fat32_mem.h @@ -0,0 +1,181 @@ +#ifndef __FAT32_MEM_H__ +#define __FAT32_MEM_H__ + +#include "common.h" +#include "fat32_disk.h" +#include "fat32_stack.h" +#include "fs/stat.h" + +struct inode; + +// Oscomp +struct fat_dirent_buf { + uint64 d_ino; // ç´¢å¼•ç»“ç‚¹å· + int64 d_off; // 到下一个direntçš„åç§» + unsigned short d_reclen; // 当å‰dirent的长度 + unsigned char d_type; // 文件类型 + char d_name[]; // 文件å +}; + +// fat32 super block information +struct fat32_sb_info { + // read-only + uint fatbase; // FAT base sector + uint n_fats; // Number of FATs (1 or 2) + uint n_sectors_fat; // Number of sectors per FAT + uint root_cluster_s; // Root directory base cluster (start) + + // FSINFO ~ may modify + uint free_count; + uint nxt_free; +}; + +// fat32 inode information +struct fat32_inode_info { + // on-disk structure + char fname[NAME_LONG_MAX]; + uchar Attr; // directory attribute + uchar DIR_CrtTimeTenth; // create time + uint16 DIR_CrtTime; // create time, 2 bytes + uint16 DIR_CrtDate; // create date, 2 bytes + uint16 DIR_LstAccDate; // last access date, 2 bytes + // (DIR_FstClusHI << 16) | (DIR_FstClusLO) + uint32 cluster_start; // start num + uint16 DIR_WrtTime; // Last modification (write) time. + uint16 DIR_WrtDate; // Last modification (write) date. + uint32 DIR_FileSize; // file size (bytes) + + // in memory structure + uint32 cluster_end; // end num + uint64 cluster_cnt; // number of clusters + uint32 parent_off; // offset in parent clusters +}; + +// 0. init the root fat32 inode +struct inode *fat32_root_inode_init(struct _superblock *); + +// 1. traverse the fat32 chain +uint fat32_fat_travel(struct inode *, uint); + +// 2. return the next cluster number +uint fat32_next_cluster(uint); + +// 3. allocate a new cluster +uint fat32_cluster_alloc(uint); + +// 4. allocate a new fat entry +uint fat32_fat_alloc(); + +// 5. set the fat entry to given value +void fat32_fat_set(uint, uint); + +// 6. current fat32 inode +// struct inode *namei(char *); + +// 7. the parent of current fat32 inode +// struct inode *namei_parent(char *, char *); + +struct inode *fat32_inode_dup(struct inode *); +void fat32_inode_update(struct inode *); +void fat32_inode_trunc(struct inode *); + +void fat32_inode_lock(struct inode *); +void fat32_inode_unlock(struct inode *); +void fat32_inode_put(struct inode *); +void fat32_inode_unlock_put(struct inode *); + +int fat32_filter_longname(dirent_l_t *, char *); +struct inode *fat32_inode_dirlookup(struct inode *, const char *, uint *); +struct inode *fat32_inode_get(uint, uint, const char *, uint); +void fat32_inode_stati(struct inode *, struct kstat *); + +uint fat32_inode_read(struct inode *, int, uint64, uint, uint); + +// 9. write the data given the fat32 inode, offset and length +uint fat32_inode_write(struct inode *, int, uint64, uint, uint); + +// 10. dup a existed fat32 inode +struct inode *fat32_inode_dup(struct inode *); + +// 11. find a existed or new fat32 inode +struct inode *fat32_inode_get(uint, uint, const char *, uint); + +// 12. lock the fat32 inode +void fat32_inode_lock(struct inode *); + +// 13. unlock the fat32 inode +void fat32_inode_unlock(struct inode *); + +// 14. put the fat32 inode +void fat32_inode_put(struct inode *); + +// 15. unlock and put the fat32 inode +void fat32_inode_unlock_put(struct inode *); + +// 16. truncate the fat32 inode +void fat32_inode_trunc(struct inode *); + +// 17. update the fat32 inode in the disk +void fat32_inode_update(struct inode *); + +// 18. cat the Name1, Name2 and Name3 of dirent_l +int fat32_filter_longname(dirent_l_t *, char *); + +// 19. reverse the dirent_l to get the long name +ushort fat32_longname_popstack(Stack_t *, uchar *, char *); + +// 20. the check sum of dirent_l +uchar ChkSum(uchar *); + +// 21. lookup the inode given its parent inode and name +struct inode *fat32_inode_dirlookup(struct inode *, const char *, uint *); +struct inode *fat32_inode_get(uint, uint, const char *, uint); +void fat32_inode_stati(struct inode *, struct kstat *); +int fat32_inode_delete(struct inode *dp, struct inode *ip); + +// 22. create the fat32 inode +struct inode *fat32_inode_create(char *path, uchar type, short major, short minor); + +// 23. allocate the fat32 inode +struct inode *fat32_inode_alloc(struct inode *, char *, uchar); + +// 24. init the fat32 fcb (short + long) +int fat32_fcb_init(struct inode *, const uchar *, uchar, char *); + +// 25. the number of files with the same name prefix +uint fat32_find_same_name_cnt(struct inode *, char *); + +// 26. the right fcb insert offset ? +uint fat32_dir_fcb_insert_offset(struct inode *, uchar); + +// 27. is empty? +int fat32_isdirempty(struct inode *); + +// 28. timer to string +int fat32_time_parser(uint16 *, char *, int); + +// 29. date to string +int fat32_date_parser(uint16 *, char *); + +// 30. delete fat32 inode +int fat32_inode_delete(struct inode *, struct inode *); + +// 31. acquire the time now +uint16 fat32_inode_get_time(int *); + +// 32. acquire the date now +uint16 fat32_inode_get_date(); + +// 33. zero the cluster given cluster num +void fat32_zero_cluster(uint64 c_num); + +// 34. short name parser +void fat32_short_name_parser(dirent_s_t dirent_l, char *name_buf); + +// 35. load inode from disk +int fat32_inode_load_from_disk(struct inode *ip); + +// 36. is the inode a directory? +int fat32_isdir(struct inode *); + +#endif \ No newline at end of file diff --git a/include/fs/fat/fat32_stack.h b/include/fs/fat/fat32_stack.h new file mode 100644 index 0000000..b441119 --- /dev/null +++ b/include/fs/fat/fat32_stack.h @@ -0,0 +1,36 @@ +#ifndef __FAT32_STACK_H__ +#define __FAT32_STACK_H__ + +#include "common.h" +#include "fs/fat/fat32_disk.h" +#define CAPACITY 30 + +typedef dirent_l_t elemtype; + +struct Stack { + int top; + elemtype *data; +}; +typedef struct Stack Stack_t; + +// 1. åˆå§‹åŒ–æ ˆ +void stack_init(Stack_t *); + +// 2. åˆ¤æ–æ ˆæ˜¯å¦ä¸ºç©º +int stack_is_empty(Stack_t *); + +// 3. åˆ¤æ–æ ˆæ˜¯å¦å·²æ»¡ +int stack_is_full(Stack_t *); + +// 4. å…¥æ ˆæ“作 +void stack_push(Stack_t *, elemtype); + +// 5. å‡ºæ ˆæ“作 +elemtype stack_pop(Stack_t *); + +// 6. èŽ·å–æ ˆé¡¶å…ƒç´ +elemtype stack_peek(Stack_t *); + +// 7. é‡Šæ”¾æ ˆåˆ†é…的空间 +void stack_free(Stack_t *); +#endif \ No newline at end of file diff --git a/include/fs/fcntl.h b/include/fs/fcntl.h new file mode 100644 index 0000000..15193a6 --- /dev/null +++ b/include/fs/fcntl.h @@ -0,0 +1,32 @@ +#ifndef __FCNTL_H__ +#define __FCNTL_H__ + +// f_flags +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 +#define O_CREATE 0x40 +#define O_DIRECTORY 0x0200000 +// #define O_CREATE 0x200 // for xv6 +#define O_TRUNC 0x400 +#define F_WRITEABLE(fp) ((fp)->f_flags > 0 ? 1 : 0) +#define F_READABLE(fp) (((fp)->f_flags & O_WRONLY) == O_WRONLY ? 0 : 1) + +// f_mode +#define IMODE_READONLY 0x01 +#define IMODE_NONE 0x00 + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_FILE 0 +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 + +#define AT_FDCWD -100 + +#define F_WRITEABLE(fp) ((fp)->f_flags > 0 ? 1 : 0) +#define F_READABLE(fp) (((fp)->f_flags & O_WRONLY) == O_WRONLY ? 0 : 1) +#endif // __FCNTL_H__ diff --git a/include/fs/fdtable.h b/include/fs/fdtable.h new file mode 100644 index 0000000..9be2f8f --- /dev/null +++ b/include/fs/fdtable.h @@ -0,0 +1,24 @@ +#ifndef __FDTABLE_H__ +#define __FDTABLE_H__ + +#include "param.h" +#include "atomic/spinlock.h" +#include "atomic/atomic.h" + +struct file; +struct fd { + struct file *file; + uint flags; +}; + +typedef fd fd_t; +// descriptor table +struct fdtable { + atomic_t ref; + struct spinlock lock; + fd_t ofile[NOFILE]; + uint max_fds; // max fd + uint cur_fd; // current fd +}; + +#endif // __FDTABLE_H__ \ No newline at end of file diff --git a/include/fs/stat.h b/include/fs/stat.h new file mode 100644 index 0000000..caad8fd --- /dev/null +++ b/include/fs/stat.h @@ -0,0 +1,53 @@ +#ifndef __FS_STAT_H__ +#define __FS_STAT_H__ + +// since mkfs will use kernel header file, add this condition preprocess +#ifndef USER +#include "common.h" +#endif + +#define TFILE 2 // for xv6 + +// type +#define T_DIR 1 // Directory +#define T_FILE 2 // File +#define T_DEVICE 3 // Device + +// device +#define mkrdev(ma, mi) ((uint)((ma) << 8 | (mi))) +#define CONSOLE 1 + +typedef unsigned long int dev_t; +typedef unsigned long int ino_t; +typedef unsigned long int nlink_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; +typedef long int off_t; +typedef long int blksize_t; +typedef long int blkcnt_t; +typedef unsigned int mode_t; +typedef long int off_t; + +struct kstat { + uint64 st_dev; + uint64 st_ino; + mode_t st_mode; + uint32 st_nlink; + uint32 st_uid; + uint32 st_gid; + uint64 st_rdev; + unsigned long __pad; + off_t st_size; + uint32 st_blksize; + int __pad2; + uint64 st_blocks; + long st_atime_sec; + long st_atime_nsec; + long st_mtime_sec; + long st_mtime_nsec; + long st_ctime_sec; + long st_ctime_nsec; + unsigned __unused[2]; +}; + +#endif // __FS_STAT_H__ diff --git a/include/fs/vfs/fs.h b/include/fs/vfs/fs.h new file mode 100644 index 0000000..924b297 --- /dev/null +++ b/include/fs/vfs/fs.h @@ -0,0 +1,155 @@ +#ifndef __VFS_FS_H__ +#define __VFS_FS_H__ + +#include "common.h" +#include "param.h" +#include "atomic/spinlock.h" +#include "atomic/semaphore.h" +#include "fs/stat.h" +#include "fs/fcntl.h" +#include "fs/vfs/fs.h" +#include "fs/fat/fat32_mem.h" + +struct kstat; +extern struct ftable _ftable; + +union file_type { + struct pipe *f_pipe; // FD_PIPE + struct inode *f_inode; // FDINODE and FD_DEVICE +}; + +typedef enum { + FAT32=1, + EXT2, +} fs_t; + +struct _superblock { + struct semaphore sem; /* binary semaphore */ + uint8 s_dev; // device number + + uint32 s_blocksize; // 逻辑å—çš„æ•°é‡ + uint32 sectors_per_block; // æ¯ä¸ªé€»è¾‘å—的扇区个数 + uint cluster_size; // size of a cluster + + // uint32 s_blocksize_bits; + uint n_sectors; // Number of sectors + uint sector_size; // size of a sector + + struct super_operations *s_op; + struct inode *s_mount; + struct inode *root; + + union { + struct fat32_sb_info fat32_sb_info; + // struct xv6fs_sb_info xv6fs_sb; + // void *generic_sbp; + }; +}; + +// abstarct everything in memory +struct file { + type_t f_type; + ushort f_mode; + uint32 f_pos; + ushort f_flags; + ushort f_count; + short f_major; // FD_DEVICE + + int f_owner; /* pid or -pgrp where SIGIO should be sent */ + union file_type f_tp; + const struct file_operations *f_op; // don't use pointer (bug maybe)!!!! + unsigned long f_version; +}; + + +struct ftable { + struct spinlock lock; + struct file file[NFILE]; +}; + +// #define NAME_MAX 10 +// struct _dirent { +// long d_ino; +// char d_name[NAME_MAX + 1]; +// }; + + +// abstract datas in disk +struct inode { + uint8 i_dev; + uint32 i_ino; // 对任æ„ç»™å®šçš„æ–‡ä»¶ç³»ç»Ÿçš„å”¯ä¸€ç¼–å·æ ‡è¯†ï¼šç”±å…·ä½“文件系统解释 + uint16 i_mode; // 访问æƒé™å’Œæ‰€æœ‰æƒ + int ref; // Reference count + int valid; + // Note: fat fs does not support hard link, reserve for vfs interface + uint16 i_nlink; + uint i_uid; + uint i_gid; + uint64 i_rdev; + uint32 i_size; + uint16 i_type; + + long i_atime; // access time + long i_mtime; // modify time + long i_ctime; // create time + uint64 i_blksize; // bytes of one block + uint64 i_blocks; // numbers of blocks + // uint32 i_blksize; + // uint32 i_blocks; + struct semaphore i_sem; /* binary semaphore */ + // struct sleeplock i_sem; + + const struct inode_operations *i_op; + struct _superblock *i_sb; + struct inode *i_mount; + // struct wait_queue *i_wait; + struct inode *parent; + + fs_t fs_type; + union { + struct fat32_inode_info fat32_i; + // struct xv6inode_info xv6_i; + // struct ext2inode_info ext2_i; + // void *generic_ip; + }; + +}; + +struct file_operations { + struct file* (*alloc) (void); + struct file* (*dup) (struct file*); + ssize_t (*read) (struct file*, uint64 __user, int); + ssize_t (*write) (struct file*, uint64 __user, int); + int (*fstat) (struct file *, uint64 __user); +}; + + +struct inode_operations { + void (*iunlock_put) (struct inode* self); + void (*iunlock) (struct inode* self); + void (*iput) (struct inode* self); + void (*ilock) (struct inode* self); + void (*itrunc) (struct inode* self); + void (*iupdate) (struct inode* self); + struct inode* (*idup) (struct inode* self); + int (*idir) (struct inode* self); // is self a directory + + // for directory inode + struct inode* (*idirlookup) (struct inode* self, const char* name, uint* poff); + int (*idelete) (struct inode* dp, struct inode* ip); + int (*idempty) (struct inode* dp); + ssize_t (*igetdents) (struct inode *dp, char *buf, size_t len); +}; + + +struct linux_dirent { + uint64 d_ino; // ç´¢å¼•ç»“ç‚¹å· + int64 d_off; // 到下一个direntçš„åç§» + unsigned short d_reclen; // 当å‰dirent的长度 + unsigned char d_type; // 文件类型 + char d_name[]; //文件å +}; + + + +#endif // __VFS_FS_H__ \ No newline at end of file diff --git a/include/fs/vfs/fs_macro.h b/include/fs/vfs/fs_macro.h new file mode 100644 index 0000000..fcd4f63 --- /dev/null +++ b/include/fs/vfs/fs_macro.h @@ -0,0 +1,7 @@ +#ifndef __VFS_FS_MACRO_H__ +#define __VFS_FS_MACRO_H__ + +#define CONSOLE 1 +#define BSIZE 512 + +#endif // __FS_MACRO_H__ \ No newline at end of file diff --git a/include/fs/vfs/ops.h b/include/fs/vfs/ops.h new file mode 100644 index 0000000..d92cf11 --- /dev/null +++ b/include/fs/vfs/ops.h @@ -0,0 +1,13 @@ +#include "fs.h" + +// file layer +struct file *filealloc(void); +void generic_fileclose(struct file *); +extern const struct file_operations* (*get_fileops[])(void); + + +// inode layer +struct inode* find_inode(char *path, int dirfd, char *name); +struct inode* namei(char *path); +struct inode* namei_parent(char *path, char *name); +extern const struct inode_operations* (*get_inodeops[])(void); \ No newline at end of file diff --git a/include/kernel/options.h b/include/kernel/options.h new file mode 100644 index 0000000..8160b8d --- /dev/null +++ b/include/kernel/options.h @@ -0,0 +1,28 @@ +#ifndef __OPTIONS_H__ +#define __OPTIONS_H__ + +// CLONE options +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_FILES 0x00000400 /* Set if open files shared between processes */ +#define CLONE_FS 0x00000200 /* set if fs info shared between processes */ +#define CLONE_THREAD 0x00010000 /* Set to add to same thread group */ +#define CLONE_SIGHAND 0x00000800 /* Set if signal handlers shared. */ +#define CLONE_PARENT_SETTID 0x00100000 /* Store TID in userlevel buffer before MM copy.*/ +#define CLONE_SETTLS 0x00080000 /* Set TLS info. */ +#define CLONE_CHILD_CLEARTID 0x00200000 /* Register exit futex and memory location to clear. */ +#define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in the child. */ + +// waitpid options +#define WNOHANG 0x00000001 +#define WUNTRACED 0x00000002 +#define WCONTINUED 0x00000008 + +#define WSTOPPED WUNTRACED +#define WEXITED 0x00000004 + +#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */ +#define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads in this group */ +#define __WALL 0x40000000 /* Wait on all children, regardless of type */ +#define __WCLONE 0x80000000 /* Wait only on non-SIGCHLD children */ + +#endif \ No newline at end of file diff --git a/include/vfs/fs.h b/include/vfs/fs.h new file mode 100644 index 0000000..4110160 --- /dev/null +++ b/include/vfs/fs.h @@ -0,0 +1,155 @@ +#ifndef __VFS_FS_H__ +#define __VFS_FS_H__ + +#include "types.h" + +#include "kernel/locks.h" +#include "kernel/semaphore.h" +#include "fs/stat.h" +#include "fs/fcntl.h" +#include "fs/vfs/fs.h" +#include "fs/fat/fat32_mem.h" + +struct kstat; +extern struct ftable _ftable; + +union file_type { + struct pipe *f_pipe; // FD_PIPE + struct inode *f_inode; // FDINODE and FD_DEVICE +}; + +typedef enum { + FAT32=1, + EXT2, +} fs_t; + +struct _superblock { + struct semaphore sem; /* binary semaphore */ + uint8_t s_dev; // device number + + uint32_t s_blocksize; // 逻辑å—çš„æ•°é‡ + uint32_t sectors_per_block; // æ¯ä¸ªé€»è¾‘å—的扇区个数 + unsigned int cluster_size; // size of a cluster + + // unsigned int32_t s_blocksize_bits; + unsigned int n_sectors; // Number of sectors + unsigned int sector_size; // size of a sector + + struct super_operations *s_op; + struct inode *s_mount; + struct inode *root; + + union { + struct fat32_sb_info fat32_sb_info; + // struct xv6fs_sb_info xv6fs_sb; + // void *generic_sbp; + }; +}; + +// abstarct everything in memory +struct file { + type_t f_type; + ushort f_mode; + uint32_t f_pos; + ushort f_flags; + ushort f_count; + short f_major; // FD_DEVICE + + int f_owner; /* pid or -pgrp where SIGIO should be sent */ + union file_type f_tp; + const struct file_operations *f_op; // don't use pointer (bug maybe)!!!! + unsigned long f_version; +}; + + +struct ftable { + spinlock_t lock; + struct file file[NFILE]; +}; + +// #define NAME_MAX 10 +// struct _dirent { +// long d_ino; +// char d_name[NAME_MAX + 1]; +// }; + + +// abstract datas in disk +struct inode { + uint8_t i_dev; + uint32_t i_ino; // 对任æ„ç»™å®šçš„æ–‡ä»¶ç³»ç»Ÿçš„å”¯ä¸€ç¼–å·æ ‡è¯†ï¼šç”±å…·ä½“文件系统解释 + uint16_t i_mode; // 访问æƒé™å’Œæ‰€æœ‰æƒ + int ref; // Reference count + int valid; + // Note: fat fs does not support hard link, reserve for vfs interface + uint16_t i_nlink; + unsigned int i_uid; + unsigned int i_gid; + uint64_t i_rdev; + uint32_t i_size; + uint16_t i_type; + + long i_atime; // access time + long i_mtime; // modify time + long i_ctime; // create time + uint64_t i_blksize; // bytes of one block + uint64_t i_blocks; // numbers of blocks + // uint32_t i_blksize; + // uint32_t i_blocks; + struct semaphore i_sem; /* binary semaphore */ + // struct sleeplock i_sem; + + const struct inode_operations *i_op; + struct _superblock *i_sb; + struct inode *i_mount; + // struct wait_queue *i_wait; + struct inode *parent; + + fs_t fs_type; + union { + struct fat32_inode_info fat32_i; + // struct xv6inode_info xv6_i; + // struct ext2inode_info ext2_i; + // void *generic_ip; + }; + +}; + +struct file_operations { + struct file* (*alloc) (void); + struct file* (*dup) (struct file*); + ssize_t (*read) (struct file*, uint64_t __user, int); + ssize_t (*write) (struct file*, uint64_t __user, int); + int (*fstat) (struct file *, uint64_t __user); +}; + + +struct inode_operations { + void (*iunlock_put) (struct inode* self); + void (*iunlock) (struct inode* self); + void (*iput) (struct inode* self); + void (*ilock) (struct inode* self); + void (*itrunc) (struct inode* self); + void (*iupdate) (struct inode* self); + struct inode* (*idup) (struct inode* self); + int (*idir) (struct inode* self); // is self a directory + + // for directory inode + struct inode* (*idirlookup) (struct inode* self, const char* name, unsigned int* poff); + int (*idelete) (struct inode* dp, struct inode* ip); + int (*idempty) (struct inode* dp); + ssize_t (*igetdents) (struct inode *dp, char *buf, size_t len); +}; + + +struct linux_dirent { + uint64_t d_ino; // ç´¢å¼•ç»“ç‚¹å· + int64 d_off; // 到下一个direntçš„åç§» + unsigned short d_reclen; // 当å‰dirent的长度 + unsigned char d_type; // 文件类型 + char d_name[]; //文件å +}; + + + +#endif // __VFS_FS_H__ \ No newline at end of file diff --git a/include/vfs/fs_macro.h b/include/vfs/fs_macro.h new file mode 100644 index 0000000..fcd4f63 --- /dev/null +++ b/include/vfs/fs_macro.h @@ -0,0 +1,7 @@ +#ifndef __VFS_FS_MACRO_H__ +#define __VFS_FS_MACRO_H__ + +#define CONSOLE 1 +#define BSIZE 512 + +#endif // __FS_MACRO_H__ \ No newline at end of file diff --git a/include/vfs/ops.h b/include/vfs/ops.h new file mode 100644 index 0000000..d92cf11 --- /dev/null +++ b/include/vfs/ops.h @@ -0,0 +1,13 @@ +#include "fs.h" + +// file layer +struct file *filealloc(void); +void generic_fileclose(struct file *); +extern const struct file_operations* (*get_fileops[])(void); + + +// inode layer +struct inode* find_inode(char *path, int dirfd, char *name); +struct inode* namei(char *path); +struct inode* namei_parent(char *path, char *name); +extern const struct inode_operations* (*get_inodeops[])(void); \ No newline at end of file diff --git a/kernel/pcb_life.c b/kernel/pcb_life.c index 6ec04a3..63f4efe 100644 --- a/kernel/pcb_life.c +++ b/kernel/pcb_life.c @@ -7,6 +7,8 @@ #include "trap/traps.h" #include "kernel/kstdio.h" #include "kernel/kdebug.h" +#include "kernel/options.h" + struct proc proc[NPROC]; struct proc* initproc; @@ -116,6 +118,100 @@ void forkret(void) { + +int do_clone(int flags, uint64_t stack, pid_t ptid, uint64_t tls, pid_t *ctid) { + int pid; + struct proc *np; + struct proc *p = current(); + + // Allocate process. + if ((np = allocproc()) == 0) { + return -1; + } + // copy saved user registers. + *(np->trapframe) = *(p->trapframe); + // Cause fork to return 0 in the child. + np->trapframe->a0 = 0; + + /* Copy vma */ + // if (vmacopy(np) < 0) { + // freeproc(np); + // spinlock_release(&np->lock); + // return -1; + // } + + // Copy user memory from parent to child. + // TODO : mmap + // if (flags & CLONE_VM) { + // np->pagetable = p->pagetable; + // } else { + // if (uvmcopy(p->pagetable, np->pagetable, p->sz) < 0) { + // freeproc(np); + // release(&np->lock); + // return -1; + // } + // } + // np->sz = p->sz; + // // increment reference counts on open file descriptors. + // // TODO : fdtable + // if (flags & CLONE_FILES) { + // // for (int i = 0; i < NOFILE; i++) + // // if (p->_ofile[i]) + // // np->_ofile[i] = p->_ofile[i]; + // } else { + // for (int i = 0; i < NOFILE; i++) + // if (p->_ofile[i]) + // np->_ofile[i] = fat32_filedup(p->_ofile[i]); + // // TODO : clone a completely same fdtable + // } + // TODO : vfs inode cmd + // np->_cwd = fat32_inode_dup(p->_cwd); + + // TODO : signal + if (flags & CLONE_SIGHAND) { + np->sig = p->sig; + } else { + // TODO : create a new signal + } + // TODO : mount point CLONE_FS + + // store the parent pid + // if (flags & CLONE_PARENT_SETTID) { + // if (either_copyin(&ptid, 1, p->pid, sizeof(pid_t)) == -1) + // return -1; + // } + // // set the tls (Thread-local Storage,TLS) + // // RISC-V使用TP寄å˜å™¨ + // if (flags & CLONE_SETTLS) { + // // np->trapframe->tp = tls; + // } + // å线程ä¸å˜å‚¨å线程 ID çš„å˜é‡æŒ‡é’ˆ + // if (flags & CLONE_CHILD_SETTID) { + // np->ctid = ctid; + // } + if (stack) { + np->trapframe->sp = stack; + } + memcpy(np->name, p->name, sizeof(p->name)); + + pid = np->pid; + np->parent = p; + // acquire(&p->lock); + // appendChild(p, np); + // release(&p->lock); + +#ifdef __DEBUG_PROC__ + printfRed("clone : %d -> %d\n", p->pid, np->pid); // debug +#endif + + PCB_Q_changeState(np, RUNNABLE); + spinlock_release(&np->lock); + return pid; +} + + + + struct proc *allocproc(void) { struct proc *p; @@ -180,4 +276,27 @@ void freeproc(struct proc *p) { p->exit_state = 0; PCB_Q_changeState(p, _UNUSED); +} + + + +void do_exit(int status){ + struct proc* p=current(); + ASSERT(p!=initproc,"init shounld not exit \0",1); + + //free p's mem + + //close p's open file + + //give children to init + + spinlock_acquire(&p->lock); + p->exit_state = status << 8; + PCB_Q_changeState(p, ZOMBIE); + sema_signal(&p->parent->sem_wait_chan_parent); + sema_signal(&p->sem_wait_chan_self); + sched(); + + ASSERT(1==0,"zombie shoudnt come here",0); + } \ No newline at end of file -- GitLab