Class: UBLK::Device

Inherits:
Object
  • Object
show all
Defined in:
lib/ublk/device.rb,
sig/ublk.rbs

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, control, info, params, mlock: true, recovering: false) ⇒ Device

Returns a new instance of Device.



71
72
73
74
75
76
77
78
79
80
# File 'lib/ublk/device.rb', line 71

def initialize(target, control, info, params, mlock: true, recovering: false)
  @target = target
  @control = control
  @info = info
  @params = params
  @mlock = mlock
  @recovering = recovering
  @started = false
  @deleted = false
end

Class Attribute Details

.ownedObject (readonly)

Returns the value of attribute owned.



16
17
18
# File 'lib/ublk/device.rb', line 16

def owned
  @owned
end

Instance Attribute Details

#infoDeviceInfo (readonly)

Returns the value of attribute info.

Returns:



19
20
21
# File 'lib/ublk/device.rb', line 19

def info
  @info
end

#paramsParams (readonly)

Returns the value of attribute params.

Returns:



19
20
21
# File 'lib/ublk/device.rb', line 19

def params
  @params
end

#targetTarget (readonly)

Returns the value of attribute target.

Returns:



19
20
21
# File 'lib/ublk/device.rb', line 19

def target
  @target
end

Class Method Details

.create(target, id: nil, queues: target.queues, depth: target.depth, max_io_bytes: 512 * 1024, recovery: false, mlock: true) ⇒ Device

Parameters:

  • target (Target)
  • id: (Integer, nil) (defaults to: nil)
  • queues: (Integer) (defaults to: target.queues)
  • depth: (Integer) (defaults to: target.depth)
  • max_io_bytes: (Integer) (defaults to: 512 * 1024)
  • recovery: (Boolean) (defaults to: false)
  • mlock: (Boolean) (defaults to: true)

Returns:



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ublk/device.rb', line 21

def self.create(target, id: nil, queues: target.queues, depth: target.depth,
                max_io_bytes: 512 * 1024, recovery: false, mlock: true)
  control = Control.new
  info = control.add_dev(id:, queues:, depth:, max_io_bytes:, recovery:)
  params = Params.from_target(target, max_io_bytes:)
  control.set_params(info.id, params)
  new(target, control, info, params, mlock:).tap { |device| owned << device }
rescue Exception
  begin
    control&.del_dev(info.id) if info
  rescue SystemCallError, Error
    nil
  end
  control&.close
  raise
end

.delete_all!void

This method returns an undefined value.



64
65
66
67
68
69
# File 'lib/ublk/device.rb', line 64

def self.delete_all!
  control = Control.new
  control.list.each { |item| control.del_dev(item.id) }
ensure
  control&.close
end

.listArray[DeviceInfo]

Returns:



38
39
40
41
42
43
# File 'lib/ublk/device.rb', line 38

def self.list
  control = Control.new
  control.list
ensure
  control&.close
end

.recover(target, id:, mlock: true) ⇒ Device

Parameters:

  • target (Target)
  • id: (Integer)
  • mlock: (Boolean) (defaults to: true)

Returns:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ublk/device.rb', line 45

def self.recover(target, id:, mlock: true)
  control = Control.new
  deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 10
  begin
    control.start_user_recovery(id)
  rescue Errno::EBUSY
    raise if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline

    sleep 0.01
    retry
  end
  info = control.get_dev_info(id)
  params = Params.from_target(target, max_io_bytes: info.max_io_bytes)
  new(target, control, info, params, mlock:, recovering: true).tap { |device| owned << device }
rescue Exception
  control&.close
  raise
end

Instance Method Details

#char_pathString

Returns:

  • (String)


84
# File 'lib/ublk/device.rb', line 84

def char_path = info.char_path

#deleteDevice

Returns:



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/ublk/device.rb', line 141

def delete
  return self if @deleted

  worker_error = nil
  begin
    stop
  rescue Exception => error
    worker_error = error
  end
  @control.del_dev(id)
  @deleted = true
  self.class.owned.delete(self)
  raise worker_error if worker_error

  self
ensure
  @control.close if @deleted
end

#idInteger

Returns:

  • (Integer)


82
# File 'lib/ublk/device.rb', line 82

def id = info.id

#pathString

Returns:

  • (String)


83
# File 'lib/ublk/device.rb', line 83

def path = info.path

#run(threads: :auto) ⇒ Device

Parameters:

  • threads: (:auto, Integer) (defaults to: :auto)

Returns:



160
161
162
163
164
165
166
167
168
# File 'lib/ublk/device.rb', line 160

def run(threads: :auto)
  raise UnsupportedError, "data plane is unavailable in this build" unless Native.const_defined?(:Server)

  start(threads:)
  @workers.each(&:join)
  self
ensure
  stop if @started
end

#start(threads: :auto) ⇒ Device

Parameters:

  • threads: (:auto, Integer) (defaults to: :auto)

Returns:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ublk/device.rb', line 86

def start(threads: :auto)
  raise DeviceError, "device has been deleted" if @deleted
  return self if @started

  count = threads == :auto ? info.queues : Integer(threads)
  raise ArgumentError, "threads must equal the hardware queue count" unless count == info.queues

  Native.lock_memory! if @mlock
  @server = Native::Server.new(id, info.queues, info.depth)
  ready = Queue.new
  @workers = count.times.map do |queue|
    Thread.new do
      @server.run(queue, target, ready)
    rescue Exception => error
      ready << error
      raise
    end.tap { |worker| worker.report_on_exception = false }
  end
  count.times do
    result = ready.pop
    raise result if result.is_a?(Exception)
  end
  if @recovering
    @control.end_user_recovery(id)
    @recovering = false
  else
    @control.start_dev(id)
  end
  @started = true
  self
rescue Exception
  @server&.close
  join_workers(@workers, suppress: true)
  @server&.release
  @server = @workers = nil
  raise
end

#stopDevice

Returns:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/ublk/device.rb', line 124

def stop
  return self unless @started || @server

  @control.stop_dev(id) if @started
  self
ensure
  @started = false
  server, workers = @server, @workers
  @server = @workers = nil
  server&.close
  begin
    join_workers(workers)
  ensure
    server&.release
  end
end