Web lists-archives.com

Re: SSD's and many edits of a single file




Hi,

re-reading the original mail of Gene
  https://lists.debian.org/debian-user/2018/04/msg00237.html
i think it is time to collect some evidence.

Following is a bash script which challenges the disk's fidelity in
respect to small writes on a relatively small file over a long time.

Gene, please consider to run it and to report the outcome

Adjustable parameters are
  file_path , chunk_size , sleep_time , duration
Edit the script to change their values. No blanks or fancy characters.
(It is advisable to store it on an unsuspicious disk.)

With the given setting of chunk_size=8, the victim file will have a size
of 524,289 bytes.

The script will print a single dot to stdout for each successful write-read
cycle.  After 60 such dots, the cycle count and a newline character get
printed.

In case of a failed read-write cycle, an ALL-CAPS message will be emitted
to stderr and the script will abort immediately.

If there is no failure, then operating system and disk are working as
they should.

Start of script. Cut out after the "---" line, store as file
"random_writer.sh", and give execution permission by
  chmod u+x random_writer.sh
-------------------------------------------------------------------------------
#!/bin/bash

# Which file to use
file_path=/home/test/random_writer_victim

# How many bytes to write in one try.
# (Write range is 65536 times chunk_size plus 1)
chunk_size=8

# Interval between writes
sleep_time=10

# Overall duration in seconds (here: half a day)
duration=43200

# Initialize file content by newline characters
echo "Victim file: $file_path"
length=$(expr 65536 '*' $chunk_size + 1)
yes "" | head -c $length | dd of="$file_path" conv=notrunc 2>/dev/null

start_time=$(date '+%s')
cycle=0
while test $(expr $(date '+%s') - $start_time) -lt $duration
do
  # Get a random write address in the range of 0 to 65535
  random_adr=$(dd if=/dev/urandom bs=1 count=2 2>/dev/null | od -d | \
               head -1 | awk '{print $2}' )
  cycle=$(expr $cycle + 1)
  text=$(printf '%'"$chunk_size"'d' $cycle)

  # Write to file (with trailing newline to keep the file editor friendly)
  echo "$text" | \
    dd of="$file_path" seek="$random_adr" bs=$chunk_size count=1 conv=notrunc \
       2>/dev/null

  # Check-read
  reread=$(dd if="$file_path" skip="$random_adr" bs=$chunk_size count=1 \
              2>/dev/null)

  # <<< Simulated mismatch
  # test $cycle = 3 && reread=X_simulated_X

  if test "$text" != "$reread"
  then
    echo
    echo "CAUGHT MISMATCH OF WRITE AND READ !" >&2
    echo "Written: '$text'" >&2
    echo "Read   : '$reread'" >&2
    exit 1
  fi 

  echo -n '.'
  if test $(expr $cycle % 60) = 0
  then
    printf '%8d\n' $cycle
  fi
  sleep $sleep_time || break
done
printf '%8d\nDone. No errors detected.\n' $cycle
-------------------------------------------------------------------------------
End of script. Cut out before the "---" line.

Have a nice day :)

Thomas