AppleCDDAFileSystemVFSOps.c [plain text]
#ifndef __APPLE_CDDA_FS_VFS_OPS_H__
#include "AppleCDDAFileSystemVFSOps.h"
#endif
#ifndef __APPLE_CDDA_FS_VNODE_OPS_H__
#include "AppleCDDAFileSystemVNodeOps.h"
#endif
#ifndef __APPLE_CDDA_FS_DEBUG_H__
#include "AppleCDDAFileSystemDebug.h"
#endif
#ifndef __APPLE_CDDA_FS_DEFINES_H__
#include "AppleCDDAFileSystemDefines.h"
#endif
#ifndef __APPLE_CDDA_FS_UTILS_H__
#include "AppleCDDAFileSystemUtils.h"
#endif
#ifndef __AIFF_SUPPORT_H__
#include "AIFFSupport.h"
#endif
#include <sys/domain.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/ubc.h>
#include <sys/vnode.h>
#include <sys/disk.h>
#include <kern/thread.h>
#include <sys/systm.h>
#include <miscfs/specfs/specdev.h>
typedef int (*PFI)();
extern char * strncpy __P ( ( char *, const char *, size_t ) ); extern int strcmp __P ( ( const char *, const char * ) );
struct slock gCDDANumberOfInstancesLock;
UInt32 gCDDANumberOfInstances = 0;
static char gAppleCDDAName[MFSNAMELEN] = "cddafs";
extern struct vnodeopv_desc gCDDA_VNodeOperationsDesc;
extern int maxvfsconf; extern int vfs_opv_numops;
struct vfsops gCDDA_VFSOps =
{
CDDA_Mount,
CDDA_Start,
CDDA_Unmount,
CDDA_Root,
CDDA_QuotaControl,
CDDA_Statfs,
CDDA_Synchronize,
CDDA_VGet,
CDDA_FileHandleToVNodePtr,
CDDA_VNodePtrToFileHandle,
CDDA_Init,
CDDA_SystemControl
};
int
CDDA_Init ( struct vfsconf * vfsConfPtr )
{
DebugLog ( ( "CDDA_Init: Entering.\n" ) );
DebugAssert ( ( vfsConfPtr != NULL ) );
DebugLog ( ( "CDDA_Init: exiting...\n" ) );
return ( 0 );
}
int
CDDA_Mount ( struct mount * mountPtr,
char * path,
caddr_t data,
struct nameidata * nameiDataPtr,
struct proc * theProcPtr )
{
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDAArguments cddaArgs;
AppleCDDANodePtr cddaNodePtr = NULL;
struct vnode * blockDeviceVNodePtr = NULL;
size_t size = 0;
int error = 0;
struct ucred * credPtr = NULL;
struct timeval now;
struct timespec timespec;
void * xmlData = NULL;
DebugLog ( ( "CDDA_Mount: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( path != NULL ) );
DebugAssert ( ( nameiDataPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
error = copyin ( data, ( caddr_t ) &cddaArgs, sizeof ( cddaArgs ) );
if ( error != 0 )
{
goto ERROR;
}
if ( ( mountPtr->mnt_flag & MNT_RDONLY ) == 0 )
{
DebugLog ( ( "Returning EROFS...\n" ) );
error = EROFS;
goto ERROR;
}
if ( mountPtr->mnt_flag & MNT_UPDATE )
{
DebugLog ( ( "Returning EOPNOTSUPP...\n" ) );
error = EOPNOTSUPP;
goto ERROR;
}
DebugLog ( ( "CDDA_Mount: cddaArgs.device = %s.\n", cddaArgs.device ) );
NDINIT ( nameiDataPtr, LOOKUP | LOCKLEAF, FOLLOW, UIO_USERSPACE, cddaArgs.device, theProcPtr );
error = namei ( nameiDataPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Mount: Error getting device: %s.\n", cddaArgs.device ) );
goto ERROR;
}
blockDeviceVNodePtr = nameiDataPtr->ni_vp;
if ( blockDeviceVNodePtr == NULL )
{
DebugLog ( ( "CDDA_Mount: blockDeviceVNodePtr is NULL.\n" ) );
error = ENOTBLK;
goto RELEASE_DEV_NODE_ERROR;
}
if ( blockDeviceVNodePtr->v_type != VBLK )
{
DebugLog ( ( "CDDA_Mount: Not a block device.\n" ) );
error = ENOTBLK;
goto RELEASE_DEV_NODE_ERROR;
}
if ( theProcPtr->p_ucred->cr_uid != 0 )
{
error = VOP_ACCESS ( blockDeviceVNodePtr, VREAD, theProcPtr->p_ucred, theProcPtr );
if ( error != 0 )
{
goto RELEASE_DEV_NODE_ERROR;
}
}
error = VOP_OPEN ( blockDeviceVNodePtr, FREAD, FSCRED, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Mount: VOP_OPEN on block device returned an error = %d.\n", error ) );
goto RELEASE_DEV_NODE_ERROR;
}
credPtr = ( theProcPtr != NULL ) ? theProcPtr->p_ucred : NOCRED;
MALLOC ( cddaMountPtr, AppleCDDAMountPtr, sizeof ( AppleCDDAMount ), M_TEMP, M_WAITOK );
bzero ( cddaMountPtr, sizeof ( AppleCDDAMount ) );
lockinit ( &cddaMountPtr->nodeInfoLock, PINOD, "cddamountlock", 0, 0 );
cddaMountPtr->numTracks = cddaArgs.numTracks;
cddaMountPtr->fileType = cddaArgs.fileType;
cddaMountPtr->fileCreator = cddaArgs.fileCreator;
DebugLog ( ( "fileType = 0x%08x, fileCreator = 0x%08x\n", cddaMountPtr->fileType, cddaMountPtr->fileCreator ) );
MALLOC ( cddaMountPtr->nodeInfoArrayPtr, AppleCDDANodeInfoPtr,
sizeof ( AppleCDDANodeInfo ) * cddaMountPtr->numTracks, M_TEMP, M_WAITOK );
bzero ( cddaMountPtr->nodeInfoArrayPtr, sizeof ( AppleCDDANodeInfo ) * cddaMountPtr->numTracks );
( void ) copyinstr ( path, mountPtr->mnt_stat.f_mntonname, MNAMELEN - 1, &size );
bzero ( mountPtr->mnt_stat.f_mntonname + size, MNAMELEN - size );
( void ) copyinstr ( cddaArgs.device, mountPtr->mnt_stat.f_mntfromname, MNAMELEN - 1, &size );
bzero ( mountPtr->mnt_stat.f_mntfromname + size, MNAMELEN - size );
now = time;
TIMEVAL_TO_TIMESPEC ( &now, ×pec );
cddaMountPtr->mountTime = timespec;
MALLOC ( cddaMountPtr->nameData, UInt8 *, cddaArgs.nameDataSize, M_TEMP, M_WAITOK );
cddaMountPtr->nameDataSize = cddaArgs.nameDataSize;
error = copyin ( cddaArgs.nameData, ( caddr_t ) cddaMountPtr->nameData, cddaMountPtr->nameDataSize );
if ( error != 0 )
{
goto FREE_NODE_INFO_ERROR;
}
error = CreateNewCDDADirectory ( mountPtr,
( char * ) &mountPtr->mnt_stat.f_mntonname[1],
kAppleCDDARootFileID,
theProcPtr,
&cddaMountPtr->root );
if ( error != 0 )
{
DebugLog ( ( "Returning error = %d after CreateNewCDDADirectory.\n", error ) );
goto FREE_TRACK_NAMES;
}
cddaMountPtr->root->v_flag |= VROOT;
cddaNodePtr = VTOCDDA ( cddaMountPtr->root );
cddaNodePtr->blockDeviceVNodePtr = blockDeviceVNodePtr;
mountPtr->mnt_flag |= ( MNT_LOCAL | MNT_RDONLY | MNT_DOVOLFS ); mountPtr->mnt_data = ( qaddr_t ) cddaMountPtr;
vfs_getnewfsid ( mountPtr );
MALLOC ( xmlData, void *, cddaArgs.xmlFileSize, M_TEMP, M_WAITOK );
error = copyin ( cddaArgs.xmlData, ( caddr_t ) xmlData, cddaArgs.xmlFileSize );
if ( error != 0 )
{
goto FREE_ROOT_DIRECTORY;
}
error = ParseTOC ( mountPtr, cddaMountPtr->numTracks, cddaArgs.xmlFileSize, xmlData, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_Mount: Error = %d returned from ParseTOC.\n", error ) );
goto FREE_ROOT_DIRECTORY;
}
VOP_UNLOCK ( cddaMountPtr->root, 0, theProcPtr );
DebugLog ( ( "CDDA_Mount: Exiting CDDA_Mount.\n" ) );
simple_lock ( &gCDDANumberOfInstancesLock );
gCDDANumberOfInstances++;
simple_unlock ( &gCDDANumberOfInstancesLock );
return ( 0 );
FREE_ROOT_DIRECTORY:
if ( cddaMountPtr->root != NULL )
{
vrele ( cddaMountPtr->root );
vgone ( cddaMountPtr->root );
}
FREE_TRACK_NAMES:
if ( cddaMountPtr->nameData != NULL )
{
FREE ( ( caddr_t ) cddaMountPtr->nameData, M_TEMP );
cddaMountPtr->nameData = NULL;
cddaMountPtr->nameDataSize = 0;
}
FREE_NODE_INFO_ERROR:
if ( cddaMountPtr->nodeInfoArrayPtr != NULL )
{
FREE ( ( caddr_t ) cddaMountPtr->nodeInfoArrayPtr, M_TEMP );
cddaMountPtr->nodeInfoArrayPtr = NULL;
}
if ( cddaMountPtr != NULL )
{
FREE ( ( caddr_t ) cddaMountPtr, M_TEMP );
cddaMountPtr = NULL;
}
RELEASE_DEV_NODE_ERROR:
vput ( blockDeviceVNodePtr );
ERROR:
return error;
}
int
CDDA_Start ( struct mount * mountPtr,
int theFlags,
struct proc * theProcPtr )
{
DebugLog ( ( "CDDA_Start: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
DebugLog ( ( "CDDA_Start: exiting...\n" ) );
return ( 0 );
}
int
CDDA_Unmount ( struct mount * mountPtr,
int theFlags,
struct proc * theProcPtr )
{
struct vnode * rootVNodePtr = NULL;
struct vnode * xmlVNodePtr = NULL;
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodePtr cddaNodePtr = NULL;
AppleCDDANodeInfoPtr nodeInfoArrayPtr = NULL;
UInt8 * nameData = NULL;
int error = 0;
int flags = 0;
DebugLog ( ( "CDDA_Unmount: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
cddaMountPtr = VFSTOCDDA ( mountPtr );
DebugAssert ( ( cddaMountPtr != NULL ) );
rootVNodePtr = cddaMountPtr->root;
DebugAssert ( ( rootVNodePtr != NULL ) );
cddaNodePtr = VTOCDDA ( rootVNodePtr );
DebugAssert ( ( cddaNodePtr != NULL ) );
xmlVNodePtr = cddaMountPtr->xmlFileVNodePtr;
DebugAssert ( ( xmlVNodePtr != NULL ) );
if ( theFlags & MNT_FORCE )
{
DebugLog ( ( "CDDA_Unmount: Setting forceclose.\n" ) );
flags |= FORCECLOSE;
}
DebugAssert ( ( rootVNodePtr != NULL ) );
DebugLog ( ( "root node's v_usecount = %d\n", rootVNodePtr->v_usecount ) );
if ( ( UBCISVALID ( xmlVNodePtr ) && !ubc_isinuse ( xmlVNodePtr, 1 ) ) ||
!UBCINFOEXISTS ( xmlVNodePtr ) )
{
DebugLog ( ( "CDDA_Unmount: setting SKIPSYSTEM.\n" ) );
xmlVNodePtr->v_flag |= VSYSTEM;
flags |= SKIPSYSTEM;
}
error = vflush ( mountPtr, rootVNodePtr, flags );
xmlVNodePtr->v_flag &= ~VSYSTEM;
if ( error != 0 )
{
DebugLog ( ( "CDDA_Unmount: Returning error = %d after vflush.\n", error ) );
return ( error );
}
if ( rootVNodePtr->v_usecount > 1 && ( flags & FORCECLOSE != FORCECLOSE ) )
{
DebugLog ( ( "CDDA_Unmount: Returning error = %d.\n", EBUSY ) );
return ( EBUSY );
}
DebugLog ( ( "CDDA_Unmount: Closing block device.\n" ) );
cddaNodePtr->blockDeviceVNodePtr->v_specflags &= ~SI_MOUNTEDON;
( void ) VOP_CLOSE ( cddaNodePtr->blockDeviceVNodePtr,
FREAD, NOCRED, theProcPtr );
vrele ( cddaNodePtr->blockDeviceVNodePtr );
DebugLog ( ( "CDDA_Unmount: Killing the XML file.\n" ) );
vrele ( xmlVNodePtr );
DebugLog ( ( "CDDA_Unmount: released the XML file.\n" ) );
vrele ( rootVNodePtr );
DebugLog ( ( "CDDA_Unmount: released the root vnode.\n" ) );
vgone ( rootVNodePtr );
DebugLog ( ( "CDDA_Unmount: All vnodes killed!\n" ) );
nameData = VFSTONAMEINFO ( mountPtr );
DebugLog ( ( "CDDA_Unmount: Free the name data.\n" ) );
FREE ( ( caddr_t ) nameData, M_TEMP );
nodeInfoArrayPtr = VFSTONODEINFO ( mountPtr );
DebugLog ( ( "CDDA_Unmount: Free the nodeinfo array.\n" ) );
FREE ( nodeInfoArrayPtr, M_TEMP );
DebugLog ( ( "CDDA_Unmount: Free the mount point data.\n" ) );
FREE ( mountPtr->mnt_data, M_TEMP );
mountPtr->mnt_data = NULL;
simple_lock ( &gCDDANumberOfInstancesLock );
gCDDANumberOfInstances--;
simple_unlock ( &gCDDANumberOfInstancesLock );
DebugLog ( ( "CDDA_Unmount: Exiting, returning error = %d.\n", error ) );
return ( error );
}
int
CDDA_Root ( struct mount * mountPtr,
struct vnode ** vNodeHandle )
{
int error = 0;
SInt32 inode = kAppleCDDARootFileID;
DebugLog ( ( "CDDA_Root: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( vNodeHandle != NULL ) );
error = CDDA_VGet ( mountPtr, ( void * ) &inode, vNodeHandle );
DebugLog ( ( "CDDA_Root: exiting...\n" ) );
return ( error );
}
int
CDDA_Statfs ( struct mount * mountPtr,
struct statfs * statFSPtr,
struct proc * theProcPtr )
{
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodePtr rootCDDANodePtr = NULL;
DebugLog ( ( "CDDA_Statfs: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( statFSPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
cddaMountPtr = VFSTOCDDA ( mountPtr );
DebugAssert ( ( cddaMountPtr != NULL ) );
rootCDDANodePtr = VTOCDDA ( cddaMountPtr->root );
DebugAssert ( ( rootCDDANodePtr != NULL ) );
DebugAssert ( ( rootCDDANodePtr->nodeType == kAppleCDDADirectoryType ) );
statFSPtr->f_flags = 0;
statFSPtr->f_bsize = kPhysicalMediaBlockSize;
statFSPtr->f_iosize = kMaxBytesPerRead * 2;
statFSPtr->f_bfree = 0; statFSPtr->f_bavail = 0; statFSPtr->f_ffree = 0;
statFSPtr->f_files = rootCDDANodePtr->u.directory.entryCount;
statFSPtr->f_blocks = rootCDDANodePtr->u.directory.directorySize / kPhysicalMediaBlockSize;
DebugLog ( ( "CDDA_Statfs: f_files = %ld.\n", statFSPtr->f_files ) );
DebugLog ( ( "CDDA_Statfs: f_blocks = %ld.\n", statFSPtr->f_blocks ) );
if ( statFSPtr != &mountPtr->mnt_stat )
{
statFSPtr->f_type = mountPtr->mnt_vfc->vfc_typenum;
bcopy ( &mountPtr->mnt_stat.f_fsid, &statFSPtr->f_fsid, sizeof ( statFSPtr->f_fsid ) );
bcopy ( mountPtr->mnt_stat.f_mntonname, statFSPtr->f_mntonname, MNAMELEN );
bcopy ( mountPtr->mnt_stat.f_mntfromname, statFSPtr->f_mntfromname, MNAMELEN );
}
strncpy ( statFSPtr->f_fstypename, mountPtr->mnt_vfc->vfc_name, ( MFSNAMELEN - 1 ) );
statFSPtr->f_fstypename[( MFSNAMELEN - 1 )] = '\0';
DebugLog ( ( "CDDA_Statfs: Exiting...\n" ) );
return ( 0 );
}
int
CDDA_VGet ( struct mount * mountPtr,
void * ino,
struct vnode ** vNodeHandle )
{
SInt32 nodeID = 0;
AppleCDDAMountPtr cddaMountPtr = NULL;
AppleCDDANodePtr parentCDDANodePtr = NULL;
struct proc * theProcPtr = NULL;
AppleCDDANodeInfoPtr nodeInfoArrayPtr = NULL;
struct vnode * vNodePtr = NULL;
int error = 0;
int index = 0;
DebugLog ( ( "CDDA_VGet: Entering.\n" ) );
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( ino != NULL ) );
DebugAssert ( ( vNodeHandle != NULL ) );
cddaMountPtr = VFSTOCDDA ( mountPtr );
DebugAssert ( ( cddaMountPtr != NULL ) );
theProcPtr = current_proc ( );
DebugAssert ( ( theProcPtr != NULL ) );
if ( mountPtr->mnt_kern_flag & MNTK_UNMOUNT )
{
*vNodeHandle = NULL;
return ( EPERM );
}
nodeID = *( SInt32 * ) ino;
if ( nodeID == kAppleCDDARootFileID )
{
DebugLog ( ( "Root vnode asked for!\n" ) );
error = vget ( cddaMountPtr->root, LK_EXCLUSIVE | LK_RETRY, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_VGet: exiting with error = %d after vget.\n", error ) );
goto Exit;
}
*vNodeHandle = cddaMountPtr->root;
}
else if ( nodeID == kAppleCDDAXMLFileID )
{
DebugLog ( ( "XML vnode asked for!\n" ) );
error = vget ( cddaMountPtr->xmlFileVNodePtr, LK_EXCLUSIVE | LK_RETRY, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_VGet: exiting with error = %d after vget.\n", error ) );
goto Exit;
}
*vNodeHandle = cddaMountPtr->xmlFileVNodePtr;
}
else
{
parentCDDANodePtr = VTOCDDA ( cddaMountPtr->root );
nodeID -= kOffsetForFiles;
nodeInfoArrayPtr = VFSTONODEINFO ( mountPtr );
DebugAssert ( ( nodeInfoArrayPtr != NULL ) );
LOOP:
DebugLog ( ( "Locking nodeInfoLock.\n" ) );
DebugLog ( ( "Looking for nodeID = %ld.\n", nodeID ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_EXCLUSIVE, NULL, theProcPtr );
index = 0;
while ( index < ( parentCDDANodePtr->u.directory.entryCount - kNumberOfFakeDirEntries ) )
{
if ( nodeInfoArrayPtr->trackDescriptor.point == ( UInt8 ) nodeID )
{
if ( nodeInfoArrayPtr->vNodePtr != NULL )
{
vNodePtr = nodeInfoArrayPtr->vNodePtr;
DebugLog ( ( "Releasing nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
error = vget ( vNodePtr, LK_EXCLUSIVE, theProcPtr );
if ( error != 0 )
{
DebugLog ( ( "CDDA_VGet: exiting with error = %d after vget.\n", error ) );
goto LOOP;
}
*vNodeHandle = vNodePtr;
goto Exit;
}
else
{
int error2 = 0;
DebugLog ( ( "Couldn't find the vnode...Calling CreateNewCDDAFile\n" ) );
DebugLog ( ( "Releasing nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
error2 = CreateNewCDDAFile ( mountPtr,
nodeInfoArrayPtr->trackDescriptor.point + kOffsetForFiles,
nodeInfoArrayPtr,
theProcPtr,
&vNodePtr );
DebugLog ( ( "Locking nodeInfoLock.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_EXCLUSIVE, NULL, theProcPtr );
nodeInfoArrayPtr->vNodePtr = vNodePtr;
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
if ( error != 0 || error2 != 0 )
{
if ( error == 0 )
error = error2;
goto Exit;
}
*vNodeHandle = vNodePtr;
goto Exit;
}
}
index++;
nodeInfoArrayPtr++;
}
DebugLog ( ( "Releasing nodeInfoLock...About to return ENOENT.\n" ) );
error = lockmgr ( &cddaMountPtr->nodeInfoLock, LK_RELEASE, NULL, theProcPtr );
return ( ENOENT );
}
Exit:
if ( *vNodeHandle == NULL )
panic ( "*vNodeHandle == NULL" );
DebugLog ( ( "CDDA_VGet: exiting...\n" ) );
return ( error );
}
int
CDDA_FileHandleToVNodePtr ( struct mount * mountPtr,
struct fid * fileHandlePtr,
struct mbuf * networkAddressPtr,
struct vnode ** vNodeHandle,
int * exportFlagsPtr,
struct ucred ** anonymousCredHandle )
{
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( fileHandlePtr != NULL ) );
DebugAssert ( ( networkAddressPtr != NULL ) );
DebugAssert ( ( vNodeHandle != NULL ) );
DebugAssert ( ( exportFlagsPtr != NULL ) );
DebugAssert ( ( anonymousCredHandle != NULL ) );
return ( EOPNOTSUPP );
}
int
CDDA_QuotaControl ( struct mount * mountPtr,
int commands,
uid_t userID,
caddr_t arguments,
struct proc * theProcPtr )
{
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
return ( EOPNOTSUPP );
}
int
CDDA_Synchronize ( struct mount * mountPtr,
int waitForIOCompletion,
struct ucred * userCredPtr,
struct proc * theProcPtr )
{
DebugAssert ( ( mountPtr != NULL ) );
DebugAssert ( ( userCredPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
return ( 0 );
}
int
CDDA_SystemControl ( int * name,
u_int nameLength,
void * oldPtr,
size_t * oldLengthPtr,
void * newPtr,
size_t newLength,
struct proc * theProcPtr )
{
DebugAssert ( ( name != NULL ) );
DebugAssert ( ( oldPtr != NULL ) );
DebugAssert ( ( oldLengthPtr != NULL ) );
DebugAssert ( ( newPtr != NULL ) );
DebugAssert ( ( theProcPtr != NULL ) );
return ( EOPNOTSUPP );
}
int
CDDA_VNodePtrToFileHandle ( struct vnode * vNodePtr,
struct fid * fileHandlePtr )
{
DebugAssert ( ( vNodePtr != NULL ) );
DebugAssert ( ( fileHandlePtr != NULL ) );
return ( EOPNOTSUPP );
}
int
Apple_CDDA_FS_Module_Start ( int loadArgument )
{
#pragma unused ( loadArgument )
struct vfsconf * newVFSConf = NULL;
int error = 0;
int index = 0;
struct vnodeopv_entry_desc * opVectorEntryDescPtr = NULL;
boolean_t funnel_state;
int ( ***opv_desc_vector_p ) ( );
int ( **opv_desc_vector ) ( );
funnel_state = thread_funnel_set ( kernel_flock, TRUE );
DebugLog ( ( "Apple_CDDA_FS_Module_Start: Entering...\n" ) );
MALLOC ( newVFSConf, void * , sizeof ( struct vfsconf ), M_TEMP, M_WAITOK );
bzero ( newVFSConf, sizeof ( struct vfsconf ) );
simple_lock_init ( &gCDDANumberOfInstancesLock );
newVFSConf->vfc_vfsops = &gCDDA_VFSOps;
strncpy ( &newVFSConf->vfc_name[0], gAppleCDDAName, MFSNAMELEN );
newVFSConf->vfc_typenum = maxvfsconf++; newVFSConf->vfc_refcount = 0;
newVFSConf->vfc_flags = (MNT_LOCAL | MNT_DOVOLFS);
newVFSConf->vfc_mountroot = NULL; newVFSConf->vfc_next = NULL;
opv_desc_vector_p = gCDDA_VNodeOperationsDesc.opv_desc_vector_p;
MALLOC ( *opv_desc_vector_p, PFI *, vfs_opv_numops * sizeof ( PFI ), M_TEMP,
M_WAITOK );
bzero ( *opv_desc_vector_p, vfs_opv_numops * sizeof ( PFI ) );
opv_desc_vector = *opv_desc_vector_p;
for ( index = 0; gCDDA_VNodeOperationsDesc.opv_desc_ops[index].opve_op; index++ )
{
opVectorEntryDescPtr = &( gCDDA_VNodeOperationsDesc.opv_desc_ops[index] );
if ( opVectorEntryDescPtr->opve_op->vdesc_offset == 0 &&
opVectorEntryDescPtr->opve_op->vdesc_offset != VOFFSET ( vop_default ) )
{
DebugLog ( ( "Apple_CDDA_FS_Module_Start: operation %s not listed in %s.\n",
opVectorEntryDescPtr->opve_op->vdesc_name, "vfs_op_descs" ) );
panic ( "Apple_CDDA_FS_Module_Start: bad operation" );
}
opv_desc_vector[opVectorEntryDescPtr->opve_op->vdesc_offset] =
opVectorEntryDescPtr->opve_impl;
}
opv_desc_vector_p = gCDDA_VNodeOperationsDesc.opv_desc_vector_p;
opv_desc_vector = *opv_desc_vector_p;
if ( opv_desc_vector[VOFFSET( vop_default )] == NULL )
{
panic ( "Apple_CDDA_FS_Module_Start: operation vector without default routine." );
}
for ( index = 0; index < vfs_opv_numops; index++ )
{
if ( opv_desc_vector[index] == NULL )
{
opv_desc_vector[index] = opv_desc_vector[VOFFSET( vop_default )];
}
}
error = vfsconf_add ( newVFSConf );
if ( error != 0 )
{
DebugLog ( ( "Apple_CDDA_FS_Module_Start: Error = %d while adding vfsconf.\n", error ) );
}
if ( newVFSConf != NULL )
{
FREE ( newVFSConf, M_TEMP );
newVFSConf = NULL;
}
DebugLog ( ( "Apple_CDDA_FS_Module_Start: exiting...\n" ) );
( void ) thread_funnel_set ( kernel_flock, funnel_state );
return ( error );
}
int
Apple_CDDA_FS_Module_Stop ( int unloadArgument )
{
int error = 0;
boolean_t funnel_state;
funnel_state = thread_funnel_set ( kernel_flock, TRUE );
DebugLog ( ( "Apple_CDDA_FS_Module_Stop: Entering.\n" ) );
simple_lock ( &gCDDANumberOfInstancesLock );
if ( gCDDANumberOfInstances > 0 )
{
error = EBUSY;
simple_unlock ( &gCDDANumberOfInstancesLock );
( void ) thread_funnel_set ( kernel_flock, funnel_state );
return error;
}
simple_unlock ( &gCDDANumberOfInstancesLock );
error = vfsconf_del ( gAppleCDDAName );
if ( error != 0 )
{
DebugLog ( ( "Error = %d while deleting from vfsconf.\n", error ) );
}
FREE ( *gCDDA_VNodeOperationsDesc.opv_desc_vector_p, M_TEMP );
DebugLog ( ( "Apple_CDDA_FS_Module_Stop: exiting...\n" ) );
( void ) thread_funnel_set ( kernel_flock, funnel_state );
return ( error );
}