Rockbox.org home
release
dev builds
extras
themes manual
wiki
device status forums
mailing lists
IRC bugs
patches
dev guide



Rockbox mail archive

Subject: Re: file read/write code
From: Greg Haerr (greg_at_censoft.com)
Date: 2002-11-08


> Correct me if I'm wrong, but it looks like you sacrify 50% transfer speed for
simpler code.
> Is there a simple way around this that I don't see?

Yes - I stated that I hadn't written the optimized case yet. I will
replace the middle section if read()/write() with a single function
similar to your fat_readwrite that will, if offset != 0 (that is, when
the data is sector-aligned), call bmap repeatedly while the sectors
are contiguous, and read/write data without the memcpy,
with the speed of your implementation. This is what I was saying
in my first email about how I hadn't quite got the optimized case
handled yet, which you did so well...

The idea here though is to
be able to use this buffer-caching throughout the fat32 implementation,
which will definitely help with the directory-reading routines. Also,
the fat-cache and directory-cache special handling goes away, as
well as having the root and other directories stay cached even when
they're not explicitly opened. For file reading, this could result in the
HD not spinning up when otherwise required.

> Thanks for the heads-up. Although I prefer to use unsigned int rather than
long.

Yes, it looks better, but it's not portable, especially for the FAT32
implementation.
I hate rewriting code, so I try to specify it for the long term.

BTW, I have now completed the optimized version of fat_bmap,
which for read and write cases is extremely fast for sequential
file i/o. Here it is. Note that I'm temporarily using file->sectornum
as a cache for the last clusternum. I would rename it but I haven't
changed any .h files yet.

/*
 * Map a FAT file logical block number into a disk sector number.
 */
unsigned long
fat_bmap(struct fat_file *file, unsigned long blk)
{
    unsigned long cluster = file->firstcluster;
    unsigned long nextcluster;
    long i, clusternum = 0, startnum = 0;
    int sector, tmp;

    sector = blk % fat_bpb.bpb_secperclus;

    if (!cluster || blk >= fat_bpb.bpb_secperclus) {
        clusternum = blk / fat_bpb.bpb_secperclus;
        if (!cluster)
            ++clusternum; /* force for loop entry for first cluster write*/
        else {
            /* optimize sequential read/write case*/
            if (clusternum > file->sectornum) {
                startnum = file->sectornum;
                cluster = file->lastcluster;
            }
        }
        for (i=startnum; i<clusternum; ++i) {
            nextcluster = get_next_cluster(cluster);
            if (!nextcluster) {
                /* not found, must be writing*/
                nextcluster = next_write_cluster(file, cluster, &tmp);
                if (!nextcluster)
                    return 0;
                if (i != clusternum-1) DEBUGF("bmap: sparse file\n");
            }
            cluster = nextcluster;
        }
    }
    file->sectornum = clusternum; /* save last clusternum for optimization*/

    /* save lastcluster for close time truncation*/
    file->lastcluster = cluster;

    return cluster2sec(cluster) + sector;
}

Regards,

Greg



Page was last modified "Jan 10 2012" The Rockbox Crew
aaa