int main(int argc, char *argv[]) { struct timeval before,after; int i,j; int n = 1000000; /* number of strings */ int len = 150; /* "length" of strings (mild variation) */ data_t* orig = create(n, len); naive_write("naive.bin", orig, n); flat_write("flat.bin", orig, n); gettimeofday(&before,NULL); data_t* naive = naive_read("naive.bin"); gettimeofday(&after,NULL); printf(" naive time: %f\n", elapsed(before,after)); gettimeofday(&before,NULL); data_t* onecopy = onecopy_read("flat.bin"); gettimeofday(&after,NULL); printf(" 1copy time: %f\n", elapsed(before,after)); gettimeofday(&before,NULL); data_t* zerocopy = zerocopy_read("flat.bin"); gettimeofday(&after,NULL); printf(" 0copy time: %f\n", elapsed(before,after)); compare(naive,onecopy, n); compare(naive,zerocopy,n); return 0; }
/* * Writes out the contents of all files. * Does not actually do the write if 'dowrite' * is not set. In this case, it just checks * to see that the config will fit. * The total length of data written (or simulated) is stored * in *total. * Does not remove .flatfsd * * Note that if the flash has been erased, aborting * early will just lose data. So we try to work around * problems as much as possible. * * Returns 0 if OK, or < 0 if error. */ int flat1_savefs(int dowrite, unsigned *total) { struct flathdr1 hdr; struct flatent ent; struct dirent *dp; DIR *dirp; int rc, ret = 0; #ifdef DEBUG syslog(LOG_DEBUG, "flat1_savefs(dowrite=%d)", dowrite); #endif /* Lets go, erase the flash first */ if ((rc = flat_erase()) < 0) return rc; /* Write out contents of all files, skip over header */ numfiles = 0; numbytes = 0; numdropped = 0; *total = sizeof(hdr); #ifndef HAS_RTC rc = writefile(FLATFSD_CONFIG, total, dowrite); if (rc < 0 && !ret) ret = rc; #endif /* Scan directory */ if ((dirp = opendir(".")) == NULL) { rc = ERROR_CODE(); if (rc < 0 && !ret) ret = rc; /* Really nothing we can do at this point */ return ret; } while ((dp = readdir(dirp)) != NULL) { if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0) || (strcmp(dp->d_name, FLATFSD_CONFIG) == 0)) continue; rc = writefile(dp->d_name, total, dowrite); if (rc < 0) { syslog(LOG_ERR, "Failed to write write file %s (%d): %m %d", dp->d_name, rc, errno); if (!ret) ret = rc; } } closedir(dirp); /* Write the terminating entry */ if (dowrite) { ent.namelen = FLATFS_EOF; ent.filelen = FLATFS_EOF; rc = flat_write(*total, &ent, sizeof(ent)); if (rc < 0 && !ret) ret = rc; } *total += sizeof(ent); #ifdef USING_MTD_DEVICE /* * We need to account for the fact that we checksum the entire device, * not just the data we wrote. On MTD devices, this data is 0xFF. */ { int checksum_len = flat_dev_length() - (BUF_SIZE - (sizeof(struct flathdr1) * 2)); flat_sum += 0xFFu * (checksum_len - *total); #ifdef DEBUG syslog(LOG_DEBUG, "flat_savefs(): added %d 0xFF bytes to " "checksum -> flat_sum=%u", checksum_len - *total, flat_sum); #endif } #endif if (dowrite) { /* Construct header */ hdr.magic = FLATFS_MAGIC_V2; hdr.chksum = flat_sum; #ifdef DEBUG syslog(LOG_DEBUG, "flat_savefs(): final checksum=%u, total=%d", flat_sum, *total); #endif rc = flat_write(0L, &hdr, sizeof(hdr)); if (rc < 0 && !ret) ret = rc; } #ifdef DEBUG syslog(LOG_DEBUG, "flat_savefs() returning ret=%d, total=%u", ret, *total); #endif return ret; }
static int writefile(char *name, unsigned int *ptotal, int dowrite) { struct flatent ent; struct stat st; unsigned int size; int fdfile, zero = 0; mode_t mode; char buf[BUF_SIZE]; int n, written; /* * Write file entry into flat fs. Names and file * contents are aligned on long word boundaries. * They are padded to that length with zeros. */ if (stat(name, &st) < 0) return ERROR_CODE(); size = strlen(name) + 1; if (size > 128) { numdropped++; return ERROR_CODE(); } ent.namelen = size; ent.filelen = st.st_size; if (dowrite && flat_write(*ptotal, &ent, sizeof(ent)) < 0) return ERROR_CODE(); *ptotal += sizeof(ent); /* Write file name out, with padding to align */ if (dowrite && flat_write(*ptotal, name, size) < 0) return ERROR_CODE(); *ptotal += size; size = ((size + 3) & ~0x3) - size; if (dowrite && flat_write(*ptotal, &zero, size) < 0) return ERROR_CODE(); *ptotal += size; /* Write out the permissions */ mode = (mode_t) st.st_mode; size = sizeof(mode); if (dowrite && flat_write(*ptotal, &mode, size) < 0) return ERROR_CODE(); *ptotal += size; /* Write the contents of the file. */ size = st.st_size; written = 0; if (size > 0) { if (dowrite) { if ((fdfile = open(name, O_RDONLY)) < 0) return ERROR_CODE(); while (size>written) { int bytes_read; n = ((size-written) > sizeof(buf))?sizeof(buf):(size-written); if ((bytes_read = read(fdfile, buf, n)) != n) { /* Somebody must have trunced the file - Log it. */ syslog(LOG_WARNING, "File %s was shorter than expected.", name); if (bytes_read <= 0) break; } if (dowrite && flat_write(*ptotal, buf, bytes_read) < 0) { close(fdfile); return (ERROR_CODE()); } *ptotal += bytes_read; written += bytes_read; } if (lseek(fdfile, 0, SEEK_END) != written) { /* * Log the file being longer than expected. * We can't write more than expected because * the size is already written. */ syslog(LOG_WARNING, "File %s was longer than expected.", name); } close(fdfile); } else { *ptotal += st.st_size; } /* Pad to align */ written = ((st.st_size + 3) & ~0x3) - st.st_size; if (dowrite && flat_write(*ptotal, &zero, written) < 0) return ERROR_CODE(); *ptotal += written; } numfiles++; numbytes += ent.filelen; return 0; }