Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -1828,6 +1828,11 @@ int Assemble(char *mddev, struct mddev_ident *ident,
close(fd);
}

if (st->ss->get_bitmap_type &&
st->ss->get_bitmap_type(st) == BITMAP_MAJOR_LOCKLESS &&
sysfs_set_str(content, NULL, "bitmap_type", "llbitmap"))
goto out;

/* If we are in the middle of a reshape we may need to restore saved data
* that was moved aside due to the reshape overwriting live data
* The code of doing this lives in Grow.c
Expand Down
10 changes: 8 additions & 2 deletions Create.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
pr_err("At least 2 nodes are needed for cluster-md\n");
return 1;
}
} else if (s->btype == BitmapLockless) {
major_num = BITMAP_MAJOR_LOCKLESS;
}

memset(&info, 0, sizeof(info));
Expand Down Expand Up @@ -1180,18 +1182,22 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
* to stop another mdadm from finding and using those devices.
*/

if (s->btype == BitmapInternal || s->btype == BitmapCluster) {
if (s->btype == BitmapInternal || s->btype == BitmapCluster ||
s->btype == BitmapLockless) {
if (!st->ss->add_internal_bitmap) {
pr_err("internal bitmaps not supported with %s metadata\n",
st->ss->name);
goto abort_locked;
}
if (st->ss->add_internal_bitmap(st, &s->bitmap_chunk,
c->delay, s->write_behind,
bitmapsize, 1, major_num)) {
bitmapsize, 1, major_num, s->assume_clean)) {
pr_err("Given bitmap chunk size not supported.\n");
goto abort_locked;
}
if (s->btype == BitmapLockless &&
sysfs_set_str(&info, NULL, "bitmap_type", "llbitmap") < 0)
goto abort_locked;
}

if (sysfs_init(&info, mdfd, NULL)) {
Expand Down
5 changes: 3 additions & 2 deletions Grow.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
free(mdi);
}

if (s->btype == BitmapInternal || s->btype == BitmapCluster) {
if (s->btype == BitmapInternal || s->btype == BitmapCluster ||
s->btype == BitmapLockless) {
int rv;
int d;
int offset_setable = 0;
Expand Down Expand Up @@ -419,7 +420,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
rv = st->ss->add_internal_bitmap(
st, &s->bitmap_chunk, c->delay,
s->write_behind, bitmapsize,
offset_setable, major);
offset_setable, major, 0);
if (!rv) {
st->ss->write_bitmap(st, fd2,
NodeNumUpdate);
Expand Down
34 changes: 34 additions & 0 deletions Incremental.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,40 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
if (d->disk.state & (1<<MD_DISK_REMOVED))
remove_disk(mdfd, st, sra, d);

if (st->ss->get_bitmap_type) {
if (st->sb == NULL) {
dfd = dev_open(devname, O_RDONLY);
if (dfd < 0) {
rv = 1;
goto out;
}

rv = st->ss->load_super(st, dfd, NULL);
close(dfd);
dfd = -1;
if (rv) {
pr_err("load super failed %d\n", rv);
goto out;
}
}

if (st->ss->get_bitmap_type(st) == BITMAP_MAJOR_LOCKLESS) {
if (sra == NULL) {
sra = sysfs_read(mdfd, NULL, (GET_DEVS | GET_STATE |
GET_OFFSET | GET_SIZE));
if (!sra) {
pr_err("can't read mdinfo\n");
rv = 1;
goto out;
}
}

rv = sysfs_set_str(sra, NULL, "bitmap_type", "llbitmap");
if (rv)
goto out;
}
}

if ((sra == NULL || active_disks >= info.array.working_disks) &&
trustworthy != FOREIGN)
rv = ioctl(mdfd, RUN_ARRAY, NULL);
Expand Down
9 changes: 7 additions & 2 deletions bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
#define BITMAP_MAJOR_LO 3
#define BITMAP_MAJOR_HI 4
#define BITMAP_MAJOR_CLUSTERED 5
#define BITMAP_MAJOR_LOCKLESS 6
#define BITMAP_MAGIC 0x6d746962

/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */
BITMAP_STALE = 1, /* the bitmap file is out of date or had -EIO */
BITMAP_WRITE_ERROR = 2, /* A write error has occurred */
BITMAP_FIRST_USE = 3,
BITMAP_CLEAN = 4,
BITMAP_DAEMON_BUSY = 5,
BITMAP_HOSTENDIAN = 15,
};

/* the superblock at the front of the bitmap file -- little endian */
Expand Down
9 changes: 8 additions & 1 deletion mdadm.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char
return MDADM_STATUS_SUCCESS;
}

if (strcmp(val, "lockless") == 0) {
s->btype = BitmapLockless;
pr_info("Experimental lockless bitmap, use at your own disk!\n");
return MDADM_STATUS_SUCCESS;
}

