LittleFS port to Teensy/SPIFlash

Ok just pushed the last update to plusNAND as well @Paul 's LittleFS library.

I added support for Bad Block Management (BBM) for the M02. As I said before its not turned on (didn't send the command). Reason: Not 100% sure I implemented correctly and since I am not getting any ECC errors no way for me to confirm (at least to my satisfaction). If anyone wants to take a look and double check please feel free.
 
Teensy LC Issue with LittleFS

@Frank B asked about if we did any testing with Teensy LC (https://forum.pjrc.com/threads/64592-Teensyduino-1-54-Beta-5?p=266527&viewfull=1#post266527) so I hooked up a LC to the littlefs_teensy_test1a sketch using a W25Q64FV to start and the sketch hangs on the first:
Code:
  file = myfs.open("structureData1/temp_test.txt", FILE_WRITE);
the preceding code seems to work to create the file and the directory:
Code:
LittleFS Test
TotalSize (Bytes): 8388608
...............
started
MAKE files
printDirectory
--------------
DIR	structureData1 / 

 0 dirs with 0 files of Size 0 Bytes
I did a erase just in case.

As a sanity check I ran SerialFlash BenchMark:
Code:
Raw SerialFlash Hardware Test

Read Chip Identification:
  JEDEC ID:     EF 40 17
  Part Nummber: W25Q64FV
  Memory Size:  8388608 bytes
  Block Size:   65536 bytes

Reading Chip...

Writing 4096 signatures

Double Checking All Signatures:
  all 4096 signatures read ok

Checking Signature Pairs
  all 2047 signature pairs read ok

Checking Read-While-Write (Program Suspend)
  write 256 bytes at 256
  write time was 405 microseconds.
  read-while-writing: 00 00 00 00 15 F5 95 4B 
  test passed, good read while writing

Checking Read-While-Erase (Erase Suspend)
  erase time was 172754 microseconds.
  erase correctly erased 65536 bytes
  read-while-erasing: 00 00 00 00 15 F5 95 4B 
  test passed, good read while erasing

All Tests Passed  :-)

Test data was written to your chip.  You must run
EraseEverything before using this chip for files.
Just to make sure.
 
Last edited:
@mjs513 Sounds like you have been busy!

What about Teensy 2? ;) (Just kidding)

MOrning @KurtE
A bit. Hate leaving things hanging so I had to finish off the BBM stuff (not much more I can do on that) and test the LC I just remembered. Going to do a few more tests just in case
 
Another data point. Just ran my bench sketch for read/write and that seemed to work except totalSize is returning 0!
Code:
LittleFS Test
.........................................................................................................................
started
Disk Stats:
Bytes Used: 8192, Bytes Total:0
Benchmark:
FILE_SIZE_MB = 1
BUF_SIZE = 2048 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
102.53,25372,16442,19975
102.67,25351,16385,19944

Starting sequential read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
507.84,6912,2980,4031
507.84,6913,2981,4031

Done
So something funny going on with LC and LittleFS.
 
Ok figured out the problem and its not LittleFS. Problem is just running out of memory within the sketch. There are a few array of 2048 and while by itself is not bad, add that with the sketch size probably causing an issue. I reduced the size of one of the arrays from 2048 to 512 and it worked as it should:
Code:
LittleFS Test
TotalSize (Bytes): 8388608
started
MAKE files
printDirectory
--------------
FILE	0_2MBfile.txt		2048000
DIR	structureData1 / 
	FILE	temp_test.txt		171

 0 dirs with 1 files of Size 171 Bytes
FILE	temp_test1.txt		171
FILE	temp_test2.txt		152
FILE	temp_test3.txt		6144

 1 dirs with 4 files of Size 2054467 Bytes

printDirectory
--------------
FILE	0_2MBfile.txt		2048000
DIR	structureData1 / 
	FILE	temp_test.txt		190

 0 dirs with 1 files of Size 190 Bytes
FILE	temp_test1.txt		190
FILE	temp_test2.txt		171
FILE	temp_test3.txt		6144

 1 dirs with 4 files of Size 2054505 Bytes

--------------
printDirectory
--------------
FILE	0_2MBfile.txt		2048000
DIR	structureData1 / 
	FILE	temp_test.txt		190

 0 dirs with 1 files of Size 190 Bytes
