Add primary cache management feature to libminixfs as mfs and ext2 currently do separately, remove cache code from mfs and ext2, and make them use the libminixfs interface. This makes all fields of the buf struct private to libminixfs and FS clients aren't supposed to access them at all. Only the opaque 'void *data' field (the FS block contents, used to be called bp) is to be accessed by the FS client. The main purpose is to implement the interface to the 2ndary vm cache just once, get rid of some code duplication, and add a little abstraction to reduce the code inertia of the whole caching business. Some minor sanity checking and prohibition done by mfs in this code as removed from the generic primary cache code as a result: - checking all inodes are not in use when allocating/resizing the cache - checking readonly filesystems aren't written to - checking the superblock isn't written to on mounted filesystems The minixfslib code relies on fs_blockstats() in the client filesystem to return some FS usage information.
92 lines
2.2 KiB
C
92 lines
2.2 KiB
C
/* Created (MFS based):
|
|
* February 2010 (Evgeniy Ivanov)
|
|
*/
|
|
|
|
#include "fs.h"
|
|
#include <assert.h>
|
|
#include <minix/vfsif.h>
|
|
#include <minix/bdev.h>
|
|
#include "inode.h"
|
|
#include "super.h"
|
|
|
|
/*===========================================================================*
|
|
* fs_sync *
|
|
*===========================================================================*/
|
|
int fs_sync()
|
|
{
|
|
/* Perform the sync() system call. Flush all the tables.
|
|
* The order in which the various tables are flushed is critical. The
|
|
* blocks must be flushed last, since rw_inode() leaves its results in
|
|
* the block cache.
|
|
*/
|
|
struct inode *rip;
|
|
|
|
assert(lmfs_nr_bufs() > 0);
|
|
|
|
if (superblock->s_rd_only)
|
|
return(OK); /* nothing to sync */
|
|
|
|
/* Write all the dirty inodes to the disk. */
|
|
for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
|
|
if(rip->i_count > 0 && rip->i_dirt == IN_DIRTY) rw_inode(rip, WRITING);
|
|
|
|
lmfs_flushall();
|
|
|
|
if (superblock->s_dev != NO_DEV) {
|
|
superblock->s_wtime = clock_time();
|
|
write_super(superblock);
|
|
}
|
|
|
|
return(OK); /* sync() can't fail */
|
|
}
|
|
|
|
|
|
/*===========================================================================*
|
|
* fs_flush *
|
|
*===========================================================================*/
|
|
int fs_flush()
|
|
{
|
|
/* Flush the blocks of a device from the cache after writing any dirty blocks
|
|
* to disk.
|
|
*/
|
|
dev_t dev = (dev_t) fs_m_in.REQ_DEV;
|
|
|
|
if(dev == fs_dev) return(EBUSY);
|
|
|
|
lmfs_flushall();
|
|
lmfs_invalidate(dev);
|
|
|
|
return(OK);
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* fs_new_driver *
|
|
*===========================================================================*/
|
|
int fs_new_driver(void)
|
|
{
|
|
/* Set a new driver endpoint for this device. */
|
|
dev_t dev;
|
|
cp_grant_id_t label_gid;
|
|
size_t label_len;
|
|
char label[sizeof(fs_dev_label)];
|
|
int r;
|
|
|
|
dev = (dev_t) fs_m_in.REQ_DEV;
|
|
label_gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
|
|
label_len = (size_t) fs_m_in.REQ_PATH_LEN;
|
|
|
|
if (label_len > sizeof(label))
|
|
return(EINVAL);
|
|
|
|
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
|
|
(vir_bytes) label, label_len);
|
|
|
|
if (r != OK) {
|
|
printf("ext2: fs_new_driver safecopyfrom failed (%d)\n", r);
|
|
return(EINVAL);
|
|
}
|
|
|
|
bdev_driver(dev, label);
|
|
|
|
return(OK);
|
|
}
|