This is an archive of the discontinued Mercurial Phabricator instance.

rust-dirstate-v2: save proper data size if no new data on append
ClosedPublic

Authored by Alphare on Apr 21 2022, 9:40 AM.

Details

Summary

This is currently only triggered with the tests ran with --rhg without
--rust, by "luck", there probably always was something to write, like an
mtime when also using Rust extensions alongside rhg.

Diff Detail

Repository
rHG Mercurial
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

Alphare created this revision.Apr 21 2022, 9:40 AM

Note: the merge into default will require some small care (basically default has more unit tests, and we need to add an unused old_data_size). I can do it.

I don't understand the justification: if it's not correct to store the file length when we're appending empty data, why is it correct to store it when data is not empty? Can't the garbage still be there?

I don't understand the justification: if it's not correct to store the file length when we're appending empty data, why is it correct to store it when data is not empty? Can't the garbage still be there?

It's never correct to store the file length, the comment just means that if we're appending, we return the position of the last write, which will always be the root node. If we're not appending, we don't write anything, the pointer is always 0, and poof.

Ok, I get it. You're saying size 0 is special because a write of size 0 does not update the current file pointer.
I did not know exactly how append mode interacted with lseek, so I did an experiment.
The following C program always prints "hi2" for me, even if redirected to a file in append mode.
I think this means that even though write in append mode always appends to the end of the file, it doesn't actually advance the file pointer to that position, so the returned value is effectively the amount you wrote, not the total size of the file.
(I did not try the same in rust)

#include <sys/types.h>                                                                                                         
#include <unistd.h>                                                                                                            
#include <stdio.h>                                                                                                             
int main() {                                                                                                                   
  write(1, "hi", 2);                                                                                                           
  off_t pos = lseek(1, 0, SEEK_CUR);                                                                                           
  printf("%ld\n", pos);                                                                                                        
  return 0;                                                                                                                    
}

Yep, same in rust:

use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write as IoWrite;

fn main() -> Result<(), std::io::Error> {
  let mut options = std::fs::OpenOptions::new();
  options.append(true);
  let mut file = options.open("x")?;
  file.write_all(b"foobar")?;
  file.flush()?;
  println!("{}", file.seek(SeekFrom::Current(0))?);
  Ok(())
}

always prints 6.

So I'm guessing this doesn't work at all?

Wow, this is actually different on different filesystems: the behavior I described happens on ZFS, while a presumably-desirable behavior (different offset every time) happens on EXT4 and XFS. This is crazy!

Relevant issue: https://github.com/prometheus/prometheus/issues/484.
Presumably hg has reasonable expectations here, the bug is in ZFS. However this does mean that we in Jane Street will experience issues since we don't seem to have a patched ZFS.
This also means that this code path is untested, yes? (Since I'm not seeing any errors) Do you know how to reproduce the append behavior so we have a test that breaks on buggy ZFS?

aalekseyev accepted this revision.Apr 21 2022, 1:55 PM

ZFS bug and lack of tests notwithstanding, the change seems good to me.

martinvonz requested changes to this revision.Apr 21 2022, 3:50 PM
martinvonz added a subscriber: martinvonz.

It looks like the tests from your other long series need to be updated in this patch (they don't compile with this patch applied).

This revision now requires changes to proceed.Apr 21 2022, 3:50 PM

It looks like the tests from your other long series need to be updated in this patch (they don't compile with this patch applied).

You may have missed my first comment here then. This patch is destined for stable where it should apply cleanly, only the merge will need to be adapted .

Relevant issue: https://github.com/prometheus/prometheus/issues/484.
Presumably hg has reasonable expectations here, the bug is in ZFS. However this does mean that we in Jane Street will experience issues since we don't seem to have a patched ZFS.
This also means that this code path is untested, yes? (Since I'm not seeing any errors) Do you know how to reproduce the append behavior so we have a test that breaks on buggy ZFS?

This is very interesting, thanks for the investigation. It is indeed untested, I can follow up with a test soon (but not this week).

It looks like the tests from your other long series need to be updated in this patch (they don't compile with this patch applied).

You may have missed my first comment here then. This patch is destined for stable where it should apply cleanly, only the merge will need to be adapted .

Ah, you're right that I missed that (well, I forgot about it). Sorry.

Relevant issue: https://github.com/prometheus/prometheus/issues/484.
Presumably hg has reasonable expectations here, the bug is in ZFS. However this does mean that we in Jane Street will experience issues since we don't seem to have a patched ZFS.
This also means that this code path is untested, yes? (Since I'm not seeing any errors) Do you know how to reproduce the append behavior so we have a test that breaks on buggy ZFS?

This is very interesting, thanks for the investigation. It is indeed untested, I can follow up with a test soon (but not this week).

Since @aalekseyev seemed happy with the patch in it's current form, I suppose I can queue it now and you add those tests in a separate patch. Thanks.

This revision was not accepted when it landed; it landed in state Needs Revision.
This revision was automatically updated to reflect the committed changes.