From 55526d6577f82349bf6bb59816680d7483b61dff Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 12 Dec 2024 18:22:10 +0100 Subject: Merging upstream version 4.3+20241202. Signed-off-by: Daniel Baumann --- .github/tools/run_mdadm_tests.sh | 18 ++++++++ .github/workflows/tests.yml | 77 ++++++++++++++++++++++++++++++++ Assemble.c | 33 +------------- Build.c | 35 +-------------- Create.c | 48 ++------------------ Grow.c | 94 +++++----------------------------------- Incremental.c | 37 +--------------- Manage.c | 12 +++++ README.md | 8 ++-- bitmap.c | 44 ++++++++++--------- config.c | 17 +++++--- mdadm.c | 87 ++++++++++++++++++------------------- mdadm.h | 32 ++++++++++---- monitor.c | 5 +-- super-intel.c | 10 ++--- test | 33 ++++++++++---- tests/04update-uuid | 34 --------------- tests/05r1-re-add-nosuper | 32 +++----------- tests/07reshape5intr | 16 ++++++- tests/func.sh | 47 ++++++++++++++++---- tests/imsm-grow-template | 2 - tests/templates/names_template | 6 ++- 22 files changed, 325 insertions(+), 402 deletions(-) create mode 100755 .github/tools/run_mdadm_tests.sh create mode 100644 .github/workflows/tests.yml diff --git a/.github/tools/run_mdadm_tests.sh b/.github/tools/run_mdadm_tests.sh new file mode 100755 index 0000000..456874b --- /dev/null +++ b/.github/tools/run_mdadm_tests.sh @@ -0,0 +1,18 @@ +#!/usr/bin/bash + +sudo make clean +sudo make -j$(nproc) +sudo make install +sudo mdadm -Ss +sudo ./test setup + +# Uncomment and adjust this to minimalize testing time for CI or test improvements. +# --tests=test1,test2,... Comma separated list of tests to run + +#sudo ./test --tests=00createnames + +sudo ./test --skip-broken --no-error --disable-integrity --disable-multipath --disable-linear --keep-going + +ret=$? +sudo ./test cleanup +exit $ret diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..ce94010 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,77 @@ +name: tests +on: + schedule: + - cron: "0 0 * * *" + pull_request: + paths: + - '*.c' + - '*.h' + - 'tests/*' + - 'test' + - '.github/*' + - '.github/workflows/*' + - '.github/tools/*' +jobs: + upstream_tests: + if: ${{ github.repository == 'md-raid-utilities/mdadm' }} + runs-on: self-hosted + timeout-minutes: 150 + name: upstream tests + steps: + - uses: actions/checkout@v4 + if: ${{ github.event_name == 'pull_request' }} + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - uses: actions/checkout@v4 + if: ${{ github.event_name == 'schedule' }} + with: + ref: main + fetch-depth: 0 + - name: 'Prepare machine' + run: | + cd .. + vagrant halt + vagrant status + vagrant up + + - name: 'Run tests' + id: testing + continue-on-error: true + run: | + cd .. + vagrant ssh -c "cd /home/vagrant/host/mdadm && .github/tools/run_mdadm_tests.sh" + + - name: 'Copy logs to host machine' + if: ${{ steps.testing.outcome == 'failure' }} + run: | + cd .. + vagrant ssh -c "sudo mkdir -p /home/vagrant/host/logs && sudo mv /var/tmp/*.log /home/vagrant/host/logs" + + - name: "Save artifacts" + if: ${{ steps.testing.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: "Logs from failed tests" + path: /home/ci/actions-runner/_work/mdadm/logs/*.log + + - name: "Clean logs" + if: ${{ steps.testing.outcome == 'failure' }} + run: | + cd .. + sudo rm /home/ci/actions-runner/_work/mdadm/logs/*.log + + - name: "Set failed" + if: ${{ steps.testing.outcome == 'failure' }} + run: exit 1 + + cleanup: + runs-on: self-hosted + needs: [upstream_tests] + steps: + - name: Restore clean VM + run: | + cd .. + vagrant up + vagrant ssh -c "sudo mdadm -Ss" + vagrant halt diff --git a/Assemble.c b/Assemble.c index 87d1ae0..37a530e 100644 --- a/Assemble.c +++ b/Assemble.c @@ -633,7 +633,6 @@ static int load_devices(struct devs *devices, char *devmap, struct mddev_dev *tmpdev; int devcnt = 0; int nextspare = 0; - int bitmap_done = 0; int most_recent = -1; int bestcnt = 0; int *best = *bestp; @@ -661,7 +660,7 @@ static int load_devices(struct devs *devices, char *devmap, if (c->update == UOPT_UUID && !ident->uuid_set) random_uuid((__u8 *)ident->uuid); - if (c->update == UOPT_PPL && ident->bitmap_fd >= 0) { + if (c->update == UOPT_PPL && ident->btype != BitmapNone) { pr_err("PPL is not compatible with bitmap\n"); close(mdfd); free(devices); @@ -728,16 +727,6 @@ static int load_devices(struct devs *devices, char *devmap, if (tst->ss->store_super(tst, dfd)) pr_err("Could not re-write superblock on %s.\n", devname); - - if (c->update == UOPT_UUID && - ident->bitmap_fd >= 0 && !bitmap_done) { - if (bitmap_update_uuid(ident->bitmap_fd, - content->uuid, - tst->ss->swapuuid) != 0) - pr_err("Could not update uuid on external bitmap.\n"); - else - bitmap_done = 1; - } } else { dfd = dev_open(devname, tmpdev->disposition == 'I' @@ -1057,26 +1046,6 @@ static int start_array(int mdfd, mddev, strerror(errno)); return 1; } - if (ident->bitmap_fd >= 0) { - if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) { - pr_err("SET_BITMAP_FILE failed.\n"); - return 1; - } - } else if (ident->bitmap_file) { - /* From config file */ - int bmfd = open(ident->bitmap_file, O_RDWR); - if (bmfd < 0) { - pr_err("Could not open bitmap file %s\n", - ident->bitmap_file); - return 1; - } - if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { - pr_err("Failed to set bitmapfile for %s\n", mddev); - close(bmfd); - return 1; - } - close(bmfd); - } /* First, add the raid disks, but add the chosen one last */ for (i = 0; i <= bestcnt; i++) { diff --git a/Build.c b/Build.c index 6f63d3f..70aab7a 100644 --- a/Build.c +++ b/Build.c @@ -40,8 +40,6 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, dev_t rdev; int subdevs = 0, missing_disks = 0; struct mddev_dev *dv; - int bitmap_fd; - unsigned long long bitmapsize; int mdfd; char chosen_name[1024]; int uuid[4] = {0,0,0,0}; @@ -110,13 +108,6 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, goto abort; } - if (s->bitmap_file && str_is_none(s->bitmap_file) == true) - s->bitmap_file = NULL; - if (s->bitmap_file && s->level <= 0) { - pr_err("bitmaps not meaningful with level %s\n", - map_num(pers, s->level)?:"given"); - goto abort; - } /* now add the devices */ for ((i=0), (dv = devlist) ; dv ; i++, dv=dv->next) { mdu_disk_info_t disk; @@ -150,31 +141,7 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, goto abort; } } - /* now to start it */ - if (s->bitmap_file) { - bitmap_fd = open(s->bitmap_file, O_RDWR); - if (bitmap_fd < 0) { - int major = BITMAP_MAJOR_HI; - bitmapsize = s->size >> 9; /* FIXME wrong for RAID10 */ - if (CreateBitmap(s->bitmap_file, 1, NULL, - s->bitmap_chunk, c->delay, - s->write_behind, bitmapsize, major)) { - goto abort; - } - bitmap_fd = open(s->bitmap_file, O_RDWR); - if (bitmap_fd < 0) { - pr_err("%s cannot be opened.\n", s->bitmap_file); - goto abort; - } - } - if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { - pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, - strerror(errno)); - close(bitmap_fd); - goto abort; - } - close(bitmap_fd); - } + if (ioctl(mdfd, RUN_ARRAY, ¶m)) { pr_err("RUN_ARRAY failed: %s\n", strerror(errno)); if (s->chunk & (s->chunk - 1)) { diff --git a/Create.c b/Create.c index 140a709..fd6c921 100644 --- a/Create.c +++ b/Create.c @@ -521,7 +521,6 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, int insert_point = subdevs * 2; /* where to insert a missing drive */ int total_slots; int rv; - int bitmap_fd; int have_container = 0; int container_fd = -1; int need_mdmon = 0; @@ -534,9 +533,9 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, struct map_ent *map = NULL; unsigned long long newsize; mdu_array_info_t inf; - int major_num = BITMAP_MAJOR_HI; - if (s->bitmap_file && strcmp(s->bitmap_file, "clustered") == 0) { + + if (s->btype == BitmapCluster) { major_num = BITMAP_MAJOR_CLUSTERED; if (c->nodes <= 1) { pr_err("At least 2 nodes are needed for cluster-md\n"); @@ -618,7 +617,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, pr_err("You haven't given enough devices (real or missing) to create this array\n"); return 1; } - if (s->bitmap_file && s->level <= 0) { + if (s->btype != BitmapNone && s->level <= 0) { pr_err("bitmaps not meaningful with level %s\n", map_num(pers, s->level)?:"given"); return 1; @@ -949,21 +948,6 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, } } - if (!s->bitmap_file && - !st->ss->external && - s->level >= 1 && - st->ss->add_internal_bitmap && - s->journaldisks == 0 && - (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && - s->consistency_policy != CONSISTENCY_POLICY_PPL) && - (s->write_behind || s->size > 100*1024*1024ULL)) { - if (c->verbose > 0) - pr_err("automatically enabling write-intent bitmap on large array\n"); - s->bitmap_file = "internal"; - } - if (s->bitmap_file && str_is_none(s->bitmap_file) == true) - s->bitmap_file = NULL; - if (s->consistency_policy == CONSISTENCY_POLICY_PPL && !st->ss->write_init_ppl) { pr_err("%s metadata does not support PPL\n", st->ss->name); @@ -1198,8 +1182,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, * to stop another mdadm from finding and using those devices. */ - if (s->bitmap_file && (strcmp(s->bitmap_file, "internal") == 0 || - strcmp(s->bitmap_file, "clustered") == 0)) { + if (s->btype == BitmapInternal || s->btype == BitmapCluster) { if (!st->ss->add_internal_bitmap) { pr_err("internal bitmaps not supported with %s metadata\n", st->ss->name); @@ -1211,7 +1194,6 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, pr_err("Given bitmap chunk size not supported.\n"); goto abort_locked; } - s->bitmap_file = NULL; } if (sysfs_init(&info, mdfd, NULL)) { @@ -1253,28 +1235,6 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, goto abort_locked; } - if (s->bitmap_file) { - int uuid[4]; - - st->ss->uuid_from_super(st, uuid); - if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, s->bitmap_chunk, - c->delay, s->write_behind, - bitmapsize, - major_num)) { - goto abort_locked; - } - bitmap_fd = open(s->bitmap_file, O_RDWR); - if (bitmap_fd < 0) { - pr_err("weird: %s cannot be opened\n", - s->bitmap_file); - goto abort_locked; - } - if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { - pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, strerror(errno)); - goto abort_locked; - } - } - if (add_disks(mdfd, &info, s, c, st, &map, devlist, total_slots, have_container, insert_point, major_num, chosen_name)) goto abort_locked; diff --git a/Grow.c b/Grow.c index 3178694..cc1be6c 100644 --- a/Grow.c +++ b/Grow.c @@ -285,7 +285,6 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) * find all the active devices, and write the bitmap block * to all devices */ - mdu_bitmap_file_t bmf; mdu_array_info_t array; struct supertype *st; char *subarray = NULL; @@ -294,40 +293,21 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) struct mdinfo *mdi; /* - * We only ever get called if s->bitmap_file is != NULL, so this check + * We only ever get called if bitmap is not none, so this check * is just here to quiet down static code checkers. */ - if (!s->bitmap_file) + if (s->btype == BitmapUnknown) return 1; - if (strcmp(s->bitmap_file, "clustered") == 0) + if (s->btype == BitmapCluster) major = BITMAP_MAJOR_CLUSTERED; - if (ioctl(fd, GET_BITMAP_FILE, &bmf) != 0) { - if (errno == ENOMEM) - pr_err("Memory allocation failure.\n"); - else - pr_err("bitmaps not supported by this kernel.\n"); - return 1; - } - if (bmf.pathname[0]) { - if (str_is_none(s->bitmap_file) == true) { - if (ioctl(fd, SET_BITMAP_FILE, -1) != 0) { - pr_err("failed to remove bitmap %s\n", - bmf.pathname); - return 1; - } - return 0; - } - pr_err("%s already has a bitmap (%s)\n", devname, bmf.pathname); - return 1; - } if (md_get_array_info(fd, &array) != 0) { pr_err("cannot get array status for %s\n", devname); return 1; } if (array.state & (1 << MD_SB_BITMAP_PRESENT)) { - if (str_is_none(s->bitmap_file) == true) { + if (s->btype == BitmapNone) { array.state &= ~(1 << MD_SB_BITMAP_PRESENT); if (md_set_array_info(fd, &array) != 0) { if (array.state & (1 << MD_SB_CLUSTERED)) @@ -342,10 +322,11 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) return 1; } - if (str_is_none(s->bitmap_file) == true) { + if (s->btype == BitmapNone) { pr_err("no bitmap found on %s\n", devname); return 1; } + if (array.level <= 0) { pr_err("Bitmaps not meaningful with level %s\n", map_num(pers, array.level)?:"of this array"); @@ -371,7 +352,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) ncopies = (array.layout & 255) * ((array.layout >> 8) & 255); bitmapsize = bitmapsize * array.raid_disks / ncopies; - if (strcmp(s->bitmap_file, "clustered") == 0 && + if (s->btype == BitmapCluster && !is_near_layout_10(array.layout)) { pr_err("only near layout is supported with clustered raid10\n"); return 1; @@ -402,8 +383,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) free(mdi); } - if (strcmp(s->bitmap_file, "internal") == 0 || - strcmp(s->bitmap_file, "clustered") == 0) { + if (s->btype == BitmapInternal || s->btype == BitmapCluster) { int rv; int d; int offset_setable = 0; @@ -432,7 +412,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) if (!dv) continue; if ((disk.state & (1 << MD_DISK_WRITEMOSTLY)) && - (strcmp(s->bitmap_file, "clustered") == 0)) { + s->btype == BitmapCluster) { pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname); free(mdi); return 1; @@ -471,7 +451,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) mdi->bitmap_offset); free(mdi); } else { - if (strcmp(s->bitmap_file, "clustered") == 0) + if (s->btype == BitmapCluster) array.state |= (1 << MD_SB_CLUSTERED); array.state |= (1 << MD_SB_BITMAP_PRESENT); rv = md_set_array_info(fd, &array); @@ -482,60 +462,6 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) pr_err("failed to set internal bitmap.\n"); return 1; } - } else { - int uuid[4]; - int bitmap_fd; - int d; - int max_devs = st->max_devs; - - /* try to load a superblock */ - for (d = 0; d < max_devs; d++) { - mdu_disk_info_t disk; - char *dv; - int fd2; - disk.number = d; - if (md_get_disk_info(fd, &disk) < 0) - continue; - if ((disk.major==0 && disk.minor == 0) || - (disk.state & (1 << MD_DISK_REMOVED))) - continue; - dv = map_dev(disk.major, disk.minor, 1); - if (!dv) - continue; - fd2 = dev_open(dv, O_RDONLY); - if (fd2 >= 0) { - if (st->ss->load_super(st, fd2, NULL) == 0) { - close(fd2); - st->ss->uuid_from_super(st, uuid); - break; - } - close(fd2); - } - } - if (d == max_devs) { - pr_err("cannot find UUID for array!\n"); - return 1; - } - if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, - s->bitmap_chunk, c->delay, s->write_behind, - bitmapsize, major)) { - return 1; - } - bitmap_fd = open(s->bitmap_file, O_RDWR); - if (bitmap_fd < 0) { - pr_err("weird: %s cannot be opened\n", s->bitmap_file); - return 1; - } - if (ioctl(fd, SET_BITMAP_FILE, bitmap_fd) < 0) { - int err = errno; - if (errno == EBUSY) - pr_err("Cannot add bitmap while array is resyncing or reshaping etc.\n"); - pr_err("Cannot set bitmap file for %s: %s\n", - devname, strerror(err)); - close_fd(&bitmap_fd); - return 1; - } - close_fd(&bitmap_fd); } return 0; diff --git a/Incremental.c b/Incremental.c index 5e59b6d..aa5db3b 100644 --- a/Incremental.c +++ b/Incremental.c @@ -544,21 +544,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, cont_err("by --incremental. Please use --assemble\n"); goto out; } - if (match && match->bitmap_file) { - int bmfd = open(match->bitmap_file, O_RDWR); - if (bmfd < 0) { - pr_err("Could not open bitmap file %s.\n", - match->bitmap_file); - goto out; - } - if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) { - close(bmfd); - pr_err("Failed to set bitmapfile for %s.\n", - chosen_name); - goto out; - } - close(bmfd); - } + /* Need to remove from the array any devices which * 'count_active' discerned were too old or inappropriate */ @@ -1400,28 +1386,7 @@ restart: if (mddev->devname && me->path && devname_matches(mddev->devname, me->path)) break; - if (mddev && mddev->bitmap_file) { - /* - * Note: early kernels will wrongly fail this, so it - * is a hint only - */ - int added = -1; - int bmfd; - bmfd = open(mddev->bitmap_file, O_RDWR); - if (is_fd_valid(bmfd)) { - added = ioctl(mdfd, SET_BITMAP_FILE, bmfd); - close_fd(&bmfd); - } - if (c->verbose >= 0) { - if (added == 0) - pr_err("Added bitmap %s to %s\n", - mddev->bitmap_file, me->path); - else if (errno != EEXIST) - pr_err("Failed to add bitmap to %s: %s\n", - me->path, strerror(errno)); - } - } /* FIXME check for reshape_active and consider not * starting array. */ diff --git a/Manage.c b/Manage.c index b9e55c4..b14a9ab 100644 --- a/Manage.c +++ b/Manage.c @@ -1448,6 +1448,18 @@ int Manage_subdevs(char *devname, int fd, int rv, err = 0; int mj, mn; + if (tst->ss->external && dv->disposition == 'A') { + pr_err("Cannot re-add member device %s to %s, it is not supported for external metadata, aborting.\n", + dv->devname, fd2devnm(fd)); + goto abort; + } + + if (array.not_persistent == 1 && dv->disposition == 'A') { + pr_err("Cannot re-add member device %s to %s, array is not persistent, aborting.\n", + dv->devname, fd2devnm(fd)); + goto abort; + } + raid_slot = -1; if (dv->disposition == 'c') { rv = parse_cluster_confirm_arg(dv->devname, &dv->devname, &raid_slot); diff --git a/README.md b/README.md index 870ecb7..0c299a9 100644 --- a/README.md +++ b/README.md @@ -51,14 +51,14 @@ Generally, if you are not sure it is better to ask on # How to Contribute Effective immediately [Github](https://github.com/md-raid-utilities/mdadm) is the primary -location for **mdadm**. Use pull request to contribute. +location for **mdadm**. Please use pull requests to contribute. It was originally hosted on [kernel.org](https://kernel.org/). You can access the old repository [here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git). -Patches sent through Mailing list are accepted but Github is preferred. Sent then to ML only -if you cannot use Github. Please add "mdadm:" to the subject to allow automation to create Github -Pull Request and run checks. +While this is the preferred contribution method, mailing list submissions are still welcome and +will be handled as has always been the case for mdadm. Please add "mdadm:" to the subject to allow +automation to create Github Pull Request and run checks. **NOTE:** Maintainers may ask you to send RFC to mailing list if the proposed code requires consultation with kernel developers. diff --git a/bitmap.c b/bitmap.c index 5110ae2..c62d18d 100644 --- a/bitmap.c +++ b/bitmap.c @@ -200,28 +200,32 @@ bitmap_file_open(char *filename, struct supertype **stp, int node_num, int fd) close(fd); return -1; } - if ((stb.st_mode & S_IFMT) == 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 if (!st->ss->locate_bitmap) { - pr_err("No bitmap possible with %s metadata\n", - st->ss->name); - close(fd); - return -1; - } else { - if (st->ss->locate_bitmap(st, fd, node_num)) { - pr_err("%s doesn't have bitmap\n", filename); - close(fd); - fd = -1; - } - } - *stp = st; + + if ((stb.st_mode & S_IFMT) != S_IFBLK) { + pr_err("bitmap file is not supported %s\n", filename); + close(fd); + return -1; + } + + if (!st) + st = guess_super(fd); + + if (!st) { + /* just look at device... */ + lseek(fd, 0, 0); + } else if (!st->ss->locate_bitmap) { + pr_err("No bitmap possible with %s metadata\n", st->ss->name); + close(fd); + return -1; + } + + if (st->ss->locate_bitmap(st, fd, node_num)) { + pr_err("%s doesn't have bitmap\n", filename); + close(fd); + fd = -1; } + *stp = st; return fd; } diff --git a/config.c b/config.c index 3359504..8a8ae5e 100644 --- a/config.c +++ b/config.c @@ -171,8 +171,7 @@ inline void ident_init(struct mddev_ident *ident) assert(ident); ident->assembled = false; - ident->bitmap_fd = -1; - ident->bitmap_file = NULL; + ident->btype = BitmapUnknown; ident->container = NULL; ident->devices = NULL; ident->devname = NULL; @@ -542,11 +541,19 @@ void arrayline(char *line) /* Ignore name in confile */ continue; } else if (strncasecmp(w, "bitmap=", 7) == 0) { - if (mis.bitmap_file) + if (mis.btype != BitmapUnknown) pr_err("only specify bitmap file once. %s ignored\n", w); - else - mis.bitmap_file = xstrdup(w + 7); + else { + char *bname = xstrdup(w + 7); + + if (strcmp(bname, STR_COMMON_NONE) == 0) + mis.btype = BitmapNone; + else if (strcmp(bname, "internal") == 0) + mis.btype = BitmapInternal; + else if (strcmp(bname, "clustered") == 0) + mis.btype = BitmapCluster; + } } else if (strncasecmp(w, "devices=", 8 ) == 0) { if (mis.devices) diff --git a/mdadm.c b/mdadm.c index 8cb4ba6..7d3b656 100644 --- a/mdadm.c +++ b/mdadm.c @@ -41,18 +41,23 @@ */ static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char *val) { - if (s->bitmap_file) { + if (s->btype != BitmapUnknown) { pr_err("--bitmap cannot be set twice. Second value: \"%s\".\n", val); return MDADM_STATUS_ERROR; } - if (strcmp(val, "internal") == 0 || strcmp(optarg, STR_COMMON_NONE) == 0) { - s->bitmap_file = val; + if (strcmp(optarg, STR_COMMON_NONE) == 0) { + s->btype = BitmapNone; + return MDADM_STATUS_SUCCESS; + } + + if (strcmp(val, "internal") == 0) { + s->btype = BitmapInternal; return MDADM_STATUS_SUCCESS; } if (strcmp(val, "clustered") == 0) { - s->bitmap_file = val; + s->btype = BitmapCluster; /* Set the default number of cluster nodes * to 4 if not already set by user */ @@ -62,17 +67,12 @@ static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char } if (strchr(val, '/')) { - pr_info("Custom write-intent bitmap file option is deprecated.\n"); - if (ask("Do you want to continue? (y/n)")) { - s->bitmap_file = val; - return MDADM_STATUS_SUCCESS; - } - + pr_err("Custom write-intent bitmap file option is not supported.\n"); return MDADM_STATUS_ERROR; } - pr_err("--bitmap value must contain a '/' or be 'internal', 'clustered' or 'none'\n"); - pr_err("Current value is \"%s\"", val); + pr_err("--bitmap value must be 'internal', 'clustered' or 'none'\n"); + pr_err("Current value is \"%s\"\n", val); return MDADM_STATUS_ERROR; } @@ -99,7 +99,6 @@ int main(int argc, char *argv[]) struct mddev_ident ident; char *configfile = NULL; int devmode = 0; - int bitmap_fd = -1; struct mddev_dev *devlist = NULL; struct mddev_dev **devlistend = & devlist; struct mddev_dev *dv; @@ -116,6 +115,7 @@ int main(int argc, char *argv[]) .bitmap_chunk = UnSet, .consistency_policy = CONSISTENCY_POLICY_UNKNOWN, .data_offset = INVALID_SECTORS, + .btype = BitmapUnknown, }; char sys_hostname[256]; @@ -1089,24 +1089,15 @@ int main(int argc, char *argv[]) case O(ASSEMBLE,'b'): /* here we simply set the bitmap file */ case O(ASSEMBLE,Bitmap): - if (!optarg) { - pr_err("bitmap file needed with -b in --assemble mode\n"); - exit(2); - } - if (strcmp(optarg, "internal") == 0 || - strcmp(optarg, "clustered") == 0) { + if (optarg && (strcmp(optarg, "internal") == 0 || + strcmp(optarg, "clustered")) == 0) { pr_err("no need to specify --bitmap when assembling" " arrays with internal or clustered bitmap\n"); continue; } - bitmap_fd = open(optarg, O_RDWR); - if (!*optarg || bitmap_fd < 0) { - pr_err("cannot open bitmap file %s: %s\n", optarg, strerror(errno)); - exit(2); - } - ident.bitmap_fd = bitmap_fd; /* for Assemble */ - continue; + pr_err("bitmap file is not supported %s\n", optarg); + exit(2); case O(ASSEMBLE, BackupFile): case O(GROW, BackupFile): /* Specify a file into which grow might place a backup, @@ -1256,12 +1247,11 @@ int main(int argc, char *argv[]) pr_err("PPL consistency policy is only supported for RAID level 5.\n"); exit(2); } else if (s.consistency_policy == CONSISTENCY_POLICY_BITMAP && - (!s.bitmap_file || str_is_none(s.bitmap_file) == true)) { + s.btype == BitmapNone) { pr_err("--bitmap is required for consistency policy: %s\n", map_num_s(consistency_policies, s.consistency_policy)); exit(2); - } else if (s.bitmap_file && - str_is_none(s.bitmap_file) == false && + } else if ((s.btype == BitmapInternal || s.btype == BitmapCluster) && s.consistency_policy != CONSISTENCY_POLICY_BITMAP && s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) { pr_err("--bitmap is not compatible with consistency policy: %s\n", @@ -1394,7 +1384,7 @@ int main(int argc, char *argv[]) c.brief = 1; if (mode == CREATE) { - if (s.bitmap_file && strcmp(s.bitmap_file, "clustered") == 0) { + if (s.btype == BitmapCluster) { locked = cluster_get_dlmlock(); if (locked != 1) exit(1); @@ -1479,7 +1469,17 @@ int main(int argc, char *argv[]) case BUILD: if (c.delay == 0) c.delay = DEFAULT_BITMAP_DELAY; - if (s.write_behind && !s.bitmap_file) { + + if (s.btype == BitmapUnknown) + s.btype = BitmapNone; + + if (s.btype != BitmapNone) { + pr_err("--build argument only compatible with --bitmap=none\n"); + rv |= 1; + break; + } + + if (s.write_behind) { pr_err("write-behind mode requires a bitmap.\n"); rv = 1; break; @@ -1490,14 +1490,6 @@ int main(int argc, char *argv[]) break; } - if (s.bitmap_file) { - if (strcmp(s.bitmap_file, "internal") == 0 || - strcmp(s.bitmap_file, "clustered") == 0) { - pr_err("'internal' and 'clustered' bitmaps not supported with --build\n"); - rv |= 1; - break; - } - } rv = Build(&ident, devlist->next, &s, &c); break; case CREATE: @@ -1505,8 +1497,7 @@ int main(int argc, char *argv[]) c.delay = DEFAULT_BITMAP_DELAY; if (c.nodes) { - if (!s.bitmap_file || - strcmp(s.bitmap_file, "clustered") != 0) { + if (s.btype != BitmapCluster) { pr_err("--nodes argument only compatible with --bitmap=clustered\n"); rv = 1; break; @@ -1524,7 +1515,7 @@ int main(int argc, char *argv[]) } } - if (s.write_behind && !s.bitmap_file) { + if (s.write_behind && s.btype == BitmapNone) { pr_err("write-behind mode requires a bitmap.\n"); rv = 1; break; @@ -1535,6 +1526,14 @@ int main(int argc, char *argv[]) break; } + if (s.btype == BitmapUnknown) { + if (c.runstop != 1 && s.level >= 1 && + ask("To optimalize recovery speed, it is recommended to enable write-indent bitmap, do you want to enable it now?")) + s.btype = BitmapInternal; + else + s.btype = BitmapNone; + } + rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c); break; case MISC: @@ -1626,7 +1625,7 @@ int main(int argc, char *argv[]) if (devs_found > 1 && s.raiddisks == 0 && s.level == UnSet) { /* must be '-a'. */ if (s.size > 0 || s.chunk || - s.layout_str || s.bitmap_file) { + s.layout_str || s.btype != BitmapNone) { pr_err("--add cannot be used with other geometry changes in --grow mode\n"); rv = 1; break; @@ -1636,7 +1635,7 @@ int main(int argc, char *argv[]) if (rv) break; } - } else if (s.bitmap_file) { + } else if (s.btype != BitmapUnknown) { if (s.size > 0 || s.raiddisks || s.chunk || s.layout_str || devs_found > 1) { pr_err("--bitmap changes cannot be used with other geometry changes in --grow mode\n"); diff --git a/mdadm.h b/mdadm.h index 5aa5085..ebb2ca1 100644 --- a/mdadm.h +++ b/mdadm.h @@ -598,9 +598,16 @@ enum prefix_standard { }; enum bitmap_update { - NoUpdate, - NameUpdate, - NodeNumUpdate, + NoUpdate, + NameUpdate, + NodeNumUpdate, +}; + +enum bitmap_type { + BitmapNone, + BitmapInternal, + BitmapCluster, + BitmapUnknown, }; enum flag_mode { @@ -640,8 +647,7 @@ struct mddev_ident { int spare_disks; struct supertype *st; char *spare_group; - char *bitmap_file; - int bitmap_fd; + enum bitmap_type btype; char *container; /* /dev/whatever name of container, or * uuid of container. You would expect @@ -693,7 +699,7 @@ struct shape { char *layout_str; int chunk; int bitmap_chunk; - char *bitmap_file; + enum bitmap_type btype; int assume_clean; bool write_zeroes; int write_behind; @@ -1899,15 +1905,23 @@ static inline sighandler_t signal_s(int sig, sighandler_t handler) } #ifdef DEBUG +#include + #define dprintf(fmt, arg...) \ - fprintf(stderr, "%s: %s: "fmt, Name, __func__, ##arg) + do { \ + struct timespec ts; \ + clock_gettime(CLOCK_MONOTONIC, &ts); \ + double timestamp = ts.tv_sec + ts.tv_nsec / 1e9; \ + fprintf(stderr, "[%10.5f] %s: %s: " fmt, timestamp, Name, __func__, ##arg); \ + } while (0) + #define dprintf_cont(fmt, arg...) \ fprintf(stderr, fmt, ##arg) #else #define dprintf(fmt, arg...) \ - ({ if (0) fprintf(stderr, "%s: %s: " fmt, Name, __func__, ##arg); 0; }) + do { } while (0) #define dprintf_cont(fmt, arg...) \ - ({ if (0) fprintf(stderr, fmt, ##arg); 0; }) + do { } while (0) #endif static inline int xasprintf(char **strp, const char *fmt, ...) { diff --git a/monitor.c b/monitor.c index 81ae889..3c54f8c 100644 --- a/monitor.c +++ b/monitor.c @@ -406,7 +406,6 @@ static int read_and_act(struct active_array *a) struct mdinfo *mdi; int ret = 0; int count = 0; - struct timeval tv; bool write_checkpoint = false; a->next_state = bad_word; @@ -453,10 +452,8 @@ static int read_and_act(struct active_array *a) check_for_cleared_bb(a, mdi); } - gettimeofday(&tv, NULL); - dprintf("(%d): %ld.%06ld state:%s prev:%s action:%s prev: %s start:%llu\n", + dprintf("(%d): state:%s prev:%s action:%s prev: %s start:%llu\n", a->info.container_member, - tv.tv_sec, tv.tv_usec, array_states[a->curr_state], array_states[a->prev_state], sync_actions[a->curr_action], diff --git a/super-intel.c b/super-intel.c index 55c71e2..7e3c5f2 100644 --- a/super-intel.c +++ b/super-intel.c @@ -5092,7 +5092,6 @@ imsm_thunderdome(struct intel_super **super_list, int len) for (i = 0; i < tbl_size; i++) { struct imsm_disk *d; struct intel_disk *idisk; - struct imsm_super *mpb = super_table[i]->anchor; s = super_table[i]; d = &s->disks->disk; @@ -5108,7 +5107,7 @@ imsm_thunderdome(struct intel_super **super_list, int len) if (!s) dprintf("marking family: %#x from %d:%d offline\n", - mpb->family_num, + super_table[i]->anchor->family_num, super_table[i]->disks->major, super_table[i]->disks->minor); super_table[i] = s; @@ -6122,7 +6121,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", basename(cntrl_path)); - if (super->orom && !imsm_orom_has_tpv_support(super->orom)) { + if (super->orom && devpath_to_vendor(pci_dev_path) != 0x8086 && + !imsm_orom_has_tpv_support(super->orom)) { pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n" "\tPlease refer to Intel(R) RSTe/VROC user guide.\n"); goto error; @@ -7056,7 +7056,8 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, int fd = -1; while (dev && !is_fd_valid(fd)) { - char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1); + char path[PATH_MAX]; + num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name); if (num > 0) fd = open(path, O_RDONLY, 0); @@ -7064,7 +7065,6 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, pr_vrb("Cannot open %s: %s\n", dev->name, strerror(errno)); } - free(path); dev = dev->next; } found = 0; diff --git a/test b/test index f8f07ff..4b37a46 100755 --- a/test +++ b/test @@ -95,11 +95,22 @@ mdadm() { return $rv } +print_time_elapsed() { + local start_sec=$1 + local end_sec=$(date +%s) + + local execution_time=$((end_sec - start_sec)) + + echo -ne "Execution time (seconds): ${execution_time} " +} + do_test() { _script=$1 _basename=`basename $_script` _broken=0 + local start_sec=$(date +%s) + if [ -f "$_script" ] then if [ -f "${_script}.broken" ]; then @@ -121,6 +132,7 @@ do_test() { echo -ne "$_script... " if ( set -ex ; . $_script ) &> $targetdir/log then + print_time_elapsed $start_sec if [ -f "${_script}.inject_error" ]; then echo "dmesg checking is skipped because test inject error" else @@ -130,6 +142,7 @@ do_test() { succeed "succeeded\n" _fail=0 else + print_time_elapsed $start_sec save_log fail _fail=1 if [ "$_broken" == "1" ]; then @@ -137,11 +150,14 @@ do_test() { fi fi restore_system_speed_limit - [ "$savelogs" == "1" ] && - mv -f $targetdir/log $logdir/$_basename.log + + [ "$savelogs" == "1" ] && mv -f $targetdir/log $logdir/$_basename.log + [ "$ctrl_c_error" == "1" ] && exit 1 - [ "$_fail" == "1" -a "$exitonerror" == "1" \ - -a "$_broken" == "0" ] && exit 1 + + [ "$_fail" == "1" -a "$exitonerror" == "1" -a "$_broken" == "0" ] && exit 1 + + [ "$_fail" == "1" ] && do_test_ret=1 fi } @@ -327,6 +343,8 @@ main() { [ "$savelogs" == "1" ] && echo "Saving logs to $logdir" + do_test_ret=0 + while true; do if [ "x$TESTLIST" != "x" ] then @@ -337,11 +355,10 @@ main() { else for script in $testdir/$prefix $testdir/$prefix*[^~] do - case $script in - *.broken) ;; + case $script in *.broken) ;; *) do_test $script - esac + esac done fi @@ -352,7 +369,7 @@ main() { done restore_selinux - exit 0 + exit $do_test_ret } parse_args $@ diff --git a/tests/04update-uuid b/tests/04update-uuid index 25314ab..ce5a958 100644 --- a/tests/04update-uuid +++ b/tests/04update-uuid @@ -22,40 +22,6 @@ mdadm -D /dev/md0 | grep -s > /dev/null 01234567:89abcdef:fedcba98:76543210 || { } mdadm -S /dev/md0 - -# now if we have a bitmap, that needs updating too. -rm -f $targetdir/bitmap -yes | mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 -mdadm -S /dev/md0 -mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2 -no_errors -mdadm -D /dev/md0 | grep -s > /dev/null 01234567:89abcdef:fedcba98:76543210 || { - echo Wrong uuid; mdadm -D /dev/md0 ; exit 2; -} -if mdadm -X $targetdir/bitmap | grep -s > /dev/null 01234567:89abcdef:fedcba98:76543210 || - mdadm -X $targetdir/bitmap | grep -s > /dev/null 67452301:efcdab89:98badcfe:10325476 -then : ; else - echo Wrong uuid; mdadm -X $targetdir/bitmap ; exit 2; -fi -mdadm -S /dev/md0 - -# and bitmap for version1 -rm -f $targetdir/bitmap -yes | mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 -mdadm -S /dev/md0 -mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2 -no_errors -mdadm -D /dev/md0 | grep -s > /dev/null 01234567:89abcdef:fedcba98:76543210 || { - echo Wrong uuid; mdadm -D /dev/md0 ; exit 2; -} -# -X cannot tell which byteorder to use for the UUID, so allow both. -if mdadm -X $targetdir/bitmap | grep -s > /dev/null 01234567:89abcdef:fedcba98:76543210 || - mdadm -X $targetdir/bitmap | grep -s > /dev/null 67452301:efcdab89:98badcfe:10325476 -then : ; else - echo Wrong uuid; mdadm -X $targetdir/bitmap ; exit 2; -fi -mdadm -S /dev/md0 - # Internal bitmaps too. mdadm -CR --assume-clean -b internal --bitmap-chunk 4 $md0 -l5 -n3 $dev0 $dev1 $dev2 mdadm -S /dev/md0 diff --git a/tests/05r1-re-add-nosuper b/tests/05r1-re-add-nosuper index 7d41fd7..750d7c1 100644 --- a/tests/05r1-re-add-nosuper +++ b/tests/05r1-re-add-nosuper @@ -1,12 +1,8 @@ - # -# create a raid1, remove a drive, and readd it. -# resync should be instant. -# Then do some IO first. Resync should still be very fast +# create a raid1 without superblock, remove a drive, and readd it. +# readd should fail. # -bmf=$targetdir/bitmap2 -rm -f $bmf -yes | mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2 +mdadm -B $md0 -l1 -n2 -d1 $dev1 $dev2 check resync check wait testdev $md0 1 $size 1 @@ -15,24 +11,8 @@ sleep 4 mdadm $md0 -f $dev2 sleep 1 mdadm $md0 -r $dev2 -mdadm $md0 --re-add $dev2 -check nosync +if mdadm $md0 --re-add $dev2; then + err "re-add should fail" +fi -mdadm $md0 -f $dev2 -sleep 1 -mdadm $md0 -r $dev2 -testdev $md0 1 $size 1 -mdadm $md0 --re-add $dev2 -check wait -cmp --bytes=$[$mdsize0*1024] $dev1 $dev2 - -mdadm $md0 -f $dev2; sleep 1 -mdadm $md0 -r $dev2 -if dd if=/dev/zero of=$md0 ; then : ; fi -blockdev --flushbufs $md0 # make sure writes have been sent -mdadm $md0 --re-add $dev2 -check recovery -check wait -# should BLKFLSBUF and then read $dev1/$dev2... -cmp --bytes=$[$mdsize0*1024] $file1 $file2 mdadm -S $md0 diff --git a/tests/07reshape5intr b/tests/07reshape5intr index 0f4803a..2af2910 100644 --- a/tests/07reshape5intr +++ b/tests/07reshape5intr @@ -31,7 +31,21 @@ do echo 1000 > /proc/sys/dev/raid/speed_limit_min echo 2000 > /proc/sys/dev/raid/speed_limit_max check wait - while ! echo check > /sys/block/md0/md/sync_action; do sleep 0.1; done + + max=5 + + for ((i = 0 ; i < max ; i++ )); do + if [[ $(echo check > /sys/block/md0/md/sync_action) != 0 ]]; then + break; + fi + sleep 1 + done + + if [[ i == max ]]; then + echo >&2 "Timeout waiting for check to succeed" + exit 1 + fi + check wait mm=`cat /sys/block/md0/md/mismatch_cnt` if [ $mm -gt 0 ] diff --git a/tests/func.sh b/tests/func.sh index 567d91d..4b4d374 100644 --- a/tests/func.sh +++ b/tests/func.sh @@ -186,7 +186,7 @@ is_raid_foreign() { # to decide if an array is foreign or local. It adds homehost if # one array is local hostname=$(hostname) - if [ `expr length "$(hostname)$name"` -lt 31 ]; then + if [ `expr length "$(hostname):$name"` -lt 31 ]; then is_foreign="no" else is_foreign="yes" @@ -202,6 +202,24 @@ restore_selinux() { setenforce $sys_selinux } +wait_for_reshape_end() { + # wait for grow-continue to finish but break if sync_action does not + # contain any reshape value + while true + do + sync_action=$(grep -Ec '(resync|recovery|reshape|check|repair) *=' /proc/mdstat) + if (( "$sync_action" != 0 )); then + sleep 1 + continue + elif [[ $(pgrep -f "mdadm --grow --continue" > /dev/null) != "" ]]; then + echo "Grow continue did not finish but reshape is done" >&2 + exit 1 + else + break + fi + done +} + setup_systemd_env() { warn "Warning! Test suite will set up systemd environment!\n" echo "Use \"systemctl show-environment\" to show systemd environment variables" @@ -357,15 +375,28 @@ check() { max=`cat /proc/sys/dev/raid/speed_limit_max` echo 200000 > /proc/sys/dev/raid/speed_limit_max sleep 0.1 - while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat || - grep -v idle > /dev/null /sys/block/md*/md/sync_action + iterations=0 + # Wait 10 seconds for one of the actions appears in sync_action. + while [ $iterations -le 10 ] do - sleep 0.5 - done - while ps auxf | grep "mdadm --grow --continue" | grep -v grep - do - sleep 1 + sync_action=$(grep -Ec '(resync|recovery|reshape|check|repair) *=' /proc/mdstat) + if (( "$sync_action" == 0 )); then + sleep 1 + iterations=$(( $iterations + 1 )) + continue + else + break + fi done + echo "Reshape has not started after 10 seconds" + + # Now let's wait for reshape to finish. + echo "Waiting for grow-continue to finish" + wait_for_reshape_end + # If we have matrix-raid there's a second process ongoing + sleep 5 + wait_for_reshape_end + echo $min > /proc/sys/dev/raid/speed_limit_min echo $max > /proc/sys/dev/raid/speed_limit_max ;; diff --git a/tests/imsm-grow-template b/tests/imsm-grow-template index f69e025..c3279fc 100644 --- a/tests/imsm-grow-template +++ b/tests/imsm-grow-template @@ -103,9 +103,7 @@ else exit 1 fi else - sleep 5 check wait - sleep 5 check wait imsm_check member $member0 $num_disks $vol0_level $vol0_comp_size $((vol0_comp_size * vol0_new_num_comps)) $vol0_offset $vol0_chunk testdev $member0 $vol0_new_num_comps $vol0_comp_size $vol0_chunk diff --git a/tests/templates/names_template b/tests/templates/names_template index c94245e..8060794 100644 --- a/tests/templates/names_template +++ b/tests/templates/names_template @@ -4,8 +4,6 @@ function names_create() { local NAME=$2 local NEG_TEST=$3 - is_raid_foreign $DEVNAME - if [[ -z "$NAME" ]]; then mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force else @@ -34,6 +32,10 @@ function names_verify() { local WANTED_NAME="$3" local EXPECTED="" + # We don't know what is saved in metadata, but we know what to expect. Therfore check if + # expecation would be foreign (no hostname information). + is_raid_foreign $WANTED_NAME + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" if [[ "$?" != "0" ]]; then echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." -- cgit v1.2.3