I have a dread sense that I'm going to regret asking questions, but I'm going to do it anyway, because hey, what the hell, I can always drink bleach.
On Fri, 24 Apr 2020 19:09:53 -0600, Theo de Raadt wrote: [snip] > > Reality hasn't changed. A sector is still 512 bytes, and > disklabel has to fit in it. I doubt that it will improve anything, but some of us (well, at least me) got intrigued by your answers and the history (I thought that sixteen was chosen because four bits and it was significant for that reason, but that was clearly leaping to the same sorts of conclusions from a different direction than disk size, which was embarrassing). So I went and had a look at the struct definition. Some summary for misc-readers who are not Theo or other devs; y'all skip over me doing base-level analysis, 'kay? Otherwise you'll be rilly annoyed with me for seeming to talk down to you, but this is for the other folks who responded on thread without looking at disklabel.h. /usr/src/sys/disklabel.h, the struct disklabel is the bit in question: struct disklabel { u_int32_t d_magic; /* the magic number */ u_int16_t d_type; /* drive type */ u_int16_t d_subtype; /* controller/d_type specific */ char d_typename[16]; /* type name, e.g. "eagle" */ char d_packname[16]; /* pack identifier */ /* disk geometry: */ u_int32_t d_secsize; /* # of bytes per sector */ u_int32_t d_nsectors; /* # of data sectors per track */ u_int32_t d_ntracks; /* # of tracks per cylinder */ u_int32_t d_ncylinders; /* # of data cylinders per unit */ u_int32_t d_secpercyl; /* # of data sectors per cylinder */ u_int32_t d_secperunit; /* # of data sectors (low part) */ u_char d_uid[8]; /* Unique label identifier. */ /* * Alternate cylinders include maintenance, replacement, configuration * description areas, etc. */ u_int32_t d_acylinders; /* # of alt. cylinders per unit */ /* hardware characteristics: */ u_int16_t d_bstarth; /* start of useable region (high part) */ u_int16_t d_bendh; /* size of useable region (high part) */ u_int32_t d_bstart; /* start of useable region */ u_int32_t d_bend; /* end of useable region */ u_int32_t d_flags; /* generic flags */ #define NDDATA 5 u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */ u_int16_t d_secperunith; /* # of data sectors (high part) */ u_int16_t d_version; /* version # (1=48 bit addressing) */ #define NSPARE 4 u_int32_t d_spare[NSPARE]; /* reserved for future use */ u_int32_t d_magic2; /* the magic number (again) */ u_int16_t d_checksum; /* xor of data incl. partitions */ /* filesystem and partition information: */ u_int16_t d_npartitions; /* number of partitions in following */ u_int32_t d_bbsize; /* size of boot area at sn0, bytes */ u_int32_t d_sbsize; /* max size of fs superblock, bytes */ /* at this point, the struct as a whole occupies 160 bytes, in general metadata about the disklabel-as-a-whole, not any specific partition. next is partitions: */ struct partition { /* the partition table */ u_int32_t p_size; /* number of sectors (low part) */ u_int32_t p_offset; /* starting sector (low part) */ u_int16_t p_offseth; /* starting sector (high part) */ u_int16_t p_sizeh; /* number of sectors (high part) */ u_int8_t p_fstype; /* filesystem type, see below */ u_int8_t p_fragblock; /* encoded filesystem frag/block */ u_int16_t p_cpg; /* UFS: FS cylinders per group */ } d_partitions[MAXPARTITIONS]; /* actually may be more */ }; struct partition is 16 bytes, times MAXPARTITIONS. Note that MAXPARTITIONS isn't defined in this header; it's in the per-arch disklabel.h (/usr/src/arch/*/include/disklabel.h). On the other hand, at the top of the file is this: /* * The absolute maximum number of disk partitions allowed. * This is the maximum value of MAXPARTITIONS for which 'struct disklabel' * is <= DEV_BSIZE bytes long. If MAXPARTITIONS is greater than this, beware. */ #define MAXMAXPARTITIONS 22 #if MAXPARTITIONS > MAXMAXPARTITIONS #warn beware: MAXPARTITIONS bigger than MAXMAXPARTITIONS #endif Now, to cut to the chase, /usr/src/arch/*/include/disklabel.h all have "#define MAXPARTITIONS 16" (whitespace varies, but the number doesn't). So the standard/universal 16 partitions take up 256 bytes in the array of struct partition. Therefore: 160 + 256 = 416 (which is, of course, less than 512) The comment on MAXMAXPARTITIONS says that 22 is the utmost limit; 16*22 = 352. Add 352 to 160 and ta-da! 512. The limit, as repeated several times. Now for the question! If you're skipping over junior-dev-level analysis, here's where I switch to whining piteously. So, and I recognize that the answer might reasonably be "go read more code and figure it out yourself," a question for Theo and others if you have a moment: why couldn't an arch expand past sixteen? It seems, both from the math calculating struct size (which may be mistaken, in which case I apologize) and in the comment for MAXMAXPARTITIONS that more *are* possible. Even if part of the reason is to preserve space within the sector for future changes (for instance, to allow the size of the global part of the struct to increase to 176 or 192 bytes, effectively leaving reserved bits), couldn't MAXPARTITIONS increase to 20 on arches where us misc-readers are whining about it? No, I haven't a patch to offer. I'm not certain that increasing MAXPARTITIONS without any other changes would break things, but with a magic number in the disklabel, I'm guessing that there are expectations of the content elsewhere that may require additional changes. But the partitions array is final in its containing struct, which looks like design for later expansion. I'm also not asking that it be done, or that anyone do the research *for* me, I'm really just wondering if someone knows the answer off-hand. What are the obstacles to increasing MAXPARTITIONS to 20 on amd64? (chosen because it's the arch I'm using) Amy! -- Amelia A. Lewis amyzing {at} talsever.com Never imagine yourself not to be otherwise than what it might appear to others that what you were or might have been was not otherwise than what you had been would have appeared to them to be otherwise. -- The Duchess [Lewis Carroll]