(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
drbd.c
       1  /*
       2   * Copyright (C) 2009 by Bastian Friedrich <bastian.friedrich@collax.com>
       3   *
       4   * This file may be redistributed under the terms of the
       5   * GNU Lesser General Public License.
       6   *
       7   * defines, structs taken from drbd source; file names represent drbd source
       8   * files.
       9   */
      10  #include <stdio.h>
      11  #include <stdlib.h>
      12  #include <unistd.h>
      13  #include <string.h>
      14  #include <errno.h>
      15  #include <ctype.h>
      16  #include <inttypes.h>
      17  #include <stddef.h>
      18  
      19  #include "superblocks.h"
      20  
      21  /*
      22   * drbd/linux/drbd.h
      23   */
      24  #define DRBD_MAGIC 0x83740267
      25  
      26  /*
      27   * user/drbdmeta.c
      28   * We support v08 and v09
      29   */
      30  #define DRBD_MD_MAGIC_08         (DRBD_MAGIC+4)
      31  #define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5)
      32  #define DRBD_MD_MAGIC_09         (DRBD_MAGIC+6)
      33  /* there is no DRBD_MD_MAGIC_09_UNCLEAN */
      34  
      35  /*
      36   * drbd/linux/drbd.h
      37   */
      38  enum drbd_uuid_index {
      39  	UI_CURRENT,
      40  	UI_BITMAP,
      41  	UI_HISTORY_START,
      42  	UI_HISTORY_END,
      43  	UI_SIZE,		/* nl-packet: number of dirty bits */
      44  	UI_FLAGS,		/* nl-packet: flags */
      45  	UI_EXTENDED_SIZE	/* Everything. */
      46  };
      47  
      48  
      49  /*
      50   * Used by libblkid to avoid unnecessary padding at the end of the structs and
      51   * too large unused structs in memory.
      52   */
      53  #define DRBD_MD_OFFSET 4096
      54  
      55  /*
      56   * user/shared/drbdmeta.c
      57   * Minor modifications wrt. types
      58   */
      59  struct md_on_disk_08 {
      60  	uint64_t la_sect;         /* last agreed size. */
      61  	uint64_t uuid[UI_SIZE];   /* UUIDs */
      62  	uint64_t device_uuid;
      63  	uint64_t reserved_u64_1;
      64  	uint32_t flags;
      65  	uint32_t magic;
      66  	uint32_t md_size_sect;
      67  	int32_t  al_offset;       /* signed sector offset to this block */
      68  	uint32_t al_nr_extents;   /* important for restoring the AL */
      69  	int32_t  bm_offset;       /* signed sector offset to the bitmap, from here */
      70  	uint32_t bm_bytes_per_bit;
      71  	uint32_t reserved_u32[4];
      72  
      73  	/* Unnecessary for libblkid **
      74  	 * char reserved[8 * 512 - (8*(UI_SIZE+3)+4*11)];
      75  	 */
      76  };
      77  
      78  /*
      79   * linux/drbd.h, v9 only
      80   */
      81  #define DRBD_PEERS_MAX 32
      82  #define HISTORY_UUIDS DRBD_PEERS_MAX
      83  
      84  /*
      85   * drbd-headers/drbd_meta_data.h
      86   * Minor modifications wrt. types
      87   */
      88  struct peer_dev_md_on_disk_9 {
      89  	uint64_t bitmap_uuid;
      90  	uint64_t bitmap_dagtag;
      91  	uint32_t flags;
      92  	int32_t bitmap_index;
      93  	uint32_t reserved_u32[2];
      94  } __attribute__((packed));
      95  
      96  struct meta_data_on_disk_9 {
      97  	uint64_t effective_size;    /* last agreed size */
      98  	uint64_t current_uuid;
      99  	uint64_t reserved_u64[4];   /* to have the magic at the same position as in v07, and v08 */
     100  	uint64_t device_uuid;
     101  	uint32_t flags;             /* MDF */
     102  	uint32_t magic;
     103  	uint32_t md_size_sect;
     104  	uint32_t al_offset;         /* offset to this block */
     105  	uint32_t al_nr_extents;     /* important for restoring the AL */
     106  	uint32_t bm_offset;         /* offset to the bitmap, from here */
     107  	uint32_t bm_bytes_per_bit;  /* BM_BLOCK_SIZE */
     108  	uint32_t la_peer_max_bio_size;   /* last peer max_bio_size */
     109  	uint32_t bm_max_peers;
     110  	int32_t node_id;
     111  
     112  	/* see al_tr_number_to_on_disk_sector() */
     113  	uint32_t al_stripes;
     114  	uint32_t al_stripe_size_4k;
     115  
     116  	uint32_t reserved_u32[2];
     117  
     118  	struct peer_dev_md_on_disk_9 peers[DRBD_PEERS_MAX];
     119  	uint64_t history_uuids[HISTORY_UUIDS];
     120  
     121  	/* Unnecessary for libblkid **
     122  	 * char padding[0] __attribute__((aligned(4096)));
     123  	 */
     124  } __attribute__((packed));
     125  
     126  
     127  static int probe_drbd_84(blkid_probe pr)
     128  {
     129  	struct md_on_disk_08 *md;
     130  	off_t off;
     131  
     132  	off = pr->size - DRBD_MD_OFFSET;
     133  
     134  	/* Small devices cannot be drbd (?) */
     135  	if (pr->size < 0x10000)
     136  		return 1;
     137  
     138  	md = (struct md_on_disk_08 *)
     139  			blkid_probe_get_buffer(pr,
     140  					off,
     141  					sizeof(struct md_on_disk_08));
     142  	if (!md)
     143  		return errno ? -errno : 1;
     144  
     145  	if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08 &&
     146  			be32_to_cpu(md->magic) != DRBD_MD_MAGIC_84_UNCLEAN)
     147  		return 1;
     148  
     149  	/*
     150  	 * DRBD does not have "real" uuids; the following resembles DRBD's
     151  	 * notion of uuids (64 bit, see struct above)
     152  	 */
     153  	blkid_probe_sprintf_uuid(pr,
     154  		(unsigned char *) &md->device_uuid, sizeof(md->device_uuid),
     155  		"%" PRIx64, be64_to_cpu(md->device_uuid));
     156  
     157  	blkid_probe_set_version(pr, "v08");
     158  
     159  	if (blkid_probe_set_magic(pr,
     160  				off + offsetof(struct md_on_disk_08, magic),
     161  				sizeof(md->magic),
     162  				(unsigned char *) &md->magic))
     163  		return 1;
     164  
     165  	return 0;
     166  }
     167  
     168  static int probe_drbd_90(blkid_probe pr)
     169  {
     170  	struct meta_data_on_disk_9 *md;
     171  	off_t off;
     172  
     173  	off = pr->size - DRBD_MD_OFFSET;
     174  
     175  	/*
     176  	 * Smaller ones are certainly not DRBD9 devices.
     177  	 * Recent utils even refuse to generate larger ones,
     178  	 * keep this as a sufficient lower bound.
     179  	 */
     180  	if (pr->size < 0x10000)
     181  		return 1;
     182  
     183  	md = (struct meta_data_on_disk_9 *)
     184  			blkid_probe_get_buffer(pr,
     185  					off,
     186  					sizeof(struct meta_data_on_disk_9));
     187  	if (!md)
     188  		return errno ? -errno : 1;
     189  
     190  	if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_09)
     191  		return 1;
     192  
     193  	/*
     194  	 * DRBD does not have "real" uuids; the following resembles DRBD's
     195  	 * notion of uuids (64 bit, see struct above)
     196  	 */
     197  	blkid_probe_sprintf_uuid(pr,
     198  		(unsigned char *) &md->device_uuid, sizeof(md->device_uuid),
     199  		"%" PRIx64, be64_to_cpu(md->device_uuid));
     200  
     201  	blkid_probe_set_version(pr, "v09");
     202  
     203  	if (blkid_probe_set_magic(pr,
     204  				off + offsetof(struct meta_data_on_disk_9, magic),
     205  				sizeof(md->magic),
     206  				(unsigned char *) &md->magic))
     207  		return 1;
     208  
     209  	return 0;
     210  }
     211  
     212  static int probe_drbd(blkid_probe pr,
     213  		const struct blkid_idmag *mag __attribute__((__unused__)))
     214  {
     215  	int ret;
     216  
     217  	ret = probe_drbd_84(pr);
     218  	if (ret <= 0) /* success or fatal (-errno) */
     219  		return ret;
     220  
     221  	return probe_drbd_90(pr);
     222  }
     223  
     224  const struct blkid_idinfo drbd_idinfo =
     225  {
     226  	.name		= "drbd",
     227  	.usage		= BLKID_USAGE_RAID,
     228  	.probefunc	= probe_drbd,
     229  	.magics		= BLKID_NONE_MAGIC
     230  };
     231