rename() + fsync() implementation
Renato Botelho
garga at FreeBSD.org
Fri Jul 3 16:59:48 UTC 2015
Some time ago we found a bug on pfSense and after investigating we figured out the root cause was passwd / group related tools was not checking if files were safe in disk, and system ended up with a 0 length passwd/group db after a power cycle. There are more context at revision [1].
After that, bapt@ suggest to do similar fix for cap_mkdb and services_mkdb, that also can be found at another review [2].
Until now there are 3 places with added code similar to:
/*
* Make sure file is safe on disk. To improve performance we will call
* fsync() to the directory where file lies
*/
if (rename(tname, dbname) == -1 ||
(dbname_dir = dirname(dbname)) == NULL ||
(dbname_dir_fd = open(dbname_dir, O_RDONLY|O_DIRECTORY)) == -1 ||
fsync(dbname_dir_fd) != 0) {
if (dbname_dir_fd != -1)
close(dbname_dir_fd);
err(1, "Cannot rename `%s' to `%s'", tname, dbname);
}
if (dbname_dir_fd != -1)
close(dbname_dir_fd);
The idea is to implement a “sync rename” function to do all these steps. I thought about it and IMO lib/libutil would be a good place to implement it. But since I’m starting to touch src now, I would like to hear more opinions about this.
Thanks!
[1] https://reviews.freebsd.org/D2978
[2] https://reviews.freebsd.org/D2982
--
Renato Botelho
More information about the freebsd-hackers
mailing list