Free Republic
Browse · Search
General/Chat
Topics · Post Article

To: cynwoody; Bikkuri; ShadowAce
What piqued my interest in btrfs was the article, Bitrot and atomic COWs: Inside “next-gen” filesystems. The "graphic gone wrong" with the JPG shown in the article is a vivid example of a flipped bit.

I encountered such a thing a few years ago while still using the ext3 filesystem and an IDE (remember those?) drive. Here's what happened. I extracted a largish tarball to build QT-4 from source. All was going well until the compile failed on a C++ file since it yelped about a missing header. I examined the source file and saw this:

#include <uniste.h>
Yes, one bit was flipped (should be unistd.h, of course). I edited the errant file and happily finished the compile. Curious as to what went amiss, I re-extracted the tarball into a partition on another drive (also IDE but on a different controller) and it was correct. That was readily visible and I caught it but I can't help but wonder how much silent data corruption has gone on through the decades on my various systems.
21 posted on 05/28/2014 3:55:15 PM PDT by re_nortex (DP - that's what I like about Texas)
[ Post Reply | Private Reply | To 20 | View Replies ]


To: re_nortex
Yes, one bit was flipped (should be unistd.h, of course). I edited the errant file and happily finished the compile. Curious as to what went amiss, I re-extracted the tarball into a partition on another drive (also IDE but on a different controller) and it was correct. That was readily visible and I caught it but I can't help but wonder how much silent data corruption has gone on through the decades on my various systems.

I got to wondering how noticeable flipped bits in binaries might be. So, I wrote a little Ruby program to flip a random bit in the cat command and see if the corrupted binary still runs:

#!/usr/bin/env ruby
require 'tmpdir'
require 'open3'
$outPath = "#{Dir.tmpdir}/catmandu"
$data = File.new(`which cat`.chomp, "rb").read
$bits = $data.length * 8
$me = IO.read __FILE__
puts "The cat command is #{$bits} bits and #{$data.length} bytes long."

def flipBit
  byte, bit = (rand*$bits).to_i.divmod 8
  d = $data.clone
  d[byte] = (d[byte].ord ^ (1<<bit)).chr
  File.open($outPath, 'wb') do |f|
    f.write d
    f.chmod 0700
  end
  return byte, bit
end

def runTest trial
  byte, bit = flipBit
  begin
    check, err, status = Open3.capture3("#{$outPath} #{__FILE__}")
  rescue => e
  end
  if check == $me && status.to_i == 0 && e == nil
    result = 'pass'
    trouble = ''
  else
    result = 'fail'
    err = e if e
    err = err.to_s.force_encoding("ASCII-8bit").tr("\n", "/")[0, 60]
    trouble = " status = #{status}: #{err}"
  end
  puts "#{'%4s' % trial}: #{result} : byte #{byte} #{bit}#{trouble}"
  result
end

if __FILE__ == $0
  trials = (ARGV[0] || 50).to_i
  failures = 0
  trials.times do |trial|
    failures += 1 if runTest(trial) == 'fail'
  end
  puts "#{failures} out of #{trials} failed."
end

I found a much lower error rate than I expected. In one run of 1000 trials, it failed only 38 times. There was a little excitement, however. About half-way through, one of the failures took the form of an output loop, requiring me to kill the corrupted child process to allow the program to complete. Most of the failures are stuff like seg faults and load errors due to symbols not found or faulty binary file format.

I have a hunch bit rot in source code and script files probably shows up more readily than in most binaries. Although a flipped bit in a comment will probably not cause a failure, a similar error elsewhere is likely to cause a syntax error or some sort of not-found condition, as in your example.

25 posted on 05/28/2014 8:09:06 PM PDT by cynwoody
[ Post Reply | Private Reply | To 21 | View Replies ]

Free Republic
Browse · Search
General/Chat
Topics · Post Article


FreeRepublic, LLC, PO BOX 9771, FRESNO, CA 93794
FreeRepublic.com is powered by software copyright 2000-2008 John Robinson