119ea8026Sopenharmony_ci# test running a filesystem to exhaustion 219ea8026Sopenharmony_ci[cases.test_exhaustion_normal] 319ea8026Sopenharmony_cidefines.ERASE_CYCLES = 10 419ea8026Sopenharmony_cidefines.ERASE_COUNT = 256 # small bd so test runs faster 519ea8026Sopenharmony_cidefines.BLOCK_CYCLES = 'ERASE_CYCLES / 2' 619ea8026Sopenharmony_cidefines.BADBLOCK_BEHAVIOR = [ 719ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_PROGERROR', 819ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_ERASEERROR', 919ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_READERROR', 1019ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_PROGNOOP', 1119ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_ERASENOOP', 1219ea8026Sopenharmony_ci] 1319ea8026Sopenharmony_cidefines.FILES = 10 1419ea8026Sopenharmony_cicode = ''' 1519ea8026Sopenharmony_ci lfs_t lfs; 1619ea8026Sopenharmony_ci lfs_format(&lfs, cfg) => 0; 1719ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 1819ea8026Sopenharmony_ci lfs_mkdir(&lfs, "roadrunner") => 0; 1919ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 2019ea8026Sopenharmony_ci 2119ea8026Sopenharmony_ci uint32_t cycle = 0; 2219ea8026Sopenharmony_ci while (true) { 2319ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 2419ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 2519ea8026Sopenharmony_ci // chose name, roughly random seed, and random 2^n size 2619ea8026Sopenharmony_ci char path[1024]; 2719ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 2819ea8026Sopenharmony_ci uint32_t prng = cycle * i; 2919ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 3019ea8026Sopenharmony_ci 3119ea8026Sopenharmony_ci lfs_file_t file; 3219ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, 3319ea8026Sopenharmony_ci LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; 3419ea8026Sopenharmony_ci 3519ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 3619ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 3719ea8026Sopenharmony_ci lfs_ssize_t res = lfs_file_write(&lfs, &file, &c, 1); 3819ea8026Sopenharmony_ci assert(res == 1 || res == LFS_ERR_NOSPC); 3919ea8026Sopenharmony_ci if (res == LFS_ERR_NOSPC) { 4019ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 4119ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 4219ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 4319ea8026Sopenharmony_ci goto exhausted; 4419ea8026Sopenharmony_ci } 4519ea8026Sopenharmony_ci } 4619ea8026Sopenharmony_ci 4719ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 4819ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 4919ea8026Sopenharmony_ci if (err == LFS_ERR_NOSPC) { 5019ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 5119ea8026Sopenharmony_ci goto exhausted; 5219ea8026Sopenharmony_ci } 5319ea8026Sopenharmony_ci } 5419ea8026Sopenharmony_ci 5519ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 5619ea8026Sopenharmony_ci // check for errors 5719ea8026Sopenharmony_ci char path[1024]; 5819ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 5919ea8026Sopenharmony_ci uint32_t prng = cycle * i; 6019ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 6119ea8026Sopenharmony_ci 6219ea8026Sopenharmony_ci lfs_file_t file; 6319ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 6419ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 6519ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 6619ea8026Sopenharmony_ci char r; 6719ea8026Sopenharmony_ci lfs_file_read(&lfs, &file, &r, 1) => 1; 6819ea8026Sopenharmony_ci assert(r == c); 6919ea8026Sopenharmony_ci } 7019ea8026Sopenharmony_ci 7119ea8026Sopenharmony_ci lfs_file_close(&lfs, &file) => 0; 7219ea8026Sopenharmony_ci } 7319ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 7419ea8026Sopenharmony_ci 7519ea8026Sopenharmony_ci cycle += 1; 7619ea8026Sopenharmony_ci } 7719ea8026Sopenharmony_ci 7819ea8026Sopenharmony_ciexhausted: 7919ea8026Sopenharmony_ci // should still be readable 8019ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 8119ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 8219ea8026Sopenharmony_ci // check for errors 8319ea8026Sopenharmony_ci char path[1024]; 8419ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 8519ea8026Sopenharmony_ci struct lfs_info info; 8619ea8026Sopenharmony_ci lfs_stat(&lfs, path, &info) => 0; 8719ea8026Sopenharmony_ci } 8819ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 8919ea8026Sopenharmony_ci 9019ea8026Sopenharmony_ci LFS_WARN("completed %d cycles", cycle); 9119ea8026Sopenharmony_ci''' 9219ea8026Sopenharmony_ci 9319ea8026Sopenharmony_ci# test running a filesystem to exhaustion 9419ea8026Sopenharmony_ci# which also requires expanding superblocks 9519ea8026Sopenharmony_ci[cases.test_exhaustion_superblocks] 9619ea8026Sopenharmony_cidefines.ERASE_CYCLES = 10 9719ea8026Sopenharmony_cidefines.ERASE_COUNT = 256 # small bd so test runs faster 9819ea8026Sopenharmony_cidefines.BLOCK_CYCLES = 'ERASE_CYCLES / 2' 9919ea8026Sopenharmony_cidefines.BADBLOCK_BEHAVIOR = [ 10019ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_PROGERROR', 10119ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_ERASEERROR', 10219ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_READERROR', 10319ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_PROGNOOP', 10419ea8026Sopenharmony_ci 'LFS_EMUBD_BADBLOCK_ERASENOOP', 10519ea8026Sopenharmony_ci] 10619ea8026Sopenharmony_cidefines.FILES = 10 10719ea8026Sopenharmony_cicode = ''' 10819ea8026Sopenharmony_ci lfs_t lfs; 10919ea8026Sopenharmony_ci lfs_format(&lfs, cfg) => 0; 11019ea8026Sopenharmony_ci 11119ea8026Sopenharmony_ci uint32_t cycle = 0; 11219ea8026Sopenharmony_ci while (true) { 11319ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 11419ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 11519ea8026Sopenharmony_ci // chose name, roughly random seed, and random 2^n size 11619ea8026Sopenharmony_ci char path[1024]; 11719ea8026Sopenharmony_ci sprintf(path, "test%d", i); 11819ea8026Sopenharmony_ci uint32_t prng = cycle * i; 11919ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 12019ea8026Sopenharmony_ci 12119ea8026Sopenharmony_ci lfs_file_t file; 12219ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, 12319ea8026Sopenharmony_ci LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; 12419ea8026Sopenharmony_ci 12519ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 12619ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 12719ea8026Sopenharmony_ci lfs_ssize_t res = lfs_file_write(&lfs, &file, &c, 1); 12819ea8026Sopenharmony_ci assert(res == 1 || res == LFS_ERR_NOSPC); 12919ea8026Sopenharmony_ci if (res == LFS_ERR_NOSPC) { 13019ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 13119ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 13219ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 13319ea8026Sopenharmony_ci goto exhausted; 13419ea8026Sopenharmony_ci } 13519ea8026Sopenharmony_ci } 13619ea8026Sopenharmony_ci 13719ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 13819ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 13919ea8026Sopenharmony_ci if (err == LFS_ERR_NOSPC) { 14019ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 14119ea8026Sopenharmony_ci goto exhausted; 14219ea8026Sopenharmony_ci } 14319ea8026Sopenharmony_ci } 14419ea8026Sopenharmony_ci 14519ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 14619ea8026Sopenharmony_ci // check for errors 14719ea8026Sopenharmony_ci char path[1024]; 14819ea8026Sopenharmony_ci sprintf(path, "test%d", i); 14919ea8026Sopenharmony_ci uint32_t prng = cycle * i; 15019ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 15119ea8026Sopenharmony_ci 15219ea8026Sopenharmony_ci lfs_file_t file; 15319ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 15419ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 15519ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 15619ea8026Sopenharmony_ci char r; 15719ea8026Sopenharmony_ci lfs_file_read(&lfs, &file, &r, 1) => 1; 15819ea8026Sopenharmony_ci assert(r == c); 15919ea8026Sopenharmony_ci } 16019ea8026Sopenharmony_ci 16119ea8026Sopenharmony_ci lfs_file_close(&lfs, &file) => 0; 16219ea8026Sopenharmony_ci } 16319ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 16419ea8026Sopenharmony_ci 16519ea8026Sopenharmony_ci cycle += 1; 16619ea8026Sopenharmony_ci } 16719ea8026Sopenharmony_ci 16819ea8026Sopenharmony_ciexhausted: 16919ea8026Sopenharmony_ci // should still be readable 17019ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 17119ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 17219ea8026Sopenharmony_ci // check for errors 17319ea8026Sopenharmony_ci char path[1024]; 17419ea8026Sopenharmony_ci struct lfs_info info; 17519ea8026Sopenharmony_ci sprintf(path, "test%d", i); 17619ea8026Sopenharmony_ci lfs_stat(&lfs, path, &info) => 0; 17719ea8026Sopenharmony_ci } 17819ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 17919ea8026Sopenharmony_ci 18019ea8026Sopenharmony_ci LFS_WARN("completed %d cycles", cycle); 18119ea8026Sopenharmony_ci''' 18219ea8026Sopenharmony_ci 18319ea8026Sopenharmony_ci# These are a sort of high-level litmus test for wear-leveling. One definition 18419ea8026Sopenharmony_ci# of wear-leveling is that increasing a block device's space translates directly 18519ea8026Sopenharmony_ci# into increasing the block devices lifetime. This is something we can actually 18619ea8026Sopenharmony_ci# check for. 18719ea8026Sopenharmony_ci 18819ea8026Sopenharmony_ci# wear-level test running a filesystem to exhaustion 18919ea8026Sopenharmony_ci[cases.test_exhuastion_wear_leveling] 19019ea8026Sopenharmony_cidefines.ERASE_CYCLES = 20 19119ea8026Sopenharmony_cidefines.ERASE_COUNT = 256 # small bd so test runs faster 19219ea8026Sopenharmony_cidefines.BLOCK_CYCLES = 'ERASE_CYCLES / 2' 19319ea8026Sopenharmony_cidefines.FILES = 10 19419ea8026Sopenharmony_cicode = ''' 19519ea8026Sopenharmony_ci uint32_t run_cycles[2]; 19619ea8026Sopenharmony_ci const uint32_t run_block_count[2] = {BLOCK_COUNT/2, BLOCK_COUNT}; 19719ea8026Sopenharmony_ci 19819ea8026Sopenharmony_ci for (int run = 0; run < 2; run++) { 19919ea8026Sopenharmony_ci for (lfs_block_t b = 0; b < BLOCK_COUNT; b++) { 20019ea8026Sopenharmony_ci lfs_emubd_setwear(cfg, b, 20119ea8026Sopenharmony_ci (b < run_block_count[run]) ? 0 : ERASE_CYCLES) => 0; 20219ea8026Sopenharmony_ci } 20319ea8026Sopenharmony_ci 20419ea8026Sopenharmony_ci lfs_t lfs; 20519ea8026Sopenharmony_ci lfs_format(&lfs, cfg) => 0; 20619ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 20719ea8026Sopenharmony_ci lfs_mkdir(&lfs, "roadrunner") => 0; 20819ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 20919ea8026Sopenharmony_ci 21019ea8026Sopenharmony_ci uint32_t cycle = 0; 21119ea8026Sopenharmony_ci while (true) { 21219ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 21319ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 21419ea8026Sopenharmony_ci // chose name, roughly random seed, and random 2^n size 21519ea8026Sopenharmony_ci char path[1024]; 21619ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 21719ea8026Sopenharmony_ci uint32_t prng = cycle * i; 21819ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 21919ea8026Sopenharmony_ci 22019ea8026Sopenharmony_ci lfs_file_t file; 22119ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, 22219ea8026Sopenharmony_ci LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; 22319ea8026Sopenharmony_ci 22419ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 22519ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 22619ea8026Sopenharmony_ci lfs_ssize_t res = lfs_file_write(&lfs, &file, &c, 1); 22719ea8026Sopenharmony_ci assert(res == 1 || res == LFS_ERR_NOSPC); 22819ea8026Sopenharmony_ci if (res == LFS_ERR_NOSPC) { 22919ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 23019ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 23119ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 23219ea8026Sopenharmony_ci goto exhausted; 23319ea8026Sopenharmony_ci } 23419ea8026Sopenharmony_ci } 23519ea8026Sopenharmony_ci 23619ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 23719ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 23819ea8026Sopenharmony_ci if (err == LFS_ERR_NOSPC) { 23919ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 24019ea8026Sopenharmony_ci goto exhausted; 24119ea8026Sopenharmony_ci } 24219ea8026Sopenharmony_ci } 24319ea8026Sopenharmony_ci 24419ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 24519ea8026Sopenharmony_ci // check for errors 24619ea8026Sopenharmony_ci char path[1024]; 24719ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 24819ea8026Sopenharmony_ci uint32_t prng = cycle * i; 24919ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 25019ea8026Sopenharmony_ci 25119ea8026Sopenharmony_ci lfs_file_t file; 25219ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 25319ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 25419ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 25519ea8026Sopenharmony_ci char r; 25619ea8026Sopenharmony_ci lfs_file_read(&lfs, &file, &r, 1) => 1; 25719ea8026Sopenharmony_ci assert(r == c); 25819ea8026Sopenharmony_ci } 25919ea8026Sopenharmony_ci 26019ea8026Sopenharmony_ci lfs_file_close(&lfs, &file) => 0; 26119ea8026Sopenharmony_ci } 26219ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 26319ea8026Sopenharmony_ci 26419ea8026Sopenharmony_ci cycle += 1; 26519ea8026Sopenharmony_ci } 26619ea8026Sopenharmony_ci 26719ea8026Sopenharmony_ciexhausted: 26819ea8026Sopenharmony_ci // should still be readable 26919ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 27019ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 27119ea8026Sopenharmony_ci // check for errors 27219ea8026Sopenharmony_ci char path[1024]; 27319ea8026Sopenharmony_ci struct lfs_info info; 27419ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 27519ea8026Sopenharmony_ci lfs_stat(&lfs, path, &info) => 0; 27619ea8026Sopenharmony_ci } 27719ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 27819ea8026Sopenharmony_ci 27919ea8026Sopenharmony_ci run_cycles[run] = cycle; 28019ea8026Sopenharmony_ci LFS_WARN("completed %d blocks %d cycles", 28119ea8026Sopenharmony_ci run_block_count[run], run_cycles[run]); 28219ea8026Sopenharmony_ci } 28319ea8026Sopenharmony_ci 28419ea8026Sopenharmony_ci // check we increased the lifetime by 2x with ~10% error 28519ea8026Sopenharmony_ci LFS_ASSERT(run_cycles[1]*110/100 > 2*run_cycles[0]); 28619ea8026Sopenharmony_ci''' 28719ea8026Sopenharmony_ci 28819ea8026Sopenharmony_ci# wear-level test + expanding superblock 28919ea8026Sopenharmony_ci[cases.test_exhaustion_wear_leveling_superblocks] 29019ea8026Sopenharmony_cidefines.ERASE_CYCLES = 20 29119ea8026Sopenharmony_cidefines.ERASE_COUNT = 256 # small bd so test runs faster 29219ea8026Sopenharmony_cidefines.BLOCK_CYCLES = 'ERASE_CYCLES / 2' 29319ea8026Sopenharmony_cidefines.FILES = 10 29419ea8026Sopenharmony_cicode = ''' 29519ea8026Sopenharmony_ci uint32_t run_cycles[2]; 29619ea8026Sopenharmony_ci const uint32_t run_block_count[2] = {BLOCK_COUNT/2, BLOCK_COUNT}; 29719ea8026Sopenharmony_ci 29819ea8026Sopenharmony_ci for (int run = 0; run < 2; run++) { 29919ea8026Sopenharmony_ci for (lfs_block_t b = 0; b < BLOCK_COUNT; b++) { 30019ea8026Sopenharmony_ci lfs_emubd_setwear(cfg, b, 30119ea8026Sopenharmony_ci (b < run_block_count[run]) ? 0 : ERASE_CYCLES) => 0; 30219ea8026Sopenharmony_ci } 30319ea8026Sopenharmony_ci 30419ea8026Sopenharmony_ci lfs_t lfs; 30519ea8026Sopenharmony_ci lfs_format(&lfs, cfg) => 0; 30619ea8026Sopenharmony_ci 30719ea8026Sopenharmony_ci uint32_t cycle = 0; 30819ea8026Sopenharmony_ci while (true) { 30919ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 31019ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 31119ea8026Sopenharmony_ci // chose name, roughly random seed, and random 2^n size 31219ea8026Sopenharmony_ci char path[1024]; 31319ea8026Sopenharmony_ci sprintf(path, "test%d", i); 31419ea8026Sopenharmony_ci uint32_t prng = cycle * i; 31519ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 31619ea8026Sopenharmony_ci 31719ea8026Sopenharmony_ci lfs_file_t file; 31819ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, 31919ea8026Sopenharmony_ci LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; 32019ea8026Sopenharmony_ci 32119ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 32219ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 32319ea8026Sopenharmony_ci lfs_ssize_t res = lfs_file_write(&lfs, &file, &c, 1); 32419ea8026Sopenharmony_ci assert(res == 1 || res == LFS_ERR_NOSPC); 32519ea8026Sopenharmony_ci if (res == LFS_ERR_NOSPC) { 32619ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 32719ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 32819ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 32919ea8026Sopenharmony_ci goto exhausted; 33019ea8026Sopenharmony_ci } 33119ea8026Sopenharmony_ci } 33219ea8026Sopenharmony_ci 33319ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 33419ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 33519ea8026Sopenharmony_ci if (err == LFS_ERR_NOSPC) { 33619ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 33719ea8026Sopenharmony_ci goto exhausted; 33819ea8026Sopenharmony_ci } 33919ea8026Sopenharmony_ci } 34019ea8026Sopenharmony_ci 34119ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 34219ea8026Sopenharmony_ci // check for errors 34319ea8026Sopenharmony_ci char path[1024]; 34419ea8026Sopenharmony_ci sprintf(path, "test%d", i); 34519ea8026Sopenharmony_ci uint32_t prng = cycle * i; 34619ea8026Sopenharmony_ci lfs_size_t size = 1 << ((TEST_PRNG(&prng) % 10)+2); 34719ea8026Sopenharmony_ci 34819ea8026Sopenharmony_ci lfs_file_t file; 34919ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 35019ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 35119ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 35219ea8026Sopenharmony_ci char r; 35319ea8026Sopenharmony_ci lfs_file_read(&lfs, &file, &r, 1) => 1; 35419ea8026Sopenharmony_ci assert(r == c); 35519ea8026Sopenharmony_ci } 35619ea8026Sopenharmony_ci 35719ea8026Sopenharmony_ci lfs_file_close(&lfs, &file) => 0; 35819ea8026Sopenharmony_ci } 35919ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 36019ea8026Sopenharmony_ci 36119ea8026Sopenharmony_ci cycle += 1; 36219ea8026Sopenharmony_ci } 36319ea8026Sopenharmony_ci 36419ea8026Sopenharmony_ciexhausted: 36519ea8026Sopenharmony_ci // should still be readable 36619ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 36719ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 36819ea8026Sopenharmony_ci // check for errors 36919ea8026Sopenharmony_ci char path[1024]; 37019ea8026Sopenharmony_ci struct lfs_info info; 37119ea8026Sopenharmony_ci sprintf(path, "test%d", i); 37219ea8026Sopenharmony_ci lfs_stat(&lfs, path, &info) => 0; 37319ea8026Sopenharmony_ci } 37419ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 37519ea8026Sopenharmony_ci 37619ea8026Sopenharmony_ci run_cycles[run] = cycle; 37719ea8026Sopenharmony_ci LFS_WARN("completed %d blocks %d cycles", 37819ea8026Sopenharmony_ci run_block_count[run], run_cycles[run]); 37919ea8026Sopenharmony_ci } 38019ea8026Sopenharmony_ci 38119ea8026Sopenharmony_ci // check we increased the lifetime by 2x with ~10% error 38219ea8026Sopenharmony_ci LFS_ASSERT(run_cycles[1]*110/100 > 2*run_cycles[0]); 38319ea8026Sopenharmony_ci''' 38419ea8026Sopenharmony_ci 38519ea8026Sopenharmony_ci# test that we wear blocks roughly evenly 38619ea8026Sopenharmony_ci[cases.test_exhaustion_wear_distribution] 38719ea8026Sopenharmony_cidefines.ERASE_CYCLES = 0xffffffff 38819ea8026Sopenharmony_cidefines.ERASE_COUNT = 256 # small bd so test runs faster 38919ea8026Sopenharmony_cidefines.BLOCK_CYCLES = [5, 4, 3, 2, 1] 39019ea8026Sopenharmony_cidefines.CYCLES = 100 39119ea8026Sopenharmony_cidefines.FILES = 10 39219ea8026Sopenharmony_ciif = 'BLOCK_CYCLES < CYCLES/10' 39319ea8026Sopenharmony_cicode = ''' 39419ea8026Sopenharmony_ci lfs_t lfs; 39519ea8026Sopenharmony_ci lfs_format(&lfs, cfg) => 0; 39619ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 39719ea8026Sopenharmony_ci lfs_mkdir(&lfs, "roadrunner") => 0; 39819ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 39919ea8026Sopenharmony_ci 40019ea8026Sopenharmony_ci uint32_t cycle = 0; 40119ea8026Sopenharmony_ci while (cycle < CYCLES) { 40219ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 40319ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 40419ea8026Sopenharmony_ci // chose name, roughly random seed, and random 2^n size 40519ea8026Sopenharmony_ci char path[1024]; 40619ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 40719ea8026Sopenharmony_ci uint32_t prng = cycle * i; 40819ea8026Sopenharmony_ci lfs_size_t size = 1 << 4; //((TEST_PRNG(&prng) % 10)+2); 40919ea8026Sopenharmony_ci 41019ea8026Sopenharmony_ci lfs_file_t file; 41119ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, 41219ea8026Sopenharmony_ci LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; 41319ea8026Sopenharmony_ci 41419ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 41519ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 41619ea8026Sopenharmony_ci lfs_ssize_t res = lfs_file_write(&lfs, &file, &c, 1); 41719ea8026Sopenharmony_ci assert(res == 1 || res == LFS_ERR_NOSPC); 41819ea8026Sopenharmony_ci if (res == LFS_ERR_NOSPC) { 41919ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 42019ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 42119ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 42219ea8026Sopenharmony_ci goto exhausted; 42319ea8026Sopenharmony_ci } 42419ea8026Sopenharmony_ci } 42519ea8026Sopenharmony_ci 42619ea8026Sopenharmony_ci int err = lfs_file_close(&lfs, &file); 42719ea8026Sopenharmony_ci assert(err == 0 || err == LFS_ERR_NOSPC); 42819ea8026Sopenharmony_ci if (err == LFS_ERR_NOSPC) { 42919ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 43019ea8026Sopenharmony_ci goto exhausted; 43119ea8026Sopenharmony_ci } 43219ea8026Sopenharmony_ci } 43319ea8026Sopenharmony_ci 43419ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 43519ea8026Sopenharmony_ci // check for errors 43619ea8026Sopenharmony_ci char path[1024]; 43719ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 43819ea8026Sopenharmony_ci uint32_t prng = cycle * i; 43919ea8026Sopenharmony_ci lfs_size_t size = 1 << 4; //((TEST_PRNG(&prng) % 10)+2); 44019ea8026Sopenharmony_ci 44119ea8026Sopenharmony_ci lfs_file_t file; 44219ea8026Sopenharmony_ci lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; 44319ea8026Sopenharmony_ci for (lfs_size_t j = 0; j < size; j++) { 44419ea8026Sopenharmony_ci char c = 'a' + (TEST_PRNG(&prng) % 26); 44519ea8026Sopenharmony_ci char r; 44619ea8026Sopenharmony_ci lfs_file_read(&lfs, &file, &r, 1) => 1; 44719ea8026Sopenharmony_ci assert(r == c); 44819ea8026Sopenharmony_ci } 44919ea8026Sopenharmony_ci 45019ea8026Sopenharmony_ci lfs_file_close(&lfs, &file) => 0; 45119ea8026Sopenharmony_ci } 45219ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 45319ea8026Sopenharmony_ci 45419ea8026Sopenharmony_ci cycle += 1; 45519ea8026Sopenharmony_ci } 45619ea8026Sopenharmony_ci 45719ea8026Sopenharmony_ciexhausted: 45819ea8026Sopenharmony_ci // should still be readable 45919ea8026Sopenharmony_ci lfs_mount(&lfs, cfg) => 0; 46019ea8026Sopenharmony_ci for (uint32_t i = 0; i < FILES; i++) { 46119ea8026Sopenharmony_ci // check for errors 46219ea8026Sopenharmony_ci char path[1024]; 46319ea8026Sopenharmony_ci struct lfs_info info; 46419ea8026Sopenharmony_ci sprintf(path, "roadrunner/test%d", i); 46519ea8026Sopenharmony_ci lfs_stat(&lfs, path, &info) => 0; 46619ea8026Sopenharmony_ci } 46719ea8026Sopenharmony_ci lfs_unmount(&lfs) => 0; 46819ea8026Sopenharmony_ci 46919ea8026Sopenharmony_ci LFS_WARN("completed %d cycles", cycle); 47019ea8026Sopenharmony_ci 47119ea8026Sopenharmony_ci // check the wear on our block device 47219ea8026Sopenharmony_ci lfs_emubd_wear_t minwear = -1; 47319ea8026Sopenharmony_ci lfs_emubd_wear_t totalwear = 0; 47419ea8026Sopenharmony_ci lfs_emubd_wear_t maxwear = 0; 47519ea8026Sopenharmony_ci // skip 0 and 1 as superblock movement is intentionally avoided 47619ea8026Sopenharmony_ci for (lfs_block_t b = 2; b < BLOCK_COUNT; b++) { 47719ea8026Sopenharmony_ci lfs_emubd_wear_t wear = lfs_emubd_wear(cfg, b); 47819ea8026Sopenharmony_ci printf("%08x: wear %d\n", b, wear); 47919ea8026Sopenharmony_ci assert(wear >= 0); 48019ea8026Sopenharmony_ci if (wear < minwear) { 48119ea8026Sopenharmony_ci minwear = wear; 48219ea8026Sopenharmony_ci } 48319ea8026Sopenharmony_ci if (wear > maxwear) { 48419ea8026Sopenharmony_ci maxwear = wear; 48519ea8026Sopenharmony_ci } 48619ea8026Sopenharmony_ci totalwear += wear; 48719ea8026Sopenharmony_ci } 48819ea8026Sopenharmony_ci lfs_emubd_wear_t avgwear = totalwear / BLOCK_COUNT; 48919ea8026Sopenharmony_ci LFS_WARN("max wear: %d cycles", maxwear); 49019ea8026Sopenharmony_ci LFS_WARN("avg wear: %d cycles", totalwear / (int)BLOCK_COUNT); 49119ea8026Sopenharmony_ci LFS_WARN("min wear: %d cycles", minwear); 49219ea8026Sopenharmony_ci 49319ea8026Sopenharmony_ci // find standard deviation^2 49419ea8026Sopenharmony_ci lfs_emubd_wear_t dev2 = 0; 49519ea8026Sopenharmony_ci for (lfs_block_t b = 2; b < BLOCK_COUNT; b++) { 49619ea8026Sopenharmony_ci lfs_emubd_wear_t wear = lfs_emubd_wear(cfg, b); 49719ea8026Sopenharmony_ci assert(wear >= 0); 49819ea8026Sopenharmony_ci lfs_emubd_swear_t diff = wear - avgwear; 49919ea8026Sopenharmony_ci dev2 += diff*diff; 50019ea8026Sopenharmony_ci } 50119ea8026Sopenharmony_ci dev2 /= totalwear; 50219ea8026Sopenharmony_ci LFS_WARN("std dev^2: %d", dev2); 50319ea8026Sopenharmony_ci assert(dev2 < 8); 50419ea8026Sopenharmony_ci''' 50519ea8026Sopenharmony_ci 506