@@ -101,6 +101,9 @@ type SysFs interface {
101
101
GetBlockDeviceScheduler (string ) (string , error )
102
102
// Get device major:minor number string.
103
103
GetBlockDeviceNumbers (string ) (string , error )
104
+ // Is the device "hidden" (meaning will not have a device handle)
105
+ // This is the case with native nvme multipathing.
106
+ IsBlockDeviceHidden (string ) (bool , error )
104
107
105
108
GetNetworkDevices () ([]os.FileInfo , error )
106
109
GetNetworkAddress (string ) (string , error )
@@ -212,6 +215,26 @@ func (fs *realSysFs) GetBlockDeviceNumbers(name string) (string, error) {
212
215
return string (dev ), nil
213
216
}
214
217
218
+ func (fs * realSysFs ) IsBlockDeviceHidden (name string ) (bool , error ) {
219
+ // See: https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-block
220
+ // https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git
221
+ // - c8487d854ba5 ("lsblk: Ignore hidden devices")
222
+ devHiddenPath := path .Join (blockDir , name , "/hidden" )
223
+ hidden , err := os .ReadFile (devHiddenPath )
224
+ if err != nil && os .IsNotExist (err ) {
225
+ // older OS may not have /hidden sysfs entry, so for sure
226
+ // it is not a hidden device...
227
+ return false , nil
228
+ }
229
+ if err != nil {
230
+ return false , fmt .Errorf ("failed to read %s: %w" , devHiddenPath , err )
231
+ }
232
+ if string (hidden ) == "1" {
233
+ return true , nil
234
+ }
235
+ return false , nil
236
+ }
237
+
215
238
func (fs * realSysFs ) GetBlockDeviceScheduler (name string ) (string , error ) {
216
239
sched , err := os .ReadFile (path .Join (blockDir , name , "/queue/scheduler" ))
217
240
if err != nil {
0 commit comments