Skip to content

Commit

Permalink
Fix #456, improve filesystem type identification
Browse files Browse the repository at this point in the history
Add a distinct type for FS_BASED entries, and an UNKNOWN value
for when a type is actually not yet identified.

This can be used to identify the FS type first at the shared
layer, then in the implementation layer as a fallback option
if not identifiable in the shared layer.

Use the volume name prefix "RAM" as a hint that the volume
is supposed to be a VOLATILE disk as opposed to a normal disk.
This is done in shared layer so it applies to all OS types.
  • Loading branch information
jphickey committed May 15, 2020
1 parent b251466 commit b51f5b6
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 90 deletions.
20 changes: 15 additions & 5 deletions src/os/inc/osapi-os-filesys.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ int32 OS_rmdir (const char *path);
* @brief Create a fixed mapping between an existing directory and a virtual OSAL mount point.
*
* This mimics the behavior of a "FS_BASED" entry in the VolumeTable but is registered
* at runtime. It is intended to be called by the PSP/BSP prior to starting the OSAL.
* at runtime. It is intended to be called by the PSP/BSP prior to starting the application.
*
* @param[out] filesys_id An OSAL ID reflecting the file system
* @param[in] phys_path The native system directory (an existing mount point)
Expand All @@ -781,10 +781,15 @@ int32 OS_FileSysAddFixedMap(uint32 *filesys_id, const char *phys_path,
* Makes a file system on the target. Highly dependent on underlying OS and
* dependent on OS volume table definition.
*
* @note The "volname" parameter of RAM disks should always begin with the string "RAM",
* e.g. "RAMDISK" or "RAM0","RAM1", etc if multiple devices are created. The underlying
* implementation uses this to select the correct filesystem type/format, and this may
* also be used to differentiate between RAM disks and real physical disks.
*
* @param[in] address The address at which to start the new disk. If address == 0
* space will be allocated by the OS.
* @param[in] devname The name of the "generic" drive
* @param[in] volname The name of the volume (if needed, used on VxWorks)
* @param[in] devname The underlying kernel device to use, if applicable.
* @param[in] volname The name of the volume (see note)
* @param[in] blocksize The size of a single block on the drive
* @param[in] numblocks The number of blocks to allocate for the drive
*
Expand Down Expand Up @@ -816,10 +821,15 @@ int32 OS_mount (const char *devname, const char *mountpoint);
*
* Initializes a file system on the target.
*
* @note The "volname" parameter of RAM disks should always begin with the string "RAM",
* e.g. "RAMDISK" or "RAM0","RAM1", etc if multiple devices are created. The underlying
* implementation uses this to select the correct filesystem type/format, and this may
* also be used to differentiate between RAM disks and real physical disks.
*
* @param[in] address The address at which to start the new disk. If address == 0,
* then space will be allocated by the OS
* @param[in] devname The name of the "generic" drive
* @param[in] volname The name of the volume (if needed, used on VxWorks)
* @param[in] devname The underlying kernel device to use, if applicable.
* @param[in] volname The name of the volume (see note)
* @param[in] blocksize The size of a single block on the drive
* @param[in] numblocks The number of blocks to allocate for the drive
*
Expand Down
23 changes: 19 additions & 4 deletions src/os/posix/src/os-impl-filesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
/****************************************************************************************
GLOBAL DATA
***************************************************************************************/
const char OS_POSIX_DEVICEFILE_PREFIX[] = "/dev/";

/****************************************************************************************
Filesys API
Expand Down Expand Up @@ -93,13 +94,26 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id)
VOLATILE_DISK_LOC_MAX
};

/*
* Determine basic type of filesystem, if not already known
*/
if (local->fstype == OS_FILESYS_TYPE_UNKNOWN &&
strncmp(local->device_name, OS_POSIX_DEVICEFILE_PREFIX, sizeof(OS_POSIX_DEVICEFILE_PREFIX)-1) == 0)
{
/*
* If referring to a real device in the /dev filesystem,
* then assume it is a normal disk.
*/
local->fstype = OS_FILESYS_TYPE_NORMAL_DISK;
}

/*
* For RAM_DISK volumes, there are two options:
* For VOLATILE volumes, there are two options:
* - The /dev/shm filesystem, if it exists
* - The /tmp filesystem
*
* The /dev/shm is preferable because it should actually be a ramdisk.
* The /dev/shm is preferable because it should actually be a ramdisk, but
* it is system-specific - should exist on Linux if it is mounted.
* The /tmp file system might be a regular persistent disk, but should always exist
* on any POSIX-compliant OS.
*/
Expand Down Expand Up @@ -252,9 +266,10 @@ int32 OS_FileSysMountVolume_Impl (uint32 filesys_id)
* mount point exists. For any other FS type, trigger an
* error to indicate that it is not implemented in this OSAL.
*/
if (local->fstype != OS_FILESYS_TYPE_VOLATILE_DISK)
if (local->fstype != OS_FILESYS_TYPE_VOLATILE_DISK &&
local->fstype != OS_FILESYS_TYPE_FS_BASED)
{
/* the mount command is only allowed on a ram disk */
/* the mount command is not implemented for this FS type */
return OS_ERR_NOT_IMPLEMENTED;
}

Expand Down
60 changes: 45 additions & 15 deletions src/os/rtems/src/os-impl-filesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ typedef struct
GLOBAL DATA
***************************************************************************************/

/*
* The prefix used for "real" device nodes on this platform
*/
const char OS_RTEMS_DEVICEFILE_PREFIX[] = "/dev/";

/*
* The implementation-specific file system state table.
* This keeps record of the RTEMS driver and mount options for each filesystem
Expand Down Expand Up @@ -116,12 +121,25 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id)
return_code = OS_ERR_NOT_IMPLEMENTED;
memset(impl,0,sizeof(*impl));

/*
* Determine basic type of filesystem, if not already known
*/
if (local->fstype == OS_FILESYS_TYPE_UNKNOWN &&
strncmp(local->device_name, OS_RTEMS_DEVICEFILE_PREFIX, sizeof(OS_RTEMS_DEVICEFILE_PREFIX)-1) == 0)
{
/*
* If referring to a real device in the /dev filesystem,
* then assume it is a normal disk.
*/
local->fstype = OS_FILESYS_TYPE_NORMAL_DISK;
}

/*
* Take action based on the type of volume
*/
switch (local->fstype)
{
case OS_FILESYS_TYPE_DEFAULT:
case OS_FILESYS_TYPE_FS_BASED:
{
/*
* This "mount" type is basically not a mount at all,
Expand Down Expand Up @@ -244,7 +262,7 @@ int32 OS_FileSysFormatVolume_Impl (uint32 filesys_id)

switch(local->fstype)
{
case OS_FILESYS_TYPE_DEFAULT:
case OS_FILESYS_TYPE_FS_BASED:
{
/*
* In this mode a format is a no-op, as it is simply a directory
Expand Down Expand Up @@ -323,14 +341,22 @@ int32 OS_FileSysMountVolume_Impl (uint32 filesys_id)
}

/*
** Mount the Disk
*/
if ( mount(impl->blockdev_name, local->system_mountpt,
impl->mount_fstype, impl->mount_options, impl->mount_data) != 0 )
* Only do the mount() syscall for real devices.
* For other types of filesystem mounts (e.g. FS_BASED), this is a no-op
*/
if (local->fstype == OS_FILESYS_TYPE_VOLATILE_DISK ||
local->fstype == OS_FILESYS_TYPE_NORMAL_DISK)
{
OS_DEBUG("OSAL: Error: mount of %s to %s failed: %s\n",
impl->blockdev_name, local->system_mountpt, strerror(errno));
return OS_ERROR;
/*
** Mount the Disk
*/
if ( mount(impl->blockdev_name, local->system_mountpt,
impl->mount_fstype, impl->mount_options, impl->mount_data) != 0 )
{
OS_DEBUG("OSAL: Error: mount of %s to %s failed: %s\n",
impl->blockdev_name, local->system_mountpt, strerror(errno));
return OS_ERROR;
}
}

return OS_SUCCESS;
Expand All @@ -350,13 +376,17 @@ int32 OS_FileSysUnmountVolume_Impl (uint32 filesys_id)
{
OS_filesys_internal_record_t *local = &OS_filesys_table[filesys_id];

/*
** Try to unmount the disk
*/
if ( unmount(local->system_mountpt) < 0)
if (local->fstype == OS_FILESYS_TYPE_VOLATILE_DISK ||
local->fstype == OS_FILESYS_TYPE_NORMAL_DISK)
{
OS_DEBUG("OSAL: RTEMS unmount of %s failed :%s\n",local->system_mountpt, strerror(errno));
return OS_ERROR;
/*
** Try to unmount the disk
*/
if ( unmount(local->system_mountpt) < 0)
{
OS_DEBUG("OSAL: RTEMS unmount of %s failed :%s\n",local->system_mountpt, strerror(errno));
return OS_ERROR;
}
}

return OS_SUCCESS;
Expand Down
3 changes: 2 additions & 1 deletion src/os/shared/inc/os-shared-filesys.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
*/
enum
{
OS_FILESYS_TYPE_DEFAULT = 0, /**< Unspecified or unknown file system type */
OS_FILESYS_TYPE_UNKNOWN = 0, /**< Unspecified or unknown file system type */
OS_FILESYS_TYPE_FS_BASED, /**< A emulated virtual file system that maps to another file system location */
OS_FILESYS_TYPE_NORMAL_DISK, /**< A traditional disk drive or something that emulates one */
OS_FILESYS_TYPE_VOLATILE_DISK, /**< A temporary/volatile file system or RAM disk */
OS_FILESYS_TYPE_MTD, /**< A "memory technology device" such as FLASH or EEPROM */
Expand Down
87 changes: 54 additions & 33 deletions src/os/shared/src/osapi-filesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ extern const OS_VolumeInfo_t OS_VolumeTable[];

#endif

/*
* A string that should be the prefix of RAM disk volume names, which
* provides a hint that the file system refers to a RAM disk.
*
* If multiple RAM disks are required then these can be numbered,
* e.g. RAM0, RAM1, etc.
*/
const char OS_FILESYS_RAMDISK_VOLNAME_PREFIX[] = "RAM";

/*----------------------------------------------------------------
*
Expand Down Expand Up @@ -146,6 +154,7 @@ int32 OS_FileSys_InitLocalFromVolTable(OS_filesys_internal_record_t *local, cons
*/
if (Vol->VolumeType == FS_BASED)
{
local->fstype = OS_FILESYS_TYPE_FS_BASED;
local->flags |= OS_FILESYS_FLAG_IS_FIXED;
}
else if (Vol->VolumeType == RAM_DISK || Vol->VolatileFlag)
Expand Down Expand Up @@ -287,24 +296,7 @@ int32 OS_FileSys_Initialize(char *address, const char *fsdevname, const char * f

/* Get the initial settings from the classic volume table.
* If this fails, that is OK - because passed-in values get preference anyway */
if (OS_FileSys_SetupInitialParamsForDevice(fsdevname, local) != OS_SUCCESS)
{
/*
* No known parameters for the device.
*
* if address was supplied, assume it is a RAM disk, otherwise
* assume it is a regular disk.
*/
if (address == NULL)
{
local->fstype = OS_FILESYS_TYPE_NORMAL_DISK;
}
else
{
local->fstype = OS_FILESYS_TYPE_VOLATILE_DISK;
}

}
OS_FileSys_SetupInitialParamsForDevice(fsdevname, local);

/* populate the VolumeName and BlockSize ahead of the Impl call,
* so the implementation can reference this info if necessary */
Expand All @@ -313,6 +305,21 @@ int32 OS_FileSys_Initialize(char *address, const char *fsdevname, const char * f
local->address = address;
strcpy(local->volume_name, fsvolname);

/*
* Determine basic type of filesystem, if not already known
*
* if either an address was supplied, or if the volume name
* contains the string "RAM" then it is a RAM disk. Otherwise
* leave the type as UNKNOWN and let the implementation decide.
*/
if (local->fstype == OS_FILESYS_TYPE_UNKNOWN &&
(local->address != NULL ||
strncmp(local->volume_name, OS_FILESYS_RAMDISK_VOLNAME_PREFIX,
sizeof(OS_FILESYS_RAMDISK_VOLNAME_PREFIX)-1) == 0))
{
local->fstype = OS_FILESYS_TYPE_VOLATILE_DISK;
}

return_code = OS_FileSysStartVolume_Impl(local_id);

if (return_code == OS_SUCCESS)
Expand Down Expand Up @@ -487,11 +494,30 @@ int32 OS_FileSysAddFixedMap(uint32 *filesys_id, const char *phys_path, const cha
/*
* mark the entry that it is a fixed disk
*/
local->flags =
OS_FILESYS_FLAG_IS_FIXED |
OS_FILESYS_FLAG_IS_READY |
OS_FILESYS_FLAG_IS_MOUNTED_SYSTEM |
OS_FILESYS_FLAG_IS_MOUNTED_VIRTUAL;
local->fstype = OS_FILESYS_TYPE_FS_BASED;
local->flags = OS_FILESYS_FLAG_IS_FIXED;

/*
* The "mount" implementation is required as it will
* create the mountpoint if it does not already exist
*/
return_code = OS_FileSysStartVolume_Impl(local_id);

if (return_code == OS_SUCCESS)
{
local->flags |= OS_FILESYS_FLAG_IS_READY;
return_code = OS_FileSysMountVolume_Impl(local_id);
}

if (return_code == OS_SUCCESS)
{
/*
* mark the entry that it is a fixed disk
*/
local->flags |=
OS_FILESYS_FLAG_IS_MOUNTED_SYSTEM |
OS_FILESYS_FLAG_IS_MOUNTED_VIRTUAL;
}

/* Check result, finalize record, and unlock global table. */
return_code = OS_ObjectIdFinalizeNew(return_code, global, filesys_id);
Expand Down Expand Up @@ -671,11 +697,12 @@ int32 OS_mount (const char *devname, const char* mountpoint)
/* mount() cannot be used on this file system at this time */
return_code = OS_ERR_INCORRECT_OBJ_STATE;
}
else if ((local->flags & OS_FILESYS_FLAG_IS_FIXED) != 0)
else if (local->system_mountpt[0] == 0)
{
/* Won't mount if FIXED, but return SUCCESS for compatibility
* with existing apps/PSP that attempt this operation. */
return_code = OS_SUCCESS;
/*
* The system mount point should be a non-empty string.
*/
return_code = OS_FS_ERR_PATH_INVALID;
}
else
{
Expand Down Expand Up @@ -751,12 +778,6 @@ int32 OS_unmount (const char *mountpoint)
/* unmount() cannot be used on this file system at this time */
return_code = OS_ERR_INCORRECT_OBJ_STATE;
}
else if ((local->flags & OS_FILESYS_FLAG_IS_FIXED) != 0)
{
/* Won't unmount if FIXED, but return SUCCESS for compatibility
* with existing apps/PSP that attempt this operation. */
return_code = OS_SUCCESS;
}
else
{
return_code = OS_FileSysUnmountVolume_Impl(local_id);
Expand Down
Loading

0 comments on commit b51f5b6

Please sign in to comment.