getroot: Correctly handle missing btrfs device identifiers.
PATCH 1/1 getroot: Correctly handle missing btrfs device identifiers.
From 97bcb9eb8c34329a8ca1ec88fd89296e273ceb24 Mon Sep 17 00:00:00 2001
From: James Johnston <[email protected]>
Date: Thu, 17 Mar 2016 15:10:49 +0000
Subject: [PATCH] getroot: Correctly handle missing btrfs device identifiers.
The btrfs driver's BTRFS_IOC_FS_INFO ioctl only tells you the maximum device ID and the number of devices. It does not tell you which device IDs may no longer be allocated - for example, if a device is later deleted from the file system, its device ID won't be allocated any more.
You must then probe each device ID with BTRFS_IOC_DEV_INFO to see if it is a valid device or not. It is not an error condition for this ioctl to return ENODEV: it seems to mean that the device was deleted by the user.
--- grub-core/osdep/linux/getroot.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
grub-core/osdep/linux/getroot.c +20 -6
@@ -242,15 +242,29 @@ grub_find_root_devices_from_btrfs (const char *dir)struct btrfs_ioctl_dev_info_args devi;memset (&devi,0 ,sizeof (devi)); devi.devid = i; +/* We have to probe all possible device IDs, since btrfs doesn't +give us a list of all the valid ones. */ if (ioctl (fd,BTRFS_IOC_DEV_INFO , &devi) <0 ) { -close (fd); -free (ret); -return NULL ; +/* ENODEV is normal, e.g. if the first device is deleted from +an array. */ +int last_error = errno; +if (last_error !=ENODEV ) + { +grub_util_warn (_ ("btrfs device info could not be read " +"for %s, device %d: errno %d" ), dir, i, + last_error); +close (fd); +free (ret); +return NULL ; + } + } +else + { + ret[j++] =xstrdup ((char *) devi.path); +if (j >= fsi.num_devices) +break ; } - ret[j++] =xstrdup ((char *) devi.path); -if (j >= fsi.num_devices) -break ; }close (fd); ret[j] =0 ;
Signature · 1 line
1.9.5.msysgit.1