FILE	temp_test1.txt		190
FILE	temp_test2.txt		171
FILE	temp_test3.txt		7168

 1 dirs with 4 files of Size 2055529 Bytes

Disk Usuage:
Bytes Used: lu, Bytes Total:lu
Test for SOME DATA TO TEST
Don't think %llu is supported on the LC though :)

Ok now to see if I can find my audio board to test wavfileplayer :)
 
@Frank B
Now that I know LittleFS works with LC I started looking at wavPlayer sketch. Think a few files are going to have modified especially play_sd_wav.cpp
 
Hi
I have installed the beta 5 and tested ListFiles example in LittleFS on my Macronix MX25L12835F chip.
Result is : initialization failed.
I run on T4.0 and everything works OK using the SerialFlash lib.

I suspect that the chip gives the wrong Id ???

Are there any plans of adding more chips?

/Tomas
 
Hi
I have installed the beta 5 and tested ListFiles example in LittleFS on my Macronix MX25L12835F chip.
Result is : initialization failed.
I run on T4.0 and everything works OK using the SerialFlash lib.

I suspect that the chip gives the wrong Id ???

Are there any plans of adding more chips?

/Tomas

Right now LittleFS does not support the Macronix MX25L12835F chip it only supports the following based on the table in the .cpp file:
Code:
	{{0xEF, 0x40, 0x15}, 24, 256, 4096, 2097152, 3000, 400000}, // Winbond W25Q16JV*IQ/W25Q16FV
	{{0xEF, 0x40, 0x16}, 24, 256, 4096, 4194304, 3000, 400000}, // Winbond W25Q32JV*IQ/W25Q32FV
	{{0xEF, 0x40, 0x17}, 24, 256, 4096, 8388608, 3000, 400000}, // Winbond W25Q64JV*IQ/W25Q64FV
	{{0xEF, 0x40, 0x18}, 24, 256, 4096, 16777216, 3000, 400000}, // Winbond W25Q128JV*IQ/W25Q128FV
	{{0xEF, 0x40, 0x19}, 32, 256, 4096, 33554432, 3000, 400000}, // Winbond W25Q256JV*IQ
	{{0xEF, 0x40, 0x20}, 32, 256, 4096, 67108864, 3500, 400000}, // Winbond W25Q512JV*IQ
	{{0xEF, 0x70, 0x17}, 24, 256, 4096, 8388608, 3000, 400000}, // Winbond W25Q64JV*IM (DTR)
	{{0xEF, 0x70, 0x18}, 24, 256, 4096, 16777216, 3000, 400000}, // Winbond W25Q128JV*IM (DTR)
	{{0xEF, 0x70, 0x19}, 32, 256, 4096, 33554432, 3000, 400000}, // Winbond W25Q256JV*IM (DTR)
	{{0xEF, 0x70, 0x20}, 32, 256, 4096, 67108864, 3500, 400000}, // Winbond W25Q512JV*IM (DTR)
	{{0x1F, 0x84, 0x01}, 24, 256, 4096, 524288, 2500, 300000}, // Adesto/Atmel AT25SF041
	{{0x01, 0x40, 0x14}, 24, 256, 4096, 1048576, 5000, 300000}, // Spansion S25FL208K
	//FRAM
	{{0x03, 0x2E, 0xC2}, 24, 64, 128, 1048576, 250, 1200},  //Cypress 8Mb FRAM
	{{0xC2, 0x24, 0x00}, 24, 64, 128, 131072, 250, 1200},  //Cypress 1Mb FRAM
	{{0xC2, 0x24, 0x01}, 24, 64, 128, 131072, 250, 1200},  //Cypress 1Mb FRAM, rev1
	{{0xAE, 0x83, 0x09}, 24, 64, 128, 131072, 250, 1200},  //ROHM MR45V100A 1 Mbit FeRAM Memory
	{{0xC2, 0x26, 0x08}, 24, 64, 128, 131072, 250, 1200},  //Cypress 4Mb FRAM
