Design: should fflush() sync extents (it currently doesn't)
System information
| Type | Version/Name |
|---|---|
| Operating System | all |
| OS Version | all |
| Architecture | all |
| UnifyFS Version | all |
Describe the problem you're observing
I naively used fflush() instead of fsync() to sync the extents in a test program. It didn't sync the extents. After laminating the file, I could not read the contents. fsync() works though.
Should we make it so fflush() behaves the same as fsync()? They're not supposed to behave the same in POSIX (sync to OS buffers, vs sync to disk). Do we want to cheat and make fflush() sync out the extents too? The benefit would be that if you're using stream IO, you already have a file pointer, so it's easier to sync with fflush() than fsync(). However, you can always use fileno() to get the file descriptor from the file pointer, which you can then pass to fsync().
Describe how to reproduce the problem
This works:
fp = fopen(path, "w");
rc = fwrite("hello world", 12, 1, fp);
rc = fclose(fp);
/* Sync the file with fsync */
fd = open(path, O_RDWR);
rc = fsync(fd);
close(fd);
/* Laminate it */
rc = chmod(path, 0444);
fp = fopen(path, "r");
fread(buf, sizeof(buf), 1, fp);
fclose(fp);
rc = strcmp("hello world", buf);
ok(rc == 0, "syncing a file with fsync works '%s': %s", buf, strerror(errno));
This does not:
fp = fopen(path, "w");
rc = fwrite("hello world", 12, 1, fp);
rc = fflush(fp);
rc = fclose(fp);
/* Laminate it */
rc = chmod(path, 0444);
fp = fopen(path, "r");
fread(buf, sizeof(buf), 1, fp);
fclose(fp);
rc = strcmp("hello world", buf);
ok(rc == 0, "syncing a file with fflush works '%s': %s", buf, strerror(errno));
Include any warning or errors or releveant debugging data
I don't see a problem with adding this, as long as we verify that multiple metadata flushes works correctly. I can easily see a use case where people iteratively fwrite and fflush.
Yes, I also think flushing extents on fflush() would be fine.
@MichaelBrim raises a good point. I'm guessing some apps may fsync() a given file multiple times, as well. A future optimization could be to track which extents are new since the last sync and then only flush the new items each time.