Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

The Linux Kernel/Storage

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

storage files & directories access Virtual File Systempage cachelogical file systemsblock devicesstorage drivers Storage functionality provides access to various storage devices via files and directories of files. Most of the storage is persistent as flash memory, SSD and legacy hard disks. Another kind of storage is temporary. The file system provides an abstraction to organize the information into separate pieces of data (called files) identified by a unique name. Each file system type defines their own structures and logic rules used to manage these groups of information and their names. Linux supports a plethora of different file system types, local and remote, native and from other operating systems. To accommodate such disparity the kernel defines a common top layer, the virtual file system (VFS) layer. Summary of the Linux kernel's storage stack|right|800x800px Files and directories Four basic files access system calls: 2 open ↪ do_sys_open - opens a file by name and returns a file descriptor (fd). Below functions operates on a fd. 2 close ↪ close_fd 2 read ↪ ksys_read 2 write ↪ ksys_write File in Linux and UNIX is not only physical file on persistent storage. File interface is used to access pipes, sockets and other pseudo-files. Modern variants: 2 openat2 ↪ do_sys_openat2 – open with extended flags and resolve control (since 5.6) 2 close_range ↪ sys_close_range – close a range of file descriptors atomically (since 5.9) Other file operations: 2 statx ↪ do_statx – extended stat with timestamps, btime, mount ID (since 4.11) 2 lseek – reposition read/write file offset 2 dup – duplicate a file descriptor 2 fcntl – manipulate file descriptor 2 truncate, 2 ftruncate – truncate a file 2 fallocate – preallocate file space 2 readahead ↪ mm/readahead.c – prefetch file data into page cache 🔨 stress-ng --open, --close, --fallocate Directory operations: 2 mkdir, 2 rmdir – create/remove directory 2 getcwd ↪ sys_getcwd – get current working directory 2 chdir ↪ sys_chdir – change working directory 3 readdir ⇾ 2 getdents 7 path_resolution 🔨 stress-ng --dentry, --dir Name operations: 2 rename – rename a file or directory 2 unlink – delete a name from the filesystem 2 readlink, 2 symlink, 2 link ⚙️ Files and directories internals linux/fs.h fs/open.c – open, close and related file operations fs/ioctl.c – 2 ioctl dispatch fs/stat.c – stat, 2 statx linux/namei.h, fs/namei.c – pathname lookup and resolution fs/read_write.c – read, write and lseek operations linux/xattr.h, fs/xattr.c – extended attributes fs/notify – filesystem event notification 2 inotify_init, 2 inotify_add_watch, 2 inotify_rm_watch – 7 inotify 2 fanotify_init, 2 fanotify_mark – 7 fanotify 🔨 stress-ng --inotify 📚 Files and directories references Input/Output, The GNU C Library VFS in Linux Kernel 2.4 Internals Unix file types File locks File locks are mechanisms that allow processes to coordinate access to shared files. These locks help prevent conflicts when multiple processes or threads attempt to access the same file simultaneously. ⚲ API 8 lslocks – list local system locks 3 lockf – apply, test or remove a POSIX lock on an open file 2 flock – apply or remove an advisory BSD lock on an open file 2 fcntl – manipulate file descriptor F_SETLK – advisory record lock F_OFD_SETLK – Open File Description Lock flock – lock parameters ⚠️ Avoid mixing flock and fcntl locks on the same file as they don’t interact with each other. ⚙️ Internals linux/filelock.h fs/locks.c – POSIX and flock file locking trace/events/filelock.h 🔨 stress-ng --flock 💾 Historical: Mandatory locking feature is no longer supported at all in Linux 5.15 and above because the implementation is unreliable. Asynchronous I/O 🚀 advanced features AIO https://lwn.net/Kernel/Index/#Asynchronous_IO 2 io_submit 2 io_setup 2 io_cancel 2 io_destroy 2 io_getevents uapi/linux/aio_abi.h fs/aio.c – async I/O implementation kernel io/aio 🔨 stress-ng --aio io_uring 🌱 New since release 5.1 in May 2019 https://blogs.oracle.com/linux/an-introduction-to-the-io_uring-asynchronous-io-framework https://thenewstack.io/how-io_uring-and-ebpf-will-revolutionize-programming-in-linux/ io_uring_enter io_uring_setup io_uring_register linux/io_uring.h uapi/linux/io_uring.h io_uring https://lwn.net/Kernel/Index/#io_uring io_uring, SCM_RIGHTS, and reference-count cycles The rapid growth of io_uring Automatic buffer selection for io_uring Operations restrictions for io_uring io_uring, SCM_RIGHTS, and reference-count cycles Redesigned workqueues for io_uring kernel/syscalls io_uring 🔨 stress-ng --io-uring Asynchronous_I/O#Forms Non-blocking I/O Allow non-blocking access to multiple file descriptors. Efficient event polling epoll ⚲ API: uapi/linux/eventpoll.h 7 epoll 2 epoll_create ↪ do_epoll_create 2 epoll_ctl ↪ do_epoll_ctl 2 epoll_wait ↪ do_epoll_wait ⚙️ Internals: fs/eventpoll.c – efficient event polling (epoll) Select (Unix) select and poll (Unix) poll 💾 Historical: Select and poll system calls are derived from UNIX ⚲ API: 2 poll ↪ do_sys_poll 2 select ↪ kern_select ⚙️ Internals: fs/select.c – select and poll implementation Vectored I/O 🚀 advanced feature Vectored I/O, also known as scatter/gather I/O, is a method of input and output by which a single procedure call sequentially reads data from multiple buffers and writes it to a single data stream, or reads data from a data stream and writes it to multiple buffers, as defined in a vector of buffers. Scatter/gather refers to the process of gathering data from, or scattering data into, the given set of buffers. Vectored I/O can operate synchronously or asynchronously. The main reasons for using vectored I/O are efficiency and convenience. ⚲ API: uapi/linux/uio.h linux/uio.h iovec 2 readv ↪ do_readv 2 writev ↪ do_writev ⚙️ Internals: iov_iter do_readv ↯ call hierarchy: vfs_readv import_iovec ext4_file_read_iter lib/iov_iter.c – I/O vector iterator operations ... 📖 References Fast Scatter-Gather I/O, The GNU C Library https://lwn.net/Kernel/Index/#Vectored_IO https://lwn.net/Kernel/Index/#Scattergather_chaining 📚 Further reading https://deepwiki.com/torvalds/linux/4-filesystems Virtual File System The virtual file system (VFS) is an abstract layer on top of a concrete logical file system. The purpose of a VFS is to allow client applications to access different types of logical file systems in a uniform way. A VFS can, for example, be used to access local and network storage devices transparently without the client application noticing the difference. It can be used to bridge the differences in Windows, classic Mac OS/macOS and Unix filesystems, so that applications can access files on local file systems of those types without having to know what type of file system they are accessing. A VFS specifies an interface (or a "contract") between the kernel and a logical file system. Therefore, it is easy to add support for new file system types to the kernel simply by fulfilling the contract. 🔧 TODO: vfsmount, vfs_create, vfs_read, vfs_write ⚙️ Internals: fs/inode.c – inode allocation and management linux/dcache.h, fs/dcache.c – dentry cache, pathname-to-inode lookup fs/super.c – superblock operations, filesystem mount/unmount linux/file.h, fs/file.c – file table, fd allocation linux/mount.h – filesystem mount structures linux/fs_context.h – filesystem mount context (replaces old mount API) fs/readdir.c – directory listing (getdents) 📚 VFS References VFS filesystems/#core-vfs-documentation VFS in Linux Kernel 2.4 Internals Logical file systems A file system (or filesystem) is used to control how data is stored and retrieved. Without a file system, information placed in a storage area would be one large body of data with no way to tell where one piece of information stops and the next begins. By separating the data into individual pieces, and giving each piece a name, the information is easily separated and identified. Each group of data is called a "file". The structure and logic rules used to manage the groups of information and their names is called a "file system". There are many different kinds of file systems. Each one has different structure and logic, properties of speed, flexibility, security, size and more. Some file systems have been designed to be used for specific applications. For example, the ISO 9660 file system is designed specifically for optical discs. File systems can be used on many different kinds of storage devices. Each storage device uses a different kind of media. The most common storage device in use today is a SSD. Other media that was used are hard disk, magnetic tape and optical disc. In some cases, the computer's main memory (RAM) is used to create a temporary file system for short-term use. Raw storage is called a block device. Linux supports many different file systems, but common choices for the system disk on a block device include the ext* family (such as ext2, ext3 and ext4), XFS, ReiserFS and btrfs. For raw Flash without a flash translation layer (FTL) or Memory Technology Device (MTD), there is UBIFS, JFFS2, and YAFFS, among others. SquashFS is a common compressed read-only file system. NFS and other network FS are described further in paragraph Network storage. ⚲ Shell interfaces: cat /proc/filesystems ls /sys/fs/ rust/kernel/fs.rs – Rust bindings 8 mount, 8 umount 8 findmnt, 1 mountpoint, 1 df New mount API (since 5.2+, replaces 2 mount): 2 fsopen ↪ sys_fsopen – open filesystem configuration context 2 fsmount ↪ sys_fsmount – create mount from fs context 2 move_mount ↪ sys_move_mount – move mount to new location 2 open_tree ↪ sys_open_tree – pick or clone a mount 2 mount_setattr ↪ sys_mount_setattr – change mount attributes (since 5.12) 2 statmount ↪ sys_statmount – query mount info (since 6.8) 2 listmount ↪ sys_listmount – list submounts (since 6.8) Infrastructure ⚲ API function register_filesystem registers structs file_system_type and stores them in linked list ⚙️ file_systems. Function ext4_init_fs registers ext4_fs_type. Operation of file system opening is called mounting: ext4_get_tree ⚙️ Internals: fs/namespace.c – mount and namespace operations 2 mount do_mount linux/buffer_head.h super_block sb_bread fs – filesystem implementations fs/ext4/ext4.h – ext4 on-disk format and internal structures ext4_sb_bread Other notable filesystems: FUSE (filesystem) FUSE – fs/fuse – filesystem in userspace OverlayFS – fs/overlayfs – union mount filesystem, used by containers Btrfs – fs/btrfs XFS – fs/xfs 📚 References: filesystems filesystems/#filesystems Page cache A page cache or disk cache is a transparent cache for the memory pages originating from a secondary storage device such as a hard disk drive. The operating system keeps a page cache in otherwise unused portions of the main memory, resulting in quicker access to the contents of cached pages and overall performance improvements. The page cache is implemented by the kernel, and is mostly transparent to applications. Usually, all physical memory not directly allocated to applications is used by the operating system for the page cache. Since the memory would otherwise be idle and is easily reclaimed when applications request it, there is generally no associated performance penalty and the operating system might even report such memory as "free" or "available". The page cache also aids in writing to a disk. Pages in the main memory that have been modified during writing data to disk are marked as "dirty" and have to be flushed to disk before they can be freed. When a file write occurs, the page backing the particular block is looked up. If it is already found in the page cache, the write is done to that page in the main memory. Otherwise, when the write perfectly falls on page size boundaries, the page is not even read from disk, but allocated and immediately marked dirty. Otherwise, the page(s) are fetched from disk and requested modifications are done. Not all cached pages can be written to as program code is often mapped as read-only or copy-on-write; in the latter case, modifications to code will only be visible to the process itself and will not be written to disk. ⚲ API: 2 fsync ↪ do_fsync 2 sync_file_range ↪ ksys_sync_file_range 2 syncfs ↪ sync_filesystem 2 sync ↪ ksys_sync – flush all filesystem caches to disk 2 cachestat ↪ sys_cachestat – per-file page cache statistics (since 6.5) ⚙️ Internals: linux/pagemap.h, mm/filemap.c – page cache core, read/write/mmap paths linux/buffer_head.h, fs/buffer.c – buffer heads, block-level page cache interface linux/writeback.h, mm/page-writeback.c – dirty page writeback throttling address_space – per-inode page cache, defined in linux/fs.h linux/backing-dev.h – backing device info, writeback bandwidth wb_workfn, do_writepages 📚 References Page cache More The future of DAX - direct access bypassing the cache Linux Page Cache in Linux Kernel 2.4 Internals Zero-copy 🚀 advanced features Writing data to storage and reading are very resource consuming operations. Copying memory is time and CPU consuming operation too. Set of methods to avoid copying operations is called zero-copy. The goal of zero-copy methods is a fast and efficient data transfer within the system. The first and simplest method is Pipeline (Unix) Pipeline, invoked by operator "|" in shells. Instead of writing data into temporary file and reading, the data is passed efficiently via a pipe bypassing a storage. The second method is Tee_(command) tee. ⚲ Syscalls: 2 pipe2 2 tee, 1 tee 2 sendfile 2 copy_file_range 2 splice 2 vmsplice ⚲ API and ⚙️ Internals: 2 pipe2 ↪ do_pipe2 - creates pipe uses pipe_fs_type, pipefifo_fops 2 tee ↪ do_tee - duplicates pipe content calls link_pipe 2 sendfile ↪ do_sendfile - transfers data between file descriptors, the output can be a socket. Used in network storage and servers. Calls: do_splice_direct, splice_direct_to_actor 2 copy_file_range ↪ vfs_copy_file_range - transfers data between files calls custom remap_file_range like nfs42_remap_file_range or custom copy_file_range like fuse_copy_file_range or do_splice_direct 2 splice ↪ do_splice - splices data to/from a pipe. There are three cases regarding which end being a pipe: do_splice_from - pipe → file Calls custom splice_write or iter_file_splice_write do_splice_read - file → pipe Calls custom splice_read or copy_splice_read splice_pipe_to_pipe - both are pipes 2 vmsplice ↪ vmsplice_to_pipe – splices user pages to a pipe vmsplice_to_user – splices a pipe to user pages ⚲ API linux/splice.h ⚙️ Internals: fs/pipe.c – pipe and FIFO implementation fs/splice.c – splice data transfer between file descriptors 🔨 stress-ng --splice, --sendfile 🔧 TODO: zerocopy_sg_from_iter builds a zerocopy skb datagram from an iov_iter. Used in tap_get_user and tun_get_user. skb_zerocopy skb_zerocopy_iter_dgram 📚 References 7 pipe 7 fifo splice and pipes filesystems/splice.html Pipes API filesystems/splice.html#pipes-api splice (system call) LTP: kernel/syscalls pipe, kernel/syscalls pipe2, kernel/syscalls tee, kernel/syscalls sendfile, kernel/syscalls copy_file_range, kernel/syscalls splice, kernel/syscalls vmsplice Block device layer The block device layer in Linux provides an abstraction for accessing storage devices, such as SSDs and USB drives, by presenting them as a series of fixed-size blocks. It sits between the hardware and the file system, allowing applications and file systems to perform read and write operations efficiently without needing to know the specifics of the underlying hardware. Key components include block drivers, the I/O scheduler, and buffer management, which work together to handle requests, optimize access patterns, and ensure data integrity. This layer supports essential features like caching, partition management, and queueing mechanisms to balance performance and reliability. ⚲ Shell interfaces: 8 blkid – locate/print block device attributes (UUID, TYPE, LABEL) 8 lsblk – list block devices in a tree with size, type, mountpoint 8 blockdev --report – read-ahead, sector size, read-only state per device /proc/partitions – major, minor, blocks, name of each block device /proc/diskstats – I/O statistics per disk and partition /sys/block/$dev/queue/scheduler – active and available I/O schedulers sos block plugin – diagnostics collection for block devices ⚲ Interfaces: linux/blk_types.h bio – main unit of I/O for the block layer and lower layers rust/kernel/block.rs – Rust bindings req_op – operations common to the bio and request structures linux/bio.h block_device block_size blk_alloc_disk allocates gendisk add_disk device_add_disk block_device_operations linux/blkdev.h gendisk dev_to_disk, disk_to_dev block_class – block devices Driver Model class register_blkdev request request_queue ⚙️ Internals. block – block layer core fs/iomap – modern filesystem I/O mapping layer (used by xfs, ext4, btrfs) block_class 👁 Examples: drivers/block/brd.c - small RAM backed block device driver drivers/block/null_blk – null block test device 🔨 stress-ng --hdd, --iomix, --seek Device mapper The device mapper is a framework provided by the kernel for mapping physical block devices onto higher-level "virtual block devices". It forms the foundation of LVM2, software RAIDs and dm-crypt disk encryption, and offers additional features such as file system snapshots. Device mapper works by passing data from a virtual block device, which is provided by the device mapper itself, to another block device. Data can be also modified in transition, which is performed, for example, in the case of device mapper providing disk encryption. User space applications that need to create new mapped devices talk to the device mapper via the libdevmapper.so shared library, which in turn issues ioctls to the /dev/mapper/control device node. Functions provided by the device mapper include linear, striped and error mappings, as well as crypt and multipath targets. For example, two disks may be concatenated into one logical volume with a pair of linear mappings, one for each disk. As another example, crypt target encrypts the data passing through the specified device, by using the Linux kernel's Crypto API. The following mapping targets are available: cache - allows the creation of hybrid volumes, by using solid-state drives (SSDs) as caches for hard disk drives (HDDs) crypt - provides data encryption, by using the Linux kernel's Crypto API delay - delays reads and/or writes to different devices (used for testing) era - behaves in a way similar to the linear target, while it keeps track of blocks that were written to within a user-defined period of time error - simulates I/O errors for all mapped blocks (used for testing) flakey - simulates periodic unreliable behaviour (used for testing) linear - maps a continuous range of blocks onto another block device mirror - maps a mirrored logical device, while providing data redundancy multipath - supports the mapping of multipathed devices, through usage of their path groups raid - offers an interface to the Linux kernel's software RAID driver (md) snapshot and snapshot-origin - used for creation of LVM snapshots, as part of the underlining copy-on-write scheme striped - strips the data across physical devices, with the number of stripes and the striping chunk size as parameters zero - an equivalent of /dev/zero, all reads return blocks of zeros, and writes are discarded 📚 References Device mapper Device mapper admin-guide/device-mapper linux/device-mapper.h drivers/md – device mapper and software RAID https://lwn.net/Kernel/Index/#Device_mapper Multi-Queue Block IO Queueing The blk-mq API enhances IO performance by leveraging multiple queues for parallel processing, addressing bottlenecks from traditional single-queue designs. It uses software queues for scheduling, merging, and reordering requests, and hardware queues to interface directly with devices. If hardware resources are limited, requests are temporarily queued for later dispatch. ⚲ Interfaces: /sys/devices/.../mq/ linux/blk-mq.h Structures: blk_mq_hw_ctx – hardware dispatch queue context blk_mq_tag_set – shared between request queues blk_mq_ops blk_mq_tags blk_mq_queue_map – map software queues to hardware queues request 👁️ Example drivers/block/null_blk – multi-queue aware block test driver ⚙️ Internals /sys/kernel/debug/block/*/hctx* block/blk-mq.h – blk-mq internal definitions blk_mq_ctx – software staging queue context block/blk-mq.c – block multi-queue core code block/blk-mq-tag.c – tag allocation using scalable bitmaps ... 📖 References Multi-Queue Block IO Queueing Mechanism (blk-mq) block/blk-mq.html I/O scheduler I/O scheduling (or disk scheduling) is the method chosen by the kernel to decide in which order the block I/O operations will be submitted to the storage volumes. I/O scheduling usually has to work with hard disk drives that have long access times for requests placed far away from the current position of the disk head (this operation is called a seek). To minimize the effect this has on system performance, most I/O schedulers implement a variant of the elevator algorithm that reorders the incoming randomly ordered requests so the associated data would be accessed with minimal arm/head movement. The particular I/O scheduler used with certain block device can be switched at run time by modifying the corresponding /sys/block/<block_device>/queue/scheduler file in the sysfs filesystem. Some I/O schedulers also have tunable parameters that can be set through files in /sys/block/<block_device>/queue/iosched/. ⚲ Interfaces: 1 ionice – set or get process I/O scheduling class and priority 2 ioprio_get, ioprio_set linux/elevator.h Function elv_register registers struct elevator_type. elevator_queue ⚙️ Internals: block/ioprio.c – I/O priority system call block/elevator.c – I/O scheduler framework block/Kconfig.iosched – I/O scheduler Kconfig options block/bfq-iosched.c – Budget Fair Queueing scheduler block/kyber-iosched.c – Kyber multiqueue scheduler block/mq-deadline.c – deadline multiqueue scheduler trace/events/block.h 📖 References: I/O scheduling Elevator algorithm Switching Scheduler block/switching-sched.html BFQ - Budget Fair Queueing block/bfq-iosched.html Deadline IO scheduler tunables deadline-iosched.html https://www.cloudbees.com/blog/linux-io-scheduler-tuning/ https://wiki.ubuntu.com/Kernel/Reference/IOSchedulers ... 📖 References Block devices block Switching Scheduler block/switching-sched.html BFQ - Budget Fair Queueing block/bfq-iosched.html Deadline IO scheduler tunables block/deadline-iosched.html Kyber I/O scheduler tunables block/kyber-iosched.html Multi-Queue Block IO Queueing Mechanism (blk-mq) block/blk-mq.html 📚 Further reading /sys/kernel/debug/block/*/ https://lwn.net/Kernel/Index/#Block_layer block devices ML LKMPG: Block Drivers LDD3:Block Drivers LDD1:Loading Block Drivers ULK3 Chapter 14. Block Device Drivers Linux SCSI Generic (sg) Driver Scsi_debug adapter driver for Linux https://github.com/doug-gilbert/sg3_utils Computer data storage Storage drivers 🔧 TODO ⚲ Shell interfaces: lsscsi – list SCSI devices and hosts sg_inq – SCSI INQUIRY, device identification /sys/class/scsi_host/, /sys/class/scsi_disk/ – SCSI sysfs attributes /proc/scsi/ – SCSI subsystem info sos scsi plugin, nvme plugin – diagnostics collection ⚙️ Internals drivers/nvmem – Non-volatile memory drivers/sdio – Secure Digital#SDIO cards Secure Digital Input Output drivers/scsi – SCSI Small Computer System Interface, SCSI scsi drivers/virtio – virtio guest drivers drivers/mtd – Memory Technology Device for 🤖 embedded devices NVMe NVM Express drivers provide accesses a computer's non-volatile storage. Local storage is attached via PCIe PCI Express bus. PCI NVMe device driver entry point is nvme_init. Remote storage driver is called target and local Proxy_pattern proxy driver is called host. Switched fabric Fabrics connect remote targets with local host. A fabric can be based on Remote direct memory access RDMA, Transmission Control Protocol TCP or Fibre Channel protocols. 📖 References: NVMe nvme ⚲ API: nvme-cli – nvme list, nvme smart-log, nvme id-ctrl, nvme error-log /sys/class/nvme-generic/ – char device access to NVMe namespaces (since 5.15) /sys/class/nvme-subsystem/ – NVMe subsystem topology /sys/class/nvme-fabrics/ – NVMe over Fabrics controllers (only with remote NVMe targets) /sys/module/nvme_core/parameters/ – NVMe core module tunables uapi/linux/nvme_ioctl.h linux/nvme.h ⚙️ Internals: drivers/nvme – NVMe drivers Host drivers/nvme/host: ⚲ Interfaces: drivers/nvme/host/nvme.h – NVMe host common definitions nvme_init_ctrl initializes a NVMe controller structures nvme_ctrl with operations nvme_ctrl_ops a subroutine of nvme_scan_work adds a new disk with device_add_disk nvme_init - local PCI nvme module init nvme_probe nvme_init_ctrl ... nvme_pci_ctrl_ops nvme_core_init - module init Fabrics ⚲ interfaces: drivers/nvme/host/fabrics.h – NVMe over Fabrics host common definitions nvmf_register_transport registers nvmf_transport_ops nvmf_init - fabrics module init ⚙️ internals: nvmf_init - fabrics module init nvmf_misc nvmf_dev_fops nvmf_dev_write nvmf_create_ctrl binds nvmf_transport_ops Target drivers/nvme/target: ⚲ Interfaces: drivers/nvme/target/nvmet.h nvmet_register_transport registers nvmet_fabrics_ops nvmet_init - module init fcloop_init - loopback test module init which can be useful to test NVMe-FC transport interfaces. NVMe over Switched fabric FabricsLayersTransmission Control Protocol TCPRDMAFibre ChannelHost modulesnvme_tcp_init_modulenvme_rdma_init_modulenvme_fc_init_moduleFabrics protocolslinux/nvme-tcp.hlinux/nvme-rdma.hlinux/nvme-fc.h linux/nvme-fc-driver.h Target modulesnvmet_tcp_init nvmet_rdma_initnvmet_fc_init_module 👁 Example: nvme_loop_init_module nvme loopback nvme_loop_transport - fabrics operations nvme_loop_create_ctrl nvme_loop_create_io_queues nvme_loop_ops - target operation nvme_loop_add_port nvme_loop_queue_response ... 🚀 Advanced 1 pidstat – reports task statistics /proc/self/io – I/O statistics for the process (see 5 proc) 💾 Historical storage drivers drivers/ata - Parallel ATA 📖 Further reading about storage bcc/ebpf storage and filesystems tools