add lab answers
This commit is contained in:
114
labcodes_answer/lab8_result/kern/fs/sfs/bitmap.c
Executable file
114
labcodes_answer/lab8_result/kern/fs/sfs/bitmap.c
Executable file
@@ -0,0 +1,114 @@
|
||||
#include <defs.h>
|
||||
#include <string.h>
|
||||
#include <bitmap.h>
|
||||
#include <kmalloc.h>
|
||||
#include <error.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define WORD_TYPE uint32_t
|
||||
#define WORD_BITS (sizeof(WORD_TYPE) * CHAR_BIT)
|
||||
|
||||
struct bitmap {
|
||||
uint32_t nbits;
|
||||
uint32_t nwords;
|
||||
WORD_TYPE *map;
|
||||
};
|
||||
|
||||
// bitmap_create - allocate a new bitmap object.
|
||||
struct bitmap *
|
||||
bitmap_create(uint32_t nbits) {
|
||||
static_assert(WORD_BITS != 0);
|
||||
assert(nbits != 0 && nbits + WORD_BITS > nbits);
|
||||
|
||||
struct bitmap *bitmap;
|
||||
if ((bitmap = kmalloc(sizeof(struct bitmap))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t nwords = ROUNDUP_DIV(nbits, WORD_BITS);
|
||||
WORD_TYPE *map;
|
||||
if ((map = kmalloc(sizeof(WORD_TYPE) * nwords)) == NULL) {
|
||||
kfree(bitmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bitmap->nbits = nbits, bitmap->nwords = nwords;
|
||||
bitmap->map = memset(map, 0xFF, sizeof(WORD_TYPE) * nwords);
|
||||
|
||||
/* mark any leftover bits at the end in use(0) */
|
||||
if (nbits != nwords * WORD_BITS) {
|
||||
uint32_t ix = nwords - 1, overbits = nbits - ix * WORD_BITS;
|
||||
|
||||
assert(nbits / WORD_BITS == ix);
|
||||
assert(overbits > 0 && overbits < WORD_BITS);
|
||||
|
||||
for (; overbits < WORD_BITS; overbits ++) {
|
||||
bitmap->map[ix] ^= (1 << overbits);
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
// bitmap_alloc - locate a cleared bit, set it, and return its index.
|
||||
int
|
||||
bitmap_alloc(struct bitmap *bitmap, uint32_t *index_store) {
|
||||
WORD_TYPE *map = bitmap->map;
|
||||
uint32_t ix, offset, nwords = bitmap->nwords;
|
||||
for (ix = 0; ix < nwords; ix ++) {
|
||||
if (map[ix] != 0) {
|
||||
for (offset = 0; offset < WORD_BITS; offset ++) {
|
||||
WORD_TYPE mask = (1 << offset);
|
||||
if (map[ix] & mask) {
|
||||
map[ix] ^= mask;
|
||||
*index_store = ix * WORD_BITS + offset;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return -E_NO_MEM;
|
||||
}
|
||||
|
||||
// bitmap_translate - according index, get the related word and mask
|
||||
static void
|
||||
bitmap_translate(struct bitmap *bitmap, uint32_t index, WORD_TYPE **word, WORD_TYPE *mask) {
|
||||
assert(index < bitmap->nbits);
|
||||
uint32_t ix = index / WORD_BITS, offset = index % WORD_BITS;
|
||||
*word = bitmap->map + ix;
|
||||
*mask = (1 << offset);
|
||||
}
|
||||
|
||||
// bitmap_test - according index, get the related value (0 OR 1) in the bitmap
|
||||
bool
|
||||
bitmap_test(struct bitmap *bitmap, uint32_t index) {
|
||||
WORD_TYPE *word, mask;
|
||||
bitmap_translate(bitmap, index, &word, &mask);
|
||||
return (*word & mask);
|
||||
}
|
||||
|
||||
// bitmap_free - according index, set related bit to 1
|
||||
void
|
||||
bitmap_free(struct bitmap *bitmap, uint32_t index) {
|
||||
WORD_TYPE *word, mask;
|
||||
bitmap_translate(bitmap, index, &word, &mask);
|
||||
assert(!(*word & mask));
|
||||
*word |= mask;
|
||||
}
|
||||
|
||||
// bitmap_destroy - free memory contains bitmap
|
||||
void
|
||||
bitmap_destroy(struct bitmap *bitmap) {
|
||||
kfree(bitmap->map);
|
||||
kfree(bitmap);
|
||||
}
|
||||
|
||||
// bitmap_getdata - return bitmap->map, return the length of bits to len_store
|
||||
void *
|
||||
bitmap_getdata(struct bitmap *bitmap, size_t *len_store) {
|
||||
if (len_store != NULL) {
|
||||
*len_store = sizeof(WORD_TYPE) * bitmap->nwords;
|
||||
}
|
||||
return bitmap->map;
|
||||
}
|
||||
|
||||
32
labcodes_answer/lab8_result/kern/fs/sfs/bitmap.h
Executable file
32
labcodes_answer/lab8_result/kern/fs/sfs/bitmap.h
Executable file
@@ -0,0 +1,32 @@
|
||||
#ifndef __KERN_FS_SFS_BITMAP_H__
|
||||
#define __KERN_FS_SFS_BITMAP_H__
|
||||
|
||||
#include <defs.h>
|
||||
|
||||
|
||||
/*
|
||||
* Fixed-size array of bits. (Intended for storage management.)
|
||||
*
|
||||
* Functions:
|
||||
* bitmap_create - allocate a new bitmap object.
|
||||
* Returns NULL on error.
|
||||
* bitmap_getdata - return pointer to raw bit data (for I/O).
|
||||
* bitmap_alloc - locate a cleared bit, set it, and return its index.
|
||||
* bitmap_mark - set a clear bit by its index.
|
||||
* bitmap_unmark - clear a set bit by its index.
|
||||
* bitmap_isset - return whether a particular bit is set or not.
|
||||
* bitmap_destroy - destroy bitmap.
|
||||
*/
|
||||
|
||||
|
||||
struct bitmap;
|
||||
|
||||
struct bitmap *bitmap_create(uint32_t nbits); // allocate a new bitmap object.
|
||||
int bitmap_alloc(struct bitmap *bitmap, uint32_t *index_store); // locate a cleared bit, set it, and return its index.
|
||||
bool bitmap_test(struct bitmap *bitmap, uint32_t index); // return whether a particular bit is set or not.
|
||||
void bitmap_free(struct bitmap *bitmap, uint32_t index); // according index, set related bit to 1
|
||||
void bitmap_destroy(struct bitmap *bitmap); // free memory contains bitmap
|
||||
void *bitmap_getdata(struct bitmap *bitmap, size_t *len_store); // return pointer to raw bit data (for I/O)
|
||||
|
||||
#endif /* !__KERN_FS_SFS_BITMAP_H__ */
|
||||
|
||||
19
labcodes_answer/lab8_result/kern/fs/sfs/sfs.c
Executable file
19
labcodes_answer/lab8_result/kern/fs/sfs/sfs.c
Executable file
@@ -0,0 +1,19 @@
|
||||
#include <defs.h>
|
||||
#include <sfs.h>
|
||||
#include <error.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* sfs_init - mount sfs on disk0
|
||||
*
|
||||
* CALL GRAPH:
|
||||
* kern_init-->fs_init-->sfs_init
|
||||
*/
|
||||
void
|
||||
sfs_init(void) {
|
||||
int ret;
|
||||
if ((ret = sfs_mount("disk0")) != 0) {
|
||||
panic("failed: sfs: sfs_mount: %e.\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
129
labcodes_answer/lab8_result/kern/fs/sfs/sfs.h
Executable file
129
labcodes_answer/lab8_result/kern/fs/sfs/sfs.h
Executable file
@@ -0,0 +1,129 @@
|
||||
#ifndef __KERN_FS_SFS_SFS_H__
|
||||
#define __KERN_FS_SFS_SFS_H__
|
||||
|
||||
#include <defs.h>
|
||||
#include <mmu.h>
|
||||
#include <list.h>
|
||||
#include <sem.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Simple FS (SFS) definitions visible to ucore. This covers the on-disk format
|
||||
* and is used by tools that work on SFS volumes, such as mksfs.
|
||||
*/
|
||||
|
||||
#define SFS_MAGIC 0x2f8dbe2a /* magic number for sfs */
|
||||
#define SFS_BLKSIZE PGSIZE /* size of block */
|
||||
#define SFS_NDIRECT 12 /* # of direct blocks in inode */
|
||||
#define SFS_MAX_INFO_LEN 31 /* max length of infomation */
|
||||
#define SFS_MAX_FNAME_LEN FS_MAX_FNAME_LEN /* max length of filename */
|
||||
#define SFS_MAX_FILE_SIZE (1024UL * 1024 * 128) /* max file size (128M) */
|
||||
#define SFS_BLKN_SUPER 0 /* block the superblock lives in */
|
||||
#define SFS_BLKN_ROOT 1 /* location of the root dir inode */
|
||||
#define SFS_BLKN_FREEMAP 2 /* 1st block of the freemap */
|
||||
|
||||
/* # of bits in a block */
|
||||
#define SFS_BLKBITS (SFS_BLKSIZE * CHAR_BIT)
|
||||
|
||||
/* # of entries in a block */
|
||||
#define SFS_BLK_NENTRY (SFS_BLKSIZE / sizeof(uint32_t))
|
||||
|
||||
/* file types */
|
||||
#define SFS_TYPE_INVAL 0 /* Should not appear on disk */
|
||||
#define SFS_TYPE_FILE 1
|
||||
#define SFS_TYPE_DIR 2
|
||||
#define SFS_TYPE_LINK 3
|
||||
|
||||
/*
|
||||
* On-disk superblock
|
||||
*/
|
||||
struct sfs_super {
|
||||
uint32_t magic; /* magic number, should be SFS_MAGIC */
|
||||
uint32_t blocks; /* # of blocks in fs */
|
||||
uint32_t unused_blocks; /* # of unused blocks in fs */
|
||||
char info[SFS_MAX_INFO_LEN + 1]; /* infomation for sfs */
|
||||
};
|
||||
|
||||
/* inode (on disk) */
|
||||
struct sfs_disk_inode {
|
||||
uint32_t size; /* size of the file (in bytes) */
|
||||
uint16_t type; /* one of SYS_TYPE_* above */
|
||||
uint16_t nlinks; /* # of hard links to this file */
|
||||
uint32_t blocks; /* # of blocks */
|
||||
uint32_t direct[SFS_NDIRECT]; /* direct blocks */
|
||||
uint32_t indirect; /* indirect blocks */
|
||||
// uint32_t db_indirect; /* double indirect blocks */
|
||||
// unused
|
||||
};
|
||||
|
||||
/* file entry (on disk) */
|
||||
struct sfs_disk_entry {
|
||||
uint32_t ino; /* inode number */
|
||||
char name[SFS_MAX_FNAME_LEN + 1]; /* file name */
|
||||
};
|
||||
|
||||
#define sfs_dentry_size \
|
||||
sizeof(((struct sfs_disk_entry *)0)->name)
|
||||
|
||||
/* inode for sfs */
|
||||
struct sfs_inode {
|
||||
struct sfs_disk_inode *din; /* on-disk inode */
|
||||
uint32_t ino; /* inode number */
|
||||
bool dirty; /* true if inode modified */
|
||||
int reclaim_count; /* kill inode if it hits zero */
|
||||
semaphore_t sem; /* semaphore for din */
|
||||
list_entry_t inode_link; /* entry for linked-list in sfs_fs */
|
||||
list_entry_t hash_link; /* entry for hash linked-list in sfs_fs */
|
||||
};
|
||||
|
||||
#define le2sin(le, member) \
|
||||
to_struct((le), struct sfs_inode, member)
|
||||
|
||||
/* filesystem for sfs */
|
||||
struct sfs_fs {
|
||||
struct sfs_super super; /* on-disk superblock */
|
||||
struct device *dev; /* device mounted on */
|
||||
struct bitmap *freemap; /* blocks in use are mared 0 */
|
||||
bool super_dirty; /* true if super/freemap modified */
|
||||
void *sfs_buffer; /* buffer for non-block aligned io */
|
||||
semaphore_t fs_sem; /* semaphore for fs */
|
||||
semaphore_t io_sem; /* semaphore for io */
|
||||
semaphore_t mutex_sem; /* semaphore for link/unlink and rename */
|
||||
list_entry_t inode_list; /* inode linked-list */
|
||||
list_entry_t *hash_list; /* inode hash linked-list */
|
||||
};
|
||||
|
||||
/* hash for sfs */
|
||||
#define SFS_HLIST_SHIFT 10
|
||||
#define SFS_HLIST_SIZE (1 << SFS_HLIST_SHIFT)
|
||||
#define sin_hashfn(x) (hash32(x, SFS_HLIST_SHIFT))
|
||||
|
||||
/* size of freemap (in bits) */
|
||||
#define sfs_freemap_bits(super) ROUNDUP((super)->blocks, SFS_BLKBITS)
|
||||
|
||||
/* size of freemap (in blocks) */
|
||||
#define sfs_freemap_blocks(super) ROUNDUP_DIV((super)->blocks, SFS_BLKBITS)
|
||||
|
||||
struct fs;
|
||||
struct inode;
|
||||
|
||||
void sfs_init(void);
|
||||
int sfs_mount(const char *devname);
|
||||
|
||||
void lock_sfs_fs(struct sfs_fs *sfs);
|
||||
void lock_sfs_io(struct sfs_fs *sfs);
|
||||
void unlock_sfs_fs(struct sfs_fs *sfs);
|
||||
void unlock_sfs_io(struct sfs_fs *sfs);
|
||||
|
||||
int sfs_rblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks);
|
||||
int sfs_wblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks);
|
||||
int sfs_rbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset);
|
||||
int sfs_wbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset);
|
||||
int sfs_sync_super(struct sfs_fs *sfs);
|
||||
int sfs_sync_freemap(struct sfs_fs *sfs);
|
||||
int sfs_clear_block(struct sfs_fs *sfs, uint32_t blkno, uint32_t nblks);
|
||||
|
||||
int sfs_load_inode(struct sfs_fs *sfs, struct inode **node_store, uint32_t ino);
|
||||
|
||||
#endif /* !__KERN_FS_SFS_SFS_H__ */
|
||||
|
||||
258
labcodes_answer/lab8_result/kern/fs/sfs/sfs_fs.c
Executable file
258
labcodes_answer/lab8_result/kern/fs/sfs/sfs_fs.c
Executable file
@@ -0,0 +1,258 @@
|
||||
#include <defs.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <kmalloc.h>
|
||||
#include <list.h>
|
||||
#include <fs.h>
|
||||
#include <vfs.h>
|
||||
#include <dev.h>
|
||||
#include <sfs.h>
|
||||
#include <inode.h>
|
||||
#include <iobuf.h>
|
||||
#include <bitmap.h>
|
||||
#include <error.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* sfs_sync - sync sfs's superblock and freemap in memroy into disk
|
||||
*/
|
||||
static int
|
||||
sfs_sync(struct fs *fs) {
|
||||
struct sfs_fs *sfs = fsop_info(fs, sfs);
|
||||
lock_sfs_fs(sfs);
|
||||
{
|
||||
list_entry_t *list = &(sfs->inode_list), *le = list;
|
||||
while ((le = list_next(le)) != list) {
|
||||
struct sfs_inode *sin = le2sin(le, inode_link);
|
||||
vop_fsync(info2node(sin, sfs_inode));
|
||||
}
|
||||
}
|
||||
unlock_sfs_fs(sfs);
|
||||
|
||||
int ret;
|
||||
if (sfs->super_dirty) {
|
||||
sfs->super_dirty = 0;
|
||||
if ((ret = sfs_sync_super(sfs)) != 0) {
|
||||
sfs->super_dirty = 1;
|
||||
return ret;
|
||||
}
|
||||
if ((ret = sfs_sync_freemap(sfs)) != 0) {
|
||||
sfs->super_dirty = 1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_get_root - get the root directory inode from disk (SFS_BLKN_ROOT,1)
|
||||
*/
|
||||
static struct inode *
|
||||
sfs_get_root(struct fs *fs) {
|
||||
struct inode *node;
|
||||
int ret;
|
||||
if ((ret = sfs_load_inode(fsop_info(fs, sfs), &node, SFS_BLKN_ROOT)) != 0) {
|
||||
panic("load sfs root failed: %e", ret);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_unmount - unmount sfs, and free the memorys contain sfs->freemap/sfs_buffer/hash_liskt and sfs itself.
|
||||
*/
|
||||
static int
|
||||
sfs_unmount(struct fs *fs) {
|
||||
struct sfs_fs *sfs = fsop_info(fs, sfs);
|
||||
if (!list_empty(&(sfs->inode_list))) {
|
||||
return -E_BUSY;
|
||||
}
|
||||
assert(!sfs->super_dirty);
|
||||
bitmap_destroy(sfs->freemap);
|
||||
kfree(sfs->sfs_buffer);
|
||||
kfree(sfs->hash_list);
|
||||
kfree(sfs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_cleanup - when sfs failed, then should call this function to sync sfs by calling sfs_sync
|
||||
*
|
||||
* NOTICE: nouse now.
|
||||
*/
|
||||
static void
|
||||
sfs_cleanup(struct fs *fs) {
|
||||
struct sfs_fs *sfs = fsop_info(fs, sfs);
|
||||
uint32_t blocks = sfs->super.blocks, unused_blocks = sfs->super.unused_blocks;
|
||||
cprintf("sfs: cleanup: '%s' (%d/%d/%d)\n", sfs->super.info,
|
||||
blocks - unused_blocks, unused_blocks, blocks);
|
||||
int i, ret;
|
||||
for (i = 0; i < 32; i ++) {
|
||||
if ((ret = fsop_sync(fs)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
warn("sfs: sync error: '%s': %e.\n", sfs->super.info, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_init_read - used in sfs_do_mount to read disk block(blkno, 1) directly.
|
||||
*
|
||||
* @dev: the block device
|
||||
* @blkno: the NO. of disk block
|
||||
* @blk_buffer: the buffer used for read
|
||||
*
|
||||
* (1) init iobuf
|
||||
* (2) read dev into iobuf
|
||||
*/
|
||||
static int
|
||||
sfs_init_read(struct device *dev, uint32_t blkno, void *blk_buffer) {
|
||||
struct iobuf __iob, *iob = iobuf_init(&__iob, blk_buffer, SFS_BLKSIZE, blkno * SFS_BLKSIZE);
|
||||
return dop_io(dev, iob, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_init_freemap - used in sfs_do_mount to read freemap data info in disk block(blkno, nblks) directly.
|
||||
*
|
||||
* @dev: the block device
|
||||
* @bitmap: the bitmap in memroy
|
||||
* @blkno: the NO. of disk block
|
||||
* @nblks: Rd number of disk block
|
||||
* @blk_buffer: the buffer used for read
|
||||
*
|
||||
* (1) get data addr in bitmap
|
||||
* (2) read dev into iobuf
|
||||
*/
|
||||
static int
|
||||
sfs_init_freemap(struct device *dev, struct bitmap *freemap, uint32_t blkno, uint32_t nblks, void *blk_buffer) {
|
||||
size_t len;
|
||||
void *data = bitmap_getdata(freemap, &len);
|
||||
assert(data != NULL && len == nblks * SFS_BLKSIZE);
|
||||
while (nblks != 0) {
|
||||
int ret;
|
||||
if ((ret = sfs_init_read(dev, blkno, data)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
blkno ++, nblks --, data += SFS_BLKSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_do_mount - mount sfs file system.
|
||||
*
|
||||
* @dev: the block device contains sfs file system
|
||||
* @fs_store: the fs struct in memroy
|
||||
*/
|
||||
static int
|
||||
sfs_do_mount(struct device *dev, struct fs **fs_store) {
|
||||
static_assert(SFS_BLKSIZE >= sizeof(struct sfs_super));
|
||||
static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_inode));
|
||||
static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_entry));
|
||||
|
||||
if (dev->d_blocksize != SFS_BLKSIZE) {
|
||||
return -E_NA_DEV;
|
||||
}
|
||||
|
||||
/* allocate fs structure */
|
||||
struct fs *fs;
|
||||
if ((fs = alloc_fs(sfs)) == NULL) {
|
||||
return -E_NO_MEM;
|
||||
}
|
||||
struct sfs_fs *sfs = fsop_info(fs, sfs);
|
||||
sfs->dev = dev;
|
||||
|
||||
int ret = -E_NO_MEM;
|
||||
|
||||
void *sfs_buffer;
|
||||
if ((sfs->sfs_buffer = sfs_buffer = kmalloc(SFS_BLKSIZE)) == NULL) {
|
||||
goto failed_cleanup_fs;
|
||||
}
|
||||
|
||||
/* load and check superblock */
|
||||
if ((ret = sfs_init_read(dev, SFS_BLKN_SUPER, sfs_buffer)) != 0) {
|
||||
goto failed_cleanup_sfs_buffer;
|
||||
}
|
||||
|
||||
ret = -E_INVAL;
|
||||
|
||||
struct sfs_super *super = sfs_buffer;
|
||||
if (super->magic != SFS_MAGIC) {
|
||||
cprintf("sfs: wrong magic in superblock. (%08x should be %08x).\n",
|
||||
super->magic, SFS_MAGIC);
|
||||
goto failed_cleanup_sfs_buffer;
|
||||
}
|
||||
if (super->blocks > dev->d_blocks) {
|
||||
cprintf("sfs: fs has %u blocks, device has %u blocks.\n",
|
||||
super->blocks, dev->d_blocks);
|
||||
goto failed_cleanup_sfs_buffer;
|
||||
}
|
||||
super->info[SFS_MAX_INFO_LEN] = '\0';
|
||||
sfs->super = *super;
|
||||
|
||||
ret = -E_NO_MEM;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
/* alloc and initialize hash list */
|
||||
list_entry_t *hash_list;
|
||||
if ((sfs->hash_list = hash_list = kmalloc(sizeof(list_entry_t) * SFS_HLIST_SIZE)) == NULL) {
|
||||
goto failed_cleanup_sfs_buffer;
|
||||
}
|
||||
for (i = 0; i < SFS_HLIST_SIZE; i ++) {
|
||||
list_init(hash_list + i);
|
||||
}
|
||||
|
||||
/* load and check freemap */
|
||||
struct bitmap *freemap;
|
||||
uint32_t freemap_size_nbits = sfs_freemap_bits(super);
|
||||
if ((sfs->freemap = freemap = bitmap_create(freemap_size_nbits)) == NULL) {
|
||||
goto failed_cleanup_hash_list;
|
||||
}
|
||||
uint32_t freemap_size_nblks = sfs_freemap_blocks(super);
|
||||
if ((ret = sfs_init_freemap(dev, freemap, SFS_BLKN_FREEMAP, freemap_size_nblks, sfs_buffer)) != 0) {
|
||||
goto failed_cleanup_freemap;
|
||||
}
|
||||
|
||||
uint32_t blocks = sfs->super.blocks, unused_blocks = 0;
|
||||
for (i = 0; i < freemap_size_nbits; i ++) {
|
||||
if (bitmap_test(freemap, i)) {
|
||||
unused_blocks ++;
|
||||
}
|
||||
}
|
||||
assert(unused_blocks == sfs->super.unused_blocks);
|
||||
|
||||
/* and other fields */
|
||||
sfs->super_dirty = 0;
|
||||
sem_init(&(sfs->fs_sem), 1);
|
||||
sem_init(&(sfs->io_sem), 1);
|
||||
sem_init(&(sfs->mutex_sem), 1);
|
||||
list_init(&(sfs->inode_list));
|
||||
cprintf("sfs: mount: '%s' (%d/%d/%d)\n", sfs->super.info,
|
||||
blocks - unused_blocks, unused_blocks, blocks);
|
||||
|
||||
/* link addr of sync/get_root/unmount/cleanup funciton fs's function pointers*/
|
||||
fs->fs_sync = sfs_sync;
|
||||
fs->fs_get_root = sfs_get_root;
|
||||
fs->fs_unmount = sfs_unmount;
|
||||
fs->fs_cleanup = sfs_cleanup;
|
||||
*fs_store = fs;
|
||||
return 0;
|
||||
|
||||
failed_cleanup_freemap:
|
||||
bitmap_destroy(freemap);
|
||||
failed_cleanup_hash_list:
|
||||
kfree(hash_list);
|
||||
failed_cleanup_sfs_buffer:
|
||||
kfree(sfs_buffer);
|
||||
failed_cleanup_fs:
|
||||
kfree(fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
sfs_mount(const char *devname) {
|
||||
return vfs_mount(devname, sfs_do_mount);
|
||||
}
|
||||
|
||||
1022
labcodes_answer/lab8_result/kern/fs/sfs/sfs_inode.c
Executable file
1022
labcodes_answer/lab8_result/kern/fs/sfs/sfs_inode.c
Executable file
File diff suppressed because it is too large
Load Diff
167
labcodes_answer/lab8_result/kern/fs/sfs/sfs_io.c
Executable file
167
labcodes_answer/lab8_result/kern/fs/sfs/sfs_io.c
Executable file
@@ -0,0 +1,167 @@
|
||||
#include <defs.h>
|
||||
#include <string.h>
|
||||
#include <dev.h>
|
||||
#include <sfs.h>
|
||||
#include <iobuf.h>
|
||||
#include <bitmap.h>
|
||||
#include <assert.h>
|
||||
|
||||
//Basic block-level I/O routines
|
||||
|
||||
/* sfs_rwblock_nolock - Basic block-level I/O routine for Rd/Wr one disk block,
|
||||
* without lock protect for mutex process on Rd/Wr disk block
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Rd/Wr
|
||||
* @blkno: the NO. of disk block
|
||||
* @write: BOOL: Read or Write
|
||||
* @check: BOOL: if check (blono < sfs super.blocks)
|
||||
*/
|
||||
static int
|
||||
sfs_rwblock_nolock(struct sfs_fs *sfs, void *buf, uint32_t blkno, bool write, bool check) {
|
||||
assert((blkno != 0 || !check) && blkno < sfs->super.blocks);
|
||||
struct iobuf __iob, *iob = iobuf_init(&__iob, buf, SFS_BLKSIZE, blkno * SFS_BLKSIZE);
|
||||
return dop_io(sfs->dev, iob, write);
|
||||
}
|
||||
|
||||
/* sfs_rwblock - Basic block-level I/O routine for Rd/Wr N disk blocks ,
|
||||
* with lock protect for mutex process on Rd/Wr disk block
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Rd/Wr
|
||||
* @blkno: the NO. of disk block
|
||||
* @nblks: Rd/Wr number of disk block
|
||||
* @write: BOOL: Read - 0 or Write - 1
|
||||
*/
|
||||
static int
|
||||
sfs_rwblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks, bool write) {
|
||||
int ret = 0;
|
||||
lock_sfs_io(sfs);
|
||||
{
|
||||
while (nblks != 0) {
|
||||
if ((ret = sfs_rwblock_nolock(sfs, buf, blkno, write, 1)) != 0) {
|
||||
break;
|
||||
}
|
||||
blkno ++, nblks --;
|
||||
buf += SFS_BLKSIZE;
|
||||
}
|
||||
}
|
||||
unlock_sfs_io(sfs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* sfs_rblock - The Wrap of sfs_rwblock function for Rd N disk blocks ,
|
||||
*
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Rd/Wr
|
||||
* @blkno: the NO. of disk block
|
||||
* @nblks: Rd/Wr number of disk block
|
||||
*/
|
||||
int
|
||||
sfs_rblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks) {
|
||||
return sfs_rwblock(sfs, buf, blkno, nblks, 0);
|
||||
}
|
||||
|
||||
/* sfs_wblock - The Wrap of sfs_rwblock function for Wr N disk blocks ,
|
||||
*
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Rd/Wr
|
||||
* @blkno: the NO. of disk block
|
||||
* @nblks: Rd/Wr number of disk block
|
||||
*/
|
||||
int
|
||||
sfs_wblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks) {
|
||||
return sfs_rwblock(sfs, buf, blkno, nblks, 1);
|
||||
}
|
||||
|
||||
/* sfs_rbuf - The Basic block-level I/O routine for Rd( non-block & non-aligned io) one disk block(using sfs->sfs_buffer)
|
||||
* with lock protect for mutex process on Rd/Wr disk block
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Rd
|
||||
* @len: the length need to Rd
|
||||
* @blkno: the NO. of disk block
|
||||
* @offset: the offset in the content of disk block
|
||||
*/
|
||||
int
|
||||
sfs_rbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset) {
|
||||
assert(offset >= 0 && offset < SFS_BLKSIZE && offset + len <= SFS_BLKSIZE);
|
||||
int ret;
|
||||
lock_sfs_io(sfs);
|
||||
{
|
||||
if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 0, 1)) == 0) {
|
||||
memcpy(buf, sfs->sfs_buffer + offset, len);
|
||||
}
|
||||
}
|
||||
unlock_sfs_io(sfs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* sfs_wbuf - The Basic block-level I/O routine for Wr( non-block & non-aligned io) one disk block(using sfs->sfs_buffer)
|
||||
* with lock protect for mutex process on Rd/Wr disk block
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @buf: the buffer uesed for Wr
|
||||
* @len: the length need to Wr
|
||||
* @blkno: the NO. of disk block
|
||||
* @offset: the offset in the content of disk block
|
||||
*/
|
||||
int
|
||||
sfs_wbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset) {
|
||||
assert(offset >= 0 && offset < SFS_BLKSIZE && offset + len <= SFS_BLKSIZE);
|
||||
int ret;
|
||||
lock_sfs_io(sfs);
|
||||
{
|
||||
if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 0, 1)) == 0) {
|
||||
memcpy(sfs->sfs_buffer + offset, buf, len);
|
||||
ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 1, 1);
|
||||
}
|
||||
}
|
||||
unlock_sfs_io(sfs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_sync_super - write sfs->super (in memory) into disk (SFS_BLKN_SUPER, 1) with lock protect.
|
||||
*/
|
||||
int
|
||||
sfs_sync_super(struct sfs_fs *sfs) {
|
||||
int ret;
|
||||
lock_sfs_io(sfs);
|
||||
{
|
||||
memset(sfs->sfs_buffer, 0, SFS_BLKSIZE);
|
||||
memcpy(sfs->sfs_buffer, &(sfs->super), sizeof(sfs->super));
|
||||
ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, SFS_BLKN_SUPER, 1, 0);
|
||||
}
|
||||
unlock_sfs_io(sfs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_sync_freemap - write sfs bitmap into disk (SFS_BLKN_FREEMAP, nblks) without lock protect.
|
||||
*/
|
||||
int
|
||||
sfs_sync_freemap(struct sfs_fs *sfs) {
|
||||
uint32_t nblks = sfs_freemap_blocks(&(sfs->super));
|
||||
return sfs_wblock(sfs, bitmap_getdata(sfs->freemap, NULL), SFS_BLKN_FREEMAP, nblks);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfs_clear_block - write zero info into disk (blkno, nblks) with lock protect.
|
||||
* @sfs: sfs_fs which will be process
|
||||
* @blkno: the NO. of disk block
|
||||
* @nblks: Rd/Wr number of disk block
|
||||
*/
|
||||
int
|
||||
sfs_clear_block(struct sfs_fs *sfs, uint32_t blkno, uint32_t nblks) {
|
||||
int ret;
|
||||
lock_sfs_io(sfs);
|
||||
{
|
||||
memset(sfs->sfs_buffer, 0, SFS_BLKSIZE);
|
||||
while (nblks != 0) {
|
||||
if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 1, 1)) != 0) {
|
||||
break;
|
||||
}
|
||||
blkno ++, nblks --;
|
||||
}
|
||||
}
|
||||
unlock_sfs_io(sfs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
44
labcodes_answer/lab8_result/kern/fs/sfs/sfs_lock.c
Executable file
44
labcodes_answer/lab8_result/kern/fs/sfs/sfs_lock.c
Executable file
@@ -0,0 +1,44 @@
|
||||
#include <defs.h>
|
||||
#include <sem.h>
|
||||
#include <sfs.h>
|
||||
|
||||
|
||||
/*
|
||||
* lock_sfs_fs - lock the process of SFS Filesystem Rd/Wr Disk Block
|
||||
*
|
||||
* called by: sfs_load_inode, sfs_sync, sfs_reclaim
|
||||
*/
|
||||
void
|
||||
lock_sfs_fs(struct sfs_fs *sfs) {
|
||||
down(&(sfs->fs_sem));
|
||||
}
|
||||
|
||||
/*
|
||||
* lock_sfs_io - lock the process of SFS File Rd/Wr Disk Block
|
||||
*
|
||||
* called by: sfs_rwblock, sfs_clear_block, sfs_sync_super
|
||||
*/
|
||||
void
|
||||
lock_sfs_io(struct sfs_fs *sfs) {
|
||||
down(&(sfs->io_sem));
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock_sfs_fs - unlock the process of SFS Filesystem Rd/Wr Disk Block
|
||||
*
|
||||
* called by: sfs_load_inode, sfs_sync, sfs_reclaim
|
||||
*/
|
||||
void
|
||||
unlock_sfs_fs(struct sfs_fs *sfs) {
|
||||
up(&(sfs->fs_sem));
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock_sfs_io - unlock the process of sfs Rd/Wr Disk Block
|
||||
*
|
||||
* called by: sfs_rwblock sfs_clear_block sfs_sync_super
|
||||
*/
|
||||
void
|
||||
unlock_sfs_io(struct sfs_fs *sfs) {
|
||||
up(&(sfs->io_sem));
|
||||
}
|
||||
Reference in New Issue
Block a user