if (strcmp(val, "clustered") == 0) {
s->btype = BitmapCluster;
/* Set the default number of cluster nodes
Expand Down Expand Up @@ -1247,7 +1253,8 @@ int main(int argc, char *argv[])
pr_err("--bitmap is required for consistency policy: %s\n",
map_num_s(consistency_policies, s.consistency_policy));
exit(2);
} else if ((s.btype == BitmapInternal || s.btype == BitmapCluster) &&
} else if ((s.btype == BitmapInternal || s.btype == BitmapCluster ||
s.btype == BitmapLockless) &&
s.consistency_policy != CONSISTENCY_POLICY_BITMAP &&
s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) {
pr_err("--bitmap is not compatible with consistency policy: %s\n",
Expand Down
5 changes: 4 additions & 1 deletion mdadm.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ enum bitmap_type {
BitmapNone,
BitmapInternal,
BitmapCluster,
BitmapLockless,
BitmapUnknown,
};

Expand Down Expand Up @@ -1155,7 +1156,9 @@ extern struct superswitch {
*/
int (*add_internal_bitmap)(struct supertype *st, int *chunkp,
int delay, int write_behind,
unsigned long long size, int may_change, int major);
unsigned long long size, int may_change,
int major, bool assume_clean);
int (*get_bitmap_type)(struct supertype *st);
/* Perform additional setup required to activate a bitmap.
*/
int (*set_bitmap)(struct supertype *st, struct mdinfo *info);
Expand Down
2 changes: 1 addition & 1 deletion super-intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -13011,7 +13011,7 @@ static int validate_internal_bitmap_imsm(struct supertype *st)
static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp,
int delay, int write_behind,
unsigned long long size, int may_change,
int amajor)
int amajor, bool assume_clean)
{
struct intel_super *super = st->sb;
int vol_idx = super->current_vol;
Expand Down
2 changes: 1 addition & 1 deletion super0.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ static __u64 avail_size0(struct supertype *st, __u64 devsize,
static int add_internal_bitmap0(struct supertype *st, int *chunkp,
int delay, int write_behind,
unsigned long long size, int may_change,
int major)
int major, bool assume_clean)
{
/*
* The bitmap comes immediately after the superblock and must be 60K in size
Expand Down
35 changes: 33 additions & 2 deletions super1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2374,11 +2374,19 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize,
return 0;
}

static int get_bitmap_type1(struct supertype *st)
{
struct mdp_superblock_1 *sb = st->sb;
bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);

return __le32_to_cpu(bms->version);
}

static int
add_internal_bitmap1(struct supertype *st,
int *chunkp, int delay, int write_behind,
unsigned long long size,
int may_change, int major)
int may_change, int major, bool assume_clean)
{
/*
* If not may_change, then this is a 'Grow' without sysfs support for
Expand Down Expand Up @@ -2408,6 +2416,14 @@ add_internal_bitmap1(struct supertype *st,
* would be non-zero
*/
creating = 1;

if (major == BITMAP_MAJOR_LOCKLESS) {
if (!creating || st->minor_version != 2) {
pr_err("lockless bitmap is only supported with creating the array with 1.2 metadata\n");
return -EINVAL;
}
}

switch(st->minor_version) {
case 0:
/*
Expand Down Expand Up @@ -2476,9 +2492,16 @@ add_internal_bitmap1(struct supertype *st,
}

room -= bbl_size;
if (chunk == UnSet && room > 128*2)
if (major == BITMAP_MAJOR_LOCKLESS) {
if (chunk != UnSet) {
pr_err("lockless bitmap doesn't support chunksize\n");
return -EINVAL;
}
room = 128*2;
} else if (chunk == UnSet && room > 128*2) {
/* Limit to 128K of bitmap when chunk size not requested */
room = 128*2;
}

if (room <= 1)
/* No room for a bitmap */
Expand Down Expand Up @@ -2537,6 +2560,13 @@ add_internal_bitmap1(struct supertype *st,
bms->cluster_name[len - 1] = '\0';
}

/* kernel will initialize bitmap */
if (major == BITMAP_MAJOR_LOCKLESS) {
bms->state = __cpu_to_le32(1 << BITMAP_FIRST_USE);
if (assume_clean)
bms->state |= __cpu_to_le32(1 << BITMAP_CLEAN);
bms->sectors_reserved = __le32_to_cpu(room);
}
*chunkp = chunk;
return 0;
}
Expand Down Expand Up @@ -2912,6 +2942,7 @@ struct superswitch super1 = {
.avail_size = avail_size1,
.add_internal_bitmap = add_internal_bitmap1,
.locate_bitmap = locate_bitmap1,
.get_bitmap_type = get_bitmap_type1,
.write_bitmap = write_bitmap1,
.free_super = free_super1,
#if __BYTE_ORDER == BIG_ENDIAN
Expand Down