and large Winbond NAND Chips:
Code:
	{{0xEF, 0xAA, 0x21}, 24, 2048, 131072, 131596288,   2000, 15000},  //Winbond W25N01G
	{{0xEF, 0xAA, 0x22}, 24, 2048, 131072, 265289728, 2000, 15000},  //Winbond W25N02G
	{{0xEF, 0xBB, 0x21}, 24, 2048, 131072, 265289728, 2000, 15000},  //Winbond W25M02
	{{0xEF, 0xBB, 0x21}, 24, 2048, 131072, 258998272, 2000, 15000},  //Winbond W25M02

There are no specific plans at the moment to support additional chips but I am sure the list will grow over time. Remember LittleFS is still what you might say is in beta testing and was only just released in TD1.54beta-5 and has since been updated a few times.

SerialFlash is still operational and there is a possibility that it may be ported over to LittleFS but do not believe that has been decided yet.

Just as a note I checked Digikey and there is a note on the Macronix MX25L12835F page that you should be aware of:
Not Recommended for New Design,
 
OK, thank's for your answer.
I'm aware of the not for new designs message.
The solution is ofcause to switch over to a supported one.
Will look in the list for someone with compatible layout: 8SOIC with at least 128KB

/Tomas
 
@Frank B
Now that I know LittleFS works with LC I started looking at wavPlayer sketch. Think a few files are going to have modified especially play_sd_wav.cpp

@mjs513 - Not sure if you ever had time to play with the wavPlayer sketch yet. I have LittleFS initially working with it. I chose to start testing with LittleFS_SPINAND using chipSelect = 4. Admittedly I am still trying to digest all of the methods needed to access the various memories available on the T4.1 and PJRC memory board. I got an audio board Rev D from PJRC and used it with the breakout board and memory board. I updated the latest TD with your LittleFS library. The next challenge was writing a sketch to copy the test wav files from a SD card to the NAND chip. So I modified a file copy sketch that I use to copy files between SDIO, and external SPI SD cards to use LittleFS. This worked well.

One thing I ran into was having to use a 'extern' declaration for this:
Code:
extern LittleFS_SPINAND myfs;  // Not sure how to avoid this declaration???

This is line #49 in 'play_littleFS_wav.cpp' which is defined in line #39 of 'littleFSWavPlayer.ino'. The original WavFilePlayer used 'SD.begin()' in the '.ino' and 'SD.open()' in 'play_SD_wav.cpp'. Just have not had enough time to understand LittleFS yet:)

Anyway here is the link to the repository if anybody wants to play:
https://github.com/wwatson4506/littleFSWavPlayer
 
@wwatson
Started working on the changes but ran into a problem when I posted the issue Paul mentioned that he wanted to modify the wavFilePlay in the library to make it more generic so kind of put it on hold. Can't find that post right now.
 
@wwatson
Started working on the changes but ran into a problem when I posted the issue Paul mentioned that he wanted to modify the wavFilePlay in the library to make it more generic so kind of put it on hold. Can't find that post right now.

You are right. I remember that post as well. Completely forgot about it. Oh well, at least I know it works. Right now I guess a lot of things are still up in the air and I have a tendency to jump the gun. It still gave me a chance to play with LittleFS and take a break from working with SdFat and MSC. I think I am finally figuring out which memory chips are what and how to access them using all of the test programs. The big one was the chip selects:) I modified my copy program that allows me to copy files between all available storage devices on for the Teensies to work with LittleFS. So far, the memory chips I have tested with LittleFS seem to work. That is how I copied the audio test files to the SPINand chip on the mem board from a USB thumb drive.
 
Very good news it has already being proven to play audio with LittleFS. I am curious about how the read speed would perform for NAND chips over QSPI in comparison with the current NOR over SPI. AFAIK QSPI should increase read speeds, but NAND is slower than NOR in read operations. I don't know if LittleFS would take a part in read speeds as well.
 
@defragster
Was trying out your new and improved LFSIntegrity.ino and wanted to test the 25Q512 Winbond flash. Did a lowlevel format and really really long using the memory breakout board:
Code:
?[  0.06 M](0.05941 M elap) Awaiting input 0123456789RdcghkFqvplmusSBbyYxfan+-? loops left 0 >
Formatting Low Level:
	.........................................................................................................................

 Done Formatting Low Level in 345834838 us.
u 
	 Updated filecount 0
F
printDirectory SPI_DISK
--------------

 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 8192, Bytes Total:67108864

On the 25Q128
Code:
Formatting Low Level:
	.........................................................................................................................

 Done Formatting Low Level in 116834058 us.
