Add support for internal bitmaps
For version 0.90 superblocks, an internal bitmap can be specified at create. Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
This commit is contained in:
parent
e793c2e583
commit
55935d5180
21
Create.c
21
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.nr_disks = array.working_disks + array.failed_disks;
|
||||||
array.layout = layout;
|
array.layout = layout;
|
||||||
array.chunk_size = chunk*1024;
|
array.chunk_size = chunk*1024;
|
||||||
printf("VERS = %d\n", vers);
|
|
||||||
|
|
||||||
if (!st->ss->init_super(&super, &array))
|
if (!st->ss->init_super(&super, &array))
|
||||||
return 1;
|
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 */
|
if ((vers % 100) >= 1) { /* can use different versions */
|
||||||
mdu_array_info_t inf;
|
mdu_array_info_t inf;
|
||||||
memset(&inf, 0, sizeof(inf));
|
memset(&inf, 0, sizeof(inf));
|
||||||
|
@ -362,6 +377,10 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
||||||
|
|
||||||
if (bitmap_file) {
|
if (bitmap_file) {
|
||||||
int uuid[4];
|
int uuid[4];
|
||||||
|
|
||||||
|
if (bitmap_chunk == UnSet)
|
||||||
|
bitmap_chunk = DEFAULT_BITMAP_CHUNK;
|
||||||
|
|
||||||
st->ss->uuid_from_super(uuid, super);
|
st->ss->uuid_from_super(uuid, super);
|
||||||
if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk, delay,
|
if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk, delay,
|
||||||
array.size*2ULL /* FIXME wrong for raid10 */)) {
|
array.size*2ULL /* FIXME wrong for raid10 */)) {
|
||||||
|
|
18
bitmap.c
18
bitmap.c
|
@ -177,10 +177,11 @@ out:
|
||||||
return info;
|
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;
|
int fd;
|
||||||
bitmap_info_t *info;
|
bitmap_info_t *info;
|
||||||
|
struct stat stb;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
fd = open(filename, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -188,13 +189,24 @@ bitmap_info_t *bitmap_file_read(char *filename, int brief)
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return NULL;
|
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);
|
info = bitmap_fd_read(fd, brief);
|
||||||
close(fd);
|
close(fd);
|
||||||
return info;
|
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
|
* Read the bitmap file and display its contents
|
||||||
|
@ -204,7 +216,7 @@ int ExamineBitmap(char *filename, int brief)
|
||||||
bitmap_info_t *info;
|
bitmap_info_t *info;
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
|
|
||||||
info = bitmap_file_read(filename, brief);
|
info = bitmap_file_read(filename, brief, st);
|
||||||
if (!info)
|
if (!info)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
|
|
2
md_p.h
2
md_p.h
|
@ -96,6 +96,8 @@ typedef struct mdp_device_descriptor_s {
|
||||||
#define MD_SB_CLEAN 0
|
#define MD_SB_CLEAN 0
|
||||||
#define MD_SB_ERRORS 1
|
#define MD_SB_ERRORS 1
|
||||||
|
|
||||||
|
#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */
|
||||||
|
|
||||||
typedef struct mdp_superblock_s {
|
typedef struct mdp_superblock_s {
|
||||||
/*
|
/*
|
||||||
* Constant generic information
|
* Constant generic information
|
||||||
|
|
12
mdadm.c
12
mdadm.c
|
@ -698,6 +698,10 @@ int main(int argc, char *argv[])
|
||||||
fprintf(stderr, Name ": bitmap file needed with -b in --assemble mode\n");
|
fprintf(stderr, Name ": bitmap file needed with -b in --assemble mode\n");
|
||||||
exit(2);
|
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);
|
bitmap_fd = open(optarg, O_RDWR);
|
||||||
if (!*optarg || bitmap_fd < 0) {
|
if (!*optarg || bitmap_fd < 0) {
|
||||||
fprintf(stderr, Name ": cannot open bitmap file %s: %s\n", optarg, strerror(errno));
|
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 (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK;
|
||||||
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
|
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
|
||||||
if (bitmap_file) {
|
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);
|
bitmap_fd = open(bitmap_file, O_RDWR,0);
|
||||||
if (bitmap_fd < 0 && errno != ENOENT) {
|
if (bitmap_fd < 0 && errno != ENOENT) {
|
||||||
perror(Name ": cannot create bitmap file");
|
perror(Name ": cannot create bitmap file");
|
||||||
|
@ -879,7 +888,6 @@ int main(int argc, char *argv[])
|
||||||
bitmap_file, bitmap_chunk, delay);
|
bitmap_file, bitmap_chunk, delay);
|
||||||
break;
|
break;
|
||||||
case CREATE:
|
case CREATE:
|
||||||
if (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK;
|
|
||||||
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
|
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
|
||||||
if (ss == NULL) {
|
if (ss == NULL) {
|
||||||
for(i=0; !ss && superlist[i]; i++)
|
for(i=0; !ss && superlist[i]; i++)
|
||||||
|
@ -958,7 +966,7 @@ int main(int argc, char *argv[])
|
||||||
case 'Q':
|
case 'Q':
|
||||||
rv |= Query(dv->devname); continue;
|
rv |= Query(dv->devname); continue;
|
||||||
case 'X':
|
case 'X':
|
||||||
rv |= ExamineBitmap(dv->devname, brief); continue;
|
rv |= ExamineBitmap(dv->devname, brief, ss); continue;
|
||||||
}
|
}
|
||||||
mdfd = open_mddev(dv->devname, 0);
|
mdfd = open_mddev(dv->devname, 0);
|
||||||
if (mdfd>=0) {
|
if (mdfd>=0) {
|
||||||
|
|
4
mdadm.h
4
mdadm.h
|
@ -185,6 +185,8 @@ extern struct superswitch {
|
||||||
int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
|
int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
|
||||||
struct supertype * (*match_metadata_desc)(char *arg);
|
struct supertype * (*match_metadata_desc)(char *arg);
|
||||||
__u64 (*avail_size)(__u64 size);
|
__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;
|
int major;
|
||||||
} super0, super1, *superlist[];
|
} super0, super1, *superlist[];
|
||||||
|
|
||||||
|
@ -240,7 +242,7 @@ extern int Kill(char *dev, int force);
|
||||||
extern int CreateBitmap(char *filename, int force, char uuid[16],
|
extern int CreateBitmap(char *filename, int force, char uuid[16],
|
||||||
unsigned long chunksize, unsigned long daemon_sleep,
|
unsigned long chunksize, unsigned long daemon_sleep,
|
||||||
unsigned long long array_size);
|
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 md_get_version(int fd);
|
||||||
extern int get_linux_version(void);
|
extern int get_linux_version(void);
|
||||||
|
|
99
super0.c
99
super0.c
|
@ -28,6 +28,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mdadm.h"
|
#include "mdadm.h"
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All handling for the 0.90.0 version superblock is in
|
* 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(" Update Time : %.24s\n", ctime(&atime));
|
||||||
printf(" State : %s\n",
|
printf(" State : %s\n",
|
||||||
(sb->state&(1<<MD_SB_CLEAN))?"clean":"active");
|
(sb->state&(1<<MD_SB_CLEAN))?"clean":"active");
|
||||||
|
if (sb->state & (1<<MD_SB_BITMAP_PRESENT))
|
||||||
|
printf("Internal Bitmap : present\n");
|
||||||
printf(" Active Devices : %d\n", sb->active_disks);
|
printf(" Active Devices : %d\n", sb->active_disks);
|
||||||
printf("Working Devices : %d\n", sb->working_disks);
|
printf("Working Devices : %d\n", sb->working_disks);
|
||||||
printf(" Failed Devices : %d\n", sb->failed_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)
|
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 spares;
|
||||||
int rfd;
|
int rfd;
|
||||||
memset(sb, 0, MD_SB_BYTES);
|
memset(sb, 0, MD_SB_BYTES + sizeof(bitmap_super_t));
|
||||||
|
|
||||||
if (info->major_version == -1) {
|
if (info->major_version == -1) {
|
||||||
/* zeroing the superblock */
|
/* 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->this_disk = sb->disks[dinfo->number];
|
||||||
sb->sb_csum = calc_sb0_csum(sb);
|
sb->sb_csum = calc_sb0_csum(sb);
|
||||||
rv = store_super0(fd, sb);
|
rv = store_super0(fd, sb);
|
||||||
|
|
||||||
|
if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
|
||||||
|
int towrite, n;
|
||||||
|
char buf[4096];
|
||||||
|
write(fd, ((char*)sb)+MD_SB_BYTES, sizeof(bitmap_super_t));
|
||||||
|
towrite = 64*1024 - MD_SB_BYTES - sizeof(bitmap_super_t);
|
||||||
|
memset(buf, 0xff, sizeof(buf));
|
||||||
|
while (towrite > 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);
|
close(fd);
|
||||||
if (rv)
|
if (rv)
|
||||||
fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
|
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);
|
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<<MD_SB_BITMAP_PRESENT);
|
||||||
|
|
||||||
|
bms->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 = {
|
struct superswitch super0 = {
|
||||||
.examine_super = examine_super0,
|
.examine_super = examine_super0,
|
||||||
.brief_examine_super = brief_examine_super0,
|
.brief_examine_super = brief_examine_super0,
|
||||||
|
@ -608,5 +701,7 @@ struct superswitch super0 = {
|
||||||
.load_super = load_super0,
|
.load_super = load_super0,
|
||||||
.match_metadata_desc = match_metadata_desc0,
|
.match_metadata_desc = match_metadata_desc0,
|
||||||
.avail_size = avail_size0,
|
.avail_size = avail_size0,
|
||||||
|
.add_internal_bitmap = add_internal_bitmap0,
|
||||||
|
.locate_bitmap = locate_bitmap0,
|
||||||
.major = 0,
|
.major = 0,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue