> > + lseek(uv->jsonfd, 0, SEEK_SET);
> > + rc = write(uv->jsonfd, gstr->str, gstr->len);
> > + if (rc != gstr->len) {
> > + warn_report("%s: write error", __func__);
> > + }
> > + rc = ftruncate(uv->jsonfd, gstr->len);
> > + if (rc != 0) {
> > + warn_report("%s: ftruncate error", __func__);
> > + }
> > + fsync(uv->jsonfd);
>
> Although the fsync helps, re-writing the file in-place is a ad idea for data
> integrity on host OS crash. Especially if the new data is shorter, we would
> easily end up with a file containing old and new data making it unparsable
> (assuming the parser doesn't ignore trailing data).
I've tried to minimize the number of syscalls for the update, hoping to
also minimize the chance for corruption.
> I'd like to suggest the write to temp file + rename dance to get atomic
> replacement. The problem with that is that it hits the DAC/MAC security
> restrictions we put QEMU under :-(
Yep. If we want allow libvirt passing file handles to qemu we can't do
the rename dance.
> My next best idea is to re-arrange things thus:
>
> lseek(fd, 0)
> ftruncate(fd, 0)
> fsync(fd)
> write(fd, str)
> fsync(fd)
>
> so we should at least reduce the liklihood of getting a mix of
> old and new data - empty file is better than a mix of data.
On parse errors the complete file content is simply ignored, so it
should not make much of a difference whenever the file is empty or
corrupted.
Reorder the calls to first ftruncate then write looks reasonable.
Not sure the extra fsync makes sense.
take care,
Gerd