1311233cfb
This patch changes the libminixfs API and implementation such that the library is at all times aware of how many total and used blocks there are in the file system. This removes the last upcall of libminixfs into file systems (fs_blockstats). In the process, make this part of the libminixfs API a little prettier and more robust. Change file systems accordingly. Since this change only adds to MFS being unable to deal with zones and blocks having different sizes, fail to mount such file systems immediately rather than triggering an assert later. Change-Id: I078e589c7e1be1fa691cf391bf5dfddd1baf2c86
119 lines
2.9 KiB
C
119 lines
2.9 KiB
C
/*
|
|
* Functions to manage the superblock of the filesystem. These functions are
|
|
* are called at the beginning and at the end of the server.
|
|
*/
|
|
|
|
#include "inc.h"
|
|
#include <string.h>
|
|
#include <minix/com.h>
|
|
#include <minix/u64.h>
|
|
#include <minix/bdev.h>
|
|
|
|
int release_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri)
|
|
{
|
|
/* Release the root dir root. */
|
|
if (vol_pri->i_count > 0) {
|
|
put_inode(vol_pri->inode_root);
|
|
vol_pri->inode_root = NULL;
|
|
vol_pri->i_count = 0;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
|
size_t __unused address)
|
|
{
|
|
/*
|
|
* This function fullfill the super block data structure using the
|
|
* information contained in the buffer.
|
|
*/
|
|
struct iso9660_dir_record *root_record;
|
|
struct inode *root;
|
|
struct dir_extent *extent;
|
|
|
|
if (vol_pri->i_count > 0)
|
|
release_vol_pri_desc(vol_pri);
|
|
|
|
memcpy(vol_pri, buf, 2048);
|
|
|
|
/* Check various fields for consistency. */
|
|
if ((memcmp(vol_pri->standard_id, "CD001",
|
|
ISO9660_SIZE_STANDARD_ID) != 0) ||
|
|
(vol_pri->vd_version != 1) ||
|
|
(vol_pri->logical_block_size_l < 2048) ||
|
|
(vol_pri->file_struct_ver != 1))
|
|
return EINVAL;
|
|
|
|
lmfs_set_blocksize(vol_pri->logical_block_size_l);
|
|
lmfs_set_blockusage(vol_pri->volume_space_size_l,
|
|
vol_pri->volume_space_size_l);
|
|
|
|
/* Read root directory record. */
|
|
root_record = (struct iso9660_dir_record *)vol_pri->root_directory;
|
|
root = alloc_inode();
|
|
extent = alloc_extent();
|
|
|
|
extent->location =
|
|
root_record->loc_extent_l + root_record->ext_attr_rec_length;
|
|
extent->length =
|
|
root_record->data_length_l / vol_pri->logical_block_size_l;
|
|
if (root_record->data_length_l % vol_pri->logical_block_size_l)
|
|
extent->length++;
|
|
|
|
if (read_inode(root, extent, 0, NULL) != OK) {
|
|
free_extent(extent);
|
|
put_inode(root);
|
|
return EINVAL;
|
|
}
|
|
|
|
free_extent(extent);
|
|
vol_pri->inode_root = root;
|
|
vol_pri->i_count = 1;
|
|
|
|
return OK;
|
|
}
|
|
|
|
int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
|
|
{
|
|
/*
|
|
* This function reads from a ISO9660 filesystem (in the device dev)
|
|
* the super block and saves it in vol_pri.
|
|
*/
|
|
size_t offset;
|
|
int vol_ok = FALSE, vol_pri_flag = FALSE;
|
|
int r;
|
|
static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
|
|
int i = 0;
|
|
|
|
for(offset = ISO9660_SUPER_BLOCK_POSITION;
|
|
!vol_ok && i++ < MAX_ATTEMPTS;
|
|
offset += ISO9660_MIN_BLOCK_SIZE) {
|
|
/* Read the sector of the super block. */
|
|
r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE,
|
|
BDEV_NOFLAGS);
|
|
|
|
if (r != ISO9660_MIN_BLOCK_SIZE) {
|
|
/* Damaged sector or what? */
|
|
return EINVAL;
|
|
}
|
|
|
|
if ((sbbuf[0] & BYTE) == VD_PRIMARY) {
|
|
/* Copy the buffer in the data structure. */
|
|
if (create_vol_pri_desc(vol_pri, sbbuf, offset) == OK) {
|
|
vol_pri_flag = TRUE;
|
|
}
|
|
}
|
|
|
|
if ((sbbuf[0] & BYTE) == VD_SET_TERM) {
|
|
/* I dont need to save anything about it */
|
|
vol_ok = TRUE;
|
|
}
|
|
}
|
|
|
|
if (vol_ok == FALSE || vol_pri_flag == FALSE)
|
|
return EINVAL; /* If no superblock was found... */
|
|
else
|
|
return OK; /* otherwise. */
|
|
}
|