Bug 1344102

Summary: fdisk does not handle 4kN devices correctly in 'Blocks' calculation
Product: Red Hat Enterprise Linux 7 Reporter: Dwight (Bud) Brown <bubrown>
Component: util-linuxAssignee: Karel Zak <kzak>
Status: CLOSED ERRATA QA Contact: Radka Brychtova <rskvaril>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 7.2CC: capsicumw, kvolny, loberman, rskvaril
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: util-linux-2.23.2-36.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-08-01 21:41:11 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1380361, 1385242, 1393867, 1400961    
Attachments:
Description Flags
change blocks calculation to use unsigned long none

Description Dwight (Bud) Brown 2016-06-08 18:43:17 UTC
Description of problem:
fdisk has well known limits of 32bits for starting LBA and number of sectors in a partition.  With 512 and 512e this results in the well known 2.14TB device size support limit.  With 4kN devices, with 4096 bytes per sector, the max size device should be ~16TB.  When creating partions of size <4095G in size, the resulting fdisk data for "Blocks" field is correct:

# fdisk -uc /dev/sdi
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Last sector, +sectors or +size{K,M,G} (256-1465130645, default 1465130645): +4095G
Partition 1 of type Linux and of size 4 TiB is set

Command (m for help): p

Disk /dev/sdi: 6001.2 GB, 6001175126016 bytes, 1465130646 sectors
Units = sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x0001a19e

   Device Boot      Start         End      Blocks   Id  System
/dev/sdi1             256  1073479935  4293918720   83  Linux

>> correct (1k) 'Blocks' calculated


Last sector, +sectors or +size{K,M,G} (256-1465130645, default 1465130645): +4096G
Partition 1 of type Linux and of size 4 TiB is set

Command (m for help): p

Disk /dev/sdi: 6001.2 GB, 6001175126016 bytes, 1465130646 sectors
Units = sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x0001a19e

   Device Boot      Start         End      Blocks   Id  System
/dev/sdi1             256  1073742079           0   83  Linux

>> incorrect (1k) 'Blocks' calculated

expert mode shows the expected data:

Command (m for help): x

Expert command (m for help): p

Disk /dev/sdi: 42 heads, 63 sectors, 91200 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00   4   5    0   6   4  195        256 1073479680 83
 2 00   0   0    0   0   0    0          0          0 00
 3 00   0   0    0   0   0    0          0          0 00
 4 00   0   0    0   0   0    0          0          0 00



Version-Release number of selected component (if applicable):
util-linux-2.23.2-26.el7_2.2.x86_64

How reproducible:


Steps to Reproduce:
1.
2.
3.

Actual results:


Expected results:


Additional info:

int dos_list_table(struct fdisk_context *cxt,
                    int xtra  __attribute__ ((__unused__)))
{
:
                        unsigned int psects = get_nr_sects(p);
                        unsigned int pblocks = psects;
>>> pblocks in unsigned int...
                        unsigned int podd = 0;
                        struct fdisk_parttype *type =
                                        fdisk_get_parttype_from_code(cxt, p->sys_ind);

                        if (cxt->sector_size < 1024) {
                                pblocks /= (1024 / cxt->sector_size);
                                podd = psects % (1024 / cxt->sector_size);
                        }
                        if (cxt->sector_size > 1024)
                                pblocks *= (cxt->sector_size / 1024);
                        printf(
                            "%s  %c %11lu %11lu %11lu%c  %2x  %s\n",
>>> but printed as unsigned long
                        partname(cxt->dev_path, i+1, w+2),
/* boot flag */         !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
                        ? '*' : '?',
/* start */             (unsigned long) cround(cxt, get_partition_start(pe)),
/* end */               (unsigned long) cround(cxt, get_partition_start(pe) + psects
                                - (psects ? 1 : 0)),
/* odd flag on end */   (unsigned long) pblocks, podd ? '+' : ' ',
>> so cast on the printf line
/* type id */           p->sys_ind,
/* type name */         type ? type->name : _("Unknown"));
                        check_consistency(cxt, p, i);
                        fdisk_warn_alignment(cxt, get_partition_start(pe), i);
                }

pblocks probably should be declared unsigned long (64 bits) vs just 32.

Comment 1 Dwight (Bud) Brown 2016-06-10 18:02:02 UTC
Created attachment 1166706 [details]
change blocks calculation to use unsigned long

with one line patch, output is now correct/as expected:

# fdisk /dev/sdi
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p

Disk /dev/sdi: 6001.2 GB, 6001175126016 bytes, 1465130646 sectors
Units = sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x0001a19e

   Device Boot      Start         End      Blocks   Id  System

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (256-1465130645, default 256): 
Using default value 256
Last sector, +sectors or +size{K,M,G} (256-1465130645, default 1465130645): 
Using default value 1465130645
Partition 1 of type Linux and of size 5.5 TiB is set

