Author Topic: DosDevIOCtl API references?  (Read 6656 times)

Dariusz Piatkowski

  • Hero Member
  • *****
  • Posts: 1317
  • Karma: +26/-0
    • View Profile
DosDevIOCtl API references?
« on: March 22, 2021, 04:49:28 pm »
Can someone point me to good references with whatever sample code one can find on the subject of DosDevIOCtl API?

I have the DEV Toolkit stuff here, along with a few OS/2 DEV books, but really they all seem to just re-hash what's in the Toolkit docs, which isn't much.

I am specifically asking because of the following: modifying DISKIO has allowed for greater range of device coverage (as far as the bigger numbers that newer devices provided and the various overflow issues the older version of DISKIO had). However, all that is predicated on the 512 byte sector size, and that was fine in the case of the old spinning drives.

The SSDs for the most part require a 4K sized sector. Not that they will NOT run with different setups, but due to the memory sizes 4K is the preferred option.

So here is the thing: attempting to re-define DISKIO code to deal with 4K sector sizes eventually produces a RC=87 from DosDevIOCtl, which means: "87_ERROR_INVALID_PARAMETER"...great!!!, but what does that mean??? LOL

I'm seeing this failure only in the Bus/Cache testing code and I think I understand why, but I haven't fully grasped it all.

Anyways, tossing the 4k setups in place causes the RC=87 failure which I'm trying to understand the reason for.

Thanks!

Dave Yeo

  • Hero Member
  • *****
  • Posts: 4787
  • Karma: +99/-1
    • View Profile
Re: DosDevIOCtl API references?
« Reply #1 on: March 22, 2021, 05:35:32 pm »
Didn't large sectors on DVD's need a filter? And does OS/2 see those sectors as 4k?

Dariusz Piatkowski

  • Hero Member
  • *****
  • Posts: 1317
  • Karma: +26/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #2 on: March 23, 2021, 03:33:20 pm »
No idea Dave, but I do see code in DISKIO that uses static sector size values for CD testing specifically.

For example this is called to get CD sizing:
Code: [Select]
...
   rc = DosDevIOCtl(handle, 0x82, 0x60, NULL, 0, NULL, (PVOID)&cdinfo, sizeof(cdinfo), &datasize);
...

where:
DosDevIOCtl (DevHandle,           /* Handle to device */
                   ulCategory,          /* Category of request */
                   ulFunction,          /* Function being requested */
                   uchParms,            /* Input/Output parameter list */
                   sizeof(uchParms),    /* Maximum output parameter size */
                   &ulParmLen,          /* Input:  size of parameter list */
                                        /* Output: size of parameters returned */
                   uchDataArea,         /* Input/Output data area */
                   sizeof(uchDataArea), /* Maximum output data size */
                   &ulDataLen);         /* Input:  size of input data area */
                                        /* Output: size of data returned   */

0x82 - therefore is 'Category of request', and 0x60 is 'Function being requested', but where can I find what these actually mean?

Basically, what I want to understand is how to change DISKIO logic to dynamically determine these values during execution so that HDDs and SSDs can be correctly tested.

I am focusing on sector size b/c the values used right now are all static.

Now, it may be that the answer is in asking perhaps a different question altogether: why didn't we use something like DosQueryFSInfo API to dynamically figure this out?

If I look at the API details the return data structure spells this out...and so why not use that information to then dynamically build the matching logic for performance testing various sector sized devices?

Here is the pertinent detail on the File-system device allocation data structure:

Code: [Select]
typedef struct _FSALLOCATE {
  ULONG      idFileSystem;  /*  File system identification. */
  ULONG      cSectorUnit;   /*  Number of sectors per allocation unit. */
  ULONG      cUnit;         /*  Number of allocation units. */
  ULONG      cUnitAvail;    /*  Number of allocation units available. */
  USHORT     cbSector;      /*  Number of bytes per sector. */
} FSALLOCATE;

Dave Yeo

  • Hero Member
  • *****
  • Posts: 4787
  • Karma: +99/-1
    • View Profile