u 
	 Updated filecount 0
F
printDirectory SPI_DISK
--------------

 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 8192, Bytes Total:16777216
Now I know the NAND formatting is implemented differently but just for comparison:
Code:
Formatting Low Level:
	..............................................................................................................................

 Done Formatting Low Level in 7203155 us.
u 
	 Updated filecount 0
F
printDirectory SPI_NAND
--------------

 0 dirs with 0 files of Size 0 Bytes
 Total 0 files of Size 0 Bytes
Bytes Used: 262144, Bytes Total:131596288

EDIT: just a note if you do a quick format no issue - goes really fast :)
 
About Formatting - yeah it is slow. 'F' has a provision for block by block feedback to SerialUSB, 'f' does not. To see signs of life in 'f' uncomment this LFSIntegrity line: #define SHOW_YIELD_CNT 1

These both present fully erased media - with loss of the LFS 'history' as it keeps it of block reuse for wear leveling. A fresh LFS will always restart using the same initial blocks:
'q' : Quick Format :: myfs.quickFormat();
'F' : Low Level Format :: myfs.lowLevelFormat('.');

Doing this leaves LFS system unchanged:
'f' : Reclaim all unused format :: myfs.formatUnused( 0, 0 );

Both 'f' and 'F' will take some long time proportionate to the number of dirty blocks on the disk they look at and the time it takes for the media to do the block format. They both do the same thing, except 'f' skips over blocks reported in use by LFS to preserve the file system.

To keep the disk from going stale as LFS discards blocks and progress across the media formatting unused dirty blocks periodically do:
Code:
	static uint32_t lastBlock=0;
...
	uint32_t cnt = 5; // pick some number for cnt that will account for disk activity of deletes, or writes where it will cause LFS to discard DIR or FILE blocks to account for the change.
	lastBlock = myfs.formatUnused( cnt, lastBlock );
When myfs.formatUnused return 0 it has completed a pass from the last start with lastBlock=0.

Calling myfs.formatUnused has the overhead of waiting for LFS to parse its directory structure ( proportional to doing a full Directory walk ) to account for all the blocks in use. Noted earlier in this thread that can take some time when there are many files and dirs where the walk has to read all the links.
>> Current QSPI NOR disk has root and 32 Dirs with 784 files. DirWalk print takes 736ms and a myfs.formatUnused(1,0) looking for a single unformatted unused block on a formatted Used disk takes 276ms.
>> With 'S' then 's' to make and delete a 2MB file: Dirty Unused blocks a single Format takes only ~90ms. And and a Dirty Unused Format for 15 blocks takes only about 450ms - but it takes 34 of those to restore all the ~500 discarded blocks.

> With faster NAND format this math changes and the dir overhead is worse and myfs.formatUnused() with not enough to do is a waste of time
>> started up a 1Gb NAND and a dir quickly was filled in the first iteration with 148 files and the DirWalk took 2.3 seconds across the 33 total dirs.
>> Doing a DirWalk takes 2.26 seconds and myfs.formatUnused() of 15 blocks takes 6.1 seconds
>> The 'S' & 's' test only takes 2 sets of 15 myfs.formatUnused() - the first is 2.14 seconds and the second partial is 4.4 seconds

Some efficiencies could be had - but some would require digging into the internals of the LFS core code. The one .cache element given holds a bitmap they use to track internally used blocks when looking for space. But the lfs_fs_traverse() doesn't use that - it does a full root down block walk.
 
@defragster - @PaulStoffregen

One thing to remember is that when using LittleFS_SPIFlash you are limited to a SPI Clock of 30Mhz but when using a NAND you can run at 55Mhz SPI Clock.

There also seems to be another issue that I don't understand.

In the case of the NAND I can run at 75Mhz SPI clock when using my stand alone NAND library but when using LittleFS seems to fail above 55Mhz which is what it is currently set as. Similarly, but worse is with LittleFS 30Mhz seems to be about the limit for the NOR W25Q512 chip even though the spec says 104Mhz max.

As a quick a dirty test I just ran a simple test sketch, just getting the JEDEC for the 25Q512 Flash chip and I can only get the correct ID if I run at 30Mhz SPI. So not sure what the problem is with going faster. Here is the sketch if you are interested:
Code:
#include <SPI.h>