Command (m for help): p

Disk /dev/sdi: 6001.2 GB, 6001175126016 bytes, 1465130646 sectors
Units = sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x0001a19e

   Device Boot      Start         End      Blocks   Id  System
/dev/sdi1             256  1465130645  5860521560   83  Linux

Command (m for help):

Comment 2 Dwight (Bud) Brown 2016-06-10 18:03:07 UTC
With original test case of +4096G:

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (256-1465130645, default 256): 
Using default value 256
Last sector, +sectors or +size{K,M,G} (256-1465130645, default 1465130645): +4096G
Partition 1 of type Linux and of size 4 TiB is set

Command (m for help): p

Disk /dev/sdi: 6001.2 GB, 6001175126016 bytes, 1465130646 sectors
Units = sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0x0001a19e

   Device Boot      Start         End      Blocks   Id  System
/dev/sdi1             256  1073742079  4294967296   83  Linux

Comment 3 capsicumw 2016-07-19 21:30:44 UTC
I have a similar issue using a 750GB drive, basic mode prints the wrong number of blocks, expert mode prints the correct number of blocks. 
It appears to be printing KiB rather than blocks.

$fdisk -v
fdisk from util-linux 2.23.2

$fdisk /dev/sde

Command (m for help): p

Disk /dev/sde: 750.2 GB, 750156374016 bytes, 1465149168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0xe861ed1b

   Device Boot      Start         End      Blocks   Id  System
/dev/sde1   *        2048      409599      203776    7  HPFS/NTFS/exFAT
/dev/sde2          409600   210124799   104857600    7  HPFS/NTFS/exFAT
/dev/sde4      1460988656  1465149167     2080256    c  W95 FAT32 (LBA)


Command (m for help): x

Expert command (m for help): p

Disk /dev/sde: 255 heads, 63 sectors, 91201 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 80  32  33    0 126  37   25       2048     407552 07
 2 00 126  38   25 169  18  791     409600  209715200 07
 3 00   0   0    0   0   0    0          0          0 00
 4 00  86   9  830  80  63   65 1460988656    4160512 0c

Comment 4 capsicumw 2016-07-19 21:53:17 UTC
And this is how I created the partition. The size of sde4, as I calculate it, should be 4160512 units of 512 bytes. 
  
Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): 
Using default response p
Partition number (2-4, default 2): 4
First sector (409600-1465149167, default 409600): 1460988656
Last sector, +sectors or +size{K,M,G} (1460988656-1465149167, default 1465149167): 
Using default value 1465149167
Partition 4 of type Linux and of size 2 GiB is set

Command (m for help): p

Disk /dev/sde: 750.2 GB, 750156374016 bytes, 1465149168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk label type: dos
Disk identifier: 0xe861ed1b

   Device Boot      Start         End      Blocks   Id  System
/dev/sde1   *        2048      409599      203776    7  HPFS/NTFS/exFAT
/dev/sde4      1460988656  1465149167     2080256   83  Linux

Command (m for help): t
...

Comment 5 capsicumw 2016-07-19 22:32:19 UTC
Also does not appear to properly report 512 byte disks. Again it seems to be reporting KiB not blocks. 

$fdisk /dev/sdd
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p

Disk /dev/sdd: 500.1 GB, 500107862016 bytes, 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xe861ed1b

   Device Boot      Start         End      Blocks   Id  System
/dev/sdd1   *        2048      409599      203776    7  HPFS/NTFS/exFAT
/dev/sdd2          409600   926574591   463082496    7  HPFS/NTFS/exFAT
/dev/sdd3       926574592   968450047    20937728    7  HPFS/NTFS/exFAT
/dev/sdd4       968450048   976771071     4160512    c  W95 FAT32 (LBA)

But when I do a raw partition copy I get 8321024 blocks(exactly double what f disk reports)
$dd if=/dev/sdd4 of=./part4dd bs=512
8321024+0 records in
8321024+0 records out
4260364288 bytes (4.3 GB) copied, 219.213 s, 19.4 MB/s

Comment 6 Karel Zak 2016-07-20 08:24:32 UTC
(In reply to capsicumw from comment #3)
> I have a similar issue using a 750GB drive, basic mode prints the wrong
> number of blocks, expert mode prints the correct number of blocks. 
> It appears to be printing KiB rather than blocks.

It's number of 1KiB blocks (!= number of sectors). This is not a bug, but a strange feature.

The bug reported by Dwight (comment #0) is about unsigned int usage.


Note that fdisk in Fedora/Upstream (and will be in RHEL8) does not use the ugly  "Blocks" column any more. It uses "Sectors" and "Size" to make it more user friendly.

Comment 13 errata-xmlrpc 2017-08-01 21:41:11 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2017:2186