Re: DosDevIOCtl API references?
« Reply #3 on: March 23, 2021, 11:22:51 pm »
I'm pretty sure for hard drives, we're stuck with 512 byte sectors. For example, on the testers list there was the recent thread "AHCI and USB 4TB Disk support" where someone had used XP and some driver to format a USB 4TB disk with FAT32. He found XP was fine with it. His NAS read it fine but the first write screwed it up. Investigation showed it used 4096 byte sectors, with the XP driver, and it was not supported by OS/2.
If we could use 4096 byte sectors, the CHS limit would be 16TB instead of 2TB and someone would have implemented it.
CD's and DVD's are a different kettle of fish and someone did mention needing a flt driver to handle the 4096 byte sectors.
The AHCI driver also has a switch, /4, for use with disks etc that are internally 4096 byte sectors, it forces the geometry to align the sectors correctly so JFS 4096 byte sectors map one to one. If you are using disks/ssd with 4096 byte sectors, it is important to align things correctly for performance, so writing one file sector aligns with 1 disk sector rather then having to write 2 sectors.

Dariusz Piatkowski

  • Hero Member
  • *****
  • Posts: 1317
  • Karma: +26/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #4 on: March 24, 2021, 01:18:11 am »
Oh Dave, you bet. My thinking about the 4K sector size is for exactly all the reasons you mentioned, with one significant exception.

DFsee has since about the early 15.x releases supported the creation of custom drive geometry such that the GEO would align itself to the 4K sector size that is needed for the SSD drives to deliver maximum performance.

JvW and I specifically discussed this around the time I was deploying my SSD for the very first time. I had ultimately ran into some problems (due to other issues) and wasn't able to test things out further...and well, since I was left w/o a functioning system my focus at that time was to simply finalize the move to the new drive and get-on with it!

Alright, now the situation is a little different.

I have my 860Evo SSD and figured I would really try to chase all the little pieces down to understand what (if any) benefits there are to be un-locked on our platform.

As such, I used DFsee again to force drive geometry for a large SSD (up to about 2T), that meant getting 4K sector sizes.

Here is the DFsee drive GEO controls screen I'm talking about:
Code: [Select]
┌───────────┤ Select pre-defined geometries, or set a custom one ├────────[X]┐
│                                                                            │
│ Geometry info for :     Whole  Phys. disk 4 FDISK  size:  465.8 GiB        │
│                                                                            │
│  476930 MiB as reported by the OS                                          │
│                                                                            │
│  476930 MiB for logical geometry :      15960    255       240             │
│                                                                            │
│                                     #Cylinders   #Heads    #Sect/track     │
│ ( ) Custom geometry, using values:  calculated   255       240             │
│                                                                            │
│ ( ) Classic desktop/3.5"  255/63   OS/2 limit  502 GB \   for other OSes   │
│ ( ) Classic laptops/2.5"  240/63   OS/2 limit  472 GB  \  no real limit    │
│ ( ) USB/SSD/4Kb-sectors   255/32   OS/2 limit  267 GB  /                   │
│ ( ) Std SSD/4Kb-sectors    64/32   OS/2 limit   67 GB /                    │
│ (*) Big SSD/4Kb-sectors  255/240   OS/2 limit 1912 GB \   for other OSes   │
│ ( ) Huge rotating disk   255/127   OS/2 limit 1012 GB  >  no limits, but   │
│ ( ) Huge rotating disk   255/255   OS/2 limit 2032 GB /   not recommended  │
│                                                                            │
│ ╔══════════════╗   Resulting Cylinder size:   29.9 MiB    ┌─────────────┐  │
│ │ Set Geometry │                                          │ Cancel/Done │  │
│ ╚══════════════╝   Alignment / Track  size:  120.0 KiB    └─────────────┘  │
│                                                                            │
└──────┤F1=Help F4=OK F12=Min Alt+F7=Move Alt+F10=Max Alt+C=Copy2Clip├───────┘

So check this out, two runs of my modified DISKIO code which measure the performance for 512 byte (normal HDD stuff we are all used to) and the SSD specific 4K byte sector sizes:

1) 512 Byte
Code: [Select]
Hard disk 4: 255 sides, 60801 cylinders, 63 sectors per track = 476937 MB

Drive cache/bus transfer rate: 280440 k/sec

Data transfer rate on cylinder 0   : 358500 k/sec

Data transfer rate on cylinder 60799: 339230 k/sec

CPU usage by full speed disk transfers: 5%

Average latency time: 0.4 ms

Multithreaded disk I/O (4 threads): 323144 k/sec, 6% CPU usage

2) 4K byte

Code: [Select]
Hard disk 4: 255 sides, 15960 cylinders, 240 sectors per track = 476929 MB

Drive cache/bus transfer rate: 188003 k/sec

Data transfer rate on cylinder 0   : 424791 k/sec

