Added code to read physical block size on Linux.
This commit is contained in:
6
NEWS
6
NEWS
@@ -1,6 +1,12 @@
|
||||
1.0.2 (?/??/2017):
|
||||
------------------
|
||||
|
||||
- GPT fdisk can now report both the physical and logical sector sizes of
|
||||
disks, but only on 2.6.32 and later Linux kernels. The verify feature now
|
||||
uses the larger of the set alignment and physical/logical block sizes for
|
||||
testing alignment, and setting alignment to something other than an exact
|
||||
multiple of the physical/logical block size results in a warning.
|
||||
|
||||
- Addition of new verification checks, mostly (but not exclusively) related
|
||||
to the new j/-j/--move-main-table option.
|
||||
|
||||
|
||||
@@ -177,6 +177,27 @@ int DiskIO::GetBlockSize(void) {
|
||||
return (blockSize);
|
||||
} // DiskIO::GetBlockSize()
|
||||
|
||||
// Returns the physical block size of the device, if possible. If this is
|
||||
// not supported, or if an error occurs, this function returns 0.
|
||||
// TODO: Get this working in more OSes than Linux.
|
||||
int DiskIO::GetPhysBlockSize(void) {
|
||||
int err = -1, physBlockSize = 0;
|
||||
|
||||
// If disk isn't open, try to open it....
|
||||
if (!isOpen) {
|
||||
OpenForRead();
|
||||
} // if
|
||||
|
||||
if (isOpen) {
|
||||
#if defined __linux__ && !defined(EFI)
|
||||
err = ioctl(fd, BLKPBSZGET, &physBlockSize);
|
||||
#endif
|
||||
} // if (isOpen)
|
||||
if (err == -1)
|
||||
physBlockSize = 0;
|
||||
return (physBlockSize);
|
||||
} // DiskIO::GetPhysBlockSize(void)
|
||||
|
||||
// Returns the number of heads, according to the kernel, or 255 if the
|
||||
// correct value can't be determined.
|
||||
uint32_t DiskIO::GetNumHeads(void) {
|
||||
|
||||
@@ -144,6 +144,13 @@ int DiskIO::GetBlockSize(void) {
|
||||
return (blockSize);
|
||||
} // DiskIO::GetBlockSize()
|
||||
|
||||
// In theory, returns the physical block size. In practice, this is only
|
||||
// supported in Linux, as of yet.
|
||||
// TODO: Get this working in Windows.
|
||||
int DiskIO:GetPhysBlockSize(void) {
|
||||
return 0;
|
||||
} // DiskIO::GetPhysBlockSize()
|
||||
|
||||
// Returns the number of heads, according to the kernel, or 255 if the
|
||||
// correct value can't be determined.
|
||||
uint32_t DiskIO::GetNumHeads(void) {
|
||||
|
||||
1
diskio.h
1
diskio.h
@@ -71,6 +71,7 @@ class DiskIO {
|
||||
int Write(void* buffer, int numBytes);
|
||||
int DiskSync(void); // resync disk caches to use new partitions
|
||||
int GetBlockSize(void);
|
||||
int GetPhysBlockSize(void);
|
||||
uint32_t GetNumHeads(void);
|
||||
uint32_t GetNumSecsPerTrack(void);
|
||||
int IsOpen(void) {return isOpen;}
|
||||
|
||||
29
gpt.cc
29
gpt.cc
@@ -64,6 +64,7 @@ static inline uint32_t log2_32(uint32_t v) {
|
||||
// Default constructor
|
||||
GPTData::GPTData(void) {
|
||||
blockSize = SECTOR_SIZE; // set a default
|
||||
physBlockSize = 0; // 0 = can't be determined
|
||||
diskSize = 0;
|
||||
partitions = NULL;
|
||||
state = gpt_valid;
|
||||
@@ -125,6 +126,7 @@ GPTData & GPTData::operator=(const GPTData & orig) {
|
||||
protectiveMBR = orig.protectiveMBR;
|
||||
device = orig.device;
|
||||
blockSize = orig.blockSize;
|
||||
physBlockSize = orig.physBlockSize;
|
||||
diskSize = orig.diskSize;
|
||||
state = orig.state;
|
||||
justLooking = orig.justLooking;
|
||||
@@ -166,7 +168,7 @@ GPTData & GPTData::operator=(const GPTData & orig) {
|
||||
// problems identified.
|
||||
int GPTData::Verify(void) {
|
||||
int problems = 0, alignProbs = 0;
|
||||
uint32_t i, numSegments;
|
||||
uint32_t i, numSegments, testAlignment = sectorAlignment;
|
||||
uint64_t totalFree, largestSegment;
|
||||
|
||||
// First, check for CRC errors in the GPT data....
|
||||
@@ -355,10 +357,15 @@ int GPTData::Verify(void) {
|
||||
|
||||
// Check that partitions are aligned on proper boundaries (for WD Advanced
|
||||
// Format and similar disks)....
|
||||
if ((physBlockSize != 0) && (blockSize != 0))
|
||||
testAlignment = physBlockSize / blockSize;
|
||||
testAlignment = max(testAlignment, sectorAlignment);
|
||||
if (testAlignment == 0) // Should not happen; just being paranoid.
|
||||
testAlignment = sectorAlignment;
|
||||
for (i = 0; i < numParts; i++) {
|
||||
if ((partitions[i].IsUsed()) && (partitions[i].GetFirstLBA() % sectorAlignment) != 0) {
|
||||
if ((partitions[i].IsUsed()) && (partitions[i].GetFirstLBA() % testAlignment) != 0) {
|
||||
cout << "\nCaution: Partition " << i + 1 << " doesn't begin on a "
|
||||
<< sectorAlignment << "-sector boundary. This may\nresult "
|
||||
<< testAlignment << "-sector boundary. This may\nresult "
|
||||
<< "in degraded performance on some modern (2009 and later) hard disks.\n";
|
||||
alignProbs++;
|
||||
} // if
|
||||
@@ -722,6 +729,7 @@ int GPTData::SetDisk(const string & deviceFilename) {
|
||||
// store disk information....
|
||||
diskSize = myDisk.DiskSize(&err);
|
||||
blockSize = (uint32_t) myDisk.GetBlockSize();
|
||||
physBlockSize = (uint32_t) myDisk.GetPhysBlockSize();
|
||||
} // if
|
||||
protectiveMBR.SetDisk(&myDisk);
|
||||
protectiveMBR.SetDiskSize(diskSize);
|
||||
@@ -801,6 +809,7 @@ int GPTData::LoadPartitions(const string & deviceFilename) {
|
||||
// store disk information....
|
||||
diskSize = myDisk.DiskSize(&err);
|
||||
blockSize = (uint32_t) myDisk.GetBlockSize();
|
||||
physBlockSize = (uint32_t) myDisk.GetPhysBlockSize();
|
||||
device = deviceFilename;
|
||||
PartitionScan(); // Check for partition types, load GPT, & print summary
|
||||
|
||||
@@ -1478,6 +1487,8 @@ void GPTData::DisplayGPTData(void) {
|
||||
cout << "Disk " << device << ": " << diskSize << " sectors, "
|
||||
<< BytesToIeee(diskSize, blockSize) << "\n";
|
||||
cout << "Logical sector size: " << blockSize << " bytes\n";
|
||||
if (physBlockSize > 0)
|
||||
cout << "Physical sector size: " << physBlockSize << " bytes\n";
|
||||
cout << "Disk identifier (GUID): " << mainHeader.diskGUID << "\n";
|
||||
cout << "Partition table holds up to " << numParts << " entries\n";
|
||||
cout << "Main partition table begins at sector " << mainHeader.partitionEntriesLBA
|
||||
@@ -2334,10 +2345,18 @@ int GPTData::IsUsedPartNum(uint32_t partNum) {
|
||||
// Set partition alignment value; partitions will begin on multiples of
|
||||
// the specified value
|
||||
void GPTData::SetAlignment(uint32_t n) {
|
||||
if (n > 0)
|
||||
if (n > 0) {
|
||||
sectorAlignment = n;
|
||||
else
|
||||
if ((physBlockSize > 0) && (n % (physBlockSize / blockSize) != 0)) {
|
||||
cout << "Warning: Setting alignment to a value that does not match the disk's\n"
|
||||
<< "physical block size! Performance degradation may result!\n"
|
||||
<< "Physical block size = " << physBlockSize << "\n"
|
||||
<< "Logical block size = " << blockSize << "\n"
|
||||
<< "Optimal alignment = " << physBlockSize / blockSize << " or multiples thereof.\n";
|
||||
} // if
|
||||
} else {
|
||||
cerr << "Attempt to set partition alignment to 0!\n";
|
||||
} // if/else
|
||||
} // GPTData::SetAlignment()
|
||||
|
||||
// Compute sector alignment based on the current partitions (if any). Each
|
||||
|
||||
5
gpt.h
5
gpt.h
@@ -68,8 +68,9 @@ protected:
|
||||
MBRData protectiveMBR;
|
||||
string device; // device filename
|
||||
DiskIO myDisk;
|
||||
uint32_t blockSize; // device block size
|
||||
uint64_t diskSize; // size of device, in blocks
|
||||
uint32_t blockSize; // device logical block size
|
||||
uint32_t physBlockSize; // device physical block size (or 0 if it can't be determined)
|
||||
uint64_t diskSize; // size of device, in logical blocks
|
||||
GPTValidity state; // is GPT valid?
|
||||
int justLooking; // Set to 1 if program launched with "-l" or if read-only
|
||||
int mainCrcOk;
|
||||
|
||||
Reference in New Issue
Block a user