Why fdisk adds half kibibyte sometimes?

0

I'm trying to partition a 1440 KiB floppy disk image using fdisk (util-linux, v2.31.1).

However, the tool is seemingly adding a 512-byte sector, no matter what units I use, and I can't tell why.


This is what I did:

Created a new DOS disklabel [...]

Command (m for help): n
[...]
First sector (1-2879, default 1): 2048
Last sector, +sectors or +size{K,M,G,T,P} (63-2879, default 2879): +1K

Created a new partition 1 of type 'Linux' and of size 1.5 KiB.

Whoa! 1.5 KiB!?

I tried using the sector count, getting the same result:

Last sector, +sectors [...]: +2

Created a new partition 1 of type 'Linux' and of size 1.5 KiB.

Now, if I use a file big enough, fdisk behaves differently with the first notation:

First sector (2048-131071, default 2048): 2048
Last sector, [...]: +1K

Created a new partition 1 of type 'Linux' and of size 1 KiB.

Not so with the second one:

Last sector, +sectors [...]: +2

Created a new partition 1 of type 'Linux' and of size 1.5 KiB.

Is this the expected behaviour? I guess it is, but why?

NiNEngine

Posted 2019-08-16T17:07:46.843

Reputation: 3

1Is it trying to align to the cylinder or to the MB? – K7AAY – 2019-08-16T21:30:54.833

"I'm trying to partition a 1440 KiB floppy disk image" -- Floppy disks are not supposed to be partitioned. The MBR and partition table is for hard disks (and SSDs). – sawdust – 2019-08-16T21:45:43.567

@sawdust Thanks for pointing that. Even so, they have a bootsector, and I'm using the same image for a floppy and a USB stick. I mentioned it was a 'floppy disk image' to explicit where the size of '1440 KiB' comes from. Using a floppy disk or a hard drive, my question remains: fdisk behaves differently because the size is small, not because it is a 'floppy disk image' (I tried with arbitrary sizes). – NiNEngine – 2019-08-17T10:22:49.240

@K7AAY It would be crazy if I tried to align to the MiB, given I have just ~1.4. I didn't decided how to align the partitions yet. But as you probably noticed, I aligned to the MiB in the example because with a larger image fdisk does not allow to choose a sector lower than 2048 (and I wanted to show how the tool behaves differently under the same input). If you try with 63, or 8, or whatever, it will do the same. – NiNEngine – 2019-08-17T10:27:40.337

"Is this the expected behaviour?" -- If you can identify the version that you're using, then you try to find the source code. Back in the day the starting sector of a partition would be aligned to the start of a cylinder. Sometimes a "guard" cylinder was added (and wasted) to physically separate partitions to satisfy paranoid operators who worried about data corruption. When zoned-bit recording was introduced and drive geometry became not-fixed and unknown externally, the megabyte alignment was adopted. IMO if you don't know the drive geometry, then partition alignment is not needed. – sawdust – 2019-08-18T00:14:07.843

@sawdust However, this is not happening especifically when the code is aligned, as I showed. Anyways, increasing the count by 512 bytes arbirarily seems not a way of aligning to cylinders nor MiB boundaries... isn't it? – NiNEngine – 2019-08-18T09:09:58.370

Partition (it's not "code") alignment (and guard cylinder/track/sectors) would be applied at the start of a new partition. That is, sectors would be reserved "in front of" the new partition, and not be part of any partition. Those sectors would be unallocated, essentially wasted, and cannot be used (by any filesystem). Alignment does not affect the size of the new partition. The issue you describe relates to partition size, and not alignment. The "extra" sector is at the end of the new partition. I suggest you look at the source code for a possible explanation. – sawdust – 2019-08-19T00:55:24.877

Answers

0

However, the tool is seemingly adding a 512-byte sector, no matter what units I use,
...
Now, if I use a file big enough, fdisk behaves differently with the first notation:
...
Is this the expected behaviour?

Apparently yes, and seems to be a bug of the "plus one" variety.
When you specify "+N" or "+" (instead of an absolute sector number) for the last sector, the utility seems to utilize this quantity as the number of sectors in (or the size of) the new partition, and adds this number to the starting sector number.

In other words, the proper calculation should be

<last sector> = <start sector> + <sector count> - 1  

But apparently the utility neglects to subtract one sector from this total to adjust the count to a displacement.

When the size of the new partition is small (i.e. just two sectors), then this "plus one" bug is quite obvious.
The actual source code needs to be inspected to determine why there is a correlation/dependency on the available size of the device.

The workaround to this apparent bug is to explicitly specify the last sector using a sector number.
For example if the starting sector is 2048, and the partition size is to be 1K bytes, then specify the last sector as 2049.


Since this "extra" sector is at the end of the new partition, this issue would be unrelated to partition alignment.
Partition alignment (and guard cylinder/track/sectors) would be applied to modify the start of a new partition.
That is, sectors would be reserved "in front of" the new partition, and not be part of any partition.
Those sectors would be unallocated, essentially wasted, and cannot be used (by any filesystem).
Alignment does not affect the size of the new partition.
The issue you describe relates to partition size, and not its alignment.


I'm trying to partition a 1440 KiB floppy disk image

Floppy disks are not supposed to be partitioned. There is just a boot sector.
The MBR and partition table is for hard disks (and SSDs).


ADDENDUM

Apparently there is some code in util-linux-2.31.1/libfdisk/src/dos.c that tries to adjust the end of the partition so that the next partition will be aligned!

static int add_partition(struct fdisk_context *cxt, size_t n,
             struct fdisk_partition *pa)
{
    ...

    if (isrel && stop - start < (cxt->grain / fdisk_get_sector_size(cxt))) {
        /* Don't try to be smart on very small partitions and don't align so small sizes */
        isrel = 0;
        if (stop > start)
            stop -= 1;
        DBG(LABEL, ul_debug("DOS: don't align end of tiny partition [start=%ju, stop=%ju, grain=%lu]",
            (uintmax_t)start,  (uintmax_t)stop, cxt->grain));
    }

    if (stop < limit && isrel && alignment_required(cxt)) {
        /* the last sector has not been exactly requested (but
         * defined by +size{K,M,G} convention), so be smart and
         * align the end of the partition. The next partition
         * will start at phy.block boundary.
         */
        stop = fdisk_align_lba_in_range(cxt, stop, start, limit);
        if (stop > start)
            stop -= 1;
        if (stop > limit)
            stop = limit;
        DBG(LABEL, ul_debug("DOS: aligned stop: %ju", (uintmax_t) stop));
    }

Some debug output (i.e. a version of the utility with debugging enabled) would help clarify what is going on.

sawdust

Posted 2019-08-16T17:07:46.843

Reputation: 14 697

Thank you for your detailed answer. Well, let me point that I didn't raise the alignment issue. But... I'm not convinced about the argument about it is totally unrelated to the size. First, it seems related given your own addendum. Second, if the partition does not end at a aligned boundary, the system must handle the last block specially, which seems not too clean. I'm still checking things... – NiNEngine – 2019-08-21T16:14:32.937

I confirmed it is an issue. Answer accepted. – NiNEngine – 2019-08-22T16:09:08.053