Data transfer rate on cylinder 15958: 414888 k/sec

CPU usage by full speed disk transfers: 4%

Average latency time: 0.0 ms

Multithreaded disk I/O (4 threads): 241640 k/sec, 3% CPU usage

Now, the cache/bus test result is suspect and I'm trying to figure this one out since that logic forces things into a 512 byte sector size and therefore cache fill and read metrics themselves.

However, if you look at the remaining data xfer rates, boy, massive difference. Heck, 360M => 425M and 340M => 415M, that's substantial.

These results can be reproduced and they show in other disk access tests as well.

Now back to one of the points you raised in your last post. There still is an ultimate limit on how big of a storage we can access in OS/2 (about 2T). If anything, the sector size increase allows us to max out the remaining hard controls, such as the: sides, cylinders and number of sectors.

I did read the posts on the testers list and as much as I wanted to respond with my findings, I didn't quite have all my work completed, so it would have been all speculation. However now, I do actually have some numbers, although more DISKIO work needs to be done for these numbers to be completely reliable.

I think I'll do a few tries of the DosQueryFSInfo API to see if the sector sizes being returned are true. If they are (and I have no reason to believe they would not be) I will try to change DISKIO logic to dynamically fetch these and adjust the testing accordingly.

EDIT
====

Well I got my answer fast enough for whether the DosQueryFSInfo API will work. The answer is NOPE, not for the purposes I want. Specifically this is a FileSystem API whereas the reall info I'm after is the DEVICE sizing itself...so it looks like it's back to the DosDevIOCtl for now...
« Last Edit: March 24, 2021, 01:39:28 am by Dariusz Piatkowski »

Lars

  • Hero Member
  • *****
  • Posts: 1271
  • Karma: +65/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #5 on: March 24, 2021, 01:42:02 pm »
OS/2 will always be stuck with a sector size of 512 unless you rewrite larger parts of the kernel. In theory, at least the .ADD drivers would be able to deal with other sector sizes as there is a "sectorsize" field. But the reality is that all code assumes a sector size of 512 bytes because the kernel does not make good use of this field.

ALIGNING on 4 kBytes is very simple: just align the 512-byte sized sectors to a multiple of eight :-)
That still does not mean that OS/2 would be able to address 4 Kbyte sectors. It expects the HW to still be able to handle 512 byte Sectors. The HW can be intelligent and internally remap this to a 4 KByte sized sector number with an appropriate offset into that 4 kByte sector.

Now you will likely bring forward the argument that using a sector size of 4 kByte is all so great with diskio. I would think that's because of the way diskio works. If you specify a sector size of 4 kBytes, in reality, OS/2 will schedule 8 transfers for a 512 byte sector size BUT the first sector will happen to start at a 4kByte boundary. THAT will lead to the HW disk cache reading in the full 4 kByte internal sector size. Therefore, the next 7 transfers will be faster because the data is already in the HW disk cache.
In reality, when reading arbitrary, random sectors, this advantage will disappear and you will be left with the exact same performance.

Don't go any further. It's of no use.
« Last Edit: March 24, 2021, 01:51:48 pm by Lars »

Dave Yeo

  • Hero Member
  • *****
  • Posts: 4787
  • Karma: +99/-1
    • View Profile
Re: DosDevIOCtl API references?
« Reply #6 on: March 24, 2021, 04:48:32 pm »
The advantage of aligning the sectors, mostly in a SSD, is less writes. Ignoring metadata, write a one byte file, JFS transfers a 4Kb block, one sector gets written, instead of 2 sectors if not aligned. With a SSD, there is a limited number of writes possible and there is also the garbage collection where data is shifted around for wear leveling. Less garbage collection equals faster and less writes equals longer lasting SSD.
For a real hard drive, aligning the sectors could cut down on fragmentation, writing one sector vs writing 2 sectors in different parts of the drive for a one byte file write.
JFS is actually kind of a crappy file system for SSD's. The journal writes cause more wear and I believe OS/2 supports writing the atime (last access time) so even reading a file updates the time metadata in the inode. OTOH, that JFS (and HPFS) use extends is good on a SSD.
Linux actually has a mount operation to turn off writing the atime and can put the journal on a different device.
Note, I'm not sure if OS/2 writes the atime.

Lars

  • Hero Member
  • *****
  • Posts: 1271
  • Karma: +65/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #7 on: March 24, 2021, 05:13:59 pm »
