~ubuntu-branches/ubuntu/utopic/mdadm/utopic

« back to all changes in this revision

Viewing changes to Assemble.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2012-06-15 15:31:59 UTC
  • mfrom: (1.1.30 sid)
  • Revision ID: package-import@ubuntu.com-20120615153159-9lp7jykbq7vua4bo
Tags: 3.2.5-1ubuntu1
* Merge from Debian testing. (LP: #920324)  Remaining changes:
  - Call checks in local-premount to avoid race condition with udev
    and opening a degraded array.
  - d/initramfs/mdadm-functions: Record in /run when boot-degraded 
    question has been asked so that it is only asked once
  - pass --test to mdadm to enable result codes for degraded arrays. 
  - debian/control: we need udev and util-linux in the right version. We
    also remove the build dependency from quilt and docbook-to-man as both
    are not used in Ubuntus mdadm.
  - debian/initramfs/hook: kept the Ubuntus version for handling the absence
    of active raid arrays in <initramfs>/etc/mdadm/mdadm.conf
  - debian/initramfs/script.local-top.DEBIAN, debian/mdadm-startall,
    debian/mdadm.raid.DEBIAN: removed. udev does its job now instead.
  - debian/mdadm-startall.sgml, debian/mdadm-startall.8: documentation of
    unused startall script
  - debian/mdadm.config, debian/mdadm.postinst - let udev do the handling
    instead. Resolved merge conflict by keeping Ubuntu's version.
  - debian/mdadm.postinst, debian/mdadm.config, initramfs/init-premount:
    boot-degraded enablement; maintain udev starting of RAID devices;
    init-premount hook script for the initramfs, to provide information at
    boot
  - debian/mkconf.in is the older mkconf. Kept the Ubuntu version.
  - debian/rules: Kept Ubuntus version for installing apport hooks, not
    installing un-used startall script.
  - debian/install-rc, check.d/_numbers, check.d/root_on_raid: Ubuntu partman
    installer changes
  - debian/presubj: Dropped this unused bug reporting file. Instead use
    source_mdadm.py act as an apport hook for bug handling.
  - d/p/debian-changes-3.1.4-1+8efb9d1ubuntu4: mdadm udev rule
    incrementally adds mdadm member when detected. Starting such an
    array in degraded mode is possible by mdadm -IRs. Using mdadm
    -ARs without stopping the array first does nothing when no
    mdarray-unassociated device is available. Using mdadm -IRs to
    start a previously partially assembled array through incremental
    mode. Keeping the mdadm -ARs for assembling arrays which were for
    some reason not assembled through incremental mode (i.e through
    mdadm's udev rule).

* Additional Ubuntu changes:
    - debian/initramfs/local-premount: add call wait_for_udev to wait a
    little longer for RAID devices to appear (LP: #942106)

* Dropped Ubuntu changes:
  - Build udeb with -O2 on ppc64, working around a link error. Builds
    fine without it on debian.
  - rename debian/mdadm.vol_id.udev to debian/mdadm.mdadm-blkid.udev so
    that the rules file ends up with a more reasonable name. debian/rules
    changes for adding ubuntu's udev rule corresponding to mdadm. As we
    are now using 'upstream' udev rules see 3.2.3-2ubuntu2.

* Changes to Ubuntu changes:
  - debian/source_mdadm.py: make apport hook python 2 and 3 compatible
    (LP: #1013171).

* New upstream release closes this bugs:
  - mdadm --detail --scan segfaults during update-initramfs (LP: #969384)

Show diffs side-by-side

added added

removed removed

Lines of Context:
311
311
 
312
312
                tst = dup_super(st);
313
313
 
314
 
                dfd = dev_open(devname, O_RDONLY|O_EXCL);
 
314
                dfd = dev_open(devname, O_RDONLY);
315
315
                if (dfd < 0) {
316
316
                        if (report_missmatch)
317
317
                                fprintf(stderr, Name ": cannot open device %s: %s\n",
409
409
                        /* tmpdev is a container.  We need to be either
410
410
                         * looking for a member, or auto-assembling
411
411
                         */
 
412
                        /* should be safe to try an exclusive open now, we
 
413
                         * have rejected anything that some other mdadm might
 
414
                         * be looking at
 
415
                         */
 
416
                        dfd = dev_open(devname, O_RDONLY | O_EXCL);
 
417
                        if (dfd < 0) {
 
418
                                if (report_missmatch)
 
419
                                        fprintf(stderr, Name ": %s is busy - skipping\n", devname);
 
420
                                goto loop;
 
421
                        }
 
422
                        close(dfd);
412
423
 
413
424
                        if (ident->container) {
414
425
                                if (ident->container[0] == '/' &&
493
504
                                           report_missmatch ? devname : NULL))
494
505
                                goto loop;
495
506
                                
 
507
                        /* should be safe to try an exclusive open now, we
 
508
                         * have rejected anything that some other mdadm might
 
509
                         * be looking at
 
510
                         */
 
511
                        dfd = dev_open(devname, O_RDONLY | O_EXCL);
 
512
                        if (dfd < 0) {
 
513
                                if (report_missmatch)
 
514
                                        fprintf(stderr, Name ": %s is busy - skipping\n", devname);
 
515
                                goto loop;
 
516
                        }
 
517
                        close(dfd);
 
518
 
496
519
                        if (st == NULL)
497
520
                                st = dup_super(tst);
498
521
                        if (st->minor_version == -1)
935
958
                                }
936
959
                                continue;
937
960
                        }
938
 
                /* If this devices thinks that 'most_recent' has failed, then
 
961
                /* If this device thinks that 'most_recent' has failed, then
939
962
                 * we must reject this device.
940
963
                 */
941
964
                if (j != most_recent &&
954
977
                        if (i < content->array.raid_disks) {
955
978
                                if (devices[j].i.recovery_start == MaxSector ||
956
979
                                    (content->reshape_active &&
957
 
                                     j >= content->array.raid_disks - content->delta_disks)) {
 
980
                                     ((i >= content->array.raid_disks - content->delta_disks) ||
 
981
                                      (i >= content->array.raid_disks - content->delta_disks - 1
 
982
                                       && content->array.level == 4)))) {
958
983
                                        okcnt++;
959
984
                                        avail[i]=1;
960
985
                                } else
964
989
                }
965
990
        }
966
991
        free(devmap);
967
 
        while (force && !enough(content->array.level, content->array.raid_disks,
968
 
                                content->array.layout, 1,
969
 
                                avail, okcnt)) {
 
992
        while (force &&
 
993
               (!enough(content->array.level, content->array.raid_disks,
 
994
                        content->array.layout, 1,
 
995
                        avail)
 
996
                ||
 
997
                (content->reshape_active && content->delta_disks > 0 &&
 
998
                 !enough(content->array.level, (content->array.raid_disks
 
999
                                                - content->delta_disks),
 
1000
                         content->new_layout, 1,
 
1001
                         avail)
 
1002
                        ))) {
970
1003
                /* Choose the newest best drive which is
971
1004
                 * not up-to-date, update the superblock
972
1005
                 * and add it.
1037
1070
                        int j = best[i];
1038
1071
                        if (j >= 0 &&
1039
1072
                            !devices[j].uptodate &&
 
1073
                            devices[j].i.recovery_start == MaxSector &&
1040
1074
                            devices[j].i.events == current_events) {
1041
1075
                                chosen_drive = j;
1042
1076
                                goto add_another;
1133
1167
        if (force && !clean &&
1134
1168
            !enough(content->array.level, content->array.raid_disks,
1135
1169
                    content->array.layout, clean,
1136
 
                    avail, okcnt)) {
 
1170
                    avail)) {
1137
1171
                change += st->ss->update_super(st, content, "force-array",
1138
1172
                                        devices[chosen_drive].devname, verbose,
1139
1173
                                               0, NULL);
1302
1336
                                                sparecnt--;
1303
1337
                                } else if (verbose > 0)
1304
1338
                                        fprintf(stderr, Name ": added %s "
1305
 
                                                        "to %s as %d\n",
 
1339
                                                        "to %s as %d%s\n",
1306
1340
                                                devices[j].devname, mddev,
1307
 
                                                devices[j].i.disk.raid_disk);
 
1341
                                                devices[j].i.disk.raid_disk,
 
1342
                                                devices[j].uptodate?"":
 
1343
                                                " (possibly out of date)");
1308
1344
                        } else if (verbose > 0 && i < content->array.raid_disks)
1309
1345
                                fprintf(stderr, Name ": no uptodate device for "
1310
1346
                                                "slot %d of %s\n",
1332
1368
                if (runstop == 1 ||
1333
1369
                    (runstop <= 0 &&
1334
1370
                     ( enough(content->array.level, content->array.raid_disks,
1335
 
                              content->array.layout, clean, avail, okcnt) &&
 
1371
                              content->array.layout, clean, avail) &&
1336
1372
                       (okcnt + rebuilding_cnt >= req_cnt || start_partial_ok)
1337
1373
                             ))) {
1338
1374
                        /* This array is good-to-go.
1438
1474
                                mddev, strerror(errno));
1439
1475
 
1440
1476
                        if (!enough(content->array.level, content->array.raid_disks,
1441
 
                                    content->array.layout, 1, avail, okcnt))
 
1477
                                    content->array.layout, 1, avail))
1442
1478
                                fprintf(stderr, Name ": Not enough devices to "
1443
1479
                                        "start the array.\n");
1444
1480
                        else if (!enough(content->array.level,
1445
1481
                                         content->array.raid_disks,
1446
1482
                                         content->array.layout, clean,
1447
 
                                         avail, okcnt))
 
1483
                                         avail))
1448
1484
                                fprintf(stderr, Name ": Not enough devices to "
1449
1485
                                        "start the array while not clean "
1450
1486
                                        "- consider --force.\n");
1472
1508
                        if (sparecnt)
1473
1509
                                fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
1474
1510
                        if (!enough(content->array.level, content->array.raid_disks,
1475
 
                                    content->array.layout, 1, avail, okcnt))
 
1511
                                    content->array.layout, 1, avail))
1476
1512
                                fprintf(stderr, " - not enough to start the array.\n");
1477
1513
                        else if (!enough(content->array.level,
1478
1514
                                         content->array.raid_disks,
1479
1515
                                         content->array.layout, clean,
1480
 
                                         avail, okcnt))
 
1516
                                         avail))
1481
1517
                                fprintf(stderr, " - not enough to start the "
1482
1518
                                        "array while not clean - consider "
1483
1519
                                        "--force.\n");
1524
1560
        int expansion = 0;
1525
1561
        struct map_ent *map = NULL;
1526
1562
        int old_raid_disks;
 
1563
        int start_reshape;
1527
1564
 
1528
1565
        sysfs_init(content, mdfd, 0);
1529
1566
 
1535
1572
                        return 1;
1536
1573
                }
1537
1574
 
1538
 
        if (st->ss->external && content->recovery_blocked)
 
1575
        /* There are two types of reshape: container wide or sub-array specific
 
1576
         * Check if metadata requests blocking container wide reshapes
 
1577
         */
 
1578
        start_reshape = (content->reshape_active &&
 
1579
                !((content->reshape_active == CONTAINER_RESHAPE) &&
 
1580
                (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
 
1581
 
 
1582
        /* Block subarray here if it is under reshape now
 
1583
         * Do not allow for any changes in this array
 
1584
         */
 
1585
        if (st->ss->external && content->recovery_blocked && start_reshape)
1539
1586
                block_subarray(content);
1540
1587
 
1541
1588
        if (sra)
1550
1597
                                working++;
1551
1598
                } else if (errno == EEXIST)
1552
1599
                        preexist++;
1553
 
        if (working == 0)
 
1600
        if (working + expansion == 0)
1554
1601
                return 1;/* Nothing new, don't try to start */
1555
1602
 
1556
1603
        map_update(&map, fd2devnum(mdfd),
1561
1608
                 (working + preexist + expansion) >=
1562
1609
                        content->array.working_disks) {
1563
1610
                int err;
1564
 
                int start_reshape;
1565
1611
 
1566
 
                /* There are two types of reshape: container wide or sub-array specific
1567
 
                 * Check if metadata requests blocking container wide reshapes
1568
 
                 */
1569
 
                start_reshape = (content->reshape_active &&
1570
 
                                 !((content->reshape_active == CONTAINER_RESHAPE) &&
1571
 
                                   (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
1572
1612
                if (start_reshape) {
1573
1613
                        int spare = content->array.raid_disks + expansion;
1574
1614
                        if (restore_backup(st, content,
1612
1652
                }
1613
1653
                if (!err)
1614
1654
                        sysfs_set_safemode(content, content->safe_mode_delay);
 
1655
 
 
1656
                /* Block subarray here if it is not reshaped now
 
1657
                 * It has be blocked a little later to allow mdmon to switch in
 
1658
                 * in to R/W state
 
1659
                 */
 
1660
                if (st->ss->external && content->recovery_blocked &&
 
1661
                    !start_reshape)
 
1662
                        block_subarray(content);
 
1663
 
1615
1664
                if (verbose >= 0) {
1616
1665
                        if (err)
1617
1666
                                fprintf(stderr, Name