The "bdev" library provides basic primitives for file systems to talk to block device drivers, hiding the details of the underlying protocol and interaction model. This version of libbdev is rather basic. It is planned to support the following features in the long run: - asynchronous requests and replies; - recovery support for underlying block drivers; - retrying of failed I/O requests. The commit also changes our block-based file systems (mfs, ext2, isofs) to make use of libbdev.
111 lines
2.8 KiB
C
111 lines
2.8 KiB
C
#include "inc.h"
|
|
#include <minix/vfsif.h>
|
|
#include <minix/ds.h>
|
|
#include <minix/bdev.h>
|
|
#include "const.h"
|
|
#include "glo.h"
|
|
|
|
|
|
/*===========================================================================*
|
|
* fs_readsuper *
|
|
*===========================================================================*/
|
|
PUBLIC int fs_readsuper() {
|
|
|
|
cp_grant_id_t label_gid;
|
|
size_t label_len;
|
|
int r = OK;
|
|
endpoint_t driver_e;
|
|
int readonly;
|
|
|
|
fs_dev = fs_m_in.REQ_DEV;
|
|
label_gid = fs_m_in.REQ_GRANT;
|
|
label_len = fs_m_in.REQ_PATH_LEN;
|
|
readonly = 1; /* Always mount devices read only. */
|
|
|
|
if (label_len > sizeof(fs_dev_label))
|
|
return(EINVAL);
|
|
|
|
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
|
|
label_len, D);
|
|
if (r != OK) {
|
|
printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
|
|
return(EINVAL);
|
|
}
|
|
|
|
r = ds_retrieve_label_endpt(fs_dev_label, &driver_e);
|
|
if (r != OK) {
|
|
printf("ISOFS %s:%d ds_retrieve_label_endpt failed for '%s': %d\n",
|
|
__FILE__, __LINE__, fs_dev_label, r);
|
|
return(EINVAL);
|
|
}
|
|
|
|
/* Map the driver endpoint for this major */
|
|
bdev_driver(fs_dev, driver_e);
|
|
|
|
/* Open the device the file system lives on */
|
|
if (bdev_open(fs_dev, readonly ? R_BIT : (R_BIT|W_BIT)) != OK) {
|
|
return(EINVAL);
|
|
}
|
|
|
|
/* Read the superblock */
|
|
r = read_vds(&v_pri, fs_dev);
|
|
if (r != OK) {
|
|
bdev_close(fs_dev);
|
|
return(r);
|
|
}
|
|
|
|
/* Return some root inode properties */
|
|
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root);
|
|
fs_m_out.RES_MODE = v_pri.dir_rec_root->d_mode;
|
|
fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size;
|
|
fs_m_out.RES_UID = SYS_UID; /* Always root */
|
|
fs_m_out.RES_GID = SYS_GID; /* operator */
|
|
|
|
fs_m_out.RES_CONREQS = 1; /* We can handle only 1 request at a time */
|
|
|
|
return(r);
|
|
}
|
|
|
|
|
|
/*===========================================================================*
|
|
* fs_mountpoint *
|
|
*===========================================================================*/
|
|
PUBLIC int fs_mountpoint()
|
|
{
|
|
/* This function looks up the mount point, it checks the condition whether
|
|
* the partition can be mounted on the inode or not.
|
|
*/
|
|
|
|
register struct dir_record *rip;
|
|
int r = OK;
|
|
|
|
/* Temporarily open the file. */
|
|
if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL)
|
|
return(EINVAL);
|
|
|
|
if (rip->d_mountpoint)
|
|
r = EBUSY;
|
|
|
|
/* If the inode is not a dir returns error */
|
|
if ((rip->d_mode & I_TYPE) != I_DIRECTORY)
|
|
r = ENOTDIR;
|
|
|
|
release_dir_record(rip);
|
|
|
|
if (r == OK)
|
|
rip->d_mountpoint = TRUE;
|
|
|
|
return(r);
|
|
}
|
|
|
|
|
|
/*===========================================================================*
|
|
* fs_unmount *
|
|
*===========================================================================*/
|
|
PUBLIC int fs_unmount(void) {
|
|
release_v_pri(&v_pri); /* Release the super block */
|
|
bdev_close(fs_dev);
|
|
unmountdone = TRUE;
|
|
return(OK);
|
|
}
|
|
|