Ok, this is a valid point. If the filesystem insists on reading a minimum of 4 kB (even if you only need 1 byte of those 4  kB) then you are right and alignment of physical 4 kB sectors to multiple of eight 512-byte sectors for a track start and the number of sectors per track being a multiple of eight (as for example: 240) will prevent touching two physical 4 kB sectors.

I seem to remember that HPFS is much more efficient in this respect. It only asks for one single (512 byte) sector if you only want to read 1 byte.
In short: HPFS should show no difference in speed in diskio for the given case.

Anybody know why 240 was picked but not 248 [which would be the maximum multiple of 8] ? Is the world already planning for 8 kB physical sector size ?
« Last Edit: March 24, 2021, 05:17:39 pm by Lars »

Lars

  • Hero Member
  • *****
  • Posts: 1271
  • Karma: +65/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #8 on: March 24, 2021, 05:31:25 pm »
No idea Dave, but I do see code in DISKIO that uses static sector size values for CD testing specifically.

For example this is called to get CD sizing:
Code: [Select]
...
   rc = DosDevIOCtl(handle, 0x82, 0x60, NULL, 0, NULL, (PVOID)&cdinfo, sizeof(cdinfo), &datasize);
...


You will find this in this zip:
https://hobbes.nmsu.edu/download/pub/os2/system/drivers/storage/IBM1S506_10-117.zip

when you read through the enclosed readme.txt, you'll find:
0x82: IOCTL_CDROMDISK2
0x60: CDROMDISK2_DRIVELETTERS

and the used structure:
  Data Packet format:

   struct DriveLetters {
      USHORT        DriveCount;         // number of supported CD-ROM drives
      USHORT        DriveFirst;         // letter of the first CD-ROM drive
   };

This call is to query how many CD-ROM drives you have and what are their drive letters (they are consecutive).
In short: this info never made it into the OS/2 programming specs as it was added to the relevant drivers much later.

You will likely want to use:
0x80: IOCTL_OEMHLP
0x0E: OEMHLP_QUERYDISKINFO

the data (? or parm ?) structure is:

OEMHLPDISKINFO and is described in file bsedev.h in the toolkit. I would expect it to always return 512 as the sector size but I am not sure (I forgot what it uses to get to its info, it possibly directly issues ATA commands to the device to get the internal info).
« Last Edit: March 24, 2021, 05:56:45 pm by Lars »

Dariusz Piatkowski

  • Hero Member
  • *****
  • Posts: 1317
  • Karma: +26/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #9 on: March 25, 2021, 01:27:00 pm »
Hi Lars!

...You will likely want to use:
0x80: IOCTL_OEMHLP
0x0E: OEMHLP_QUERYDISKINFO

the data (? or parm ?) structure is:

OEMHLPDISKINFO and is described in file bsedev.h in the toolkit. I would expect it to always return 512 as the sector size but I am not sure (I forgot what it uses to get to its info, it possibly directly issues ATA commands to the device to get the internal info).

Thank you sir...this is exactly what I was looking for. I did find the data structure in bsedev.h file, it appears to have the sector sizing along with a pile of other stuff. I may have seen this in the DANI drivers and/or utilities code before as well, most likely didn't even realize the details it contained and the relevance to what I was looking for.

Good stuff, another lesson learned!

Re: this topic in particular, Dave highlighted the reasons why I'm pursuing making changes to DISKIO and why the underlining changes to the device geo structure may be relevant to us. While the point he raised about the JFS FS structure is very valid, the fact that most JFS deployments probably utilize a 4K block (due to the partition/volume size) lends itself extremely well to syncing up with how the physical SSD hardware itself is organized.

My interest in making the underlying DISKIO changes is to develop a true capability to assess this, given the departure from the 512 byte sector size.

One step at a time though, let me see if I can get my physical device info first with the 0x80 category call to DosDevIOCtl AND using the 0x0E function call to query the device capabilities.

Lars

  • Hero Member
  • *****
  • Posts: 1271
  • Karma: +65/-0
    • View Profile
Re: DosDevIOCtl API references?
« Reply #10 on: March 25, 2021, 01:52:01 pm »
By the way, it is possible that you need to use DosPhysicalDisk instead of DosOpen to get a device handle to use with the DosDevIoctl call. Or you need some special "filename" to use DosOpen. Read the info of these two API functions and then let trial and error guide you.
« Last Edit: March 25, 2021, 04:10:46 pm by Lars »