fs/littlefs: Suppport the duplication function

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: I64191bdeab3723b22476d27c44852493eed1b07e
This commit is contained in:
Xiang Xiao 2021-03-22 17:39:44 +08:00 committed by Abdelatif Guettouche
parent db8e498e4f
commit b2563b99ca

View File

@ -44,6 +44,12 @@
* Private Types
****************************************************************************/
struct littlefs_file_s
{
struct lfs_file file;
int refs;
};
/* This structure represents the overall mountpoint state. An instance of
* this structure is retained as inode private data on each mountpoint that
* is mounted with a littlefs filesystem.
@ -224,7 +230,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
@ -243,6 +249,8 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
return -ENOMEM;
}
priv->refs = 1;
/* Take the semaphore */
ret = littlefs_semtake(fs);
@ -254,7 +262,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
/* Try to open the file */
oflags = littlefs_convert_oflags(oflags);
ret = lfs_file_open(&fs->lfs, priv, relpath, oflags);
ret = lfs_file_open(&fs->lfs, &priv->file, relpath, oflags);
if (ret < 0)
{
/* Error opening file */
@ -268,7 +276,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
if (oflags & LFS_O_APPEND)
{
ret = lfs_file_seek(&fs->lfs, priv, 0, LFS_SEEK_END);
ret = lfs_file_seek(&fs->lfs, &priv->file, 0, LFS_SEEK_END);
if (ret >= 0)
{
filep->f_pos = ret;
@ -283,8 +291,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
* e.g. total 8M, fileA 6M, O_TRUNC re-wrting fileA 6M, meet error.
*/
lfs_file_sync(&fs->lfs, priv);
lfs_file_sync(&fs->lfs, &priv->file);
littlefs_semgive(fs);
/* Attach the private date to the struct file instance */
@ -293,7 +300,7 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
return OK;
errout_with_file:
lfs_file_close(&fs->lfs, priv);
lfs_file_close(&fs->lfs, &priv->file);
errout:
littlefs_semgive(fs);
errsem:
@ -308,7 +315,7 @@ errsem:
static int littlefs_close(FAR struct file *filep)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
@ -323,16 +330,20 @@ static int littlefs_close(FAR struct file *filep)
ret = littlefs_semtake(fs);
if (ret < 0)
{
goto errsem;
return ret;
}
if (--priv->refs <= 0)
{
lfs_file_close(&fs->lfs, &priv->file);
}
lfs_file_close(&fs->lfs, priv);
littlefs_semgive(fs);
if (priv->refs <= 0)
{
kmm_free(priv);
}
/* Now free the pointer */
errsem:
kmm_free(priv);
return OK;
}
@ -344,7 +355,7 @@ static ssize_t littlefs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
ssize_t ret;
@ -362,14 +373,23 @@ static ssize_t littlefs_read(FAR struct file *filep, FAR char *buffer,
return ret;
}
ret = lfs_file_read(&fs->lfs, priv, buffer, buflen);
if (filep->f_pos != priv->file.pos)
{
ret = lfs_file_seek(&fs->lfs, &priv->file, filep->f_pos, LFS_SEEK_SET);
if (ret < 0)
{
goto out;
}
}
ret = lfs_file_read(&fs->lfs, &priv->file, buffer, buflen);
if (ret > 0)
{
filep->f_pos += ret;
}
out:
littlefs_semgive(fs);
return ret;
}
@ -381,7 +401,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
size_t buflen)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
ssize_t ret;
@ -399,14 +419,23 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
return ret;
}
ret = lfs_file_write(&fs->lfs, priv, buffer, buflen);
if (filep->f_pos != priv->file.pos)
{
ret = lfs_file_seek(&fs->lfs, &priv->file, filep->f_pos, LFS_SEEK_SET);
if (ret < 0)
{
goto out;
}
}
ret = lfs_file_write(&fs->lfs, &priv->file, buffer, buflen);
if (ret > 0)
{
filep->f_pos += ret;
}
out:
littlefs_semgive(fs);
return ret;
}
@ -417,7 +446,7 @@ static ssize_t littlefs_write(FAR struct file *filep, const char *buffer,
static off_t littlefs_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
off_t ret;
@ -435,14 +464,13 @@ static off_t littlefs_seek(FAR struct file *filep, off_t offset, int whence)
return ret;
}
ret = lfs_file_seek(&fs->lfs, priv, offset, whence);
ret = lfs_file_seek(&fs->lfs, &priv->file, offset, whence);
if (ret >= 0)
{
filep->f_pos = ret;
}
littlefs_semgive(fs);
return ret;
}
@ -483,7 +511,7 @@ static int littlefs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
static int littlefs_sync(FAR struct file *filep)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
@ -499,7 +527,7 @@ static int littlefs_sync(FAR struct file *filep)
return ret;
}
ret = lfs_file_sync(&fs->lfs, priv);
ret = lfs_file_sync(&fs->lfs, &priv->file);
littlefs_semgive(fs);
return ret;
@ -514,7 +542,28 @@ static int littlefs_sync(FAR struct file *filep)
static int littlefs_dup(FAR const struct file *oldp, FAR struct file *newp)
{
return -ENOSYS;
FAR struct littlefs_mountpt_s *fs;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
/* Recover our private data from the struct file instance */
priv = oldp->f_priv;
inode = oldp->f_inode;
fs = inode->i_private;
ret = littlefs_semtake(fs);
if (ret < 0)
{
return ret;
}
priv->refs++;
newp->f_priv = priv;
littlefs_semgive(fs);
return ret;
}
/****************************************************************************
@ -529,7 +578,7 @@ static int littlefs_dup(FAR const struct file *oldp, FAR struct file *newp)
static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
@ -549,7 +598,7 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
return ret;
}
buf->st_size = lfs_file_size(&fs->lfs, priv);
buf->st_size = lfs_file_size(&fs->lfs, &priv->file);
littlefs_semgive(fs);
if (buf->st_size < 0)
@ -576,7 +625,7 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
static int littlefs_truncate(FAR struct file *filep, off_t length)
{
FAR struct littlefs_mountpt_s *fs;
FAR struct lfs_file *priv;
FAR struct littlefs_file_s *priv;
FAR struct inode *inode;
int ret;
@ -594,7 +643,7 @@ static int littlefs_truncate(FAR struct file *filep, off_t length)
return ret;
}
ret = lfs_file_truncate(&fs->lfs, priv, length);
ret = lfs_file_truncate(&fs->lfs, &priv->file, length);
littlefs_semgive(fs);
return ret;
@ -680,13 +729,12 @@ static int littlefs_closedir(FAR struct inode *mountpt,
ret = littlefs_semtake(fs);
if (ret < 0)
{
goto errsem;
return ret;
}
lfs_dir_close(&fs->lfs, priv);
littlefs_semgive(fs);
errsem:
kmm_free(priv);
return OK;
}
@ -740,7 +788,6 @@ static int littlefs_readdir(FAR struct inode *mountpt,
}
littlefs_semgive(fs);
return ret;
}
@ -778,7 +825,6 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
}
littlefs_semgive(fs);
return ret;
}
@ -1135,7 +1181,6 @@ static int littlefs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
}
littlefs_semgive(fs);
return ret;
}