From 5e068d22c8a88cb8cea02a579228de28c30e82ac Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 5 Sep 2025 10:37:48 +0800 Subject: [PATCH] Btrfs (Linux): refactors Btrfs allocation to use profile string Fixes #1941 --- src/detection/btrfs/btrfs.h | 4 +-- src/detection/btrfs/btrfs_linux.c | 58 ++++++++++++++++++------------- src/modules/btrfs/btrfs.c | 8 ++--- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/detection/btrfs/btrfs.h b/src/detection/btrfs/btrfs.h index 19338ce64..3fca95784 100644 --- a/src/detection/btrfs/btrfs.h +++ b/src/detection/btrfs/btrfs.h @@ -8,8 +8,8 @@ typedef struct FFBtrfsDiskUsage uint64_t total; uint64_t used; const char* type; - bool dup; - uint8_t copies; // 1=single/raid0/raid5/raid6, 2=dup/raid1/raid10, 3=raid1c3, 4=raid1c4 + const char* profile; // single / dup / raidx + uint8_t copies; } FFBtrfsDiskUsage; typedef struct FFBtrfsResult diff --git a/src/detection/btrfs/btrfs_linux.c b/src/detection/btrfs/btrfs_linux.c index 3c4455910..e48496fff 100644 --- a/src/detection/btrfs/btrfs_linux.c +++ b/src/detection/btrfs/btrfs_linux.c @@ -73,35 +73,43 @@ static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buff item->globalReservationUsed = ffStrbufToUInt(buffer, 0); item->globalReservationUsed = item->globalReservationTotal - item->globalReservationUsed; - #define FF_BTRFS_DETECT_TYPE(index, _type) \ - if (ffReadFileBufferRelative(subfd, #_type "/total_bytes", buffer)) \ - item->allocation[index].total = ffStrbufToUInt(buffer, 0); \ - \ - if (ffReadFileBufferRelative(subfd, #_type "/bytes_used", buffer)) \ - item->allocation[index].used = ffStrbufToUInt(buffer, 0); \ - \ - item->allocation[index].dup = faccessat(subfd, #_type "/dup/", F_OK, 0) == 0; \ - do { \ - uint8_t _copies = 1; \ - if (faccessat(subfd, #_type "/raid1c4/", F_OK, 0) == 0) _copies = 4; \ - else if (faccessat(subfd, #_type "/raid1c3/", F_OK, 0) == 0) _copies = 3; \ - else if (faccessat(subfd, #_type "/raid1/", F_OK, 0) == 0) _copies = 2; \ - else if (faccessat(subfd, #_type "/raid10/", F_OK, 0) == 0) _copies = 2; \ - else if (item->allocation[index].dup) _copies = 2; /* DUP on single device */ \ - item->allocation[index].copies = _copies; \ - } while(0); \ - \ - item->allocation[index].type = #_type; + #define FF_BTRFS_DETECT_PROFILE(_index, _type, _profile, _copies) \ + else if (faccessat(subfd, _type "/" _profile "/", F_OK, 0) == 0) { \ + item->allocation[_index].profile = _profile; \ + item->allocation[_index].copies = _copies; \ + } - FF_BTRFS_DETECT_TYPE(0, data); - FF_BTRFS_DETECT_TYPE(1, metadata); - FF_BTRFS_DETECT_TYPE(2, system); + #define FF_BTRFS_DETECT_TYPE(_index, _type) \ + do { \ + item->allocation[_index].type = _type; \ + if (ffReadFileBufferRelative(subfd, _type "/total_bytes", buffer)) \ + item->allocation[_index].total = ffStrbufToUInt(buffer, 0); \ + \ + if (ffReadFileBufferRelative(subfd, _type "/bytes_used", buffer)) \ + item->allocation[_index].used = ffStrbufToUInt(buffer, 0); \ + \ + if (false) {} \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "single", 1) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "dup", 2) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid0", 1) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1", 2) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid10", 2) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c3", 3) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c4", 4) \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid5", 1) /* (n-1)/n */ \ + FF_BTRFS_DETECT_PROFILE(_index, _type, "raid6", 1) /* (n-2)/n */ \ + else { \ + item->allocation[_index].profile = "unknown"; \ + item->allocation[_index].copies = 1; \ + } \ + } while (0) + + FF_BTRFS_DETECT_TYPE(0, "data"); + FF_BTRFS_DETECT_TYPE(1, "metadata"); + FF_BTRFS_DETECT_TYPE(2, "system"); #undef FF_BTRFS_DETECT_TYPE - if (item->allocation[0].copies > 1) // index 0 = data - item->totalSize /= item->allocation[0].copies; - return NULL; } diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 947af51b1..b3f968d88 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -27,9 +27,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i } uint64_t used = 0, allocated = 0, total = result->totalSize; - for (int i = 0; i < 3; ++i) + for (uint32_t i = 0; i < ARRAY_SIZE(result->allocation); ++i) { - uint64_t times = result->allocation[i].dup ? 2 : 1; + uint64_t times = result->allocation[i].copies; used += result->allocation[i].used * times; allocated += result->allocation[i].total * times; } @@ -180,11 +180,11 @@ bool ffGenerateBtrfsJsonResult(FF_MAYBE_UNUSED FFBtrfsOptions* options, yyjson_m yyjson_mut_obj_add_uint(doc, obj, "sectorSize", btrfs->sectorSize); yyjson_mut_obj_add_uint(doc, obj, "totalSize", btrfs->totalSize); yyjson_mut_val* allocation = yyjson_mut_obj_add_arr(doc, obj, "allocation"); - for (int i = 0; i < 3; ++i) + for (uint32_t i = 0; i < ARRAY_SIZE(btrfs->allocation); ++i) { yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, allocation); yyjson_mut_obj_add_str(doc, item, "type", btrfs->allocation[i].type); - yyjson_mut_obj_add_bool(doc, item, "dup", btrfs->allocation[i].dup); + yyjson_mut_obj_add_str(doc, item, "profile", btrfs->allocation[i].profile); yyjson_mut_obj_add_uint(doc, item, "copies", btrfs->allocation[i].copies); yyjson_mut_obj_add_uint(doc, item, "used", btrfs->allocation[i].used); yyjson_mut_obj_add_uint(doc, item, "total", btrfs->allocation[i].total);