@@ -886,6 +886,11 @@ static int lfs_dir_compact(lfs_t *lfs,
886
886
// drop caches and create tail
887
887
lfs -> pcache .block = 0xffffffff ;
888
888
889
+ if (ack == -1 ) {
890
+ // If we can't fit in this block, we won't fit in next block
891
+ return LFS_ERR_NOSPC ;
892
+ }
893
+
889
894
lfs_mdir_t tail ;
890
895
int err = lfs_dir_alloc (lfs , & tail , dir -> split , dir -> tail );
891
896
if (err ) {
@@ -1971,49 +1976,53 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
1971
1976
}
1972
1977
1973
1978
static int lfs_file_relocate (lfs_t * lfs , lfs_file_t * file ) {
1974
- relocate :;
1975
- // just relocate what exists into new block
1976
- lfs_block_t nblock ;
1977
- int err = lfs_alloc (lfs , & nblock );
1978
- if (err ) {
1979
- return err ;
1980
- }
1981
-
1982
- err = lfs_bd_erase (lfs , nblock );
1983
- if (err ) {
1984
- if (err == LFS_ERR_CORRUPT ) {
1985
- goto relocate ;
1986
- }
1987
- return err ;
1988
- }
1989
-
1990
- // either read from dirty cache or disk
1991
- for (lfs_off_t i = 0 ; i < file -> off ; i ++ ) {
1992
- uint8_t data ;
1993
- err = lfs_cache_read (lfs , & lfs -> rcache , & file -> cache ,
1994
- file -> block , i , & data , 1 );
1979
+ while (true) {
1980
+ // just relocate what exists into new block
1981
+ lfs_block_t nblock ;
1982
+ int err = lfs_alloc (lfs , & nblock );
1995
1983
if (err ) {
1996
1984
return err ;
1997
1985
}
1998
1986
1999
- err = lfs_cache_prog (lfs , & lfs -> pcache , & lfs -> rcache ,
2000
- nblock , i , & data , 1 );
1987
+ err = lfs_bd_erase (lfs , nblock );
2001
1988
if (err ) {
2002
1989
if (err == LFS_ERR_CORRUPT ) {
2003
1990
goto relocate ;
2004
1991
}
2005
1992
return err ;
2006
1993
}
2007
- }
2008
1994
2009
- // copy over new state of file
2010
- memcpy (file -> cache .buffer , lfs -> pcache .buffer , lfs -> cfg -> prog_size );
2011
- file -> cache .block = lfs -> pcache .block ;
2012
- file -> cache .off = lfs -> pcache .off ;
2013
- lfs -> pcache .block = 0xffffffff ;
1995
+ // either read from dirty cache or disk
1996
+ for (lfs_off_t i = 0 ; i < file -> off ; i ++ ) {
1997
+ uint8_t data ;
1998
+ err = lfs_cache_read (lfs , & lfs -> rcache , & file -> cache ,
1999
+ file -> block , i , & data , 1 );
2000
+ if (err ) {
2001
+ return err ;
2002
+ }
2014
2003
2015
- file -> block = nblock ;
2016
- return 0 ;
2004
+ err = lfs_cache_prog (lfs , & lfs -> pcache , & lfs -> rcache ,
2005
+ nblock , i , & data , 1 );
2006
+ if (err ) {
2007
+ if (err == LFS_ERR_CORRUPT ) {
2008
+ goto relocate ;
2009
+ }
2010
+ return err ;
2011
+ }
2012
+ }
2013
+
2014
+ // copy over new state of file
2015
+ memcpy (file -> cache .buffer , lfs -> pcache .buffer , lfs -> cfg -> prog_size );
2016
+ file -> cache .block = lfs -> pcache .block ;
2017
+ file -> cache .off = lfs -> pcache .off ;
2018
+ lfs -> pcache .block = 0xffffffff ;
2019
+
2020
+ file -> block = nblock ;
2021
+ return 0 ;
2022
+
2023
+ relocate :
2024
+ continue ;
2025
+ }
2017
2026
}
2018
2027
2019
2028
static int lfs_file_flush (lfs_t * lfs , lfs_file_t * file ) {
@@ -2067,6 +2076,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
2067
2076
}
2068
2077
2069
2078
break ;
2079
+
2070
2080
relocate :
2071
2081
LFS_DEBUG ("Bad block at %d" , file -> block );
2072
2082
err = lfs_file_relocate (lfs , file );
@@ -2091,48 +2101,58 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
2091
2101
}
2092
2102
2093
2103
int lfs_file_sync (lfs_t * lfs , lfs_file_t * file ) {
2094
- int err = lfs_file_flush (lfs , file );
2095
- if (err ) {
2096
- return err ;
2097
- }
2098
-
2099
- if ((file -> flags & LFS_F_DIRTY ) &&
2100
- !(file -> flags & LFS_F_ERRED ) &&
2101
- !lfs_pairisnull (file -> pair )) {
2102
- // update dir entry
2103
- // TODO keep list of dirs including these guys for no
2104
- // need of another reload?
2105
- lfs_mdir_t cwd ;
2106
- err = lfs_dir_fetch (lfs , & cwd , file -> pair );
2104
+ while (true) {
2105
+ int err = lfs_file_flush (lfs , file );
2107
2106
if (err ) {
2108
2107
return err ;
2109
2108
}
2110
2109
2111
- // either update the references or inline the whole file
2112
- if (!(file -> flags & LFS_F_INLINE )) {
2113
- int err = lfs_dir_commit (lfs , & cwd ,
2114
- LFS_MKATTR (LFS_TYPE_CTZSTRUCT , file -> id ,
2115
- & file -> ctz .head , sizeof (file -> ctz ),
2116
- LFS_MKATTR (LFS_FROM_ATTRS , file -> id , file -> cfg -> attrs , 0 ,
2117
- NULL )));
2110
+ if ((file -> flags & LFS_F_DIRTY ) &&
2111
+ !(file -> flags & LFS_F_ERRED ) &&
2112
+ !lfs_pairisnull (file -> pair )) {
2113
+ // update dir entry
2114
+ // TODO keep list of dirs including these guys for no
2115
+ // need of another reload?
2116
+ lfs_mdir_t cwd ;
2117
+ err = lfs_dir_fetch (lfs , & cwd , file -> pair );
2118
2118
if (err ) {
2119
2119
return err ;
2120
2120
}
2121
- } else {
2121
+
2122
+ // either update the references or inline the whole file
2122
2123
int err = lfs_dir_commit (lfs , & cwd ,
2123
- LFS_MKATTR (LFS_TYPE_INLINESTRUCT , file -> id ,
2124
- file -> cache .buffer , file -> ctz .size ,
2125
2124
LFS_MKATTR (LFS_FROM_ATTRS , file -> id , file -> cfg -> attrs , 0 ,
2126
- NULL )));
2125
+ (file -> flags & LFS_F_INLINE ) ?
2126
+ LFS_MKATTR (LFS_TYPE_INLINESTRUCT , file -> id ,
2127
+ file -> cache .buffer , file -> ctz .size , NULL ) :
2128
+ LFS_MKATTR (LFS_TYPE_CTZSTRUCT , file -> id ,
2129
+ & file -> ctz .head , sizeof (file -> ctz ), NULL )));
2127
2130
if (err ) {
2131
+ if (err == LFS_ERR_NOSPC && (file -> flags & LFS_F_INLINE )) {
2132
+ goto relocate ;
2133
+ }
2128
2134
return err ;
2129
2135
}
2136
+
2137
+ file -> flags &= ~LFS_F_DIRTY ;
2130
2138
}
2131
2139
2132
- file -> flags &= ~LFS_F_DIRTY ;
2133
- }
2140
+ return 0 ;
2134
2141
2135
- return 0 ;
2142
+ relocate :
2143
+ // inline file doesn't fit anymore
2144
+ file -> block = 0xfffffffe ;
2145
+ file -> off = file -> pos ;
2146
+
2147
+ lfs_alloc_ack (lfs );
2148
+ err = lfs_file_relocate (lfs , file );
2149
+ if (err ) {
2150
+ return err ;
2151
+ }
2152
+
2153
+ file -> flags &= ~LFS_F_INLINE ;
2154
+ file -> flags |= LFS_F_WRITING ;
2155
+ }
2136
2156
}
2137
2157
2138
2158
lfs_ssize_t lfs_file_read (lfs_t * lfs , lfs_file_t * file ,
@@ -3304,6 +3324,7 @@ static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t pair[2],
3304
3324
// TODO rename to lfs_dir_relocate?
3305
3325
static int lfs_relocate (lfs_t * lfs ,
3306
3326
const lfs_block_t oldpair [2 ], const lfs_block_t newpair [2 ]) {
3327
+ // TODO name lfs_dir_relocate?
3307
3328
// find parent
3308
3329
lfs_mdir_t parent ;
3309
3330
int32_t tag = lfs_parent (lfs , oldpair , & parent );
0 commit comments