Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jul 2015 13:59:43 -0300
From:      Renato Botelho <garga@FreeBSD.org>
To:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   rename() + fsync() implementation
Message-ID:  <2770DA5F-D7F2-46D9-9158-10C86115F8AC@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
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) =3D=3D -1 ||
            (dbname_dir =3D dirname(dbname)) =3D=3D NULL ||
            (dbname_dir_fd =3D open(dbname_dir, O_RDONLY|O_DIRECTORY)) =
=3D=3D -1 ||
            fsync(dbname_dir_fd) !=3D 0) {
                if (dbname_dir_fd !=3D -1)
                        close(dbname_dir_fd);
                err(1, "Cannot rename `%s' to `%s'", tname, dbname);
        }

        if (dbname_dir_fd !=3D -1)
                close(dbname_dir_fd);

The idea is to implement a =E2=80=9Csync rename=E2=80=9D 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=E2=80=99m 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2770DA5F-D7F2-46D9-9158-10C86115F8AC>