#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/geom_dbg.h>
#include <geom/label/g_label.h>
#define SWAP_VERSION 1
#define SWAP_UUID_LENGTH 16
#define SWAP_LABEL_LENGTH 16
#define SWAP_SIGNATURE "SWAPSPACE2"
#define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
struct swap_header_v1_2 {
char bootbits[1024];
uint32_t version;
uint32_t last_page;
uint32_t nr_badpages;
unsigned char uuid[SWAP_UUID_LENGTH];
char volume_name[SWAP_LABEL_LENGTH];
uint32_t padding[117];
uint32_t badpages[1];
};
typedef union {
struct swap_header_v1_2 header;
struct {
uint8_t reserved[PAGE_SIZE - SWAP_SIGNATURE_SZ];
char signature[SWAP_SIGNATURE_SZ];
} tail;
} swhdr_t;
#define sw_version header.version
#define sw_volume_name header.volume_name
#define sw_signature tail.signature
static void
g_label_swaplinux_taste(struct g_consumer *cp, char *label, size_t size)
{
struct g_provider *pp;
swhdr_t *hdr;
g_topology_assert_not();
pp = cp->provider;
label[0] = '\0';
KASSERT(pp->sectorsize != 0, ("Tasting a disk with 0 sectorsize"));
if ((PAGE_SIZE % pp->sectorsize) != 0)
return;
hdr = (swhdr_t *)g_read_data(cp, 0, PAGE_SIZE, NULL);
if (hdr == NULL)
return;
if (hdr->sw_version == SWAP_VERSION &&
!memcmp(hdr->sw_signature, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ))
G_LABEL_DEBUG(1, "linux swap detected on %s.", pp->name);
else
goto exit_free;
if (hdr->sw_volume_name[0] == '\0')
goto exit_free;
hdr->sw_volume_name[sizeof(hdr->sw_volume_name) - 1] = '\0';
strlcpy(label, hdr->sw_volume_name, size);
exit_free:
g_free(hdr);
}
struct g_label_desc g_label_swaplinux = {
.ld_taste = g_label_swaplinux_taste,
.ld_dirprefix = "swaplinux/",
.ld_enabled = 1
};
G_LABEL_INIT(swaplinux, g_label_swaplinux, "Create device nodes for Linux swap");