diff --git a/fs/spiffs/src/spiffs.h b/fs/spiffs/src/spiffs.h index 91532ff259d..02c35214e0c 100644 --- a/fs/spiffs/src/spiffs.h +++ b/fs/spiffs/src/spiffs.h @@ -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) } diff --git a/fs/spiffs/src/spiffs_core.c b/fs/spiffs/src/spiffs_core.c index 45ec5d5fae8..a00f142c647 100644 --- a/fs/spiffs/src/spiffs_core.c +++ b/fs/spiffs/src/spiffs_core.c @@ -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); } } diff --git a/fs/spiffs/src/spiffs_vfs.c b/fs/spiffs/src/spiffs_vfs.c index ffc04b3fff9..d2286f917ad 100644 --- a/fs/spiffs/src/spiffs_vfs.c +++ b/fs/spiffs/src/spiffs_vfs.c @@ -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)); diff --git a/fs/spiffs/src/spiffs_volume.c b/fs/spiffs/src/spiffs_volume.c index 84b8b882bfd..c529f62578e 100644 --- a/fs/spiffs/src/spiffs_volume.c +++ b/fs/spiffs/src/spiffs_volume.c @@ -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) */