fs/mmap/msync:support msync.

Summary:
  1.Added msync callback in struct mm_map_entry_s
  2.Added msync API in fs_msync.c
  3.Added static msync_rammap for rammap.

Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
chenrun1 2024-05-29 11:47:01 +08:00 committed by Xiang Xiao
parent 484600bd75
commit d04205aa3d
10 changed files with 227 additions and 11 deletions

View File

@ -799,6 +799,33 @@ int fs_getfilep(int fd, FAR struct file **filep)
return OK;
}
/****************************************************************************
* Name: fs_reffilep
*
* Description:
* To specify filep increase the reference count.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_FS_REFCOUNT
void fs_reffilep(FAR struct file *filep)
{
/* This interface is used to increase the reference count of filep */
irqstate_t flags;
DEBUGASSERT(filep);
flags = spin_lock_irqsave(NULL);
filep->f_refs++;
spin_unlock_irqrestore(NULL, flags);
}
/****************************************************************************
* Name: fs_putfilep
*
@ -811,7 +838,6 @@ int fs_getfilep(int fd, FAR struct file **filep)
* file' instance.
****************************************************************************/
#ifdef CONFIG_FS_REFCOUNT
int fs_putfilep(FAR struct file *filep)
{
irqstate_t flags;

View File

@ -18,7 +18,7 @@
#
# ##############################################################################
set(SRCS fs_mmap.c fs_munmap.c fs_mmisc.c)
set(SRCS fs_mmap.c fs_munmap.c fs_mmisc.c fs_msync.c)
if(CONFIG_FS_RAMMAP)
list(APPEND SRCS fs_rammap.c)

View File

@ -18,7 +18,7 @@
#
############################################################################
CSRCS += fs_mmap.c fs_munmap.c fs_mmisc.c
CSRCS += fs_mmap.c fs_munmap.c fs_mmisc.c fs_msync.c
ifeq ($(CONFIG_FS_RAMMAP),y)
CSRCS += fs_rammap.c

View File

@ -44,7 +44,7 @@ static int unmap_anonymous(FAR struct task_group_s *group,
FAR void *start,
size_t length)
{
FAR void *newaddr;
FAR void *newaddr = NULL;
off_t offset;
bool kernel = entry->priv.i;
int ret = OK;

95
fs/mmap/fs_msync.c Normal file
View File

@ -0,0 +1,95 @@
/****************************************************************************
* fs/mmap/fs_msync.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/mman.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sched.h>
#include "inode/inode.h"
#include "fs_rammap.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: msync
*
* Description:
* Equivalent to the standard msync() function except that it accepts
* a struct file instance instead of a memory address and it does not set
* the errno variable.
*
* Input Parameters:
* file - A pointer to the struct file instance representing the
* mappedfile
* start - The starting address of the memory region to be synchronized
* length - The length of the memory region to be synchronized
* flags - Flags that determine the type of synchronization to be
* performed
*
* Returned Value:
* On success, returns 0 (OK); On failure, returns a negated errno value.
*
****************************************************************************/
int msync(FAR void *start, size_t length, int flags)
{
FAR struct mm_map_entry_s *entry;
int ret;
ret = mm_map_lock();
if (ret < 0)
{
return ret;
}
entry = mm_map_find(get_current_mm(), start, length);
if (!entry)
{
ferr("ERROR: Region not found\n");
ret = -ENOMEM;
goto out;
}
if (entry->msync == NULL)
{
ret = OK;
goto out;
}
ret = entry->msync(entry, start, length, flags);
out:
mm_map_unlock();
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
return ret;
}

View File

@ -49,14 +49,84 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: msync_rammap
****************************************************************************/
static int msync_rammap(FAR struct mm_map_entry_s *entry, FAR void *start,
size_t length, int flags)
{
FAR struct file *filep = (FAR void *)((uintptr_t)entry->priv.p & ~1);
FAR uint8_t *wrbuffer = start;
ssize_t nwrite = 0;
off_t offset;
off_t fpos;
off_t opos;
offset = (uintptr_t)start - (uintptr_t)entry->vaddr;
if (length > entry->length - offset)
{
length = entry->length - offset;
}
opos = file_seek(filep, 0, SEEK_CUR);
if (opos < 0)
{
ferr("ERROR: Get current position failed\n");
return opos;
}
fpos = file_seek(filep, entry->offset + offset, SEEK_SET);
if (fpos < 0)
{
ferr("ERRORL Seek to position %"PRIdOFF" failed\n", fpos);
return fpos;
}
while (length > 0)
{
nwrite = file_write(filep, wrbuffer, length);
if (nwrite < 0)
{
/* Handle the special case where the write was interrupted by a
* signal.
*/
if (nwrite != -EINTR)
{
/* All other write errors are bad. */
ferr("ERROR: Write failed: offset=%"PRIdOFF" nwrite=%zd\n",
entry->offset, nwrite);
break;
}
}
/* Increment number of bytes written */
wrbuffer += nwrite;
length -= nwrite;
}
/* Restore file pos */
file_seek(filep, opos, SEEK_SET);
return nwrite >= 0 ? 0 : nwrite;
}
/****************************************************************************
* Name: unmap_rammap
****************************************************************************/
static int unmap_rammap(FAR struct task_group_s *group,
FAR struct mm_map_entry_s *entry,
FAR void *start,
size_t length)
{
FAR struct file *filep = (FAR void *)((uintptr_t)entry->priv.p & ~1);
enum mm_map_type_e type = (uintptr_t)entry->priv.p & 1;
FAR void *newaddr = NULL;
off_t offset;
enum mm_map_type_e type = entry->priv.i;
int ret = OK;
/* Get the offset from the beginning of the region and the actual number
@ -94,6 +164,8 @@ static int unmap_rammap(FAR struct task_group_s *group,
kumm_free(entry->vaddr);
}
fs_putfilep(filep);
/* Then remove the mapping from the list */
ret = mm_map_remove(get_group_mm(group), entry);
@ -248,8 +320,10 @@ int rammap(FAR struct file *filep, FAR struct mm_map_entry_s *entry,
/* Add the buffer to the list of regions */
out:
entry->priv.i = type;
fs_reffilep(filep);
entry->priv.p = (FAR void *)((uintptr_t)filep | type);
entry->munmap = unmap_rammap;
entry->msync = msync_rammap;
ret = mm_map_add(get_current_mm(), entry);
if (ret < 0)

View File

@ -1159,6 +1159,22 @@ int nx_open(FAR const char *path, int oflags, ...);
int fs_getfilep(int fd, FAR struct file **filep);
/****************************************************************************
* Name: fs_reffilep
*
* Description:
* To specify filep increase the reference count.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
void fs_reffilep(FAR struct file *filep);
/****************************************************************************
* Name: fs_putfilep
*

View File

@ -56,11 +56,14 @@ struct mm_map_entry_s
int i;
} priv;
/* Drivers which register mappings may also implement the unmap function
* to undo anything done in mmap.
* Nb. Implementation must NOT use "this_task()->group" since it is not
* valid during process exit. The argument "group" will be NULL in this
* case.
int (*msync)(FAR struct mm_map_entry_s *entry, FAR void *start,
size_t length, int flags);
/* Drivers which register mappings may also
* implement the unmap function to undo anything done in mmap.
* Nb. Implementation must NOT use "this_task()->group" since
* this is not valid during process exit. The argument "group" will be
* NULL in this case.
*/
int (*munmap)(FAR struct task_group_s *group,

View File

@ -248,6 +248,7 @@ SYSCALL_LOOKUP(fchown, 3)
SYSCALL_LOOKUP(utimens, 2)
SYSCALL_LOOKUP(lutimens, 2)
SYSCALL_LOOKUP(futimens, 2)
SYSCALL_LOOKUP(msync, 3)
SYSCALL_LOOKUP(munmap, 2)
#if defined(CONFIG_PSEUDOFS_SOFTLINKS)

View File

@ -77,6 +77,7 @@
"mq_timedreceive","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","ssize_t","mqd_t","FAR char *","size_t","FAR unsigned int *","FAR const struct timespec *"
"mq_timedsend","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","FAR const char *","size_t","unsigned int","FAR const struct timespec *"
"mq_unlink","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","FAR const char *"
"msync","sys/mman.h","","int","FAR void *","size_t","int"
"munmap","sys/mman.h","","int","FAR void *","size_t"
"nanosleep","time.h","","int","FAR const struct timespec *","FAR struct timespec *"
"nx_mkfifo","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0","int","FAR const char *","mode_t","size_t"

Can't render this file because it has a wrong number of fields in line 2.