From 55935d51800231d7c4ee26fafe5553f8a1471d09 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 7 Jun 2005 23:03:47 +0000 Subject: [PATCH] Add support for internal bitmaps For version 0.90 superblocks, an internal bitmap can be specified at create. Signed-off-by: Neil Brown --- Create.c | 21 +++++++++++- bitmap.c | 18 +++++++++-- md_p.h | 2 ++ mdadm.c | 12 +++++-- mdadm.h | 4 ++- super0.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 147 insertions(+), 9 deletions(-) diff --git a/Create.c b/Create.c index de9a44f9..5a359ee8 100644 --- a/Create.c +++ b/Create.c @@ -341,11 +341,26 @@ int Create(struct supertype *st, char *mddev, int mdfd, array.nr_disks = array.working_disks + array.failed_disks; array.layout = layout; array.chunk_size = chunk*1024; - printf("VERS = %d\n", vers); + if (!st->ss->init_super(&super, &array)) return 1; + if (bitmap_file && strcmp(bitmap_file, "internal")==0) { + if ((vers%100) < 2) { + fprintf(stderr, Name ": internal bitmaps not supported by this kernel.\n"); + return 1; + } + if (!st->ss->add_internal_bitmap(super, bitmap_chunk, delay, + size ? size : maxsize)) { + fprintf(stderr, Name ": Given bitmap chunk size not supported.\n"); + return 1; + } + bitmap_file = NULL; + } + + + if ((vers % 100) >= 1) { /* can use different versions */ mdu_array_info_t inf; memset(&inf, 0, sizeof(inf)); @@ -362,6 +377,10 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (bitmap_file) { int uuid[4]; + + if (bitmap_chunk == UnSet) + bitmap_chunk = DEFAULT_BITMAP_CHUNK; + st->ss->uuid_from_super(uuid, super); if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk, delay, array.size*2ULL /* FIXME wrong for raid10 */)) { diff --git a/bitmap.c b/bitmap.c index 57969a67..83a70bcc 100644 --- a/bitmap.c +++ b/bitmap.c @@ -177,10 +177,11 @@ out: return info; } -bitmap_info_t *bitmap_file_read(char *filename, int brief) +bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype *st) { int fd; bitmap_info_t *info; + struct stat stb; fd = open(filename, O_RDONLY); if (fd < 0) { @@ -188,13 +189,24 @@ bitmap_info_t *bitmap_file_read(char *filename, int brief) filename, strerror(errno)); return NULL; } + fstat(fd, &stb); + if ((S_IFMT & stb.st_mode) == S_IFBLK) { + /* block device, so we are probably after an internal bitmap */ + if (!st) st = guess_super(fd); + if (!st) { + /* just look at device... */ + lseek(fd, 0, 0); + } else { + st->ss->locate_bitmap(st, fd); + } + } info = bitmap_fd_read(fd, brief); close(fd); return info; } -int ExamineBitmap(char *filename, int brief) +int ExamineBitmap(char *filename, int brief, struct supertype *st) { /* * Read the bitmap file and display its contents @@ -204,7 +216,7 @@ int ExamineBitmap(char *filename, int brief) bitmap_info_t *info; int rv = 1; - info = bitmap_file_read(filename, brief); + info = bitmap_file_read(filename, brief, st); if (!info) return rv; diff --git a/md_p.h b/md_p.h index aeaf8788..31eaafd2 100644 --- a/md_p.h +++ b/md_p.h @@ -96,6 +96,8 @@ typedef struct mdp_device_descriptor_s { #define MD_SB_CLEAN 0 #define MD_SB_ERRORS 1 +#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ + typedef struct mdp_superblock_s { /* * Constant generic information diff --git a/mdadm.c b/mdadm.c index c8b8e470..39cad1ae 100644 --- a/mdadm.c +++ b/mdadm.c @@ -698,6 +698,10 @@ int main(int argc, char *argv[]) fprintf(stderr, Name ": bitmap file needed with -b in --assemble mode\n"); exit(2); } + if (strcmp(optarg, "internal")==0) { + fprintf(stderr, Name ": there is no need to specify --bitmap when assembling arrays with internal bitmaps\n"); + continue; + } bitmap_fd = open(optarg, O_RDWR); if (!*optarg || bitmap_fd < 0) { fprintf(stderr, Name ": cannot open bitmap file %s: %s\n", optarg, strerror(errno)); @@ -863,6 +867,11 @@ int main(int argc, char *argv[]) if (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK; if (delay == 0) delay = DEFAULT_BITMAP_DELAY; if (bitmap_file) { + if (strcmp(bitmap_file, "internal")==0) { + fprintf(stderr, Name ": 'internal' bitmaps not supported with --build\n"); + rv |= 1; + break; + } bitmap_fd = open(bitmap_file, O_RDWR,0); if (bitmap_fd < 0 && errno != ENOENT) { perror(Name ": cannot create bitmap file"); @@ -879,7 +888,6 @@ int main(int argc, char *argv[]) bitmap_file, bitmap_chunk, delay); break; case CREATE: - if (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK; if (delay == 0) delay = DEFAULT_BITMAP_DELAY; if (ss == NULL) { for(i=0; !ss && superlist[i]; i++) @@ -958,7 +966,7 @@ int main(int argc, char *argv[]) case 'Q': rv |= Query(dv->devname); continue; case 'X': - rv |= ExamineBitmap(dv->devname, brief); continue; + rv |= ExamineBitmap(dv->devname, brief, ss); continue; } mdfd = open_mddev(dv->devname, 0); if (mdfd>=0) { diff --git a/mdadm.h b/mdadm.h index 5733a038..fb1773d8 100644 --- a/mdadm.h +++ b/mdadm.h @@ -185,6 +185,8 @@ extern struct superswitch { int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname); struct supertype * (*match_metadata_desc)(char *arg); __u64 (*avail_size)(__u64 size); + int (*add_internal_bitmap)(void *sbv, int chunk, int delay, unsigned long long size); + void (*locate_bitmap)(struct supertype *st, int fd); int major; } super0, super1, *superlist[]; @@ -240,7 +242,7 @@ extern int Kill(char *dev, int force); extern int CreateBitmap(char *filename, int force, char uuid[16], unsigned long chunksize, unsigned long daemon_sleep, unsigned long long array_size); -extern int ExamineBitmap(char *filename, int brief); +extern int ExamineBitmap(char *filename, int brief, struct supertype *st); extern int md_get_version(int fd); extern int get_linux_version(void); diff --git a/super0.c b/super0.c index 2b571473..6ea5c15d 100644 --- a/super0.c +++ b/super0.c @@ -28,6 +28,7 @@ */ #include "mdadm.h" +#include /* * All handling for the 0.90.0 version superblock is in @@ -81,6 +82,8 @@ static void examine_super0(void *sbv) printf(" Update Time : %.24s\n", ctime(&atime)); printf(" State : %s\n", (sb->state&(1<state & (1<active_disks); printf("Working Devices : %d\n", sb->working_disks); printf(" Failed Devices : %d\n", sb->failed_disks); @@ -324,10 +327,10 @@ static __u64 event_super0(void *sbv) static int init_super0(void **sbp, mdu_array_info_t *info) { - mdp_super_t *sb = malloc(MD_SB_BYTES); + mdp_super_t *sb = malloc(MD_SB_BYTES + sizeof(bitmap_super_t)); int spares; int rfd; - memset(sb, 0, MD_SB_BYTES); + memset(sb, 0, MD_SB_BYTES + sizeof(bitmap_super_t)); if (info->major_version == -1) { /* zeroing the superblock */ @@ -441,6 +444,27 @@ static int write_init_super0(struct supertype *st, void *sbv, mdu_disk_info_t *d sb->this_disk = sb->disks[dinfo->number]; sb->sb_csum = calc_sb0_csum(sb); rv = store_super0(fd, sb); + + if (sb->state & (1< 0) { + n = towrite; + if (n > sizeof(buf)) + n = sizeof(buf); + n = write(fd, buf, n); + if (n > 0) + towrite -= n; + else + break; + } + if (towrite) + rv = -2; + } + close(fd); if (rv) fprintf(stderr, Name ": failed to write superblock to %s\n", devname); @@ -591,6 +615,75 @@ static __u64 avail_size0(__u64 devsize) return MD_NEW_SIZE_SECTORS(devsize); } +static int add_internal_bitmap0(void *sbv, int chunk, int delay, unsigned long long size) +{ + /* + * The bitmap comes immediately after the superblock and must be 60K in size + * at most. The default size is between 30K and 60K + * + * size is in K, chunk is in bytes !!! + */ + + unsigned long long bits = size; + unsigned long long max_bits = 60*1024*8; + unsigned long long min_chunk; + mdp_super_t *sb = sbv; + bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MD_SB_BYTES); + + + min_chunk = 1024; + while (bits > max_bits) { + min_chunk *= 2; + bits = (bits+1)/2; + } + if (chunk == UnSet) + chunk = min_chunk; + else if (chunk < min_chunk) + return 0; /* chunk size too small */ + + sb->state |= (1<magic = __le32_to_cpu(BITMAP_MAGIC); + bms->version = __le32_to_cpu(BITMAP_MAJOR); + uuid_from_super0((int*)bms->uuid, sb); + bms->chunksize = __le32_to_cpu(chunk); + bms->daemon_sleep = __le32_to_cpu(delay); + bms->sync_size = __le64_to_cpu(size); + + + return 1; +} + + +void locate_bitmap0(struct supertype *st, int fd) +{ + unsigned long long dsize; + unsigned long size; + unsigned long long offset; +#ifdef BLKGETSIZE64 + if (ioctl(fd, BLKGETSIZE64, &dsize) != 0) +#endif + { + if (ioctl(fd, BLKGETSIZE, &size)) + return; + else + dsize = ((unsigned long long)size)<<9; + } + + if (dsize < MD_RESERVED_SECTORS*2) + return; + + offset = MD_NEW_SIZE_SECTORS(dsize>>9); + + offset *= 512; + + offset += MD_SB_BYTES; + + lseek64(fd, offset, 0); +} + + + struct superswitch super0 = { .examine_super = examine_super0, .brief_examine_super = brief_examine_super0, @@ -608,5 +701,7 @@ struct superswitch super0 = { .load_super = load_super0, .match_metadata_desc = match_metadata_desc0, .avail_size = avail_size0, + .add_internal_bitmap = add_internal_bitmap0, + .locate_bitmap = locate_bitmap0, .major = 0, }; -- 2.39.2