nuclear@90: /* This code is used by the kernel AND by userspace filesystem-related tools. nuclear@90: * The kernel-specific parts are conditionally compiled in #ifdef KERNEL blocks nuclear@90: * the rest of the code should be independent. nuclear@90: */ nuclear@88: #include nuclear@89: #include nuclear@94: #include nuclear@90: #include nuclear@94: #include nuclear@88: #include "fs.h" nuclear@93: #include "bdev.h" nuclear@90: nuclear@89: nuclear@93: int openfs(struct filesys *fs, dev_t dev); nuclear@94: static int read_superblock(struct filesys *fs); nuclear@94: static int write_superblock(struct filesys *fs); nuclear@94: static int get_inode(struct filesys *fs, int ino, struct inode *inode); nuclear@94: static int put_inode(struct filesys *fs, struct inode *inode); nuclear@90: nuclear@93: int openfs(struct filesys *fs, dev_t dev) nuclear@93: { nuclear@93: int res; nuclear@93: struct block_device *bdev; nuclear@94: nuclear@94: assert(BLKSZ % sizeof(struct inode) == 0); nuclear@89: nuclear@93: if(!(bdev = blk_open(dev))) { nuclear@93: return -ENOENT; nuclear@90: } nuclear@94: fs->bdev = bdev; nuclear@90: nuclear@93: /* read the superblock */ nuclear@94: if(!(fs->sb = malloc(BLKSZ))) { nuclear@93: res = -ENOMEM; nuclear@93: goto done; nuclear@93: } nuclear@94: if((res = read_superblock(fs)) != 0) { nuclear@93: goto done; nuclear@93: } nuclear@90: nuclear@93: nuclear@93: done: nuclear@93: blk_close(bdev); nuclear@93: return res; nuclear@90: } nuclear@88: nuclear@94: static int read_superblock(struct filesys *fs) nuclear@88: { nuclear@94: struct superblock *sb = fs->sb; nuclear@94: nuclear@93: /* read superblock and verify */ nuclear@94: if(blk_read(fs->bdev, 1, 1, sb) == -1) { nuclear@93: printf("failed to read superblock\n"); nuclear@93: return -EIO; nuclear@93: } nuclear@93: if(sb->magic != MAGIC) { nuclear@93: printf("invalid magic\n"); nuclear@93: return -EINVAL; nuclear@93: } nuclear@93: if(sb->ver > FS_VER) { nuclear@93: printf("invalid version: %d\n", sb->ver); nuclear@93: return -EINVAL; nuclear@93: } nuclear@93: if(sb->blksize != BLKSZ) { nuclear@93: printf("invalid block size: %d\n", sb->blksize); nuclear@93: return -EINVAL; nuclear@93: } nuclear@89: nuclear@93: /* allocate and populate in-memory bitmaps */ nuclear@93: if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) { nuclear@93: return -ENOMEM; nuclear@88: } nuclear@94: if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) { nuclear@93: printf("failed to read inode bitmap\n"); nuclear@93: free(sb->ibm); nuclear@93: return -EIO; nuclear@93: } nuclear@93: if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) { nuclear@93: free(sb->ibm); nuclear@93: return -ENOMEM; nuclear@93: } nuclear@94: if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) { nuclear@93: printf("failed to read block bitmap\n"); nuclear@93: free(sb->ibm); nuclear@93: free(sb->bm); nuclear@93: return -EIO; nuclear@93: } nuclear@93: nuclear@94: /* read the root inode */ nuclear@94: if(!(sb->root = malloc(sizeof *sb->root))) { nuclear@94: free(sb->ibm); nuclear@94: free(sb->bm); nuclear@94: return -ENOMEM; nuclear@94: } nuclear@94: if(get_inode(fs, sb->root_ino, sb->root) == -1) { nuclear@94: printf("failed to read root inode\n"); nuclear@94: return -1; nuclear@94: } nuclear@94: nuclear@93: return 0; nuclear@88: } nuclear@94: nuclear@94: static int write_superblock(struct filesys *fs) nuclear@94: { nuclear@94: struct superblock *sb = fs->sb; nuclear@94: nuclear@94: /* write back any changes in the root inode */ nuclear@94: if(put_inode(fs, sb->root) == -1) { nuclear@94: return -1; nuclear@94: } nuclear@94: /* write back the block bitmap */ nuclear@94: if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) { nuclear@94: return -1; nuclear@94: } nuclear@94: /* write back the inode bitmap */ nuclear@94: if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) { nuclear@94: return -1; nuclear@94: } nuclear@94: return 0; nuclear@94: } nuclear@94: nuclear@94: /* number of inodes in a block */ nuclear@94: #define BLK_INODES (BLKSZ / sizeof(struct inode)) nuclear@94: nuclear@94: /* copy the requested inode from the disk, into the buffer passed in the last arg */ nuclear@94: static int get_inode(struct filesys *fs, int ino, struct inode *inode) nuclear@94: { nuclear@94: struct inode *buf = malloc(BLKSZ); nuclear@94: assert(buf); nuclear@94: nuclear@94: if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) { nuclear@94: free(buf); nuclear@94: return -1; nuclear@94: } nuclear@94: memcpy(inode, buf + ino % BLK_INODES, sizeof *inode); nuclear@94: free(buf); nuclear@94: return 0; nuclear@94: } nuclear@94: nuclear@94: /* write the inode to the disk */ nuclear@94: static int put_inode(struct filesys *fs, struct inode *inode) nuclear@94: { nuclear@94: struct inode *buf = malloc(BLKSZ); nuclear@94: assert(buf); nuclear@94: nuclear@94: if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) { nuclear@94: free(buf); nuclear@94: return -1; nuclear@94: } nuclear@94: memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode); nuclear@94: nuclear@94: if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) { nuclear@94: free(buf); nuclear@94: return -1; nuclear@94: } nuclear@94: free(buf); nuclear@94: return 0; nuclear@94: }