diff options
author | srs5694 <srs5694@users.sourceforge.net> | 2010-03-19 14:21:59 -0400 |
---|---|---|
committer | srs5694 <srs5694@users.sourceforge.net> | 2010-03-19 14:21:59 -0400 |
commit | a8582cfe6c1aa5e5f80458ac72d881a04ae0ba44 (patch) | |
tree | 93cbbc9e8013e2404ab2fe7740eccdf28dc966cf | |
parent | 55d926192adc984462509b2966e23bc0d1129bbd (diff) | |
download | gptfdisk-a8582cfe6c1aa5e5f80458ac72d881a04ae0ba44.tar.gz |
Changes to sector alignment policies and behavior when restoring a
backup fails
-rw-r--r-- | CHANGELOG | 19 | ||||
-rw-r--r-- | attributes.cc | 2 | ||||
-rw-r--r-- | diskio.cc | 8 | ||||
-rw-r--r-- | diskio.h | 6 | ||||
-rw-r--r-- | gdisk.8 | 2 | ||||
-rw-r--r-- | gdisk.cc | 7 | ||||
-rw-r--r-- | gpt.cc | 68 | ||||
-rw-r--r-- | gpt.h | 19 | ||||
-rw-r--r-- | mbr.cc | 5 | ||||
-rw-r--r-- | mbr.h | 2 | ||||
-rw-r--r-- | sgdisk.8 | 8 | ||||
-rw-r--r-- | sgdisk.cc | 2 | ||||
-rw-r--r-- | support.cc | 6 | ||||
-rw-r--r-- | support.h | 2 |
14 files changed, 122 insertions, 34 deletions
@@ -1,3 +1,22 @@ +0.6.6 (?/?/2010): +----------------- + +- More alignment changes: GPT fdisk now attempts to determine the + alignment value based on alignment of current partitions, if any are + defined. If no partitions are defined, a default value of 2048 is + set. If the computed value is less than 8 on drives over about 596GiB, + it's reset to 8, since the drive might be a WD Advanced Format unit + that requires an 8-sector (or larger power-of-2) alignment value + for proper functioning. The 2048-sector default provides better + alignment in some RAID configurations. + +- Changed behavior when a backup restore fails. Previously, GPT fdisk + would create a fresh blank set of partitions. Now it does so only + if the failure occurs when interpreting the backup's contents; if the + user typed the wrong filename, the in-memory data structures aren't + touched. + + 0.6.5 (3/7/2010): ----------------- diff --git a/attributes.cc b/attributes.cc index ac9f1fc..f210522 100644 --- a/attributes.cc +++ b/attributes.cc @@ -73,7 +73,7 @@ void Attributes::ChangeAttributes(void) { do { response = GetNumber(0, 64, -1, (string) "Toggle which attribute field (0-63, 64 to exit): "); if (response != 64) { - bitValue = PowerOf2(NUM_ATR - response - 1); // Find the integer value of the bit + bitValue = PowerOf2(uint32_t (NUM_ATR - response - 1)); // Find the integer value of the bit if ((bitValue & attributes) == bitValue) { // bit is set attributes -= bitValue; // so unset it cout << "Have disabled the '" << atNames[response] << "' attribute.\n"; @@ -34,6 +34,7 @@ #include "support.h" #include "diskio.h" +#include "gpt.h" using namespace std; @@ -93,11 +94,12 @@ int DiskIO::OpenForWrite(const string & filename) { // returns 1-sector alignment for unusual sector sizes and drives smaller than // a size defined by SMALLEST_ADVANCED_FORMAT, and 8-sector alignment for // larger drives with 512-byte sectors. -int DiskIO::FindAlignment(void) { - int err, result; +uint32_t DiskIO::FindAlignment(void) { + int err; + uint32_t result; if ((GetBlockSize() == 512) && (DiskSize(&err) >= SMALLEST_ADVANCED_FORMAT)) { - result = 8; // play it safe; align for 4096-byte sectors + result = DEFAULT_ALIGNMENT; // play it safe; align for 4096-byte sectors } else { result = 1; // unusual sector size; assume it's the real physical size } // if/else @@ -35,10 +35,6 @@ using namespace std; -// Below constant corresponds to an 800GB disk -- a somewhat arbitrary -// cutoff -#define SMALLEST_ADVANCED_FORMAT UINT64_C(1677721600) - /*************************************** * * * DiskIO class and related structures * @@ -71,7 +67,7 @@ class DiskIO { int Write(void* buffer, int numBytes); void DiskSync(void); // resync disk caches to use new partitions int GetBlockSize(void); - int FindAlignment(void); + uint32_t FindAlignment(void); int FindAlignment(const string & filename); int IsOpen(void) {return isOpen;} int IsOpenForWrite(void) {return openForWrite;} @@ -458,7 +458,7 @@ important filesystem data structures can span physical sectors on the disk. To minimize such problems, GPT fdisk aligns the start of partitions on the boundary of presumed physical sectors. You can set the number of logical sectors per physical sector with this option. The default is 1 on disks -smaller than 800GB and 8 on larger disks. +smaller than 596 GiB and 8 on larger disks with 512\-byte logical sectors. .TP .B m @@ -318,6 +318,7 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { uint32_t pn, temp1, temp2; int goOn = 1; GUIDData aGUID; + ostringstream prompt; do { cout << "\nExpert command (? for help): "; @@ -355,8 +356,10 @@ void ExpertsMenu(string filename, GPTDataTextUI* theGPT) { theGPT->ShowDetails(); break; case 'l': case 'L': - temp1 = GetNumber(1, 128, 8, (string) - "Enter the sector alignment value (1-128, default = 8): "); + prompt.seekp(0); + prompt << "Enter the sector alignment value (1-" << MAX_ALIGNMENT << ", default = " + << DEFAULT_ALIGNMENT << "): "; + temp1 = GetNumber(1, MAX_ALIGNMENT, DEFAULT_ALIGNMENT, prompt.str()); theGPT->SetAlignment(temp1); break; case 'm': case 'M': @@ -14,6 +14,7 @@ #include <stdint.h> #include <fcntl.h> #include <string.h> +#include <math.h> #include <time.h> #include <sys/stat.h> #include <errno.h> @@ -641,6 +642,7 @@ int GPTData::LoadPartitions(const string & deviceFilename) { if (allOK) CheckGPTSize(); myDisk.Close(); + ComputeAlignment(); } else { allOK = 0; } // if/else @@ -1116,20 +1118,20 @@ int GPTData::LoadGPTBackup(const string & filename) { if (!LoadPartitionTable(mainHeader, backupFile, (uint64_t) (3 - shortBackup))) cerr << "Warning! Read error " << errno << " loading partition table; strange behavior now likely!\n"; - } else { allOK = 0; } // if/else + // Something went badly wrong, so blank out partitions + if (allOK == 0) { + cerr << "Improper backup file! Clearing all partition data!\n"; + ClearGPTData(); + protectiveMBR.MakeProtectiveMBR(); + } // if } else { allOK = 0; cerr << "Unable to open file " << filename << " for reading! Aborting!\n"; } // if/else - // Something went badly wrong, so blank out partitions - if (allOK == 0) { - ClearGPTData(); - protectiveMBR.MakeProtectiveMBR(); - } // if return allOK; } // GPTData::LoadGPTBackup() @@ -2123,6 +2125,60 @@ int GPTData::IsFreePartNum(uint32_t partNum) { return retval; } // GPTData::IsFreePartNum() + +/*********************************************************** + * * + * Change how functions work or return information on them * + * * + ***********************************************************/ + +// Set partition alignment value; partitions will begin on multiples of +// the specified value +void GPTData::SetAlignment(uint32_t n) { + uint32_t l2; + + sectorAlignment = n; + l2 = (uint32_t) log2(n); + if (PowerOf2(l2) != n) + cout << "Information: Your alignment value is not a power of 2.\n"; +} // GPTData::SetAlignment() + +// Compute sector alignment based on the current partitions (if any). Each +// partition's starting LBA is examined, and if it's divisible by a power-of-2 +// value less than the maximum found so far (or 2^31 for the first partition +// found), then the alignment value is adjusted down. If the computed +// alignment is less than 8 and the disk is bigger than SMALLEST_ADVANCED_FORMAT, +// resets it to 8. This is a safety measure for WD Advanced Format and +// similar drives. If no partitions are defined, the alignment value is set +// to DEFAULT_ALIGNMENT (2048). The result is that new drives are aligned to +// 2048-sector multiples but the program won't complain about other alignments +// on existing disks unless a smaller-than-8 alignment is used on small disks +// (as safety for WD Advanced Format drives). +// Returns the computed alignment value. +uint32_t GPTData::ComputeAlignment(void) { + uint32_t i = 0, found, exponent = 31; + uint64_t align = DEFAULT_ALIGNMENT; + + for (i = 0; i < mainHeader.numParts; i++) { + if (partitions[i].IsUsed()) { + found = 0; + while (!found) { + align = PowerOf2(exponent); + if ((partitions[i].GetFirstLBA() % align) == 0) { + found = 1; + } else { + exponent--; + } // if/else + } // while + } // if + } // for + if ((align < 8) && (diskSize >= SMALLEST_ADVANCED_FORMAT)) + align = 8; +// cout << "Setting alignment to " << align << "\n"; + SetAlignment(align); + return align; +} // GPTData::ComputeAlignment() + /******************************** * * * Endianness support functions * @@ -16,7 +16,7 @@ #ifndef __GPTSTRUCTS #define __GPTSTRUCTS -#define GPTFDISK_VERSION "0.6.5" +#define GPTFDISK_VERSION "0.6.6-pre1" // Constants used by GPTData::PartsToMBR(). MBR_EMPTY must be the lowest- // numbered value to refer to partition numbers. (Most will be 0 or positive, @@ -24,6 +24,16 @@ #define MBR_EFI_GPT -1 #define MBR_EMPTY -2 +// Default values for sector alignment +#define DEFAULT_ALIGNMENT 2048 +#define MAX_ALIGNMENT 32768 + +// Below constant corresponds to an 800GB disk -- a somewhat arbitrary +// cutoff +//#define SMALLEST_ADVANCED_FORMAT UINT64_C(1677721600) +// Now ~596GiB (640MB), since WD has introduced a smaller Advanced Format drive +#define SMALLEST_ADVANCED_FORMAT UINT64_C(1250263728) + using namespace std; class PartNotes; @@ -79,7 +89,7 @@ protected: int secondPartsCrcOk; int apmFound; // set to 1 if APM detected int bsdFound; // set to 1 if BSD disklabel detected in MBR - int sectorAlignment; // Start & end partitions at multiples of sectorAlignment + uint32_t sectorAlignment; // Start & end partitions at multiples of sectorAlignment int beQuiet; WhichToUse whichWasUsed; @@ -177,8 +187,9 @@ public: int IsFreePartNum(uint32_t partNum); // Change how functions work, or return information on same - void SetAlignment(int n) {sectorAlignment = n;} - int GetAlignment(void) {return sectorAlignment;} + void SetAlignment(uint32_t n); + uint32_t ComputeAlignment(void); // Set alignment based on current partitions + uint32_t GetAlignment(void) {return sectorAlignment;} void JustLooking(int i = 1) {justLooking = i;} void BeQuiet(int i = 1) {beQuiet = i;} WhichToUse WhichWasUsed(void) {return whichWasUsed;} @@ -85,7 +85,7 @@ int MBRData::ReadMBRData(const string & deviceFilename) { canDeleteMyDisk = 1; } // if if (myDisk->OpenForRead(deviceFilename)) { - ReadMBRData(myDisk); + allOK = ReadMBRData(myDisk); } else { allOK = 0; } // if @@ -101,7 +101,7 @@ int MBRData::ReadMBRData(const string & deviceFilename) { // Note that any extended partition(s) present will be explicitly stored // in the partitions[] array, along with their contained partitions; the // extended container partition(s) should be ignored by other functions. -void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) { +int MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) { int allOK = 1, i, j, logicalNum; int err = 1; TempMBR tempMBR; @@ -201,6 +201,7 @@ void MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) { } // for } // if (hybrid detection code) } // no initial error + return allOK; } // MBRData::ReadMBRData(DiskIO * theDisk, int checkBlockSize) // This is a recursive function to read all the logical partitions, following the @@ -89,7 +89,7 @@ public: // File I/O functions... int ReadMBRData(const string & deviceFilename); - void ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1); + int ReadMBRData(DiskIO * theDisk, int checkBlockSize = 1); // ReadLogicalPart() returns last partition # read to logicals[] array, // or -1 if there was a problem.... int ReadLogicalPart(uint32_t extendedStart, uint32_t diskOffset, @@ -149,10 +149,10 @@ sibling. Options available in \fBsgdisk\fR are: .B \-a, \-\-set\-alignment=value Set the sector alignment multiple. GPT fdisk aligns the start of partitions to sectors that are multiples of this value, which defaults to 8 on disks -larger than 800GiB with 512\-byte sectors and to 1 on smaller disks or those -with non\-512\-byte sectors. This alignment value is necessary to obtain -optimum performance with Western Digital Advanced Format and similar drives -with larger physical than logical sector sizes. +larger than 596 GiB with 512\-byte logical sectors and to 1 on smaller +disks or those with non\-512\-byte sectors. This alignment value is +necessary to obtain optimum performance with Western Digital Advanced +Format and similar drives with larger physical than logical sector sizes. .TP .B \-b, \-\-backup=file @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { GPTData theGPT; int opt, numOptions = 0, saveData = 0, neverSaveData = 0; int partNum = 0, deletePartNum = 0, infoPartNum = 0, bsdPartNum = 0, saveNonGPT = 1; - int alignment = 8, retval = 0, pretend = 0; + int alignment = DEFAULT_ALIGNMENT, retval = 0, pretend = 0; unsigned int hexCode; uint32_t tableSize = 128; uint64_t startSector, endSector; @@ -246,11 +246,11 @@ void ReverseBytes(void* theValue, int numBytes) { // Compute (2 ^ value). Given the return type, value must be 63 or less. // Used in some bit-fiddling functions -uint64_t PowerOf2(int value) { +uint64_t PowerOf2(uint32_t value) { uint64_t retval = 1; - int i; + uint32_t i; - if ((value < 64) && (value >= 0)) { + if (value < 64) { for (i = 0; i < value; i++) { retval *= 2; } // for @@ -55,6 +55,6 @@ string BytesToSI(uint64_t size); unsigned char StrToHex(const string & input, unsigned int position); int IsLittleEndian(void); // Returns 1 if CPU is little-endian, 0 if it's big-endian void ReverseBytes(void* theValue, int numBytes); // Reverses byte-order of theValue -uint64_t PowerOf2(int value); +uint64_t PowerOf2(uint32_t value); #endif |