Patch title: Release 84 bulk changes
Abstract:
File: /pliant/linux/storage/raid.pli
Key:
    Removed line
    Added line
   
abstract
  [The 'raid_convert' function will allow you to change the 
  highlight "THIS IS VERY ALPHA CODE: IT MAY DESTROY ALL YOU
 


module "/pliant/language/stream.pli"
abstract
  [The 'raid_convert' function will allow you to change the 
  highlight "THIS IS VERY ALPHA CODE: IT MAY DESTROY ALL YOU
 


module "/pliant/language/stream.pli"
module "/pliant/language/context.pli"
module "/pliant/admin/file.pli"
module "/pliant/admin/execute.pli"
module "/pliant/language/os.pli"
module "/pliant/linux/storage/filesystem.pli"
module "/pliant/linux/storage/partition.pli"
module "/pliant/linux/misc/warn.pli"
if os_api<>"linux"
  error "This module is dealing only with Linux software RAI



function raid_convert old new
  arg_rw Raid old new
  var Int old_unit := old:chunk_size*old:data_disks_count
  var Int new_unit := new:chunk_size*new:data_disks_count
module "/pliant/admin/file.pli"
module "/pliant/admin/execute.pli"
module "/pliant/language/os.pli"
module "/pliant/linux/storage/filesystem.pli"
module "/pliant/linux/storage/partition.pli"
module "/pliant/linux/misc/warn.pli"
if os_api<>"linux"
  error "This module is dealing only with Linux software RAI



function raid_convert old new
  arg_rw Raid old new
  var Int old_unit := old:chunk_size*old:data_disks_count
  var Int new_unit := new:chunk_size*new:data_disks_count
  os_sysinfo (var os_sysinfo sys)
  var Int memory_physical := sys totalram
  var Int common_unit := ppcm old_unit new_unit
  while common_unit<64*2^10
    common_unit*=2
  var Int common_unit := ppcm old_unit new_unit
  while common_unit<64*2^10
    common_unit*=2
  if common_unit>memory_physical\2
  if common_unit>memory_assigned
    error "The conversion would consume too much memory.[lf]
  var Address chunks := memory_allocate common_unit null
  var Address checksum := memory_allocate new:chunk_size nul
  var Intn size := min old:size new:size
  var CBool forward := new:data_disks_count>=old:data_disks_
  var DateTime start := datetime
  var Intn position := shunt forward 0 (size-1)\common_unit*
  while (shunt forward position<size position>=0)
    console "converted " (shunt forward position size-positi
    var Int step := min size-position common_unit
    old read position 0 chunks step
    new write position 0 chunks step
    if new:level=1
      for (var Int i) 1 new:checksum_disks_count
        new write position i chunks common_unit
    eif new:level=5
      for (var Int base) 0 common_unit-1 step new_unit
        memory_clear checksum new:chunk_size
        for (var Int i) 0 new_unit-1 step new:chunk_size
          memory_xor checksum (chunks translate Byte base+i)
        new write position+base 1 checksum new:chunk_size
    position += shunt forward common_unit -common_unit
  position := size
  memory_clear chunks common_unit
  while position<new:size
    console "cleared " (position-size)\2^20 " MB (" 100*(pos
    var Int step := min new:size-position common_unit
    new write position 0 chunks step
    if new:level=1
      for (var Int i) 1 new:checksum_disks_count
        new write position i chunks step
    eif new:level=5
      for (var Int base) 0 step-1 step new_unit
        new write position+base 1 chunks new:chunk_size
    position += step
  memory_free chunks
  memory_free checksum
  if speed_report
    console "conversion passed (in " (cast datetime:seconds-



if false
  
  doc
    para
      [All the rest of the script is just for building a sam
    ['raid_configure' will write the /etc/raidtab file with 
    [Since this function will destroy existing configuration
  
  function raid_configure raid_device devices_names level ch
    arg Str raid_device devices_names ; arg Int level chunks
    var Str dev := shunt (raid_device search ":" -1)=(-1) "d
    var Array:Str devices
    var Str names := devices_names
    while names<>""
      if (names parse any:(var Str name1) _ any:(var Str nam
        devices += shunt (name1 search ":" -1)=(-1) "device:
        names := name2
      else
        devices += shunt (names search ":" -1)=(-1) "device:
        names := ""
    (var Stream rt) open filename out
    rt writeline "raiddev "+file_os_name:dev
    rt writeline "  raid-level "+string:level
    rt writeline "  nr-raid-disks "+(string devices:size)
    rt writeline "  nr-spare-disks 0"
    rt writeline "  persistent-superblock 1"
    rt writeline "  chunk-size "+(string chunksize\1024)
    for (var Int i) 0 devices:size-1
      rt writeline "  device "+(file_os_name devices:i)
      rt writeline "  raid-disk "+string:i
  
  function raid_configure raid_device devices_names level ch
    arg Str raid_device devices_names ; arg Int level chunks
    if (file_query "file:/etc/raidtab" standard)=defined and
      file_copy "file:/etc/raidtab" "file:/etc/raidtab.backu
      console "Your /etc/raidtab file has been saved to /etc
    raid_configure raid_device devices_names level chunksize
  
  doc
    [Wait's for the resync to finish in the kernel.]
  
  function raid_wait
    while true
      var CBool more := false
      (var Stream s) open "file:/proc/mdstat" in
      while not s:atend
        if (s:readline search "resync" -1)<>-1
          more := true
      if not more
        return
      s close
      console "waiting for raid resync[cr]"
      sleep 60
      console "                       [cr]"
  
  
  doc
    [These two functions are simply generating a sample file
  
  function generate_file name size
    arg Str name ; arg Int size
    console "generating a " size\2^20 " MB test file" eol
    (var Stream s) open name out
    for (var Int i) 1 size\Int:size
      s raw_write addressof:i Int:size
    s close
      
  function check_file name size
    arg Str name ; arg Int size
    console "checking the " size\2^20 " MB test file" eol
    (var Stream s) open name in
    for (var Int i) 1 size\Int:size
      s raw_read addressof:(var Int j) Int:size
      if j<>i
        error error_id_corrupted "The test file is corrupted
      
  
  doc
    [This is my test process. It will build a RAID array, th
    [If you want to use it, you have to update the constants
    [If you get 'sample test passed.' message at the end, th
  
  function run_sample_raid_test
    constant raid_device "md0"
    constant initial_devices "hda5 hda6 hda7"
    constant initial_raid_level 5
    constant initial_chunksize 16*2^10
    constant final_devices "hda5 hda6 hda7 hda8"
    constant final_raid_level 5
    constant final_chunksize 64*2^10
    constant test_file_size 64*2^20
    constant doit false
    # do not allow to run this test if the constants have no
    # order to match site test configuration
    if not doit
      console "You must update the constants at the top of f
      return
    var Str dev := shunt (raid_device search ":" -1)=(-1) "d
    warn "You are attempting to run raid test reconfigure ut
    # initial cleanup
    filesystem_dismount "file:/mnt/raid"
    execute "raidstop "+file_os_name:dev quiet
    # create a sample raid
    raid_configure raid_device initial_devices initial_raid_
    execute "mkraid --really-force "+file_os_name:dev quiet
    raid_wait
    format_partition dev "name [dq]test[dq]"
    filesystem_mount dev "file:/mnt/raid/" ""
    file_copy "/" "file:/mnt/raid/pliant/" extended+recursiv
    execute "tar -zc -f /mnt/raid/pliant.tgz /pliant/"
    generate_file "file:/mnt/raid/test" test_file_size
    filesystem_dismount dev
    # now convert it
    var Array:Str deads := raid_convert raid_device initial_
    raid_configure raid_device final_devices final_raid_leve
    execute "mkraid --really-force --dangerous-no-resync "+f
    for (var Int i) 0 deads:size-1
      execute "raidhotremove "+file_os_name:dev+" "+deads:i 
    # and finally test it
    filesystem_mount dev "file:/mnt/raid/" ""
    if (execute "tar -ztv -f /mnt/raid/pliant.tgz" quiet)<>0
      error "The tar file is corrupted" ?
    check_file "file:/mnt/raid/test" test_file_size ?
    # final cleanup
    filesystem_dismount dev
    execute "raidstop "+file_os_name:dev quiet
    console "sample test passed." eol
  
  export run_sample_raid_test
    error "The conversion would consume too much memory.[lf]
  var Address chunks := memory_allocate common_unit null
  var Address checksum := memory_allocate new:chunk_size nul
  var Intn size := min old:size new:size
  var CBool forward := new:data_disks_count>=old:data_disks_
  var DateTime start := datetime
  var Intn position := shunt forward 0 (size-1)\common_unit*
  while (shunt forward position<size position>=0)
    console "converted " (shunt forward position size-positi
    var Int step := min size-position common_unit
    old read position 0 chunks step
    new write position 0 chunks step
    if new:level=1
      for (var Int i) 1 new:checksum_disks_count
        new write position i chunks common_unit
    eif new:level=5
      for (var Int base) 0 common_unit-1 step new_unit
        memory_clear checksum new:chunk_size
        for (var Int i) 0 new_unit-1 step new:chunk_size
          memory_xor checksum (chunks translate Byte base+i)
        new write position+base 1 checksum new:chunk_size
    position += shunt forward common_unit -common_unit
  position := size
  memory_clear chunks common_unit
  while position<new:size
    console "cleared " (position-size)\2^20 " MB (" 100*(pos
    var Int step := min new:size-position common_unit
    new write position 0 chunks step
    if new:level=1
      for (var Int i) 1 new:checksum_disks_count
        new write position i chunks step
    eif new:level=5
      for (var Int base) 0 step-1 step new_unit
        new write position+base 1 chunks new:chunk_size
    position += step
  memory_free chunks
  memory_free checksum
  if speed_report
    console "conversion passed (in " (cast datetime:seconds-



if false
  
  doc
    para
      [All the rest of the script is just for building a sam
    ['raid_configure' will write the /etc/raidtab file with 
    [Since this function will destroy existing configuration
  
  function raid_configure raid_device devices_names level ch
    arg Str raid_device devices_names ; arg Int level chunks
    var Str dev := shunt (raid_device search ":" -1)=(-1) "d
    var Array:Str devices
    var Str names := devices_names
    while names<>""
      if (names parse any:(var Str name1) _ any:(var Str nam
        devices += shunt (name1 search ":" -1)=(-1) "device:
        names := name2
      else
        devices += shunt (names search ":" -1)=(-1) "device:
        names := ""
    (var Stream rt) open filename out
    rt writeline "raiddev "+file_os_name:dev
    rt writeline "  raid-level "+string:level
    rt writeline "  nr-raid-disks "+(string devices:size)
    rt writeline "  nr-spare-disks 0"
    rt writeline "  persistent-superblock 1"
    rt writeline "  chunk-size "+(string chunksize\1024)
    for (var Int i) 0 devices:size-1
      rt writeline "  device "+(file_os_name devices:i)
      rt writeline "  raid-disk "+string:i
  
  function raid_configure raid_device devices_names level ch
    arg Str raid_device devices_names ; arg Int level chunks
    if (file_query "file:/etc/raidtab" standard)=defined and
      file_copy "file:/etc/raidtab" "file:/etc/raidtab.backu
      console "Your /etc/raidtab file has been saved to /etc
    raid_configure raid_device devices_names level chunksize
  
  doc
    [Wait's for the resync to finish in the kernel.]
  
  function raid_wait
    while true
      var CBool more := false
      (var Stream s) open "file:/proc/mdstat" in
      while not s:atend
        if (s:readline search "resync" -1)<>-1
          more := true
      if not more
        return
      s close
      console "waiting for raid resync[cr]"
      sleep 60
      console "                       [cr]"
  
  
  doc
    [These two functions are simply generating a sample file
  
  function generate_file name size
    arg Str name ; arg Int size
    console "generating a " size\2^20 " MB test file" eol
    (var Stream s) open name out
    for (var Int i) 1 size\Int:size
      s raw_write addressof:i Int:size
    s close
      
  function check_file name size
    arg Str name ; arg Int size
    console "checking the " size\2^20 " MB test file" eol
    (var Stream s) open name in
    for (var Int i) 1 size\Int:size
      s raw_read addressof:(var Int j) Int:size
      if j<>i
        error error_id_corrupted "The test file is corrupted
      
  
  doc
    [This is my test process. It will build a RAID array, th
    [If you want to use it, you have to update the constants
    [If you get 'sample test passed.' message at the end, th
  
  function run_sample_raid_test
    constant raid_device "md0"
    constant initial_devices "hda5 hda6 hda7"
    constant initial_raid_level 5
    constant initial_chunksize 16*2^10
    constant final_devices "hda5 hda6 hda7 hda8"
    constant final_raid_level 5
    constant final_chunksize 64*2^10
    constant test_file_size 64*2^20
    constant doit false
    # do not allow to run this test if the constants have no
    # order to match site test configuration
    if not doit
      console "You must update the constants at the top of f
      return
    var Str dev := shunt (raid_device search ":" -1)=(-1) "d
    warn "You are attempting to run raid test reconfigure ut
    # initial cleanup
    filesystem_dismount "file:/mnt/raid"
    execute "raidstop "+file_os_name:dev quiet
    # create a sample raid
    raid_configure raid_device initial_devices initial_raid_
    execute "mkraid --really-force "+file_os_name:dev quiet
    raid_wait
    format_partition dev "name [dq]test[dq]"
    filesystem_mount dev "file:/mnt/raid/" ""
    file_copy "/" "file:/mnt/raid/pliant/" extended+recursiv
    execute "tar -zc -f /mnt/raid/pliant.tgz /pliant/"
    generate_file "file:/mnt/raid/test" test_file_size
    filesystem_dismount dev
    # now convert it
    var Array:Str deads := raid_convert raid_device initial_
    raid_configure raid_device final_devices final_raid_leve
    execute "mkraid --really-force --dangerous-no-resync "+f
    for (var Int i) 0 deads:size-1
      execute "raidhotremove "+file_os_name:dev+" "+deads:i 
    # and finally test it
    filesystem_mount dev "file:/mnt/raid/" ""
    if (execute "tar -ztv -f /mnt/raid/pliant.tgz" quiet)<>0
      error "The tar file is corrupted" ?
    check_file "file:/mnt/raid/test" test_file_size ?
    # final cleanup
    filesystem_dismount dev
    execute "raidstop "+file_os_name:dev quiet
    console "sample test passed." eol
  
  export run_sample_raid_test