Class: VirtFS::BlockIO

Inherits:
Object
  • Object
show all
Defined in:
lib/virtfs/block_io.rb

Overview

Block IO Adapter, used internally by VirtFS to perform read and write operations via an underlying ‘block-like’ interface.

The class requires a handle to an object defining #raw_read and #raw_write methods facilitating raw block access.

This class behaves similarily to a tradional disk device, providing a ‘seek’ position at which read/write operations occur after which the pos is updated

Constant Summary collapse

MIN_BLOCKS_TO_CACHE =
64

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_obj) ⇒ BlockIO

BlockIO initializer

Parameters:

  • io_obj (RawIO)

    instance of class defining #raw_read and #raw_write



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/virtfs/block_io.rb', line 21

def initialize(io_obj)
  @io_obj          = io_obj
  @block_size      = @io_obj.block_size   # Size of block in bytes
  @size            = @io_obj.size         # Size of file in bytes
  @size_in_blocks  = @size / @block_size  # Size of file in blocks
  @start_byte_addr = 0
  @end_byte_addr   = @size - 1
  @lba_end         = @size_in_blocks - 1
  @seek_pos        = 0
  @cache_range     = Range.new(-1, -1)
  @offset          = 0
end

Instance Attribute Details

#offsetObject

Optional absolute block offset, always applied



15
16
17
# File 'lib/virtfs/block_io.rb', line 15

def offset
  @offset
end

Instance Method Details

#closeObject

Close block device, after this no additional read/writes can occur



103
104
105
# File 'lib/virtfs/block_io.rb', line 103

def close
  @io_obj.close
end

#read(len) ⇒ Array<Byte>?

Read len bytes from the block device and update seek_pos

Parameters:

  • len (Integer)

    number of bytes to read

Returns:

  • (Array<Byte>, nil)

    array of up to len bytes read from block device, or nil if no bytes can be read



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/virtfs/block_io.rb', line 39

def read(len)
  return nil if @seek_pos >= @end_byte_addr
  len = @end_byte_addr - @seek_pos if (@seek_pos + len) > @end_byte_addr

  start_sector, start_offset = @seek_pos.divmod(@block_size)
  end_sector = (@seek_pos + len - 1) / @block_size
  num_sector = end_sector - start_sector + 1

  rbuf = bread_cached(start_sector, num_sector)
  @seek_pos += len

  rbuf[start_offset, len]
end

#seek(amt, whence = IO::SEEK_SET) ⇒ Object

Advance seek pointer via the specified mechanism

Parameters:

  • amt (Integer)

    absolute amount which to advance seek pointer

  • whence (IO::SEEK_SET, IO::SEEK_CUR, IO::SEEK_END) (defaults to: IO::SEEK_SET)

    mechanism which to update seek pos

See Also:

  • IO::SEEK_SET
  • IO::SEEK_CUR
  • IO::SEEK_END


85
86
87
88
89
90
91
92
93
94
95
# File 'lib/virtfs/block_io.rb', line 85

def seek(amt, whence = IO::SEEK_SET)
  case whence
  when IO::SEEK_CUR
    @seek_pos += amt
  when IO::SEEK_END
    @seek_pos = @end_byte_addr + amt
  when IO::SEEK_SET
    @seek_pos = amt + @start_byte_addr
  end
  @seek_pos
end

#sizeInteger

Returns size of block device.

Returns:

  • (Integer)

    size of block device



98
99
100
# File 'lib/virtfs/block_io.rb', line 98

def size
  @size
end

#write(buf, len) ⇒ Integer?

Write buffer of specified length to block device and update seek_pos

Parameters:

  • buf (Array<Byte>)

    bytes to write to disk device

Returns:

  • (Integer, nil)

    number of bytes written to device, or nil if none can be written



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/virtfs/block_io.rb', line 58

def write(buf, len)
  return nil if @seek_pos >= @end_byte_addr
  len = @end_byte_addr - @seek_pos if (@seek_pos + len) > @end_byte_addr

  start_sector, start_offset = @seek_pos.divmod(@block_size)
  end_sector = (@seek_pos + len - 1) / @block_size
  num_sector = end_sector - start_sector + 1

  rbuf = bread(start_sector, num_sector)
  rbuf[start_offset, len] = buf[0, len]

  bwrite(start_sector, num_sector, rbuf)
  @seek_pos += len

  len
end