PHYSIO(9)

πŸ“¦
version 15.1 Β· 3 versions
, in freebsd 14.5, freebsd 15.1, nixpkgs unstable

πŸ’« PHYSIO(9) β€” the physio man page, but make it make sense πŸ’«

okay bestie, so this is a page from the Kernel Developer's Manual (section 9, kernel-adjacent, very demure, very mindful) and it's all about physio β€” the little helper that kicks off I/O on raw devices. πŸŽ€ lowkey iconic of the kernel devs to document it. let's get into it ✨


🌸 NAME 🌸

physio β€” initiate I/O on raw devices. that's it. that's the whole vibe. πŸ’…


✨ SYNOPSIS ✨

first, the little summoning circle of includes:

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>

and then the function itself, looking all official:

int
physio(struct cdev *dev, struct uio *uio, int ioflag);

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so physio() is a helper function β€” and like, a particularly helpful one β€” that usually gets called from character device read() and write() routines to start I/O on a user process buffer. it's giving "middle management of the kernel" but make it cute. πŸ”₯

the max amount of data you can transfer with each call? that's decided by dev->si_iosize_max. no cap. that's the ceiling. πŸ™ˆ

what physio() does is take your I/O request, converts it into a strategy() request, and then hands that new request over to the driver's strategy() routine for processing. passing the baton. very main character energy. πŸ‘‘

here's the slightly spicy part: since uio normally describes user space addresses, physio() has to lock those pages into memory. how? by calling vmapbuf() for the appropriate pages. locked in, literally. πŸ”’

also physio() always awaits the completion of the entire requested transfer before returning β€” unless an error condition gets detected earlier. so it's not one of those "fire and forget" situations, it's a "wait for the whole thing, no skipping ahead" situation. πŸ’―

and a break-down of the arguments, because we love a list:

  • dev β€” the device number that identifies the device you're interacting with. it's the "who" of the whole operation. 🫢
  • uio β€” the description of the entire transfer, as requested by the user process. right now, the results of passing a uio structure with the uio_segflg set to anything other than UIO_USERSPACE are undefined. so like… don't. fr fr, don't. πŸ’€
  • ioflag β€” the ioflag argument from the read() or write() function that's calling physio(). it just comes along for the ride. πŸš—

πŸ“ RETURN VALUES πŸ“

if everything slays, physio() returns 0. πŸŽ‰

EFAULT gets returned if the address range described by uio is not accessible by the requesting process. like, the memory said "not today". 😭

beyond that, physio() will return any error resulting from calls to the device strategy routine β€” and it figures that out by examining the B_ERROR buffer flag and the b_error field. detective work. πŸ•΅οΈβ€β™€οΈ

⚠️ little note bestie: the actual transfer size may be less than what was requested by uio if the device signals an "end of file" condition. so don't come for it, it's literally just what the device said. πŸ’…

🌈 SEE ALSO 🌈

iykyk, go read those if you want the full picture. πŸ“š


πŸ’œ HISTORY πŸ’œ

real ones know: the physio manual page is originally from NetBSD, with minor changes so it applies to FreeBSD. giving credit where it's due, periodt. 🫑

and the physio call itself has been completely re-written to provide higher I/O and paging performance. glow-up of the century, honestly. πŸ”₯✨


kiss kiss, that's the page πŸ’‹ β€” this little gem is from the Debian edition of the man page, dated January 19, 2012, and it's PHYSIO(9) all the way down. πŸ§šβ€β™€οΈπŸŽ€ love u, bye! πŸ¦‹

πŸ“¦ where this page comes from