Hi Folks Attached are four patches which extend the cyg_fs_getinfo call to retrieve information about the current filesystem disk usage. Using the key FS_INFO_BLOCK_USAGE you can get the current total number of blocks in the filesystem, the number of free blocks and the size of a block.
With fatfs this is straight forward since there are blocks of fixed size. With romfs and ramfs the blocks are 1 byte in size. romfs never has any free blocks, so all you can find out is how big the disk is. ramfs can be dynamically sized on the heap. In this case the call is not implemented. When a fixed pool is used the call is implemented. jffs2 works in terms of flash blocks. I have committed romfs, ramfs and fatfs. I know Gary is working in updating the jffs2 port to the latest mtd release in git, so i've not committed this yet. Gary, should i commit? Andrew
Index: fs/fat/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/fat/current/ChangeLog,v retrieving revision 1.12 diff -u -r1.12 ChangeLog --- fs/fat/current/ChangeLog 3 Aug 2005 20:40:48 -0000 1.12 +++ fs/fat/current/ChangeLog 4 Aug 2006 09:15:54 -0000 @@ -1,3 +1,11 @@ +2006-08-04 Paul Fine <[EMAIL PROTECTED]> + Andrew Lunn <[EMAIL PROTECTED]> + + * src/fats.c: Added functionality to the fatfs_getinfo() function + to return disk usage information about the filesystem, making this + information accessible through the cyg_fs_getinfo() interface. + * tests/fatfs1.c: Added code to test the disk usage. + 2005-07-30 Andrew Lunn <[EMAIL PROTECTED]> * src/fatfs_supp.c: Correct types to remove compiler warnings. Index: fs/fat/current/src/fatfs.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/fat/current/src/fatfs.c,v retrieving revision 1.4 diff -u -r1.4 fatfs.c --- fs/fat/current/src/fatfs.c 11 Nov 2004 19:33:30 -0000 1.4 +++ fs/fat/current/src/fatfs.c 4 Aug 2006 09:15:54 -0000 @@ -1109,6 +1109,22 @@ err = fatfs_get_attrib(mte, dir, name, (cyg_fs_attrib_t*)buf); break; #endif // CYGCFG_FS_FAT_USE_ATTRIBUTES +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + case FS_INFO_BLOCK_USAGE: { + cyg_uint32 total_clusters; + cyg_uint32 free_clusters; + struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf; + fatfs_disk_t *disk = (fatfs_disk_t *) mte->data; + + err = fatfs_get_disk_usage(disk, &total_clusters, &free_clusters); + if (err) + return err; + usage->total_blocks = total_clusters; + usage->free_blocks = free_clusters; + usage->block_size = disk->cluster_size; + break; + } +#endif default: err = EINVAL; break; Index: fs/fat/current/tests/fatfs1.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/fat/current/tests/fatfs1.c,v retrieving revision 1.2 diff -u -r1.2 fatfs1.c --- fs/fat/current/tests/fatfs1.c 27 Mar 2005 18:22:01 -0000 1.2 +++ fs/fat/current/tests/fatfs1.c 4 Aug 2006 09:15:54 -0000 @@ -432,6 +432,9 @@ { int err; int existingdirents=-1; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif CYG_TEST_INIT(); @@ -448,6 +451,16 @@ listdir( "/", true, -1, &existingdirents ); // -------------------------------------------------------------- +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- createfile( "/foo", 20257 ); checkfile( "foo" ); @@ -480,6 +493,15 @@ checkfile( "/bar/bundy" ); comparefiles("/fee", "bundy" ); +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif // -------------------------------------------------------------- diag_printf("<INFO>: unlink fee\n");
? fs/ram/current/tests/ramfs3.c Index: fs/ram/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/ram/current/ChangeLog,v retrieving revision 1.17 diff -u -r1.17 ChangeLog --- fs/ram/current/ChangeLog 17 May 2006 16:12:11 -0000 1.17 +++ fs/ram/current/ChangeLog 4 Aug 2006 09:16:15 -0000 @@ -1,3 +1,10 @@ +2006-06-25 Andrew Lunn <[EMAIL PROTECTED]> + + * src/ramfs.c (find_direntry): Don't search off the end of the + directory node into hyperspace. + * src/ramfs.c (ramfs_getinfo): Support for block usage call. + * tests/ramfs1.c (main): Add file system block usage test. + 2006-05-17 Andy Jackson <[EMAIL PROTECTED]> * tests/ramfs1.c (createfile): Fix compile warnings. Index: fs/ram/current/src/ramfs.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/ram/current/src/ramfs.c,v retrieving revision 1.9 diff -u -r1.9 ramfs.c --- fs/ram/current/src/ramfs.c 2 Oct 2005 14:03:14 -0000 1.9 +++ fs/ram/current/src/ramfs.c 4 Aug 2006 09:16:15 -0000 @@ -1210,11 +1210,11 @@ ramfs_dirent *d; cyg_uint8 *buf; size_t size; - + // look for a first name fragment for(;;) { - err = findbuffer_node( dir, pos, &buf, &size, false ); + err = findbuffer_node( dir, pos, &buf, &size, false ); if( err != ENOERR || size == 0) return NULL; @@ -1223,7 +1223,10 @@ if( size < sizeof(ramfs_dirent) || !d->inuse || !d->first ) { pos += sizeof(ramfs_dirent); - continue; + if ( pos < dir->size ) + continue; + // End if directory, didn't find it. + return NULL; } break; @@ -1248,17 +1251,17 @@ fraglen = d->fraglen; // compare strings, if different, look for another - if( memcmp( frag, d->name, fraglen ) != 0 ) - break; - + if( memcmp( frag, d->name, fraglen ) != 0 ) { + break; + } frag += fraglen; // If we are at the last fragment, then the whole name string // has matched and we have a successful search. - if( d->last ) - return first; - + if( d->last ) + return first; + // Otherwise move on to next entry in chain err = findbuffer_node( dir, d->next, &buf, &size, false ); if( err != ENOERR ) @@ -1977,7 +1980,7 @@ // ------------------------------------------------------------------------- // ramfs_getinfo() -// Getinfo. Currently only support pathconf(). +// Getinfo. Currently only support pathconf() and filesystem usage. static int ramfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ) @@ -1996,7 +1999,26 @@ case FS_INFO_CONF: err = ramfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf ); break; - +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY) + // When using malloc for storage this does not make much + // sense, so only implement this when using pre-allocated + // blocks + case FS_INFO_BLOCK_USAGE: { + struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf; + ramfs_block *b; + + usage->total_blocks = CYGNUM_FS_RAM_BLOCKS_ARRAY_SIZE; + usage->free_blocks = 0; + // Iterate over the free list to count its size + b = block_free_list; + while(b) { + usage->free_blocks++; + b=*(ramfs_block **)b; + } + usage->block_size = CYGNUM_RAMFS_BLOCK_SIZE; + return ENOERR; + } +#endif default: err = EINVAL; } Index: fs/ram/current/tests/ramfs1.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/ram/current/tests/ramfs1.c,v retrieving revision 1.3 diff -u -r1.3 ramfs1.c --- fs/ram/current/tests/ramfs1.c 17 May 2006 16:12:12 -0000 1.3 +++ fs/ram/current/tests/ramfs1.c 4 Aug 2006 09:16:16 -0000 @@ -61,6 +61,7 @@ #include <pkgconf/hal.h> #include <pkgconf/kernel.h> #include <pkgconf/io_fileio.h> +#include <pkgconf/fs_ram.h> #include <cyg/kernel/ktypes.h> // base kernel types #include <cyg/infra/cyg_trac.h> // tracing macros @@ -415,6 +416,9 @@ { int err; int existingdirents=-1; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY) + struct cyg_fs_block_usage usage; +#endif CYG_TEST_INIT(); @@ -431,7 +435,16 @@ listdir( "/", true, -1, &existingdirents ); if ( existingdirents < 2 ) CYG_TEST_FAIL("Not enough dir entries\n"); - + // -------------------------------------------------------------- +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif // -------------------------------------------------------------- createfile( "/foo", 202 ); @@ -552,6 +565,16 @@ listdir( "..", true, existingdirents+3, NULL ); // -------------------------------------------------------------- +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) && defined(CYGPKG_FS_RAM_BLOCKS_ARRAY) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- diag_printf("<INFO>: unlink tinky\n"); err = unlink( "tinky" );
Index: fs/rom/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/rom/current/ChangeLog,v retrieving revision 1.19 diff -u -r1.19 ChangeLog --- fs/rom/current/ChangeLog 15 Feb 2006 20:04:51 -0000 1.19 +++ fs/rom/current/ChangeLog 4 Aug 2006 09:21:05 -0000 @@ -1,3 +1,8 @@ +2006-08-04 Andrew Lunn <[EMAIL PROTECTED]> + + * src/romfs.c (romfs_getinfo): Support for block usage call. + * tests/romfs1.c (main): Add file system block usage test. + 2006-02-15 Andrew Lunn <[EMAIL PROTECTED]> Peter Korsgaard <[EMAIL PROTECTED]> Index: fs/rom/current/src/romfs.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/rom/current/src/romfs.c,v retrieving revision 1.7 diff -u -r1.7 romfs.c --- fs/rom/current/src/romfs.c 5 Oct 2004 08:00:43 -0000 1.7 +++ fs/rom/current/src/romfs.c 4 Aug 2006 09:21:05 -0000 @@ -800,7 +800,7 @@ // ------------------------------------------------------------------------- // romfs_getinfo() -// Getinfo. Currently only support pathconf(). +// Getinfo. Currently only support pathconf() and file system block usage static int romfs_getinfo ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, void *buf, int len ) @@ -819,7 +819,16 @@ case FS_INFO_CONF: err = romfs_pathconf( ds.node, (struct cyg_pathconf_info *)buf ); break; - +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + case FS_INFO_BLOCK_USAGE: { + struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf; + struct romfs_disk *disk = (struct romfs_disk*) mte->data; + usage->total_blocks = disk->disksize; + usage->free_blocks = 0; + usage->block_size = 1; + return ENOERR; + } +#endif default: err = EINVAL; } Index: fs/rom/current/tests/romfs1.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/rom/current/tests/romfs1.c,v retrieving revision 1.1 diff -u -r1.1 romfs1.c --- fs/rom/current/tests/romfs1.c 13 Dec 2004 15:34:53 -0000 1.1 +++ fs/rom/current/tests/romfs1.c 4 Aug 2006 09:21:06 -0000 @@ -91,11 +91,11 @@ //========================================================================== #define SHOW_RESULT( _fn, _res ) \ -diag_printf("<FAIL>: " #_fn "() returned %d %s\n", _res, _res<0?strerror(errno):""); + diag_printf("<FAIL>: " #_fn "() returned %d %s\n", (int)_res, _res<0?strerror(errno):""); #define CHKFAIL_TYPE( _fn, _res, _type ) { \ if ( _res != -1 ) \ - diag_printf("<FAIL>: " #_fn "() returned %d (expected -1)\n", _res); \ + diag_printf("<FAIL>: " #_fn "() returned %d (expected -1)\n", (int)_res); \ else if ( errno != _type ) \ diag_printf("<FAIL>: " #_fn "() failed with errno %d (%s),\n expected %d (%s)\n", errno, strerror(errno), _type, strerror(_type) ); \ } @@ -166,7 +166,7 @@ } else { - diag_printf(" [mode %08x ino %08x nlink %d size %d]", + diag_printf(" [mode %08x ino %08x nlink %d size %ld]", sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); } } @@ -286,6 +286,9 @@ { int err; char address[16]; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif CYG_TEST_INIT(); @@ -377,6 +380,17 @@ CHKFAIL_TYPE( umount, err, EINVAL ); #endif +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- + err = umount( "/" ); if( err < 0 ) SHOW_RESULT( umount, err );
? fs/jffs2/current/support/jffs2.ecm ? fs/jffs2/current/support/mktestfs.sh Index: fs/jffs2/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/ChangeLog,v retrieving revision 1.51 diff -u -r1.51 ChangeLog --- fs/jffs2/current/ChangeLog 9 May 2006 16:17:55 -0000 1.51 +++ fs/jffs2/current/ChangeLog 4 Aug 2006 09:16:45 -0000 @@ -1,3 +1,9 @@ +2006-06-25 Andrew Lunn <[EMAIL PROTECTED]> + + * src/fs-ecos.c (jffs2_getinfo): Add cyg_fs_getinfo support + for getting the block usage of the file system. + * tests/jffs2_1.c: Test for new getinfo call. + 2006-03-09 Andrew Lunn <[EMAIL PROTECTED]> * src/fs-ecos.c: Generalise the check for broken ARM compilers Index: fs/jffs2/current/src/fs-ecos.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/fs-ecos.c,v retrieving revision 1.39 diff -u -r1.39 fs-ecos.c --- fs/jffs2/current/src/fs-ecos.c 9 May 2006 16:17:55 -0000 1.39 +++ fs/jffs2/current/src/fs-ecos.c 4 Aug 2006 09:16:47 -0000 @@ -1171,7 +1171,7 @@ // ------------------------------------------------------------------------- // jffs2_getinfo() -// Getinfo. Currently only support pathconf(). +// Getinfo. Currently only support pathconf() and block usage static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, int key, void *buf, int len) @@ -1195,6 +1195,18 @@ err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf); break; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + case FS_INFO_BLOCK_USAGE: { + struct cyg_fs_block_usage *usage = (struct cyg_fs_block_usage *) buf; + struct super_block *jffs2_sb = (struct super_block *)mte->data; + struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb); + + usage->total_blocks = c->flash_size; + usage->free_blocks = c->free_size; + usage->block_size = 1; + return ENOERR; + } +#endif default: err = EINVAL; } Index: fs/jffs2/current/tests/jffs2_1.c =================================================================== RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/tests/jffs2_1.c,v retrieving revision 1.5 diff -u -r1.5 jffs2_1.c --- fs/jffs2/current/tests/jffs2_1.c 3 Aug 2005 20:39:51 -0000 1.5 +++ fs/jffs2/current/tests/jffs2_1.c 4 Aug 2006 09:16:48 -0000 @@ -420,6 +420,9 @@ int err; //int i; int existingdirents=-1; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif CYG_TEST_INIT(); @@ -436,6 +439,15 @@ listdir( "/", true, -1, &existingdirents ); if ( existingdirents < 2 ) CYG_TEST_FAIL("Not enough dir entries\n"); +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo("/", FS_INFO_BLOCK_USAGE, &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif // --------------------------------------------------------------