From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1Od1hn-0006Fm-6p for mharc-grub-devel@gnu.org; Sun, 25 Jul 2010 09:57:27 -0400 Received: from [140.186.70.92] (port=50763 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OcPOf-0005Li-1D for grub-devel@gnu.org; Fri, 23 Jul 2010 17:03:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OcPOd-0004Dz-JB for grub-devel@gnu.org; Fri, 23 Jul 2010 17:03:08 -0400 Received: from mail-qy0-f169.google.com ([209.85.216.169]:58398) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OcPOd-0004Ds-Fe for grub-devel@gnu.org; Fri, 23 Jul 2010 17:03:07 -0400 Received: by qyk9 with SMTP id 9so488150qyk.0 for ; Fri, 23 Jul 2010 14:03:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:content-type; bh=5GdL9rrQIxCgaDdptpug2Aq6vZrB/nzRBXmAS7pE+yk=; b=Q/QRHYAwGjfp0OTwV/NqqOPJE9RJV6uJmMoHgEZCfW9H9C/OtOz+ez8n3MoD7nxbzY hrD/O0v5rFNCVSUr/mriqao2Yk5ifUDt3tYslhKY1UD8xoIXDbcFQ2v20SlGlbs5Diyz B4mQrdrHzoFXknsEh9UOedyDbOCGZ0zUvzGrE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :content-type; b=kdGHv6Qi9ppTAtV3wvjw8bVBtPs8euJZgsP+Xf065VmRmBr+4GsxWtlTd3hUDtcJif XRtogAU6VjBmOZH9kf969c9kY5fBWRS1+I65A/IKeG41uxb0XRnyMrLmEWsDuLn+pwwz 5xEeGlWy63/ymijmF/dA+CTdYM434ewFDPjk4= Received: by 10.224.96.209 with SMTP id i17mr2977359qan.132.1279918986056; Fri, 23 Jul 2010 14:03:06 -0700 (PDT) Received: from [192.168.21.179] ([70.49.181.158]) by mx.google.com with ESMTPS id j28sm729670qck.35.2010.07.23.14.03.04 (version=SSLv3 cipher=RC4-MD5); Fri, 23 Jul 2010 14:03:05 -0700 (PDT) Message-ID: <4C4A036B.2060308@gmail.com> Date: Fri, 23 Jul 2010 17:02:35 -0400 From: Doug Nazar User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.7) Gecko/20100713 Thunderbird/3.1.1 MIME-Version: 1.0 To: grub-devel@gnu.org Content-Type: multipart/mixed; boundary="------------040008040008090208040107" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Mailman-Approved-At: Sun, 25 Jul 2010 09:57:23 -0400 Subject: Couple changes for Linux raid metadata 1.x support X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Jul 2010 21:03:10 -0000 This is a multi-part message in MIME format. --------------040008040008090208040107 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Strange timing. I ran into needing support for 1.2 metadata a few days ago. Wrote the code yesterday and when I pulled to check for conflicts before I submitted someone else had also just written the code. Here are a few changes I had that are not in the tree: - Don't use disks with outdated superblocks - Don't use disks that are being rebuilt/transfomed - Check superblock checksums - Check superblock is in the correct location - Update the recovery code to use the start_sector Doug --------------040008040008090208040107 Content-Type: text/plain; name="grub-update-raid-metadata-1x-support.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="grub-update-raid-metadata-1x-support.diff" === modified file 'disk/dmraid_nvidia.c' --- disk/dmraid_nvidia.c 2010-07-18 17:31:10 +0000 +++ disk/dmraid_nvidia.c 2010-07-23 03:23:14 +0000 @@ -137,6 +137,7 @@ array->number = 0; array->total_devs = sb.array.total_volumes; array->chunk_size = sb.array.stripe_block_size; + array->freshness = 0; array->index = sb.unit_number; array->uuid_len = sizeof (sb.array.signature); array->uuid = grub_malloc (sizeof (sb.array.signature)); === modified file 'disk/mdraid_linux.c' --- disk/mdraid_linux.c 2010-07-20 10:10:49 +0000 +++ disk/mdraid_linux.c 2010-07-23 05:22:12 +0000 @@ -229,6 +229,10 @@ are already appropriately aligned, we can omit this and avoid suboptimal assembly in some cases. */ +#define MD_FEATURE_BITMAP_OFFSET 1 +#define MD_FEATURE_RECOVERY_OFFSET 2 +#define MD_FEATURE_RESHAPE_ACTIVE 4 + #define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */ static grub_err_t @@ -262,6 +266,7 @@ array->total_devs = sb->raid_disks; array->disk_size = (sb->size) ? sb->size * 2 : sector; array->chunk_size = sb->chunk_size >> 9; + array->freshness = sb->events; array->index = sb->this_disk.number; array->uuid_len = 16; array->uuid = grub_malloc (16); @@ -279,6 +284,31 @@ return 0; } +static grub_uint32_t +grub_mdraid_calc_csum(struct grub_raid_super_1x * sb) +{ + grub_uint32_t disk_csum; + grub_uint32_t csum; + grub_uint64_t newcsum; + int size = 256 + sb->max_dev*2; + grub_uint32_t *isuper = (grub_uint32_t*)sb; + int i; + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + newcsum = 0; + for (i=0; size>=4; size -= 4 ) + newcsum += *isuper++; + + if (size == 2) + newcsum += *(grub_uint16_t*) isuper; + + csum = (newcsum & 0xffffffff) + (newcsum >> 32); + sb->sb_csum = disk_csum; + + return csum; +} + static grub_err_t grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector, struct grub_raid_super_1x *sb, @@ -293,6 +323,18 @@ "Unsupported RAID version: %d", sb->major_version); + if (sb->super_offset != sector) + /* We're not where we're supposed to be. Usually caused by a 1.0 + superblock at the end of a disk with a single large partition. */ + return grub_error (GRUB_ERR_OUT_OF_RANGE, "wrong superblock location"); + + if (sb->feature_map & MD_FEATURE_RECOVERY_OFFSET) + /* Disk is currently being recovered. Silently ignore it. */ + return grub_error (GRUB_ERR_OUT_OF_RANGE, "recovery in progress"); + + if (sb->feature_map & MD_FEATURE_RESHAPE_ACTIVE) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "reshape active"); + /* Multipath. */ if ((int) sb->level == -4) sb->level = 1; @@ -315,6 +357,12 @@ return grub_errno; } + if (grub_mdraid_calc_csum(real_sb) != real_sb->sb_csum) + { + grub_free (real_sb); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "csum invalid"); + } + array->name = grub_strdup (real_sb->set_name); if (! array->name) { @@ -328,6 +376,7 @@ array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); array->disk_size = grub_le_to_cpu64 (real_sb->size); array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); + array->freshness = grub_le_to_cpu32(real_sb->events); if (grub_le_to_cpu32 (real_sb->dev_number) < grub_le_to_cpu32 (real_sb->max_dev)) array->index = grub_le_to_cpu16 === modified file 'disk/raid.c' --- disk/raid.c 2010-07-22 08:38:06 +0000 +++ disk/raid.c 2010-07-23 05:22:34 +0000 @@ -130,8 +130,8 @@ disk->id = array->number; disk->data = array; - grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name, - array->total_devs, (unsigned long long) array->disk_size); + grub_dprintf ("raid", "%s: total_devs=%d, nr_devs=%d, disk_size=%lld\n", name, + array->total_devs, array->nr_devs, (unsigned long long) array->disk_size); switch (array->level) { @@ -495,21 +495,48 @@ /* FIXME: Check whether the update time of the superblocks are the same. */ + if (new_array->freshness < array->freshness) + { + /* This disk is outdated. Don't add it to the array. */ + grub_dprintf ("raid", "member '%s' is not fresh: disk: %llu, array: %llu\n", + disk->name, new_array->freshness, array->freshness); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "disk not fresh"); + } + if (array->total_devs == array->nr_devs) /* We found more members of the array than the array actually has according to its superblock. This shouldn't happen normally. */ - grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?", + grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?\n", array->total_devs); if (array->device[new_array->index] != NULL) /* We found multiple devices with the same number. Again, this shouldn't happen. */ - grub_dprintf ("raid", "Found two disks with the number %d?!?", + grub_dprintf ("raid", "Found two disks with the number %d?!?\n", new_array->number); if (new_array->disk_size < array->disk_size) array->disk_size = new_array->disk_size; + + if (new_array->freshness > array->freshness) + { + int i; + + /* Kick out all already found array members that are outdated */ + for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++) + if (array->device[i]) + { + grub_dprintf ("raid", "member '%s' is not fresh: disk: %llu, array: %llu\n", + array->device[i]->name, array->freshness, new_array->freshness); + grub_disk_close (array->device[i]); + array->device[i] = 0; + array->nr_devs--; + } + + array->freshness = new_array->freshness; + } + break; } === modified file 'disk/raid5_recover.c' --- disk/raid5_recover.c 2009-07-31 04:38:20 +0000 +++ disk/raid5_recover.c 2010-07-23 05:22:46 +0000 @@ -45,7 +45,8 @@ if (i == disknr) continue; - err = grub_disk_read (array->device[i], sector, 0, size, buf2); + err = grub_disk_read (array->device[i], + array->start_sector[i] + sector, 0, size, buf2); if (err) { === modified file 'disk/raid6_recover.c' --- disk/raid6_recover.c 2010-01-03 22:05:07 +0000 +++ disk/raid6_recover.c 2010-07-23 05:23:13 +0000 @@ -119,7 +119,9 @@ else { if ((array->device[pos]) && - (! grub_disk_read (array->device[pos], sector, 0, size, buf))) + (! grub_disk_read (array->device[pos], + array->start_sector[pos] + sector, + 0, size, buf))) { grub_raid_block_xor (pbuf, buf, size); grub_raid_block_mul (raid6_table2[i][i], buf, size); @@ -149,7 +151,8 @@ { /* One bad device */ if ((array->device[p]) && - (! grub_disk_read (array->device[p], sector, 0, size, buf))) + (! grub_disk_read (array->device[p], + array->start_sector[p] + sector, 0, size, buf))) { grub_raid_block_xor (buf, pbuf, size); goto quit; @@ -162,7 +165,8 @@ } grub_errno = GRUB_ERR_NONE; - if (grub_disk_read (array->device[q], sector, 0, size, buf)) + if (grub_disk_read (array->device[q], array->start_sector[q] + sector, + 0, size, buf)) goto quit; grub_raid_block_xor (buf, qbuf, size); @@ -180,12 +184,14 @@ goto quit; } - if (grub_disk_read (array->device[p], sector, 0, size, buf)) + if (grub_disk_read (array->device[p], array->start_sector[p] + sector, + 0, size, buf)) goto quit; grub_raid_block_xor (pbuf, buf, size); - if (grub_disk_read (array->device[q], sector, 0, size, buf)) + if (grub_disk_read (array->device[q], array->start_sector[q] + sector, + 0, size, buf)) goto quit; grub_raid_block_xor (qbuf, buf, size); === modified file 'include/grub/raid.h' --- include/grub/raid.h 2010-07-20 10:10:49 +0000 +++ include/grub/raid.h 2010-07-23 04:31:24 +0000 @@ -43,6 +43,8 @@ grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */ grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte sectors. */ + grub_uint64_t freshness; /* Indicator of freshness of disk. All valid + devices will have the same highest number */ int index; /* Index of current device. */ int uuid_len; /* The length of uuid. */ char *uuid; /* The UUID of the device. */ --------------040008040008090208040107--