mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-08-25 04:18:57 +08:00
dosfs: Remove fat_file_datasync()
The fat_file_datasync() read every cluster of the file into the cache and then synchronized it step-by-step. For unmodified buffers this is a non-operation. For modified buffers this will wake-up the swapout task which performs then a single buffer write operation. This is usually quite inefficient. Firstly we do single buffer writes, secondly we may perform a lot of unnecessary read operations (for huge files this is really bad), and thirdly this leads likely to cache evictions. The synchronization procedure is replaced by a simple rtems_bdbuf_sync_dev(). This has the side-effect that also buffers not related to the file are synchronized, but since the modified list is normally short this should be acceptable.
This commit is contained in:
@@ -774,65 +774,6 @@ fat_file_mark_removed(
|
||||
fat_fd->flags |= FAT_FILE_REMOVED;
|
||||
}
|
||||
|
||||
/* fat_file_datasync --
|
||||
* Synchronize fat-file - flush all buffered data to the media.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* mt_entry - mount table entry
|
||||
* fat_fd - fat-file descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RC_OK on success, or -1 if error occured and errno set appropriately
|
||||
*/
|
||||
int
|
||||
fat_file_datasync(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
fat_file_fd_t *fat_fd
|
||||
)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
fat_fs_info_t *fs_info = mt_entry->fs_info;
|
||||
uint32_t cur_cln = fat_fd->cln;
|
||||
rtems_bdbuf_buffer *block = NULL;
|
||||
uint32_t sec = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (fat_fd->fat_file_size == 0)
|
||||
return RC_OK;
|
||||
|
||||
/*
|
||||
* we can use only one bdbuf :( and we also know that cache is useless
|
||||
* for sync operation, so don't use it
|
||||
*/
|
||||
rc = fat_buf_release(fs_info);
|
||||
if (rc != RC_OK)
|
||||
return rc;
|
||||
|
||||
/* for each cluster of the file ... */
|
||||
while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
|
||||
{
|
||||
sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
|
||||
/* for each sector in cluster ... */
|
||||
for ( i = 0; i < fs_info->vol.spc; i++ )
|
||||
{
|
||||
/* ... sync it */
|
||||
sc = rtems_bdbuf_read(fs_info->vol.dd, (sec + i), &block);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one( EIO );
|
||||
|
||||
sc = rtems_bdbuf_sync(block);
|
||||
if ( sc != RTEMS_SUCCESSFUL )
|
||||
rtems_set_errno_and_return_minus_one( EIO );
|
||||
}
|
||||
|
||||
rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
|
||||
if ( rc != RC_OK )
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* fat_file_size --
|
||||
* Calculate fat-file size - fat-file is nothing that clusters chain, so
|
||||
* go through all clusters in the chain and count it. Only
|
||||
|
||||
@@ -167,11 +167,6 @@ fat_file_truncate(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
fat_file_fd_t *fat_fd,
|
||||
uint32_t new_length);
|
||||
|
||||
int
|
||||
fat_file_datasync(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
fat_file_fd_t *fat_fd);
|
||||
|
||||
|
||||
int
|
||||
fat_file_ioctl(rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
fat_file_fd_t *fat_fd,
|
||||
|
||||
@@ -399,6 +399,10 @@ int msdos_get_dotdot_dir_info_cluster_num_and_offset(
|
||||
char *dir_entry
|
||||
);
|
||||
|
||||
int msdos_sync_unprotected(msdos_fs_info_t *fs_info);
|
||||
|
||||
int msdos_sync(rtems_libio_t *iop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -457,34 +457,3 @@ msdos_dir_stat(
|
||||
* RETURNS:
|
||||
*
|
||||
*/
|
||||
|
||||
/* msdos_dir_sync --
|
||||
* The following routine does a syncronization on a MSDOS directory node.
|
||||
* DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
|
||||
* Entry Structure should not be updated for directories, so only call
|
||||
* to corresponding fat-file routine.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* iop - file control block
|
||||
*
|
||||
* RETURNS:
|
||||
* RC_OK on success, or -1 if error occured (errno set apropriately).
|
||||
*/
|
||||
int
|
||||
msdos_dir_sync(rtems_libio_t *iop)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
|
||||
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
|
||||
|
||||
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one(EIO);
|
||||
|
||||
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,40 @@
|
||||
|
||||
#include "msdos.h"
|
||||
|
||||
static int
|
||||
msdos_file_update(rtems_libio_t *iop)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
|
||||
|
||||
/*
|
||||
* if fat-file descriptor is not marked as "removed", synchronize
|
||||
* size, first cluster number, write time and date fields of the file
|
||||
*/
|
||||
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||
{
|
||||
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* msdos_file_close --
|
||||
* Close fat-file which correspondes to the file. If fat-file descriptor
|
||||
* which correspondes to the file is not marked "removed", synchronize
|
||||
@@ -45,40 +79,13 @@ msdos_file_close(rtems_libio_t *iop)
|
||||
int rc = RC_OK;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
|
||||
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
|
||||
|
||||
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one(EIO);
|
||||
|
||||
/*
|
||||
* if fat-file descriptor is not marked as "removed", synchronize
|
||||
* size, first cluster number, write time and date fields of the file
|
||||
*/
|
||||
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||
{
|
||||
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rc = msdos_file_update(iop);
|
||||
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
@@ -276,67 +283,14 @@ msdos_file_sync(rtems_libio_t *iop)
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one(EIO);
|
||||
|
||||
/* synchronize file data */
|
||||
rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||
rc = msdos_file_update(iop);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* if fat-file descriptor is not marked "removed" - synchronize file
|
||||
* metadata
|
||||
*/
|
||||
if (!FAT_FILE_IS_REMOVED(fat_fd))
|
||||
{
|
||||
rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
|
||||
if (rc != RC_OK)
|
||||
{
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/* msdos_file_datasync --
|
||||
* Synchronize file - synchronize only file data (metadata is letf intact).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* iop - file control block
|
||||
*
|
||||
* RETURNS:
|
||||
* RC_OK on success, or -1 if error occured (errno set appropriately)
|
||||
*/
|
||||
int
|
||||
msdos_file_datasync(rtems_libio_t *iop)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
|
||||
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
|
||||
|
||||
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one(EIO);
|
||||
|
||||
/* synchronize file data */
|
||||
fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
|
||||
rc = msdos_sync_unprotected(fs_info);
|
||||
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return RC_OK;
|
||||
|
||||
@@ -27,7 +27,7 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
|
||||
rtems_filesystem_default_lseek_directory,
|
||||
msdos_dir_stat,
|
||||
rtems_filesystem_default_ftruncate_directory,
|
||||
msdos_dir_sync,
|
||||
msdos_dir_sync,
|
||||
msdos_sync,
|
||||
msdos_sync,
|
||||
rtems_filesystem_default_fcntl
|
||||
};
|
||||
|
||||
@@ -28,6 +28,6 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = {
|
||||
msdos_file_stat,
|
||||
msdos_file_ftruncate,
|
||||
msdos_file_sync,
|
||||
msdos_file_datasync,
|
||||
msdos_sync,
|
||||
rtems_filesystem_default_fcntl
|
||||
};
|
||||
|
||||
@@ -1646,3 +1646,34 @@ int msdos_find_node_by_cluster_num_in_fat_file(
|
||||
}
|
||||
return MSDOS_NAME_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
int
|
||||
msdos_sync_unprotected(msdos_fs_info_t *fs_info)
|
||||
{
|
||||
int rc = fat_buf_release(&fs_info->fat);
|
||||
rtems_status_code sc = rtems_bdbuf_syncdev(fs_info->fat.vol.dd);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
errno = EIO;
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
msdos_sync(rtems_libio_t *iop)
|
||||
{
|
||||
int rc = RC_OK;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
|
||||
|
||||
sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
|
||||
MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one(EIO);
|
||||
|
||||
rc = msdos_sync_unprotected(fs_info);
|
||||
|
||||
rtems_semaphore_release(fs_info->vol_sema);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
ACLOCAL_AMFLAGS = -I ../aclocal
|
||||
|
||||
SUBDIRS =
|
||||
SUBDIRS += fsdosfssync01
|
||||
SUBDIRS += imfs_fserror
|
||||
SUBDIRS += imfs_fslink
|
||||
SUBDIRS += imfs_fspatheval
|
||||
|
||||
@@ -79,6 +79,7 @@ AC_CHECK_SIZEOF([blkcnt_t])
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
fsdosfssync01/Makefile
|
||||
imfs_fserror/Makefile
|
||||
imfs_fslink/Makefile
|
||||
imfs_fspatheval/Makefile
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
rtems_tests_PROGRAMS = fsdosfssync01
|
||||
fsdosfssync01_SOURCES = init.c
|
||||
|
||||
dist_rtems_tests_DATA = fsdosfssync01.scn fsdosfssync01.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
|
||||
LINK_OBJS = $(fsdosfssync01_OBJECTS)
|
||||
LINK_LIBS = $(fsdosfssync01_LDLIBS)
|
||||
|
||||
fsdosfssync01$(EXEEXT): $(fsdosfssync01_OBJECTS) $(fsdosfssync01_DEPENDENCIES)
|
||||
@rm -f fsdosfssync01$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
@@ -0,0 +1,11 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: fsdosfssync01
|
||||
|
||||
directives:
|
||||
|
||||
TBD
|
||||
|
||||
concepts:
|
||||
|
||||
TBD
|
||||
@@ -0,0 +1,2 @@
|
||||
*** TEST FSDOSFSSYNC 1 ***
|
||||
*** END OF TEST FSDOSFSSYNC 1 ***
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tmacros.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/blkdev.h>
|
||||
#include <rtems/dosfs.h>
|
||||
#include <rtems/ramdisk.h>
|
||||
|
||||
static void create_file(const char *file)
|
||||
{
|
||||
int fd;
|
||||
int rv;
|
||||
|
||||
fd = creat(file, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
rv = fsync(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static void write_to_file(const char *file, bool sync)
|
||||
{
|
||||
int fd;
|
||||
char buf [1];
|
||||
ssize_t n;
|
||||
off_t pos;
|
||||
int rv;
|
||||
|
||||
fd = open(file, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
n = write(fd, buf, sizeof(buf));
|
||||
rtems_test_assert(n == (ssize_t) sizeof(buf));
|
||||
|
||||
pos = lseek(fd, 0, SEEK_END);
|
||||
rtems_test_assert(pos == sizeof(buf));
|
||||
|
||||
if (sync) {
|
||||
rv = fsync(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static void check_file_size(const char *file, off_t size)
|
||||
{
|
||||
int fd;
|
||||
off_t pos;
|
||||
int rv;
|
||||
|
||||
fd = open(file, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
pos = lseek(fd, 0, SEEK_END);
|
||||
rtems_test_assert(pos == size);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static void test(const char *rda, const char *mnt, const char *file)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
int disk_fd;
|
||||
int rv;
|
||||
|
||||
sc = rtems_disk_io_initialize();
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
disk_fd = open(rda, O_RDWR);
|
||||
rtems_test_assert(disk_fd >= 0);
|
||||
|
||||
rv = msdos_format(rda, NULL);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = mount_and_make_target_path(
|
||||
rda,
|
||||
mnt,
|
||||
RTEMS_FILESYSTEM_TYPE_DOSFS,
|
||||
RTEMS_FILESYSTEM_READ_WRITE,
|
||||
NULL
|
||||
);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
create_file(file);
|
||||
rv = rtems_disk_fd_purge(disk_fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
write_to_file(file, false);
|
||||
rv = rtems_disk_fd_purge(disk_fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
check_file_size(file, 0);
|
||||
|
||||
write_to_file(file, true);
|
||||
rv = rtems_disk_fd_purge(disk_fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
check_file_size(file, 1);
|
||||
|
||||
rv = unmount(mnt);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = close(disk_fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
puts("\n\n*** TEST FSDOSFSSYNC 1 ***");
|
||||
|
||||
test("/dev/rda", "/mnt", "/mnt/file");
|
||||
|
||||
puts("*** END OF TEST FSDOSFSSYNC 1 ***");
|
||||
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
rtems_ramdisk_config rtems_ramdisk_configuration [] = {
|
||||
{ .block_size = 512, .block_num = 1024 }
|
||||
};
|
||||
|
||||
size_t rtems_ramdisk_configuration_size = 1;
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_EXTRA_DRIVERS RAMDISK_DRIVER_TABLE_ENTRY
|
||||
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
|
||||
|
||||
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 6
|
||||
|
||||
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
|
||||
|
||||
#define CONFIGURE_FILESYSTEM_DOSFS
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
|
||||
#define CONFIGURE_EXTRA_TASK_STACKS (8 * 1024)
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#include <rtems/confdefs.h>
|
||||
Reference in New Issue
Block a user