diff --git a/include/stupidfs.h b/include/stupidfs.h index b5d8b54..6ea38f8 100644 --- a/include/stupidfs.h +++ b/include/stupidfs.h @@ -130,6 +130,9 @@ struct stpdfs_inode { #define STPDFS_INODE_SIZE sizeof(struct inode) # define STPDFS_NDIR 7 /**< Number of direct block */ +# define STPDFS_SIND 7 /**< Indirect block */ +# define STPDFS_DIND 8 /**< Double indirect */ +# define STPDFS_TIND 9 /**< Triple indirect */ # define STPDFS_INO_FLAG_ALOC (1 << 15) # define STPDFS_INO_FLAG_LZP (1 << 1) diff --git a/libstpdfs/inode.c b/libstpdfs/inode.c index 100b8c9..47cf6d1 100644 --- a/libstpdfs/inode.c +++ b/libstpdfs/inode.c @@ -1,15 +1,122 @@ +#include "stpdfs.h" +#include "stupidfs.h" #include +#include +#include #define INODE_CACHE 50 +#define IBLOCK(x) (x / STPDFS_INODES_PER_BLOCK + 2) -struct stpdfs_inode_info icache[INODE_CACHE]; +static struct stpdfs_inode_info icache[INODE_CACHE] = {0}; -struct inode * -stpdfs_inode_get(struct stpdfs_sb *sb, uint32_t ino) +struct stpdfs_inode_info * +stpdfs_inode_get(struct stpdfs_super_info *sbi, uint32_t inum) { + struct stpdfs_inode_info *empty; + int idx; + + empty = NULL; + for (idx = 0; idx < INODE_CACHE; idx++) + { + if (icache[idx].refcount > 0 && icache[idx].inum == inum) + { + icache[idx].refcount++; + return (&icache[idx]); + } + + if (empty == NULL && icache[idx].refcount == 0) + { + empty = &icache[idx]; + } + } + + if (empty == NULL) return (NULL); + + empty->sbi = sbi; + empty->inum = inum; + empty->refcount = 1; + empty->valid = 0; + + return (empty); +} + +struct stpdfs_inode_info * +stpdfs_inode_alloc(struct stpdfs_super_info *sbi) +{ + uint32_t inum; + struct stpdfs_buffer *buff; + struct stpdfs_inode *dinode; + + for (inum = 1; inum < sbi->sb.isize; inum++) + { + buff = stpdfs_bread(sbi->fd, IBLOCK(inum)); + dinode = (struct stpdfs_inode *)buff->data + inum % STPDFS_INODES_PER_BLOCK; + if ((dinode->flags & STPDFS_INO_FLAG_ALOC) == 0) + { + dinode->flags = STPDFS_INO_FLAG_ALOC; + stpdfs_bwrite(buff); + stpdfs_brelse(buff); + + return (stpdfs_inode_get(sbi, inum)); + } + + stpdfs_brelse(buff); + } + return (NULL); } +void +stpdfs_inode_update(struct stpdfs_inode_info *ip) +{ + struct stpdfs_buffer *buff; + struct stpdfs_inode *dinode; + + buff = stpdfs_bread(ip->sbi->fd, IBLOCK(ip->inum)); + dinode = (struct stpdfs_inode *)buff->data + ip->inum % STPDFS_INODES_PER_BLOCK; + memcpy(dinode, &ip->inode, sizeof(struct stpdfs_inode)); + stpdfs_bwrite(buff); + stpdfs_brelse(buff); +} + +int +stpdfs_inode_bmap(struct stpdfs_inode_info *ip, uint32_t blocknum) +{ + uint32_t *addrs; + uint32_t index; + struct stpdfs_buffer *buff; + + if (blocknum < STPDFS_NDIR) + { + if (ip->inode.zones[blocknum] == 0) + { + ip->inode.zones[blocknum] = stpdfs_super_balloc(ip->sbi); + } + return (ip->inode.zones[blocknum]); + } + + index = blocknum - STPDFS_NDIR; + if (blocknum < (STPDFS_BLOCK_SIZE/sizeof(int32_t) + STPDFS_SIND)) + { + if (ip->inode.zones[STPDFS_SIND] == 0) + { + ip->inode.zones[STPDFS_SIND] = stpdfs_super_balloc(ip->sbi); + } + + buff = stpdfs_bread(ip->sbi->fd, ip->inode.zones[STPDFS_SIND]); + addrs = (uint32_t *)buff->data; + if (addrs[index] == 0) + { + addrs[index] = stpdfs_super_balloc(ip->sbi); + } + stpdfs_brelse(buff); + return (addrs[index]); + } + + /* TODO double and triple ind */ + return (0); +} + struct stpdfs_dirent * stpdfs_lookup(struct stpdfs_inode *dir, struct stpdfs_dirent *dentry, int flags) { diff --git a/libstpdfs/stpdfs.h b/libstpdfs/stpdfs.h index 5c9292b..8b95a93 100644 --- a/libstpdfs/stpdfs.h +++ b/libstpdfs/stpdfs.h @@ -12,9 +12,16 @@ struct stpdfs_super_info { }; struct stpdfs_inode_info { - struct stpdfs_inode ino; - int fd; + int valid; int refcount; + uint32_t inum; + struct stpdfs_super_info *sbi; + + struct stpdfs_inode inode; +}; + +struct stpdfs_file { + }; struct stpdfs_buffer { @@ -40,6 +47,8 @@ void stpdfs_bpin(struct stpdfs_buffer *buff); int stpdfs_read_super(struct stpdfs_super_info *sbi, int fd); int stpdfs_super_validate(struct stpdfs_sb *sb); int stpdfs_super_kill(struct stpdfs_super_info *sbi); +uint32_t stpdfs_super_balloc(struct stpdfs_super_info *sbi); +int stpdfs_super_bfreee(struct stpdfs_super_info *sbi, uint32_t blocknum); uint32_t stpdfs_alloc_block(int fd, struct stpdfs_sb *sb); int stpdfs_free_block(int fd, struct stpdfs_sb *sb, uint32_t blocknum); diff --git a/libstpdfs/super.c b/libstpdfs/super.c index d476840..45b5485 100644 --- a/libstpdfs/super.c +++ b/libstpdfs/super.c @@ -1,4 +1,6 @@ +#include "stupidfs.h" #include +#include #include #include #include @@ -70,7 +72,78 @@ stpdfs_super_kill(struct stpdfs_super_info *sbi) stpdfs_bwrite(buff); stpdfs_brelse(buff); + end: close(sbi->fd); + + return (0); } + +uint32_t +stpdfs_super_balloc(struct stpdfs_super_info *sbi) +{ + uint32_t blocknum; + struct stpdfs_free freelist; + struct stpdfs_buffer *buff; + + sbi->sb.state = STPDFS_DIRTY; +redo: + sbi->sb.freelist.nfree--; + blocknum = sbi->sb.freelist.free[sbi->sb.freelist.nfree]; + if (sbi->sb.freelist.nfree == 0 && blocknum != 0) + { + buff = stpdfs_bread(sbi->fd, blocknum); + memcpy(&sbi->sb.freelist, buff->data, sizeof(struct stpdfs_free)); + goto redo; + } + + buff = stpdfs_bread(sbi->fd, 1); + memcpy(buff->data, &sbi->sb, sizeof(struct stpdfs_sb)); + stpdfs_bwrite(buff); + + buff = stpdfs_bread(sbi->fd, blocknum); + memset(buff->data, 0, STPDFS_BLOCK_SIZE); + stpdfs_bwrite(buff); + stpdfs_brelse(buff); + + sbi->sb.time = time(NULL); + + return (blocknum); +} + +int +stpdfs_super_bfreee(struct stpdfs_super_info *sbi, uint32_t blocknum) +{ + struct stpdfs_free copy; + struct stpdfs_buffer *buff; + + if (blocknum == 0 || blocknum >= sbi->sb.fsize) + { + return (-1); + } + + sbi->sb.state = STPDFS_DIRTY; + + if (sbi->sb.freelist.nfree == 100) + { + buff = stpdfs_bread(sbi->fd, blocknum); + memcpy(buff->data, &sbi->sb.freelist, sizeof(struct stpdfs_free)); + stpdfs_bwrite(buff); + stpdfs_brelse(buff); + sbi->sb.freelist.nfree = 1; + sbi->sb.freelist.free[0] = blocknum; + } + else + { + sbi->sb.freelist.free[sbi->sb.freelist.nfree++] = blocknum; + } + + sbi->sb.time = time(NULL); + + buff = stpdfs_bread(sbi->fd, 1); + memcpy(buff->data, &sbi->sb, sizeof(struct stpdfs_sb)); + stpdfs_bwrite(buff); + + return (0); +} \ No newline at end of file