hsfs_vfsops.c revision cf83459a3a773fbf09bbf2d90428884d292a6584
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* VFS operations for High Sierra filesystem
*/
#include <sys/isa_defs.h>
#include <sys/sysmacros.h>
#include <sys/pathname.h>
#include <sys/bootconf.h>
/*
* These are needed for the CDROMREADOFFSET Code
*/
#define HSFS_CLKSET
/*
* Options for mount.
*/
#define HOPT_GLOBAL MNTOPT_GLOBAL
#define HOPT_NOGLOBAL MNTOPT_NOGLOBAL
#define HOPT_MAPLCASE "maplcase"
#define HOPT_NOMAPLCASE "nomaplcase"
#define HOPT_NOTRAILDOT "notraildot"
#define HOPT_TRAILDOT "traildot"
#define HOPT_NRR "nrr"
#define HOPT_RR "rr"
static mntopt_t hsfs_options[] = {
};
static mntopts_t hsfs_proto_opttbl = {
sizeof (hsfs_options) / sizeof (mntopt_t),
};
static int hsfsinit(int, char *);
"hsfs",
VSW_HASPROTO, /* We don't suppport remounting */
};
};
static struct modlinkage modlinkage = {
};
char _depends_on[] = "fs/specfs";
int
_init()
{
return (mod_install(&modlinkage));
}
int
_fini()
{
return (EBUSY);
}
int
{
}
/* default mode, uid, gid */
uid_t hsfs_default_uid = 0;
static void hs_copylabel(struct hs_volume *, unsigned char *);
static int hsfsfstype;
static int
{
static const fs_operation_def_t hsfs_vfsops_template[] = {
};
int error;
if (error != 0) {
return (error);
}
if (error != 0) {
(void) vfs_freevfsops_by_type(fstype);
return (error);
}
hsfsfstype = fstype;
return (0);
}
/*ARGSUSED*/
static int
{
int vnode_busy;
int error;
int flags; /* this will hold the mount specific data */
return (error);
return (ENOTDIR);
/* mount option must be read only, else mount will be rejected */
return (EROFS);
/*
* We already told the framework that we don't support remounting.
*/
return (EBUSY);
}
/*
* Check for the options that actually affect things
* at our level.
*/
flags = 0;
flags |= HSFSMNT_NORRIP;
if (error)
return (error);
return (error);
}
/*
* If the device is a tape, return error
*/
return (ENOTBLK);
}
/*
* Mount the filesystem.
*/
return (error);
}
/*ARGSUSED*/
static int
int flag,
{
return (EPERM);
/*
* forced unmount is not supported by this file system
* and thus, ENOTSUP is being returned.
*/
return (ENOTSUP);
return (EBUSY);
/* destroy all old pages and hsnodes for this vfs */
if (hs_synchash(vfsp))
return (EBUSY);
break;
}
panic("hsfs_unmount: vfs not mounted?");
/*NOTREACHED*/
}
/* free path table space */
/* free path table index table */
/* free "mounted on" pathame */
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
/*ARGSUSED*/
static int
{
return (EINVAL);
return (0);
}
/*
* Previously nodeid was declared as uint32_t. This has been changed
* to conform better with the ISO9660 standard. The standard states that
* a LBN can be a 32 bit number, as the MAKE_NODEID macro shifts this
* LBN 11 places left (LBN_TO_BYTE) and then shifts the result 5 right
* (divide by 32) we are left with the potential of an overflow if
* confined to a 32 bit value.
*/
static int
{
int error;
/*
* Look for vnode on hashlist.
* If found, it's now active and the refcnt was incremented.
*/
/*
* Not in cache, so we need to remake it.
* hs_remakenode() will read the directory entry
* and then check again to see if anyone else has
* put it in the cache.
*/
return (error);
}
return (0);
}
/*
* Compute a CD-ROM fsid by checksumming the first 64K of data on the CD
* We use the 'fsp' argument to determine the location of the root
* directory entry, and we start reading from there.
*/
static int
{
int error;
int fsid;
/*
* An error on read or a partial read means we asked
* for a nonexistant/corrupted piece of the device
* (including past-the-end of the media). Don't
* try to use the checksumming method then.
*/
int i;
fsid = 0;
for (i = 0; i < CHECKSUM_SIZE / sizeof (int); i++)
} else {
/*
* Fallback - use creation date
*/
}
return (fsid);
}
/*ARGSUSED*/
static int
char *path,
int mount_flags,
int isroot)
{
int error;
int fsid;
/*
* Open the device
*/
/*
* Open the target device (file) for read only.
*/
return (error);
}
/*
* Refuse to go any further if this
* device is being used for swapping
*/
goto cleanup;
}
goto cleanup;
}
/*
* Make sure we have a nonzero size partition.
* The current version of the SD driver will *not* fail the open
* of such a partition so we have to check for it here.
*/
goto cleanup;
}
/*
* Init a new hsfs structure.
*/
/* hardwire perms, uid, gid */
/*
* Look for a Standard File Structure Volume Descriptor,
* of which there must be at least one.
* If found, check for volume size consistency.
*
* XXX - va_size may someday not be large enough to do this correctly.
*/
if (error)
goto cleanup;
/*
* Generate a file system ID from the CD-ROM,
* and check it for uniqueness.
*
* What we are aiming for is some chance of integrity
* across disk change. That is, if a client has an fhandle,
* it will be valid as long as the same disk is mounted.
*/
} else /* make sure that the fsid is unique */
break;
}
}
hs_mounttab = fsp;
/*
* If the root directory does not appear to be
* valid, use what it points to as "." instead.
* Some Defense Mapping Agency disks are non-conformant
* in this way.
*/
goto cleanup;
}
} else {
}
/* mark vnode as VROOT */
/* Here we take care of some special case stuff for mountroot */
if (isroot) {
}
/* XXX - ignore the path table for now */
if (use_rrip)
/*
* if RRIP, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags
*/
if (IS_RRIP_IMPLEMENTED(fsp))
/* set the magic word */
return (0);
if (fsp)
return (error);
}
/*
* hs_findhsvol()
*
* Locate the Standard File Structure Volume Descriptor and
* parse it into an hs_volume structure.
*
* XXX - May someday want to look for Coded Character Set FSVD, too.
*/
static int
{
int i;
int error;
if (error != 0) {
return (error);
}
for (i = 0; i < HSV_ID_STRLEN; i++)
goto cantfind;
goto cantfind;
switch (HSV_DESC_TYPE(volp)) {
case VD_SFS:
/* Standard File Structure */
return (error);
case VD_CCFS:
/* Coded Character File Structure */
case VD_BOOT:
case VD_UNSPEC:
case VD_EOV:
break;
}
++secno;
if (error != 0) {
error);
return (error);
}
}
return (EINVAL);
}
/*
* hs_parsehsvol
*
* Parse the Standard File Structure Volume Descriptor into
* an hs_volume structure. We can't just bcopy it into the
* structure because of byte-ordering problems.
*
*/
static int
{
"SFSVD is zero");
return (EINVAL);
}
#if defined(_LITTLE_ENDIAN)
#else
#endif
/*
* Make sure that lbn_size is a power of two and otherwise valid.
*/
"hsfs: %d-byte logical block size not supported",
return (EINVAL);
}
}
/*
* hs_findisovol()
*
* Locate the Primary Volume Descriptor
* parse it into an hs_volume structure.
*
* XXX - Supplementary, Partition not yet done
*/
static int
{
int i;
int error;
int foundpvd = 0;
if (error != 0) {
return (error);
}
for (i = 0; i < ISO_ID_STRLEN; i++)
goto cantfind;
goto cantfind;
switch (ISO_DESC_TYPE(volp)) {
case ISO_VD_PVD:
/* Standard File Structure */
if (foundpvd != 1) {
return (error);
}
foundpvd = 1;
}
break;
case ISO_VD_SVD:
/* Supplementary Volume Descriptor */
break;
case ISO_VD_BOOT:
break;
case ISO_VD_VPD:
/* currently cannot handle partition */
break;
case VD_EOV:
break;
}
++secno;
if (error != 0) {
error);
return (error);
}
}
if (foundpvd) {
return (0);
}
return (EINVAL);
}
/*
* hs_parseisovol
*
* Parse the Primary Volume Descriptor into an hs_volume structure.
*
*/
static int
{
"PVD is zero");
return (EINVAL);
}
#if defined(_LITTLE_ENDIAN)
#else
#endif
/*
* Make sure that lbn_size is a power of two and otherwise valid.
*/
"hsfs: %d-byte logical block size not supported",
return (EINVAL);
}
}
/*
* Common code for mount and umount.
* Check that the user's argument is a reasonable
* thing on which to mount, and return the device number if so.
*/
static int
{
int error;
/*
* Get the device to be mounted
*/
if (error) {
return (ENODEV); /* needs translation */
}
return (error);
}
return (ENOTBLK);
}
/*
* Can we read from the device?
*/
return (error);
}
/*
* Ensure that this device isn't already mounted,
* unless this is a REMOUNT request or we are told to suppress
* mount checks.
*/
if ((flags & MS_NOCHECK) == 0) {
return (EBUSY);
return (EBUSY);
}
return (ENXIO);
return (0);
}
static void
{
/* cdrom volid is at most 32 bytes */
}
/*
* Mount root file system.
* "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to
* remount the root file system, and ROOT_UNMOUNT if called to
* unmount the root (e.g., as part of a system shutdown).
*
* XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP
* operation, goes along with auto-configuration. A mechanism should be
* provided by which machine-INdependent code in the kernel can say "get me the
* right root file system" and "get me the right initial swap area", and have
* that done in what may well be a machine-dependent fashion.
* Unfortunately, it is also file-system-type dependent (NFS gets it via
* bootparams calls, UFS gets it from various and sundry machine-dependent
* mechanisms, as SPECFS does for swap).
*/
static int
{
int error;
static int hsfsrootdone = 0;
if (hsfsrootdone++)
return (EBUSY);
rootdev = getrootdev();
return (ENODEV);
} else if (why == ROOT_REMOUNT) {
return (0);
} else if (why == ROOT_UNMOUNT) {
return (0);
}
if (error) {
return (error);
}
/*
* XXX - assumes root device is not indirect, because we don't set
* rootvp. Is rootvp used for anything? If so, make another arg
* to mountfs.
*/
if (error) {
if (rootvp) {
}
return (error);
}
#ifdef HSFS_CLKSET
clkset(-1L);
} else
} else
#else /* HSFS_CLKSET */
clkset(-1L);
#endif /* HSFS_CLKSET */
return (0);
}
/*
* hs_findvoldesc()
*
* Return the sector where the volume descriptor lives. This is
* a fixed value for "normal" cd-rom's, but can change for
* multisession cd's.
*
* desc_sec is the same for high-sierra and iso 9660 formats, why
* there are two differnt #defines used in the code for this is
* beyond me. These are standards, cast in concrete, right?
* To be general, however, this function supports passing in different
* values.
*/
static int
{
int secno;
int error;
int rval; /* ignored */
#ifdef CDROMREADOFFSET
/*
* Issue the Read Offset ioctl directly to the
* device. Ignore any errors and set starting
* secno to the default, otherwise add the
* VOLDESC sector number to the offset.
*/
if (error) {
} else {
}
#else
#endif
return (secno);
}