fs/spiffs: Fix an error in who the deferred 'unlink' is handling in close(). Modify read() and write behavior() so that they do not return so many partial reads and writes.
This commit is contained in:
parent
294456fa20
commit
e90723307e
@ -319,15 +319,17 @@ ssize_t spiffs_fobj_read(FAR struct spiffs_s *fs,
|
||||
* Free all resources used by a file object
|
||||
*
|
||||
* Input Parameters:
|
||||
* fs - A reference to the volume structure
|
||||
* fobj - A reference to the file object to be removed
|
||||
* fs - A reference to the volume structure
|
||||
* fobj - A reference to the file object to be removed
|
||||
* unlink - Remove the file is it is appropriate to do so
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spiffs_fobj_free(FAR struct spiffs_s *fs, FAR struct spiffs_file_s *fobj);
|
||||
void spiffs_fobj_free(FAR struct spiffs_s *fs,
|
||||
FAR struct spiffs_file_s *fobj, bool unlink);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
@ -1604,7 +1604,7 @@ void spiffs_object_event(FAR struct spiffs_s *fs,
|
||||
|
||||
/* Remove the file object */
|
||||
|
||||
spiffs_fobj_free(fs, fobj);
|
||||
spiffs_fobj_free(fs, fobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,18 +541,21 @@ static int spiffs_close(FAR struct file *filep)
|
||||
|
||||
filep->f_priv = NULL;
|
||||
|
||||
/* If the reference count decremented to zero and the file has been
|
||||
* unlinked, then free resources related to the open file.
|
||||
/* If the reference count decremented to zero then free resources related
|
||||
* to the open file.
|
||||
*/
|
||||
|
||||
if (fobj->crefs == 0 && (fobj->flags & SFO_FLAG_UNLINKED) != 0)
|
||||
if (fobj->crefs == 0)
|
||||
{
|
||||
/* Free the file object while we hold the lock? Weird but this
|
||||
* should be safe because the object is unlinked and could not
|
||||
* have any other references.
|
||||
*
|
||||
* If the file was unlinked while it was opened, then now would be
|
||||
* the time to perform the unlink operation.
|
||||
*/
|
||||
|
||||
spiffs_fobj_free(fs, fobj);
|
||||
spiffs_fobj_free(fs, fobj, (fobj->flags & SFO_FLAG_UNLINKED) != 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -727,9 +730,11 @@ static ssize_t spiffs_write(FAR struct file *filep, FAR const char *buffer,
|
||||
off_t offset_in_cpage;
|
||||
|
||||
offset_in_cpage = offset - fobj->cache_page->offset;
|
||||
|
||||
spiffs_cacheinfo("Storing to cache page %d for fobj %d offset=%d:%d buflen=%d\n",
|
||||
fobj->cache_page->cpndx, fobj->objid, offset,
|
||||
offset_in_cpage, buflen);
|
||||
|
||||
cache = spiffs_get_cache(fs);
|
||||
cpage_data = spiffs_get_cache_page(fs, cache, fobj->cache_page->cpndx);
|
||||
|
||||
@ -1489,7 +1494,7 @@ static int spiffs_unbind(FAR void *handle, FAR struct inode **mtdinode,
|
||||
{
|
||||
/* Free the file object */
|
||||
|
||||
spiffs_fobj_free(fs, fobj);
|
||||
spiffs_fobj_free(fs, fobj, false);
|
||||
}
|
||||
|
||||
/* Free allocated working buffers */
|
||||
@ -1638,7 +1643,7 @@ static int spiffs_unlink(FAR struct inode *mountpt, FAR const char *relpath)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we will ne to re-open the file */
|
||||
/* Otherwise, we will need to re-open the file */
|
||||
/* Allocate new file object */
|
||||
|
||||
fobj = (FAR struct spiffs_file_s *)kmm_zalloc(sizeof(struct spiffs_file_s));
|
||||
|
@ -290,32 +290,34 @@ ssize_t spiffs_fobj_write(FAR struct spiffs_s *fs,
|
||||
FAR const void *buffer, off_t offset, size_t len)
|
||||
{
|
||||
ssize_t remaining = len;
|
||||
ssize_t nwritten = 0;
|
||||
ssize_t total = 0;
|
||||
|
||||
if (fobj->size != SPIFFS_UNDEFINED_LEN && offset < fobj->size)
|
||||
if (fobj->size != SPIFFS_UNDEFINED_LEN)
|
||||
{
|
||||
FAR const uint8_t *tmp;
|
||||
ssize_t wrsize;
|
||||
|
||||
wrsize = MIN((ssize_t)(fobj->size - offset), len);
|
||||
nwritten = spiffs_object_modify(fs, fobj, offset,
|
||||
(FAR uint8_t *)buffer, wrsize);
|
||||
if (nwritten <= 0)
|
||||
while (offset < fobj->size)
|
||||
{
|
||||
return nwritten;
|
||||
ssize_t nwritten;
|
||||
ssize_t wrsize;
|
||||
|
||||
wrsize = MIN((ssize_t)(fobj->size - offset), remaining);
|
||||
nwritten = spiffs_object_modify(fs, fobj, offset,
|
||||
(FAR uint8_t *)buffer, wrsize);
|
||||
if (nwritten <= 0)
|
||||
{
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
remaining -= nwritten;
|
||||
buffer += nwritten;
|
||||
offset += nwritten;
|
||||
total += nwritten;
|
||||
}
|
||||
|
||||
remaining -= nwritten;
|
||||
|
||||
tmp = (FAR const uint8_t *)buffer;
|
||||
tmp += nwritten;
|
||||
buffer = tmp;
|
||||
offset += nwritten;
|
||||
}
|
||||
|
||||
if (remaining > 0)
|
||||
while (remaining > 0)
|
||||
{
|
||||
ssize_t nappend;
|
||||
|
||||
nappend = spiffs_object_append(fs, fobj, offset,
|
||||
(FAR uint8_t *)buffer, remaining);
|
||||
if (nappend < 0)
|
||||
@ -323,10 +325,13 @@ ssize_t spiffs_fobj_write(FAR struct spiffs_s *fs,
|
||||
return (ssize_t)nappend;
|
||||
}
|
||||
|
||||
nwritten += nappend;
|
||||
remaining -= nappend;
|
||||
buffer += nappend;
|
||||
offset += nappend;
|
||||
total += nappend;
|
||||
}
|
||||
|
||||
return (ssize_t)nwritten;
|
||||
return (ssize_t)total;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -354,6 +359,7 @@ ssize_t spiffs_fobj_read(FAR struct spiffs_s *fs,
|
||||
size_t buflen, off_t fpos)
|
||||
{
|
||||
ssize_t nread;
|
||||
ssize_t total;
|
||||
|
||||
/* Make sure that read access is supported */
|
||||
|
||||
@ -380,32 +386,32 @@ ssize_t spiffs_fobj_read(FAR struct spiffs_s *fs,
|
||||
/* Truncate */
|
||||
|
||||
buflen = fobj->size - fpos;
|
||||
|
||||
/* Check if we are already at or beyond the end of the file */
|
||||
|
||||
if (buflen <= 0)
|
||||
{
|
||||
/* Return zero (meaning EOF) */
|
||||
|
||||
nread = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Then read from the file object */
|
||||
|
||||
nread = spiffs_object_read(fs, fobj, fpos, buflen,
|
||||
(FAR uint8_t *)buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/* Read data from the file object until either we have read all of the
|
||||
* requested data, or until a read error occurs.
|
||||
*/
|
||||
|
||||
total = 0;
|
||||
while (buflen > 0)
|
||||
{
|
||||
/* Reading within file size */
|
||||
/* Read from the file object */
|
||||
|
||||
nread = spiffs_object_read(fs, fobj, fpos, buflen,
|
||||
(FAR uint8_t *)buffer);
|
||||
if (nread < 0)
|
||||
{
|
||||
ferr("ERROR: spiffs_object_read() failed: %d\n", (int)nread);
|
||||
return nread;
|
||||
}
|
||||
|
||||
total += nread;
|
||||
buffer += nread;
|
||||
fpos += nread;
|
||||
buflen -= nread;
|
||||
}
|
||||
|
||||
return nread;
|
||||
return total;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -423,7 +429,8 @@ ssize_t spiffs_fobj_read(FAR struct spiffs_s *fs,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spiffs_fobj_free(FAR struct spiffs_s *fs, FAR struct spiffs_file_s *fobj)
|
||||
void spiffs_fobj_free(FAR struct spiffs_s *fs,
|
||||
FAR struct spiffs_file_s *fobj, bool unlink)
|
||||
{
|
||||
FAR struct spiffs_file_s *curr;
|
||||
int ret;
|
||||
@ -459,12 +466,17 @@ void spiffs_fobj_free(FAR struct spiffs_s *fs, FAR struct spiffs_file_s *fobj)
|
||||
|
||||
DEBUGASSERT(curr != NULL);
|
||||
|
||||
/* Now we can remove the file by truncating it to zero length */
|
||||
/* Now we can remove the file by truncating it to zero length if it was
|
||||
* unlinked.
|
||||
*/
|
||||
|
||||
ret = spiffs_object_truncate(fs, fobj, 0, true);
|
||||
if (ret < 0)
|
||||
if (unlink)
|
||||
{
|
||||
ferr("ERROR: spiffs_object_truncate failed: %d\n", ret);
|
||||
ret = spiffs_object_truncate(fs, fobj, 0, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: spiffs_object_truncate failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Then free the file object itself (which contains the lock we hold) */
|
||||
|
Loading…
Reference in New Issue
Block a user