@@ -101,6 +101,9 @@ type SysFs interface {
101101 GetBlockDeviceScheduler (string ) (string , error )
102102 // Get device major:minor number string.
103103 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 )
104107
105108 GetNetworkDevices () ([]os.FileInfo , error )
106109 GetNetworkAddress (string ) (string , error )
@@ -212,6 +215,26 @@ func (fs *realSysFs) GetBlockDeviceNumbers(name string) (string, error) {
212215 return string (dev ), nil
213216}
214217
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+
215238func (fs * realSysFs ) GetBlockDeviceScheduler (name string ) (string , error ) {
216239 sched , err := os .ReadFile (path .Join (blockDir , name , "/queue/scheduler" ))
217240 if err != nil {
0 commit comments