1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 */ 4 5 #include <sys/param.h> 6 #include <sys/systm.h> 7 #include <sys/kernel.h> 8 #include <sys/malloc.h> 9 10 #include <geom/geom.h> 11 #include <geom/geom_dbg.h> 12 #include <geom/label/g_label.h> 13 14 /* 15 * Taken from 16 * https://github.com/util-linux/util-linux/blob/master/include/swapheader.h 17 */ 18 19 #define SWAP_VERSION 1 20 #define SWAP_UUID_LENGTH 16 21 #define SWAP_LABEL_LENGTH 16 22 #define SWAP_SIGNATURE "SWAPSPACE2" 23 #define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1) 24 25 struct swap_header_v1_2 { 26 char bootbits[1024]; /* Space for disklabel etc. */ 27 uint32_t version; 28 uint32_t last_page; 29 uint32_t nr_badpages; 30 unsigned char uuid[SWAP_UUID_LENGTH]; 31 char volume_name[SWAP_LABEL_LENGTH]; 32 uint32_t padding[117]; 33 uint32_t badpages[1]; 34 }; 35 36 typedef union { 37 struct swap_header_v1_2 header; 38 struct { 39 uint8_t reserved[PAGE_SIZE - SWAP_SIGNATURE_SZ]; 40 char signature[SWAP_SIGNATURE_SZ]; 41 } tail; 42 } swhdr_t; 43 44 #define sw_version header.version 45 #define sw_volume_name header.volume_name 46 #define sw_signature tail.signature 47 48 static void 49 g_label_swaplinux_taste(struct g_consumer *cp, char *label, size_t size) 50 { 51 struct g_provider *pp; 52 swhdr_t *hdr; 53 54 g_topology_assert_not(); 55 pp = cp->provider; 56 label[0] = '\0'; 57 58 KASSERT(pp->sectorsize != 0, ("Tasting a disk with 0 sectorsize")); 59 if ((PAGE_SIZE % pp->sectorsize) != 0) 60 return; 61 62 hdr = (swhdr_t *)g_read_data(cp, 0, PAGE_SIZE, NULL); 63 if (hdr == NULL) 64 return; 65 66 /* Check version and magic string */ 67 if (hdr->sw_version == SWAP_VERSION && 68 !memcmp(hdr->sw_signature, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ)) 69 G_LABEL_DEBUG(1, "linux swap detected on %s.", pp->name); 70 else 71 goto exit_free; 72 73 /* Check for volume label */ 74 if (hdr->sw_volume_name[0] == '\0') 75 goto exit_free; 76 77 /* Terminate label */ 78 hdr->sw_volume_name[sizeof(hdr->sw_volume_name) - 1] = '\0'; 79 strlcpy(label, hdr->sw_volume_name, size); 80 81 exit_free: 82 g_free(hdr); 83 } 84 85 struct g_label_desc g_label_swaplinux = { 86 .ld_taste = g_label_swaplinux_taste, 87 .ld_dirprefix = "swaplinux/", 88 .ld_enabled = 1 89 }; 90 91 G_LABEL_INIT(swaplinux, g_label_swaplinux, "Create device nodes for Linux swap"); 92