#define SPICONFIG   SPISettings(40000000, MSBFIRST, SPI_MODE0)


void setup() {
  while(!Serial);
  digitalWrite(5, HIGH);
  pinMode(5, OUTPUT);
  SPI.begin();

  uint8_t buf[4] = {0x9F, 0, 0, 0};
  SPI.beginTransaction(SPICONFIG);
  digitalWrite(5, LOW);
  SPI.transfer(buf, 4);
  digitalWrite(5, HIGH);
  SPI.endTransaction();

  Serial.printf("Flash ID: %02X %02X %02X \n", buf[1], buf[2], buf[3]);
}

void loop() {
  // put your main code here, to run repeatedly:

}
The timing table does state that:
Code:
Clock frequency for Read Data instruction (03h) has a max SPI clock 50 MHz
but for the 25Q512 LittleFS is using 0x13 (read 4 byte) which should allow you to go to 104Mhz - I think. I always have problem with datasheets.

The one note is that I can push the 30Mhz to 45Mhz and it will still work. But at 50Mhz it fails.
 
@PaulStoffregen - @All

In looking at the code for the 25Q512 you are using 4-byte addressing mode. A quick question though, don't you have to enter 4-byte address mode first like this:
Code:
	if(info->addrbits == 32) {
		port->beginTransaction(SPICONFIG);
		digitalWrite(pin, LOW);
		delayNanoseconds(50);
		port->transfer(0xB7);
		digitalWrite(pin, HIGH);
		port->endTransaction();
	}
or am I missing something - which is probably the case?
 
Question: is it right to assume that no new block is allocated in LFS without an ERASE?

Perhaps it can do a partial block update program 'in place' - but it cannot allocate/use a new block without calling 'erase' on it first based on this from LittleFS\src\littlefs\DESIGN.md::
Code:
 168:     // Erase a block. A block must be erased before being programmed.
  169:     // The state of an erased block is undefined. Negative error codes
  170      // are propogated to the user.

This was used earlier to some degree to detect disk change and when to trust a bitmap.
To be fully usable each erase entry point could set a flag on an erase. The flag could be used to determine if allocated blocks were changed since last bitmap update. This could save both the LFS_Traverse time as well as allowing the state of formatted blocks to be known.

It is perhaps possible that 'deleting' files could Free blocks that only a traverse would detect - where the headers and dir entries for those blocks might take an update showing them free and dirty. But the bitmap would be updated after each complete pass over the blocks to account for that, but without Erase changes it could complete to the last disk block before restarting.

Given that the formatUnused could often avoid traverse when doing small block groups in a repeat fashion while the media was in use between groups, then on returning would know to update or not the LFS_Traverse bits and keep track safely of where it left off. As noted some time back the traverse can take a significant time.


ALSO: given every block is validated to be FULLY empty on erase request - the formatUnused checking only the first 32 or 256 bytes should always detect a dirty block - and if not then it would get formatted before use on erase(). That would speed up the unusedFormat a great deal - this was the original process. Even reading 256 bytes would save 15/16 th's of the time now used to detect 'clean' 4096 byte blocks.
 
Updated LFSIntegrity to have a 'w'ipe of files and dirs.

I'll post code later in the AM - time this AM for a few hours Zzzz's ....

Massive speed up crossing already formatted blocks for formatUnused()
Updated LittleFS and LittleFS_NAND:
Code:
static bool blockIsBlank(struct lfs_config *config, lfs_block_t block, void *readBuf, [B]bool full=true[/B] );
static bool blockIsBlank(struct lfs_config *config, lfs_block_t block, void *readBuf, [B]bool full[/B] )
{
	if (!readBuf) return false;
	for (lfs_off_t offset=0; offset < config->block_size; offset += config->read_size) {
		memset(readBuf, 0, config->read_size);
		config->read(config, block, offset, readBuf, config->read_size);
		const uint8_t *buf = (uint8_t *)readBuf;
		for (unsigned int i=0; i < config->read_size; i++) {
			if (buf[i] != 0xFF) return false;
		}
[B]		if ( !full )
			return true; // first bytes read as 0xFF
[/B]	}
	return true; // all bytes read as 0xFF
}
>> This allows formatUnused to check only the first read_size block for 0xFF's and call it good.
Note 1: any LFS used block starts with HEADER info that seems to contraindicate not having at least on zero bit!
Note 2: If unusedFormat somehow makes a mistake: No block is used by LFS without requesting a normal FORMAT that will still do a "full" blockIsBlank(,,,full=true) verify and format if needed.

