Add UUID reading support using libblkid

This fixes the Btrfs case where the root UUIDs are not
present in the /dev/disk/by-uuid directory.
This commit is contained in:
Andrea Mazzoleni 2015-12-10 22:50:20 +01:00
parent 82d98e3a23
commit 5541f8d5e6
5 changed files with 99 additions and 8 deletions

View file

@ -1,6 +1,11 @@
SnapRAID HISTORY
================
9.2 2015/12
===========
* Adds UUID support to Btrfs filesystems. It's available only if the
libblkid library is available on the system.
9.1 2015/11
===========
* Fixes a bug when reading a content file with a deleted entry bigger

View file

@ -1537,6 +1537,7 @@ int windows_readlink(const char* file, char* buffer, size_t size)
int devuuid(uint64_t device, char* uuid, size_t uuid_size)
{
/* just use the volume serial number returned in the device parameter */
log_tag("uuid:windows:%08x:%u:\n", (unsigned)device, (unsigned)device);
snprintf(uuid, uuid_size, "%08x", (unsigned)device);
return 0;

View file

@ -122,6 +122,13 @@
#include <linux/fiemap.h>
#endif
#if HAVE_BLKID_BLKID_H
#include <blkid/blkid.h>
#if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE
#define HAVE_BLKID 1
#endif
#endif
/**
* Includes some standard headers.
*/

View file

@ -68,12 +68,21 @@ const char* stat_desc(struct stat* st)
return "unknown";
}
#if HAVE_FSTATAT
/**
* This function get the UUID using the /dev/disk/by-uuid/ links.
* Comparing with the libblkid library, it works also from not root processes.
* Cache used by blkid.
*/
int devuuid(uint64_t device, char* uuid, size_t uuid_size)
#if HAVE_BLKID
static blkid_cache cache = 0;
#endif
/**
* Get the UUID using the /dev/disk/by-uuid/ links.
* It doesn't require root permission, and the uuid are always updated.
* It doesn't work with Btrfs filesystems that don't export the main UUID
* in /dev/disk/by-uuid/.
*/
#if HAVE_FSTATAT
static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
{
int ret;
DIR* d;
@ -98,6 +107,8 @@ int devuuid(uint64_t device, char* uuid, size_t uuid_size)
continue;
}
log_tag("uuid:dev:%s:%u:%u:\n", dd->d_name, major(st.st_rdev), minor(st.st_rdev));
/* if it matches, we have the uuid */
if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) {
/* found */
@ -111,17 +122,65 @@ int devuuid(uint64_t device, char* uuid, size_t uuid_size)
closedir(d);
return -1;
}
#else
#endif
/**
* Get the UUID using liblkid.
* It uses a cache to work without root permission, resultin in UUID
* not necessarely recent.
* We could call blkid_probe_all() to refresh the UUID, but it would
* require root permission to read the superblocks, and to have
* all the disks spinning.
*/
#if HAVE_BLKID
static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size)
{
char* devname;
char* uuidname;
devname = blkid_devno_to_devname(device);
if (!devname) {
/* device mapping failed */
return -1;
}
uuidname = blkid_get_tag_value(cache, "UUID", devname);
if (!uuidname) {
/* uuid mapping failed */
free(devname);
return -1;
}
log_tag("uuid:blkid:%s:%u:%u:\n", uuidname, major(device), minor(device));
pathcpy(uuid, uuid_size, uuidname);
free(devname);
free(uuidname);
return 0;
}
#endif
int devuuid(uint64_t device, char* uuid, size_t uuid_size)
{
/* first try with the /dev/disk/by-uuid version */
#if HAVE_FSTATAT
if (devuuid_dev(device, uuid, uuid_size) == 0)
return 0;
#endif
/* fall back to blkid for other cases */
#if HAVE_BLKID
if (devuuid_blkid(device, uuid, uuid_size) == 0)
return 0;
#endif
/* not supported */
(void)device;
(void)uuid;
(void)uuid_size;
/* not supported */
return -1;
}
#endif
int filephy(const char* path, uint64_t size, uint64_t* physical)
{
@ -1005,11 +1064,25 @@ int devquery(tommy_list* high, tommy_list* low, int operation)
void os_init(int opt)
{
#if HAVE_BLKID
int ret;
ret = blkid_get_cache(&cache, NULL);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("WARNING Failed to get blkid cache\n");
/* LCOV_EXCL_STOP */
}
#endif
(void)opt;
}
void os_done(void)
{
#if HAVE_BLKID
if (cache != 0)
blkid_put_cache(cache);
#endif
}
void os_abort(void)

View file

@ -93,6 +93,11 @@ AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", [])
AC_CHECK_FUNCS([pthread_create])
AC_SEARCH_LIBS([exp], [m])
dnl Checks for libblkid
AC_CHECK_HEADERS([blkid/blkid.h])
AC_SEARCH_LIBS([blkid_probe_all], [blkid])
AC_CHECK_FUNCS([blkid_devno_to_devname blkid_get_tag_value])
dnl Checks for architecture
AC_C_BIGENDIAN