Quick Preview of a formatted disk - this is a FAST TO FORMAT SPI_NAND disk that is Large at Bytes Total:265,289,728
'Swf' : make a 2MB file, wipe all files, 'f'ormatUnused :: formatUnused :: Done Formatting Low Level in 1,210,826 us.
...versus...
'SwF' : make a 2MB file, wipe all files, lowLevelFormat :: Done Formatting Low Level in 74,828,860 us.

THANKS FRANKB - for HardFault detection! - recursive deleteAllDirectory(myfs.open("/"), szNone ); had a couple of issues - and seeing this POP up made fixing them easier than some of the compile errors. Not that the output told me anything other than ... 'Major Issue', which was all I needed combined with the output the preceded it! No HANGS and NO need to push Button!

@Paul - this needs to be in TD 1.54 Beta 7 - Please!
Code:
Hardfault.
Return Address: 0x863B0C48
	(IACCVIOL) Instruction Access Violation
Code:
Hardfault.
Return Address: 0x1153A
	(DACCVIOL) Data Access Violation
	(MMARVALID) Accessed Address: 0x0 (nullptr)

BTW: New computer tuned up and working very well! SublimeText and TSET working thanks to github and forum notes.
 
@mjs513 - KurtE - Paul ... @all:

Just pushed up an update to : github.com/Defragster/LFSintegrity

In the process the NAND branch was deleted. { New machine new entry to github - still stuck on some Pull Request for changes not here ??? }

INTENDED UPDATES:
> LFSIntegrity as it is here - updated from Beta 6 release that had some extras/issues

> LFS and NAND
- > code as it was here
- > edit to formatUnused to do a quick out on blockIsBlank() as noted in p#821

> Add T_4.1 folder to extras for common quick test

> It does include at least on edit to the 'lookAhead' size ... This will use RAM but should allow LFS to hold whole media bitmap - assuming it keeps it up to date and doesn't re-read it by traverse

@mjs513 - please do a code compare if possible to assure I didn't have any other tweaks/edits no in line with your current?

Here is what change to formatUnused does on SPI NAND in LFSIntegrity with : "BSwf"
Code:
Start Big write of 132493312 Big write /0_bigfile.txt took 136.52 Sec for 132491264 Bytes : file3.size()=132491264
	Big write KBytes per second 970.48 

Start Big write of 2048000 Bytes.........................
Big write /0_2MBfile.txt took  2.15 Sec for 2048000 Bytes : file3.size()=2048000
	Big write KBytes per second 950.73 

Wipe All Files and DIRS:
	Removed>	0_2MBfile.txt
	Removed>	0_bigfile.txt

 myfs.formatUnused( 0 ) ...
	 [B]formatUnused :: Done Formatting Low Level in 2,590,362 us.[/B]

And for LLformat of the same: "BSwF"
Code:
Start Big write of 132493312 Big write /0_bigfile.txt took 137.88 Sec for 132491264 Bytes : file3.size()=132491264
	Big write KBytes per second 960.89 

Start Big write of 2048000 Bytes.........................
Big write /0_2MBfile.txt took  2.15 Sec for 2048000 Bytes : file3.size()=2048000
	Big write KBytes per second 950.70 

Wipe All Files and DIRS:
	Removed>	0_2MBfile.txt
	Removed>	0_bigfile.txt

Formatting Low Level:
 [B]Done Formatting Low Level in 39,053,222 us.[/B]
 
@defragster- @KurtE
NAND Branch if I remember correctly was incorporated into LittleFS packaged with beta6, so that should be the latest. I will take a look and let your know.

The only change is to blockisBlank correct?
 
Last edited:
Yes, the meaningful change is to blockisBlank() in two places ( NAND and LFS other) and the call change in formatUnused.

I had a good compare post of the times - forgot to post as I ran off - came back with more info accumulated ... messed up and just deleted ...

<edit>: and of course edits to LFSIntegrity ...
 
Last edited:
Back
Top