DGX & Cluster Storage

Everything storage on a DGX cluster: the storage hierarchy, NVMe and nvme-cli, RAID levels and why /raid is RAID 0, mdadm, local caching (FS-Cache, staging, container caches), shared and parallel filesystems, GPUDirect Storage, tuning and benchmarking with fio, data loading and checkpointing. Part B covers changing node storage layouts the BCM way.

Part A: Storage fundamentals

1. The storage hierarchy for AI

A training job reads data that starts far away (shared storage) and must end up in GPU memory. Each tier is faster and smaller than the one below it:

TierExample on DGX H100Rough scaleRole
GPU memory (HBM3)80 GB per GPU, 640 GB per node~3 TB/s per GPUModel weights, activations, the current batch
Host memory (DRAM)2 TBHundreds of GB/sLinux page cache, data-loader buffers, pinned staging
Local NVMe (/raid)8 × 3.84 TB in RAID 0 ≈ 30 TBTens of GB/s aggregateNode-local cache / scratch: staged datasets, NFS cache, container images
Shared high-performance storageParallel filesystem over the storage networkPB scale, high aggregate bandwidth across nodesThe source of truth for datasets and checkpoints
Capacity / archiveNFS filers, object storage (S3), tapeCheapest per TBRaw data lakes, long-term retention, home directories
The goal is to keep GPUs fed: the closer and faster the data, the less the GPUs wait. Local NVMe exists to absorb repeated reads (epoch after epoch) so they don't all hit shared storage, while shared storage keeps anything that must survive.
Shared storage is the warehouse, /raid is the stockroom at the back of the shop, DRAM is the shelf behind the counter, and HBM is what's in the cashier's hands. If the stockroom burns down you restock from the warehouse; you never keep the only copy of anything in the stockroom.

1b. Where each file lives, and which network it crosses

Knowing the tiers isn't enough: questions describe a specific file (a container image, a checkpoint, a home directory) and ask where it belongs or why something is slow. This map covers the usual artifacts on a DGX cluster. Paths are typical examples; sites name their mounts differently.

ArtifactTypical pathLives onTypeReached overWhy there
OS, kernel, drivers (GPU driver, DOCA/OFED, Fabric Manager)/, /boot, /usr/lib/modulesLocal OS mirror (2 × M.2 NVMe, RAID 1). Not /raid.Block (local filesystem)Written by BCM at provisioning over in-bandThe node must boot and run with shared storage down. The master copy is the BCM software image.
BCM software images, PXE boot files/cm/images/<image> on the head nodeHead node disk (kept in sync with the passive head node in an HA pair)Local filesystem on the head nodeServed to nodes over in-band (PXE, then the node installer syncs the image)One central definition of every node's OS (Part B)
Cluster-wide software/cm/shared (BCM), modules, toolsNFS export from the head node or a NASShared file (NFS)In-bandInstall once, visible on every node
Container imagesEnroot cache/data on /raid (ENROOT_CACHE_PATH, ENROOT_DATA_PATH); Docker data-root on /raid; or prebuilt .sqsh files on shared storageLocal /raid cache, or a shared copyLocal file / shared filePulled from nvcr.io north-south over in-band once; a shared .sqsh comes over the storage or in-band networkA 15–30 GB NGC image pulled once per node, not per job (NGC guide)
Node logs/var/log, the systemd journal, dmesgLocal OS drive, forwarded to the head node or monitoring stackBlock (local filesystem)Forwarding over in-band. The BMC's own event log (SEL) is read over OOB.Readable locally even when the network is the problem
Home directories, code, configs/home/<user>NFS user storageShared file (NFS)In-band (not the storage fabric)Same scripts and .bashrc on every node; small, backed up. Not for datasets or checkpoints.
Active training datasets/lustre/datasets/… (master), staged to /raid/data/…Parallel filesystem (high-performance storage); repeated reads from the local cacheShared file (parallel FS)Storage fabric; from /raid it's local PCIeAggregate bandwidth from many storage servers; local NVMe absorbs epoch after epoch
Checkpoints/lustre/<project>/checkpoints/Parallel filesystemShared file (parallel FS)Storage fabricMust survive node loss; every rank writes its shard in parallel
Model weights for fine-tuning or inferenceMaster in object storage, NGC, or the parallel FS; cached at /raid/models or a NIM cache (NIM_CACHE_PATH)Master copy shared, working copy cached locallyObject or shared file, then local fileStorage fabric or in-band (north-south) once, then localSee loading model weights
Job scratch/raid/tmp/$SLURM_JOB_IDLocal /raidLocal fileNone (local)Fast and disposable; cleaned in the Slurm epilog
Raw data lake, archives, old checkpointss3://ai-data-lake/raw-2026/Object storage (S3-compatible)ObjectUsually north-south over in-band, or the storage Ethernet where the design shares itCheap and durable for immutable data; subsets are staged into the parallel FS for training

Block, file, and object: what the "type" column means

TypeHow it's usedOn a DGX cluster
BlockA raw disk (or LUN) that one host owns; the host puts its own filesystem on itThe OS mirror and /raid. Not shared between nodes.
FileA shared directory tree with POSIX semantics (open, seek, rename, permissions) mounted by many hostsNFS for homes and software; Lustre, WEKA, Storage Scale, VAST for datasets and checkpoints
ObjectWhole objects in buckets, addressed by key over an HTTP API (S3). No in-place edits or POSIX mounts by default.Data lake, archives, model registries. Staged or streamed, not used as a working directory.

Which network, step by step: one training job

#StepWhat movesNetwork
1Node bootsPXE boot, software image sync from the head nodeIn-band
2Job submitted and startedSlurm control trafficIn-band
3Container readyImage pulled from nvcr.io to /raid (first time), or a shared .sqsh readIn-band (north-south), or storage
4Code and configs readScripts from $HOMEIn-band (NFS)
5Data stagedDataset shards from the parallel FS to /raid (prolog or first step)Storage fabric
6Weights loadedEach GPU's shard of the starting model or checkpointStorage fabric, or local NVMe if cached
7Every training stepBatches from /raid or the parallel FS into GPU memory (GDS can skip CPU memory); gradients exchanged between GPUsLocal PCIe / storage fabric for data; NVLink inside the node and the compute fabric between nodes for gradients
8CheckpointModel and optimizer state, sharded by rankStorage fabric
9MonitoringLogs, DCGM metrics, job outputIn-band
10A node hangsPower cycle and console through the BMCOut-of-band
11Run finishedFinal model exported to object storage or a registryIn-band (north-south) or storage
The compute fabric carries only GPU-to-GPU traffic. Data and checkpoints use the storage fabric; homes, software, containers, and control use in-band; BMCs use out-of-band. Designs that share a fabric (DGX BasePOD's management-plus-storage Ethernet, or GB200's combined storage and in-band network) still keep the compute fabric separate. More on the networks in AI factory architecture.

2. Disk basics: disks, partitions, filesystems

ConceptWhat it isExample
Disk (SSD / NVMe)The physical storage device./dev/nvme0n1
PartitionA slice of the disk set aside for a purpose. The partition table (GPT) records where each slice starts and ends./dev/nvme0n1p2 = 100 GB for the OS
FilesystemThe structure written inside a partition so it can store files (ext4, xfs).ext4 on the OS partition
Mount pointWhere the filesystem appears in the directory tree./, /boot/efi, /raid
RAIDCombines several disks into one logical device for speed, redundancy, or both./dev/md0 (OS mirror), /dev/md1 (data stripe)
One OS disk, split into partitions: /boot/efi / (OS root) /var swap / other
$ lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
nvme0n1      1.7T disk
├─nvme0n1p1  512M part vfat    /boot/efi
└─nvme0n1p2  1.7T part linux_raid_member
  └─md0      1.7T raid1 ext4   /
nvme1n1      1.7T disk          (mirror of nvme0n1)
nvme2n1      3.5T disk linux_raid_member
  └─md1     27.9T raid0 ext4   /raid
... nvme3n1 – nvme9n1 (the other 7 data drives, also in md1)
Device names (md0/md1, nvme numbering) and filesystem types vary by DGX model and OS release. Use lsblk and cat /proc/mdstat on the actual system.

3. NVMe fundamentals

ConceptMeaning
NVMe (Non-Volatile Memory Express)A storage protocol designed for flash over PCIe. It replaced SATA/SAS (designed for spinning disks).
QueuesUp to 64K I/O queues, each up to 64K commands deep, one or more per CPU core. That parallelism is why NVMe is so fast.
PCIe lanesA typical drive uses x4. Roughly ~8 GB/s for Gen4 x4 and ~16 GB/s for Gen5 x4 theoretical.
NamespaceA logical "disk" exposed by the controller (nvme0n1 = controller 0, namespace 1). Drives can be split into several namespaces.
Form factorsM.2 (small stick: DGX boot/OS drives), U.2 (2.5" hot-swap: DGX data drives), E1.S / E3.S (newer data-centre form factors)
EnduranceFlash wears out. Rated as DWPD (drive writes per day over the warranty) or TBW (total terabytes written).
NVMe-oFNVMe over Fabrics: NVMe commands over RDMA (IB/RoCE) or TCP, so remote flash looks almost local
NVMe performance comes from parallelism (many queues, many outstanding I/Os). A single-threaded cp or dd barely scratches it. Benchmarks and data loaders need multiple workers and queue depth to see the real numbers.

4. nvme-cli: inventory, health, and erase

sudo nvme list                       # all NVMe devices: model, serial, size, firmware
sudo nvme smart-log /dev/nvme2       # health
#   critical_warning      : 0        <- non-zero = act now
#   temperature           : 38 C
#   available_spare       : 100%
#   percentage_used       : 3%       <- endurance consumed (can exceed 100%)
#   data_units_written    : ...
#   media_errors          : 0        <- should stay 0
#   num_err_log_entries   : 0
#   unsafe_shutdowns      : 4
sudo nvme error-log /dev/nvme2
sudo nvme id-ctrl /dev/nvme2 | grep -E 'mn|fr'    # model, firmware revision
sudo nvme fw-log /dev/nvme2

# Erasing (DESTROYS DATA)
sudo nvme format /dev/nvme2n1 --ses=1    # secure erase user data
sudo nvme sanitize /dev/nvme2 -a 2       # block-erase sanitize (drive-wide)
SMART fieldWatch for
critical_warningAny non-zero bit (spare low, temperature, reliability degraded, read-only mode)
percentage_usedEndurance consumed. Plan replacement as it approaches 100%.
media_errorsUnrecovered data errors. Rising = replace the drive.
available_spareRemaining spare blocks. Dropping toward the threshold = failing.
On DGX systems, nvsm show health and nvsm show storage summarize drive and RAID health, and nvsm dump health collects it for support. See NVSM mastery.

5. RAID levels

LevelHow it worksUsable capacity (n disks)SurvivesPerformanceTypical use
RAID 0 (stripe)Data split in chunks across all disks100% (n × size)0 failures: any disk lost = all data lostBest: reads and writes scale with n, no parity costScratch / cache (DGX /raid)
RAID 1 (mirror)Identical copy on each disk1 disk's worth (50% with 2)n − 1 failuresReads can use both; writes go to allOS / boot (DGX OS drives)
RAID 5Striping + 1 distributed parity block(n − 1) × size1 failureGood reads; writes pay a parity penalty (read-modify-write, about 4 I/Os per small write)General file servers
RAID 6Striping + 2 parity blocks(n − 2) × size2 failuresBigger write penalty (about 6 I/Os)Large-capacity arrays where rebuilds take long
RAID 10Mirrored pairs, striped together50%1 per mirror pair (at least 1)Fast reads and writes, no parityDatabases, write-heavy important data
"0 = zero protection. 1 = one copy extra. 5 = one parity. 6 = two parities. 10 = 1 + 0."
RAID is not a backup. It protects against a disk failing (except RAID 0, which doesn't even do that), not against deletion, corruption, ransomware, or losing the whole node.

6. RAID calculator

Bandwidth figures are idealized upper bounds. Real arrays are limited by PCIe topology, CPU, filesystem, and access pattern. Measure with fio.

7. Software RAID with mdadm

DGX systems use Linux software RAID (md, managed with mdadm) rather than a hardware RAID card. NVMe drives are fast enough that a RAID controller would be a bottleneck, and software RAID is flexible and transparent.

cat /proc/mdstat                     # all md arrays and their state
#   md1 : active raid0 nvme9n1[7] nvme8n1[6] ... nvme2n1[0]
#   md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
#         [UU]                       <- both mirror halves Up; [U_] = degraded

sudo mdadm --detail /dev/md0         # state, members, failed/spare devices
sudo mdadm --examine /dev/nvme0n1p2  # RAID metadata on one member

# RAID 1: replace a failed mirror member
sudo mdadm /dev/md0 --fail /dev/nvme1n1p2 --remove /dev/nvme1n1p2
# (swap the drive, partition it like the other one, then)
sudo mdadm /dev/md0 --add /dev/nvme1n1p2      # rebuild starts; watch /proc/mdstat

# RAID 0: there's nothing to rebuild. A lost member means re-creating the array:
sudo mdadm --create /dev/md1 --level=0 --raid-devices=8 /dev/nvme{2..9}n1
sudo mkfs.ext4 /dev/md1   # then mount at /raid and refill the cache
On DGX OS, NVIDIA provides a helper for the data array (for example configure_raid_array.py) and documents the exact steps to recreate and remount /raid after a drive replacement. Use the documented procedure for your DGX model rather than raw mdadm where one exists.

8. How storage is laid out on DGX systems

SystemOS drivesData / cache drives
DGX H100 / H2002 × 1.92 TB M.2 NVMe, RAID 18 × 3.84 TB U.2 NVMe, RAID 0 at /raid (~30 TB)
DGX A1002 × 1.92 TB M.2 NVMe, RAID 14 × 3.84 TB U.2 (~15 TB) standard, or 8 (~30 TB) on the larger configuration, RAID 0
DGX B2002 × ~1.9 TB M.2 NVMe, RAID 18 × 3.84 TB U.2 NVMe, RAID 0 (~30 TB)
Drive counts and sizes come from NVIDIA's DGX user guides and can change between configurations and SKUs. Check the user guide for the exact system.
StoragePurposeIf it fails
OS RAID 1DGX OS / BCM-provisioned OSOne drive can fail with no outage; replace it and rebuild
/raid RAID 0Fast local cache and scratch: datasets, NFS cache, container images, temporary job filesAny one drive lost = the whole array is lost. Recreate it and repopulate from shared storage.
Shared storage (over the storage network)Home directories, datasets, checkpoints, resultsProtected by the storage system (its own RAID/erasure coding, snapshots, backups)

9. Why /raid is RAID 0 (and why that's fine)

Why it's effective

  1. Aggregate bandwidth. Striping spreads each large read across all 8 drives at once, so a big sequential read gets roughly 8× one drive's throughput. That's what keeps a data loader feeding 8 GPUs.
  2. Aggregate IOPS. Small random reads (many small image or audio files) are spread across 8 controllers and their queues.
  3. All capacity usable. No space spent on mirrors or parity: ~30 TB usable from ~30 TB raw.
  4. No write penalty. No parity to compute or read-modify-write, so staging a dataset or writing scratch output is as fast as the drives allow.
  5. Simple and cheap in software. md RAID 0 has almost no CPU overhead.

Why the risk is acceptable

RAID 0 for speed and capacity where data is re-creatable; RAID 1 for the OS where availability matters; shared storage for anything that must survive. That's the DGX storage design in one sentence.
"Store the only copy of checkpoints or results on /raid" is wrong. So is "convert /raid to RAID 5 for safety on DGX": it cuts capacity and write performance and still doesn't replace shared storage. The local array is a cache.
Losing one RAID 0 member is also more likely than losing one specific drive: with 8 drives, the array fails if any of them fails. That's another reason nothing irreplaceable should live there.

10. Local caching techniques

FS-Cache with cachefilesd (persistent NFS cache)

Linux FS-Cache lets network filesystems (NFS) cache file data on a local disk. The cachefilesd daemon manages that cache. DGX systems use /raid as the cache location, so repeated reads of NFS-hosted datasets come from local NVMe instead of the network.

# /etc/cachefilesd.conf
dir /raid/fscache
tag dgxcache
brun 25%   bcull 15%   bstop 5%     # start culling when free space drops

sudo systemctl enable --now cachefilesd

# Mount NFS with the fsc option to enable caching for that mount
sudo mount -t nfs -o fsc,vers=4.1 nfs01:/datasets /mnt/datasets
cat /proc/fs/fscache/stats            # hit/miss counters
FS-Cache is transparent: users read /mnt/datasets as usual. The first epoch pulls from NFS, and later epochs hit the local cache. It's a read cache: writes still go to the NFS server.
DGX OS documents (and may preconfigure) cachefilesd with /raid/fscache. Parallel filesystems (Lustre, WEKA, Storage Scale) have their own client-side caching instead of FS-Cache.

Other caching patterns

TechniqueHowWhen
Dataset stagingCopy the dataset to /raid at job start (Slurm prolog, or the job's first step) with parallel tools (rsync in parallel, parallel/mpirun copy, fpsync)Datasets that fit in ~30 TB and are read many times
Page cacheLinux keeps recently read file data in spare DRAM (up to ~2 TB on DGX H100) automaticallyDatasets that fit in memory get RAM-speed reads after the first pass
Container image cachePoint Enroot/Docker storage at /raid (for example ENROOT_CACHE_PATH, ENROOT_DATA_PATH, Docker data-root)Big NGC images pulled once per node, not per job (see NGC mastery)
Scratch for job temp filesTMPDIR=/raid/tmp/$SLURM_JOB_ID, cleaned in the epilogShuffle buffers, compiled kernels, intermediate outputs
Burst buffersA fast tier in front of the parallel FS (some storage systems or schedulers manage it)Checkpoint bursts, write-heavy phases
Local caches need housekeeping: without cleanup (Slurm epilog, culling thresholds, quotas), /raid fills up and the next job fails with "No space left on device." Also, jobs scheduled to a different node find a cold cache. Node-local data and scheduler placement go together.

11. Shared storage: NFS and parallel filesystems

TypeExamplesStrengthsLimits
NFSLinux NFS server, NAS appliancesSimple, universal; home directories, software, small shared dataA single server path can bottleneck many GPU nodes; metadata-heavy workloads struggle
NFS over RDMA / nconnectNFS with RDMA transport or multiple TCP connectionsMuch higher throughput from the same protocolStill bounded by the server design
Parallel filesystemsLustre (for example DDN EXAScaler), IBM Storage Scale (GPFS), WEKA, BeeGFSData striped across many servers: aggregate bandwidth scales with servers; designed for thousands of clientsMore complex to run; need tuned clients
Scale-out NAS / all-flashVAST, NetApp, PureNFS-compatible with high parallel performanceVendor-specific features
Object storageS3-compatible storesCheap, huge, durable; great for raw data lakesNot POSIX; usually staged or streamed rather than mounted
DGX BasePOD / SuperPOD reference architectures use a dedicated storage network (Ethernet or InfiniBand, on separate NIC ports from the GPU compute fabric) and NVIDIA-certified high-performance storage partners. Keep storage traffic off the compute fabric so checkpoint writes don't slow NCCL collectives.
On DGX H100, the compute fabric uses the 8 ConnectX-7 ports (one per GPU); storage and in-band management use separate ports (BlueField-3 / ConnectX). See DGX H100 specs.

12. GPUDirect Storage (GDS)

Normally, reading a file into GPU memory goes storage → CPU memory (bounce buffer) → GPU. GPUDirect Storage lets storage DMA directly into GPU memory, skipping the CPU bounce buffer.

NVMe / NIC CPU memory GPU memory without GDS: bounce buffer, extra copy, CPU load with GDS: direct DMA (cuFile API)
PieceRole
cuFile API (libcufile)The API applications (or frameworks like DALI, RAPIDS, PyTorch extensions) use for GDS reads and writes
nvidia-fs kernel moduleEnables the direct path (lsmod | grep nvidia_fs)
gdscheck -pChecks the platform: driver, filesystem support, and whether GDS is usable (in /usr/local/cuda/gds/tools/)
gdsioGDS I/O benchmark
Supported storageLocal NVMe (ext4/xfs), NVMe-oF, and many parallel filesystems / NFS over RDMA from certified vendors
GDS gives higher bandwidth, lower latency, and lower CPU usage for I/O-bound GPU workloads. It's the storage counterpart of GPUDirect RDMA (which does the same for network traffic). Applications must use cuFile (directly or through a framework) to benefit.
GDS support depends on filesystem, RAID configuration, driver, and OFED versions. Run gdscheck -p and check the GDS support matrix. Without support, cuFile can fall back to a compatibility mode that still goes through CPU memory.

Enabling GDS, step by step

This follows NVIDIA's GDS Installation and Troubleshooting Guide and the DGX OS 7 user guide. On a BCM cluster, make these changes in the software image (packages, modprobe files) and the category (kernel parameters), not on single nodes.

  1. Check the hardware path. A GDS-capable data-center GPU (A100, H100, H200, B200, L4, L40S and others; see the support matrix), supported storage (local NVMe, NVMe-oF, or a GDS-enabled filesystem such as Lustre/EXAScaler, WekaFS, Storage Scale, BeeGFS, VAST/NFS over RDMA), and a working driver: nvidia-smi. Check PCIe placement with nvidia-smi topo -m. GDS is fastest when the NVMe drive or NIC sits under the same PCIe switch as the GPU.
  2. IOMMU off or pass-through (x86). Check with journalctl -k -b | grep -i iommu. NVIDIA recommends intel_iommu=off / amd_iommu=off for the best functionality and performance; iommu=pt is supported on some platforms (for example DGX A100). A fully enabled IOMMU isn't guaranteed to work. This step is skipped on Arm (Grace) platforms.
  3. Disable PCIe ACS for peer-to-peer performance: kernel parameter pci=disable_acs_redir=…, then update-grub and reboot. gdscheck -p reports switches that still have ACS enabled.
  4. Storage transport drivers, only if needed. NVMe, NVMe-oF and NFS over RDMA need NVIDIA's patched storage drivers: DOCA (doca-ofed, mlnx-nvme-dkms, plus mlnx-nfsrdma-dkms for NFS over RDMA), or the legacy mlnxofedinstall --with-nvmf --with-nfsrdma. Run update-initramfs -u and reboot. Not required on DGX OS 6 or later. Don't mix MLNX_OFED and DOCA storage packages.
  5. Install GDS. DGX OS: sudo apt install nvidia-gds. This meta-package pulls in nvidia-fs (a DKMS kernel module), libcufile and gds-tools. On other distros it comes from the CUDA repository; from CUDA 13.4, nvidia-fs is installed separately from the nvidia-fs downloads page. The kernel headers for the running kernel must be present so DKMS can build the module.
  6. Load the module. sudo modprobe nvidia_fs, check with lsmod | grep nvidia_fs and cat /proc/driver/nvidia-fs/stats. For RDMA filesystems, lsmod | grep nvidia_fs | grep ib_core shows it's hooked into the RDMA stack. WekaFS and Storage Scale also need nvidia_peermem loaded (persist it with /etc/modules-load.d/).
  7. Prepare the filesystem. Only ext4 and XFS are supported block filesystems. ext4 must be mounted with data=ordered written explicitly in the mount options, or the library won't recognize it. GDS supports md RAID 0 only. NVMe devices with block-integrity capability aren't supported. For parallel filesystems, follow the vendor's GDS client settings (for Lustre, LNet multi-rail peer selection).
  8. Configure cuFile if the defaults don't fit. /etc/cufile.json is installed by the package. Edit it to list RDMA NIC IPs (rdma_dev_addr_list for WekaFS and NFS over RDMA), set logging, toggle allow_compat_mode, or deny-list mounts. Per-application or container overrides go in a separate file pointed to by CUFILE_ENV_PATH_JSON.
  9. Verify, then measure. /usr/local/cuda/gds/tools/gdscheck.py -p (older releases ship a gdscheck binary). It lists each filesystem or device as nvfs/dmabuf/p2pdma (real GDS paths) or compat, and shows IOMMU and ACS state. Then gdsio … -x 0 (GDS) compared with -x 1 (CPU path), and gds_stats -p <pid> -l 3 while the job runs.
journalctl -k -b | grep -i iommu                 # want: IOMMU off (or pt where supported)
sudo apt install nvidia-gds                      # DGX OS; pulls nvidia-fs (DKMS), libcufile, gds-tools
sudo modprobe nvidia_fs && lsmod | grep nvidia_fs
mount | grep data=ordered                        # ext4 must show data=ordered explicitly
/usr/local/cuda/gds/tools/gdscheck.py -p         # NVMe : nvfs  (not just "compat")
/usr/local/cuda/gds/tools/gdsio -f /raid/gds/f -d 0 -w 8 -s 10G -i 1M -x 0 -I 0
cat /proc/driver/nvidia-fs/stats                 # GDS read/write counters climbing = real GDS
tail cufile.log                                  # written in the app's working directory by default
DGX extras: on DGX A100/A800, NVIDIA recommends enabling NVMe relaxed ordering for GDS (sudo /bin/nvidia-relaxed-ordering-nvme.sh enable). NVMe interrupt coalescing is configured automatically by the nvidia-nvme-options package.

The newer path: PCI P2PDMA (no nvidia-fs for NVMe)

On recent stacks, local NVMe can use the upstream Linux PCI P2PDMA feature instead of nvidia-fs. It needs:

gdscheck -p then shows NVMe : p2pdma. If both paths are available, P2PDMA takes precedence. On x86, P2PDMA doesn't support RAID volumes (only Arm does). The DGX OS 7 GDS install steps are written for systems that do not use P2PDMA.

GDS exam gotchas

ClaimReality
"GDS data passes through host RAM / CPU caches"False on the GDS path: storage or the NIC DMAs straight into GPU memory. The CPU still runs the control path (open, submit, completion). In compatibility mode data does go through a CPU bounce buffer.
"GDS only works with local NVMe" / "only with InfiniBand storage"Both false. It covers local PCIe NVMe and remote RDMA-backed filesystems (and NVMe-oF).
"Loading nvidia-fs is enough"No. The filesystem must support GDS (ext4 with explicit data=ordered, XFS, or a GDS-enabled parallel FS), RAID must be RAID 0, IOMMU/ACS must be right, and the app must use cuFile (directly or through a framework).
"No /etc/cufile.json means no GDS"The package installs a default file and GDS works with its defaults. You edit it (or point CUFILE_ENV_PATH_JSON at an override) only to change behavior, for example RDMA NIC lists for WekaFS or NFS over RDMA.
"It's working, I got no errors"With allow_compat_mode true (the default), cuFile silently falls back to POSIX I/O. Prove the GDS path with gdscheck -p (nvfs/dmabuf/p2pdma, not compat), /proc/driver/nvidia-fs/stats, and gdsio -x 0 beating -x 1.
"modprobe nvidia_fs fails with a key/permission error"UEFI Secure Boot with a locally built (DKMS) module that isn't signed by an enrolled key. Sign it and enroll the key with MOK (mokutil), same as for the NVIDIA driver (bring-up guide). Don't just disable Secure Boot.
"GDS = GPUDirect RDMA"Related but different. GPUDirect RDMA (nvidia_peermem or DMA-BUF) is NIC ↔ GPU for networking such as NCCL. GDS is storage ↔ GPU through cuFile and nvidia-fs. RDMA filesystems use both.
"Turn the IOMMU fully on for safety"NVIDIA recommends off (or pt on supported platforms) for GDS on x86. A fully enabled IOMMU isn't guaranteed to work or perform.

13. Filesystems and tuning

TopicGuidance
ext4 vs XFSBoth are fine on NVMe. XFS handles very large files and parallel writers well; ext4 is the common default. DGX OS formats /raid with its documented default.
Mount optionsnoatime avoids a metadata write on every read
I/O schedulerNVMe usually uses none (the device handles ordering): cat /sys/block/nvme2n1/queue/scheduler
TRIM / discardTells the SSD which blocks are free, sustaining write performance. Prefer a periodic fstrim (timer) over the discard mount option.
Free spaceFlash performance degrades when nearly full. Keep headroom on /raid.
NUMA localityRun data-loader workers on CPUs local to the drives/NICs and GPUs they serve. Check with nvidia-smi topo -m and lstopo.
Many small filesMetadata overhead dominates. Pack samples into shards (WebDataset tar, TFRecord, Parquet).

14. Benchmarking with fio

# Sequential read bandwidth (large blocks, many jobs, direct I/O to bypass the page cache)
fio --name=seqread --directory=/raid/fiotest --rw=read --bs=1M --size=20G \
    --numjobs=16 --iodepth=32 --ioengine=libaio --direct=1 --group_reporting

# Random 4K read IOPS
fio --name=randread --directory=/raid/fiotest --rw=randread --bs=4k --size=10G \
    --numjobs=16 --iodepth=64 --ioengine=libaio --direct=1 --group_reporting

# Sequential write (staging / checkpoint-like)
fio --name=seqwrite --directory=/raid/fiotest --rw=write --bs=1M --size=20G \
    --numjobs=8 --iodepth=32 --ioengine=libaio --direct=1 --group_reporting
OptionWhy
--direct=1Bypasses the page cache; otherwise you measure RAM, not disks
--numjobs, --iodepthParallelism: NVMe needs many outstanding I/Os
--bs=1M vs 4kBandwidth test vs IOPS test
--directory (a file test)Safe: creates test files. Pointing --filename at a raw device (/dev/md1) destroys the filesystem on writes.
Benchmarking with dd or a single cp shows a fraction of NVMe capability (one stream, shallow queue). A "slow" result from dd doesn't mean the array is slow.
For shared storage, measure from many nodes at once (for example with fio --client, IOR, or mdtest for metadata). Single-client numbers hide aggregate limits.

15. Data loading and checkpointing patterns

Feeding the GPUs

Checkpoints

The bytes-per-parameter figure depends on precision, optimizer, and framework (for example whether FP32 master weights are kept). Use it as an order-of-magnitude estimate.

15b. Loading model weights across a cluster

A job can't start until its weights are in GPU memory. On one node that's a file read; across dozens of nodes it's a storage and network event.

The problem: a thundering herd

A 70B-parameter model in BF16 is about 140 GB (2 bytes per parameter). If 32 inference replicas each read the full file from shared storage at the same moment, that's about 4.5 TB requested in one burst. NFS on the in-band network collapses under that. A parallel filesystem handles it far better, but it still competes with every other job's checkpoint traffic. Load time becomes start-up time, and for autoscaled inference it becomes user-visible latency.

What each GPU actually needs

ParallelismWhat a GPU holdsLoad consequence
Tensor / pipeline parallelOnly its slice (a fraction of each layer, or a range of layers)With a sharded checkpoint format, each rank reads only its own bytes. Nobody needs the whole file.
Data parallel replicasEach replica (one TP×PP group) holds a full copy of the modelReplicas read the same bytes again and again. This is the duplication that caching or broadcast removes.
Sharded data parallel (FSDP, ZeRO-3)A slice of parameters and optimizer state per rankResume reads are spread across all ranks, much like tensor parallelism

Two loading patterns

Staged local cacheDirect sharded streaming
HowCopy the weights to each node's /raid once, then every GPU loads from local NVMeEach rank reads its own shard straight from the parallel filesystem in parallel
ToolsSlurm prolog or sbcast (copies a file to local disk on every allocated node); Kubernetes init container or DaemonSet that warms a hostPath cache; NIM's model cache (NIM_CACHE_PATH) on local disk or a shared volumeDistributed checkpoint formats (PyTorch Distributed Checkpoint, Megatron/NeMo distributed checkpoints) where each rank writes and reads its own files
NetworkStorage fabric (or in-band from NGC/Hugging Face) once per node, then local PCIeStorage fabric on every load, spread across many storage servers
Best forInference fleets, autoscaling, repeated restarts of the same model, fine-tuning from a fixed baseLarge training jobs resuming from their own recent checkpoint (written moments ago, never cached anywhere)
Watch outCache is lost if /raid is wiped or the node is replaced, and stale versions need invalidationNeeds a parallel FS sized for the burst; NFS can't do this
Rule of thumb: read-many, change-rarely weights (inference, base models) belong in a local cache staged once per node. Just-written checkpoints are streamed back as shards from the parallel filesystem. Either way the bytes travel over the storage fabric (or in-band for internet pulls), never the compute fabric, unless a loader deliberately broadcasts between GPUs.
Part B: Changing node storage the BCM way

16. The scenario

A BCM-managed DGX cluster is already in production, and the root partition on the compute nodes' local OS drives turns out to be too small. How do you grow it so the new size sticks on every node, including after reboots, reprovisioning, and future node replacements?

Three ideas drive the answer:

17. Quick recap: BCM, the head node, and software images

With BCM, you never treat a compute node as the place where truth lives. You change the definition on the head node, then let BCM apply it to the nodes.
A franchise restaurant chain. To change the kitchen layout, you don't let each branch manager knock down walls however they like. Head office updates the blueprint, and every branch is rebuilt to match it.

18. Where BCM keeps the partition layout

BCM stores the partition layout as part of the node's provisioning definition on the head node, not on the node. In BCM this is the disk setup: an XML description of disks, partitions, sizes, filesystems, mount points, and software RAID. It's attached to the category (or to an individual node as an override), and it's used together with the software image whenever the node is provisioned.

<!-- simplified idea of a BCM disk setup -->
<diskSetup>
  <device>
    <blockdev>/dev/nvme0n1</blockdev>
    <partition id="efi">  <size>512M</size> <filesystem>fat</filesystem>  <mountPoint>/boot/efi</mountPoint> </partition>
    <partition id="root"> <size>200G</size> <filesystem>ext4</filesystem> <mountPoint>/</mountPoint> </partition>
    <partition id="var">  <size>max</size>  <filesystem>ext4</filesystem> <mountPoint>/var</mountPoint> </partition>
  </device>
  <!-- plus RAID definitions, e.g. the OS mirror and the /raid stripe -->
</diskSetup>

The idea to remember is that both the OS contents and the disk layout (including RAID) are defined centrally on the head node.

19. What "reprovisioning" means (AUTO vs FULL)

Provisioning means putting the OS onto a node. Reprovisioning means doing it again so the node picks up a changed definition.

Install modeWhat the node installer doesWhen it's used
AUTO (default)Checks that the existing partitions match the disk setup. If they match, it syncs only the changed files from the image (fast). If they don't match, it falls back to a full install.Normal reboots
FULLRepartitions the disk according to the disk setup, creates fresh filesystems, and copies the whole image. Local data on those partitions is wiped.New nodes, corrupted disks, partition layout changes
NOSYNCDoesn't touch the disk.Rare special cases
Changing the size of a partition is a layout change, not a file change, so the node needs a full reprovision to repartition its disk. Normal file updates (new packages, config) can be pushed with a simple sync.
A FULL install wipes the partitions it rebuilds. Make sure nothing important is stored only on the node's local disks, and drain the node in Slurm first so no jobs are running on it.

20. Protecting /raid and other local data

cmsh
% category use dgx-h100
% show                      # look for exclude-list properties for sync/update/full install
% set excludelistupdate     # opens an editor; e.g. ensure "- /raid/*" style entries exist
% commit
Exclude-list property names and syntax vary between BCM versions. Check the BCM administrator manual for your release. The concept to know is that local data directories are excluded from image sync, and a FULL install wipes whatever it repartitions.
Because /raid is a cache, losing it in a FULL reprovision is acceptable. But exclude it from routine syncs so normal reboots and image updates don't throw away a warm cache.

21. Why fixing nodes by hand over SSH backfires

The by-hand approach (SSH in and run parted / resize2fs on each node) feels natural, but in BCM it's wrong for several reasons:

  1. It isn't persistent. The head node still has the old layout. The next time BCM reprovisions that node (a new node, a reinstall after a failure, or AUTO noticing the partitions don't match), it rebuilds the disk to the old size and your change is gone.
  2. It causes configuration drift. Some nodes end up resized and some don't, so the nodes are no longer identical, which is exactly what BCM exists to prevent.
  3. It doesn't scale. Doing it by hand on 32, 128, or 1000 DGX nodes is slow and error-prone.
  4. It's risky. Resizing a live root partition (on top of an md mirror) by hand can corrupt the filesystem. BCM's reprovisioning builds the layout cleanly from a known definition.
Writing a correction in pencil on your own photocopy of a contract. The next time someone prints a fresh copy from the master file, your correction isn't there.

22. Know your tools: which ones touch storage?

ToolWhat it's forStorage role
BCM (cmsh, Base View)Provisioning nodes, software images, disk layout, categories, exclude listsDefines node storage layout centrally
mdadm, /proc/mdstatSoftware RAID create, inspect, rebuildRAID state on a node
nvme-cliNVMe inventory, SMART health, firmware, eraseDrive health
nvsmDGX system health, including drives and RAIDHealth reporting
parted / resize2fsLow-level partition and filesystem tools on one machineSingle-node only; not persistent under BCM
fio / gdsioStorage benchmarksPerformance measurement
DCGM (dcgmi)GPU monitoring, health checks, diagnosticsNone. "DCGM storage policies" isn't a thing.
nvidia-smiQuerying and configuring GPUsNone. It doesn't partition disks.
When an answer uses a GPU tool for a disk task, it's a distractor. Match the tool to the layer: GPU, OS/storage, or cluster provisioning.

23. Weighing the common approaches

WRONGLog in to every node and grow the partition live with parted and resize2fs

These are real tools and would work on a standalone server, but in BCM the change isn't persistent: the head node's definition still has the old layout and will put it back on the next reprovision. It also causes drift between nodes and doesn't scale.

WRONGUse a DCGM policy to control how much disk GPU jobs get

DCGM is for GPU monitoring and diagnostics. It has no ability to partition disks or set storage quotas.

CORRECTChange the disk layout (and image, if needed) centrally on the head node, then reprovision the nodes

This follows BCM's model: change the central definition on the head node, then reprovision the nodes so they're rebuilt to match. The change is persistent, consistent across all nodes, and repeatable for new or replacement nodes.

WRONGUse nvidia-smi to reassign local disk space set aside for GPU offload

nvidia-smi configures GPUs (clocks, power, MIG, ECC), not SSD partitions. Disk space "set aside for GPU offload" isn't something nvidia-smi configures.

24. What the real procedure looks like

  1. Drain the nodes in Slurm so no jobs are running on them:
    scontrol update nodename=dgx[01-04] state=drain reason="repartition OS disk"
  2. Back up anything stored only on the nodes' local disks (ideally nothing: /raid is a cache).
  3. Edit the disk layout on the head node for the category:
    cmsh
    % category use dgx-h100
    % set disksetup        # opens the disk setup XML in an editor: change the root partition size
    % commit
    (If the OS contents also need to change, update the software image on the head node too.)
  4. Tell BCM the nodes need a full install on their next boot:
    % device use dgx01
    % set nextinstallmode full
    % commit
  5. Reboot the nodes (BCM power control through the BMC; see Redfish & BMC). They PXE boot, and the node installer repartitions the disks with the new layout and copies the image.
  6. Verify on a node (lsblk, df -h, cat /proc/mdstat), then resume the nodes in Slurm.

Any new or replacement DGX added to that category later gets the new layout automatically. That's the payoff of doing it centrally.

25. How to spot the right answers on similar questions

Practice

26. "Where should this data live?" chooser

Pick a question above.

27. Sample outputs

What the commands in this guide print. Expand a command to see a typical result and what to check in it.

Illustrative output, not captured from a real system. Hostnames, serial numbers, GUIDs, MAC and IP addresses are invented, and columns and wording vary between versions. Learn the shape of each output and the fields called out under it.
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTDisks, partitions, RAID, mounts
NAME          SIZE TYPE  FSTYPE            MOUNTPOINT
nvme0n1       1.7T disk
├─nvme0n1p1   512M part  vfat              /boot/efi
└─nvme0n1p2   1.7T part  linux_raid_member
  └─md0       1.7T raid1 ext4              /
nvme1n1       1.7T disk
├─nvme1n1p1   512M part  vfat
└─nvme1n1p2   1.7T part  linux_raid_member
  └─md0       1.7T raid1 ext4              /
nvme2n1       3.5T disk  linux_raid_member
└─md1        27.9T raid0 ext4              /raid
nvme3n1       3.5T disk  linux_raid_member
└─md1        27.9T raid0 ext4              /raid
...
nvme9n1       3.5T disk  linux_raid_member
└─md1        27.9T raid0 ext4              /raid

What to look at: Expect / on md0 (raid1 over the two M.2 drives) and /raid on md1 (raid0 over the eight U.2 drives, about 28T). A data drive with no md1 under it, or /raid missing its mount point, means the array is incomplete or not mounted.

sudo nvme listAll NVMe drives: model, size, firmware
Node                  SN                   Model                                    Namespace Usage                      Format           FW Rev
--------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1          S6EXNE0T100001       SAMSUNG MZ1L21T9HCLS-00A07               1           1.92  TB /   1.92  TB    512   B +  0 B   GDC7302Q
/dev/nvme1n1          S6EXNE0T100002       SAMSUNG MZ1L21T9HCLS-00A07               1           1.92  TB /   1.92  TB    512   B +  0 B   GDC7302Q
/dev/nvme2n1          X1A0A0EXAMPL         KIOXIA KCM6DRUL3T84                      1           3.84  TB /   3.84  TB    512   B +  0 B   0107
/dev/nvme3n1          X1A0A0EXAMPM         KIOXIA KCM6DRUL3T84                      1           3.84  TB /   3.84  TB    512   B +  0 B   0107
...
/dev/nvme9n1          X1A0A0EXAMPT         KIOXIA KCM6DRUL3T84                      1           3.84  TB /   3.84  TB    512   B +  0 B   0106

What to look at: A DGX H100 should list 10 drives: two 1.92 TB boot M.2 and eight 3.84 TB data U.2. A missing drive or one with a different FW Rev (nvme9n1 here) is a finding to fix before acceptance.

sudo nvme smart-log /dev/nvme2Drive health and endurance
Smart Log for NVME device:nvme2 namespace-id:ffffffff
critical_warning                        : 0
temperature                             : 38 C (311 Kelvin)
available_spare                         : 100%
available_spare_threshold               : 10%
percentage_used                         : 3%
endurance group critical warning summary: 0
data_units_read                         : 412,904,113
data_units_written                      : 98,233,710
host_read_commands                      : 3,301,882,019
host_write_commands                     : 905,771,402
controller_busy_time                    : 1,894
power_cycles                            : 41
power_on_hours                          : 6,512
unsafe_shutdowns                        : 4
media_errors                            : 0
num_err_log_entries                     : 0
Warning Temperature Time                : 0
Critical Composite Temperature Time     : 0

What to look at: critical_warning and media_errors should both be 0; any non-zero critical_warning means act now. Watch percentage_used for wear (it can exceed 100%) and available_spare dropping toward its threshold.

sudo nvme id-ctrl /dev/nvme2 | grep -E 'mn|fr'Drive model and firmware revision
mn        : KIOXIA KCM6DRUL3T84
fr        : 0107
frmw      : 0x17
mntmt     : 273

What to look at: mn is the model and fr the firmware revision; compare fr across all data drives and nodes. The extra lines (frmw, mntmt) only match the grep pattern and can be ignored.

sudo nvsm show healthDGX health summary incl. drives
Checks
------
Verify installed DIMM memory sticks ...................... Healthy
Number of logical CPU cores [224] ........................ Healthy
Verify chassis fan presence .............................. Healthy
...
Check SMART status of NVMe device nvme2n1 ................ Healthy
Check SMART status of NVMe device nvme9n1 ................ Healthy
Verify md0 RAID array status ............................. Healthy
Verify md1 RAID array status ............................. Healthy
Verify GPU 0000:1b:00.0 link speed [32GT/s] .............. Healthy
...

Health Summary
--------------
205 out of 205 checks are healthy
0 out of 205 checks are unhealthy
0 out of 205 checks are unknown
0 out of 205 checks are informational

Overall system status is Healthy

What to look at: The summary should read Overall system status is Healthy with 0 unhealthy checks. Any Unhealthy SMART or RAID line names the drive or array to investigate, and nvsm dump health collects it for support.

cat /proc/mdstatState of all md RAID arrays
Personalities : [raid1] [raid0] [linear] [multipath] [raid6] [raid5] [raid4] [raid10]
md1 : active raid0 nvme9n1[7] nvme8n1[6] nvme7n1[5] nvme6n1[4] nvme5n1[3] nvme4n1[2] nvme3n1[1] nvme2n1[0]
      30004846592 blocks super 1.2 512k chunks

md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
      1874715648 blocks super 1.2 [2/2] [UU]
      bitmap: 3/14 pages [12KB], 65536KB chunk

unused devices: <none>

What to look at: md0 should show [2/2] [UU]; [2/1] [U_] means the OS mirror is degraded and running on one drive. RAID 0 has no redundancy indicator, so for md1 check that all eight members are listed.

sudo mdadm --detail /dev/md0Array state, members, failed devices
/dev/md0:
           Version : 1.2
     Creation Time : Mon Oct  5 10:12:44 2026
        Raid Level : raid1
        Array Size : 1874715648 (1787.86 GiB 1919.71 GB)
     Used Dev Size : 1874715648 (1787.86 GiB 1919.71 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Tue Nov 10 19:05:12 2026
             State : clean, degraded
    Active Devices : 1
   Working Devices : 1
    Failed Devices : 1
     Spare Devices : 0

Consistency Policy : bitmap

              Name : dgx01:0  (local to host dgx01)
              UUID : 3a1f9c2e:5b7d4e10:9c8a7b6d:1e2f3a4b
            Events : 4821

    Number   Major   Minor   RaidDevice State
       0     259        2        0      active sync   /dev/nvme0n1p2
       -       0        0        1      removed

       1     259        5        -      faulty   /dev/nvme1n1p2

What to look at: A healthy mirror shows State : clean with 2 active devices and two active sync rows. Here State is clean, degraded and nvme1n1p2 is faulty, so that member must be removed, the drive replaced, and the new partition added back.

sudo mdadm /dev/md0 --fail /dev/nvme1n1p2 --remove /dev/nvme1n1p2Remove a failed mirror member
mdadm: set /dev/nvme1n1p2 faulty in /dev/md0
mdadm: hot removed /dev/nvme1n1p2 from /dev/md0

What to look at: Both lines should appear before you pull the drive. "Device or resource busy" on remove means the member was not marked faulty first.

sudo mdadm /dev/md0 --add /dev/nvme1n1p2Re-add a drive and start rebuild
mdadm: added /dev/nvme1n1p2

$ cat /proc/mdstat
md0 : active raid1 nvme1n1p2[2] nvme0n1p2[0]
      1874715648 blocks super 1.2 [2/1] [U_]
      [===>.................]  recovery = 17.4% (326201344/1874715648) finish=41.2min speed=626104K/sec
      bitmap: 3/14 pages [12KB], 65536KB chunk

What to look at: A recovery progress bar means the rebuild started; the array stays [U_] until it reaches 100% and then shows [UU]. If no recovery line appears, the new partition is likely too small or the wrong device.

cat /proc/fs/fscache/statsFS-Cache hit/miss counters
FS-Cache statistics
Cookies: idx=3 dat=12873 spc=0
Objects: alc=12850 nal=0 avl=12850 ded=0
ChkAux : non=0 ok=0 upd=0 obs=0
Pages  : mrk=1532876 unc=0
Acquire: n=12876 nul=0 noc=0 ok=12876 nbf=0 oom=0
Lookups: n=12850 neg=12840 pos=10 crt=12840 tmo=0
Invals : n=0 run=0
Updates: n=0 nul=0 run=0
Relinqs: n=24 nul=0 wcr=0 rtr=0
Retrvls: n=482391 ok=401220 wt=1203 nod=81171 nbf=0 int=0 oom=0
Retrvls: ops=482391 owt=2 abt=0
Stores : n=81171 ok=81171 agn=0 nbf=0 oom=0
Stores : ops=81171 run=162342 pgs=81171 rxd=81171 olm=0
...

What to look at: On Retrvls, ok counts pages served from the local cache and nod counts misses that went to NFS; ok should climb on the second epoch. All zeros means the NFS mount lacks the fsc option or cachefilesd isn't running.

journalctl -k -b | grep -i iommuIOMMU state for GPUDirect Storage
Nov 10 08:12:01 dgx01 kernel: Command line: BOOT_IMAGE=/boot/vmlinuz-5.15.0-1063-nvidia root=/dev/md0 ro intel_iommu=off console=tty0
Nov 10 08:12:01 dgx01 kernel: Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.15.0-1063-nvidia root=/dev/md0 ro intel_iommu=off console=tty0
Nov 10 08:12:01 dgx01 kernel: DMAR: IOMMU disabled

What to look at: For GDS through nvidia-fs you want IOMMU disabled (or pass-through where supported). Lines like "DMAR: IOMMU enabled" or "Default domain type: Translated" mean P2P DMA goes through the IOMMU and GDS may fall back or fail.

sudo modprobe nvidia_fs && lsmod | grep nvidia_fsLoad and confirm the GDS kernel module
nvidia_fs             266240  0

What to look at: One nvidia_fs line means the module is loaded. No output, or "Key was rejected by service" from modprobe, usually means Secure Boot is blocking an unsigned DKMS module.

mount | grep data=orderedext4 journal mode for GDS
/dev/md1 on /raid type ext4 (rw,relatime,stripe=256,data=ordered)

What to look at: GDS on ext4 needs data=ordered to appear explicitly in the mount options. If /raid is missing from this output, add data=ordered to its fstab or BCM fsmount options and remount.

/usr/local/cuda/gds/tools/gdscheck.py -pIs GPUDirect Storage usable here?
 GDS release version: 1.7.2.11
 nvidia_fs version:  2.17 libcufile version: 2.12
 Platform: x86_64
 ============
 ENVIRONMENT:
 ============
 =====================
 DRIVER CONFIGURATION:
 =====================
 NVMe P2PDMA        : Unsupported
 NVMe               : Supported
 NVMeOF             : Unsupported
 SCSI               : Unsupported
 ...
 NFS                : Unsupported
 WekaFS             : Unsupported
 Userspace RDMA     : Unsupported
 --Mellanox PeerDirect : Enabled
 --rdma library        : Not Loaded (libcufile_rdma.so)
 =====================
 CUFILE CONFIGURATION:
 =====================
 properties.use_pci_p2pdma : false
 properties.use_compat_mode : true
 properties.force_compat_mode : false
 ...
 =========
 GPU INFO:
 =========
 GPU index 0 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 ...
 GPU index 7 NVIDIA H100 80GB HBM3 bar:1 bar size (MiB):131072 supports GDS, IOMMU State: Disabled
 ==============
 PLATFORM INFO:
 ==============
 IOMMU: disabled
 Nvidia Driver Info Status: Supported(Nvidia Open Driver Installed)
 Platform verification succeeded

What to look at: NVMe : Supported, every GPU "supports GDS", and Platform verification succeeded are what you want. Unsupported for your filesystem, "Found ACS enabled for switch", or IOMMU: enabled mean I/O will silently use compat mode while use_compat_mode is true.

/usr/local/cuda/gds/tools/gdsio -f /raid/gds/f -d 0 -w 8 -s 10G -i 1M -x 0 -I 0GDS read throughput test
IoType: READ XferType: GPUD Threads: 8 DataSetSize: 10485760/10485760(KiB) IOSize: 1024(KiB) Throughput: 12.851403 GiB/sec, Avg_Latency: 607.312500 usecs ops: 10240 total_time 0.778164 secs

What to look at: XferType GPUD means the GPU-direct path (-x 0). Rerun with -x 1 (CPU path); if GPUD isn't clearly faster, or the run errors with compat mode disabled, GDS isn't really active.

cat /proc/driver/nvidia-fs/statsGDS driver counters
GDS Version: 1.7.2.11
NVFS statistics(ver: 4.0)
NVFS Driver(version: 2.17.5)
Mellanox PeerDirect Supported: True
IO stats: Disabled, peer IO stats: Disabled
Logging level: info

Active Shadow-Buffer (MiB): 0
Active Process: 0
Reads                           : err=0 io_state_err=0
Sparse Reads                    : n=0 io=0 holes=0 pages=0
Writes                          : err=0 io_state_err=0 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0
Mmap                            : n=8 ok=8 err=0 munmap=8
Bar1-map                        : n=8 ok=8 err=0 free=8 callbacks=0 active=0 delay-frees=0
Error                           : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0
Ops                             : Read=10240 Write=0 BatchIO=0

What to look at: The Ops Read and Write counters should climb while a GDS job runs; if they stay at 0, the application is using the POSIX compat path. Non-zero err values or Error counters point to driver or DMA mapping problems.

fio --name=seqread --directory=/raid/fiotest --rw=read --bs=1M --size=20G --numjobs=16 --iodepth=32 --ioengine=libaio --direct=1 --group_reportingSequential read bandwidth of /raid
seqread: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=32
...
fio-3.28
Starting 16 processes
Jobs: 16 (f=16): [R(16)][100.0%][r=48.6GiB/s][r=49.8k IOPS][eta 00m:00s]
seqread: (groupid=0, jobs=16): err= 0: pid=40211: Tue Nov 10 19:40:02 2026
  read: IOPS=49.1k, BW=47.9GiB/s (51.5GB/s)(320GiB/6676msec)
    slat (usec): min=8, max=1210, avg=21.40, stdev=9.85
    clat (usec): min=412, max=48121, avg=10392.11, stdev=2101.66
     lat (usec): min=431, max=48140, avg=10413.62, stdev=2101.70
    clat percentiles (usec):
     |  1.00th=[ 5604],  5.00th=[ 7111], 50.00th=[10421], 95.00th=[13829],
     | 99.00th=[16581], 99.90th=[21890], 99.99th=[37487]
  cpu          : usr=0.61%, sys=6.12%, ctx=318201, majf=0, minf=8457
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
...
Run status group 0 (all jobs):
   READ: bw=47.9GiB/s (51.5GB/s), 47.9GiB/s-47.9GiB/s (51.5GB/s-51.5GB/s), io=320GiB (344GB), run=6676-6676msec

Disk stats (read/write):
    md1: ios=327012/0, merge=0/0, ticks=3391201/0, in_queue=3391201, util=99.71%, aggrUtil=99.60%

What to look at: Read the BW on the READ summary line and compare it to the node's baseline and to other nodes. err= must be 0, and a node far below its peers usually has a missing RAID member, a drive at reduced PCIe link, or a test that hit the page cache without --direct=1.

cmsh -c "category use dgx-h100; get excludelistupdate"Paths BCM won't touch on imageupdate
# Exclude list for imageupdate (sync from image to running node)
- /cm/shared/*
- /home/*
- /proc/*
- /sys/*
- /dev/*
- /tmp/*
- /raid/*
- /var/log/*
- /var/spool/*
- /var/lib/docker/*
...

What to look at: /raid/* must be on the update and sync exclude lists, or an imageupdate can delete the node-local cache. A missing /home/* or /cm/shared/* entry is equally dangerous because those are shared mounts.

scontrol update nodename=dgx[01-04] state=drain reason="repartition OS disk"Drain nodes before repartitioning
(no output on success)

$ sinfo -R
REASON                                   USER      TIMESTAMP           NODELIST
repartition OS disk                      root      2026-11-10T19:45:12 dgx[01-04]

What to look at: Success prints nothing; confirm with sinfo -R that the nodes show your reason. Wait until running jobs finish and the nodes show drained (not draining) before setting a FULL install.

[bcm-head01->device[dgx01]]% set nextinstallmode fullOne-time FULL reinstall on next boot
[bcm-head01->device[dgx01]]% set nextinstallmode full
[bcm-head01->device*[dgx01*]]% commit
[bcm-head01->device[dgx01]]% get nextinstallmode
FULL
[bcm-head01->device[dgx01]]% get installmode
AUTO

What to look at: nextinstallmode applies to the next boot only and is cleared afterwards, while installmode stays AUTO. Setting installmode itself to FULL would wipe and repartition the node, including /raid, on every boot.

28. Scenarios

29. Searchable reference

ItemMeaning

30. Flashcards (click to flip)

31. Exam traps

  1. DGX /raid is RAID 0 (speed + capacity for a cache); the OS drives are RAID 1.
  2. RAID 0 survives zero drive failures. RAID 1 survives n−1. RAID 5 one, RAID 6 two.
  3. RAID is not a backup.
  4. Checkpoints and results go to shared storage, never only to /raid.
  5. DGX uses software RAID (mdadm): cat /proc/mdstat, mdadm --detail.
  6. [U_] in /proc/mdstat = degraded mirror.
  7. NFS caching on DGX: cachefilesd + /raid/fscache + mount option fsc.
  8. GPUDirect Storage: storage → GPU memory directly through cuFile / nvidia-fs; check with gdscheck -p.
  9. fio --direct=1 to avoid measuring the page cache; NVMe needs parallelism (numjobs, iodepth).
  10. NVMe health: nvme smart-log (critical_warning, percentage_used, media_errors).
  11. BCM layout change → edit disk setup on the head node → FULL install. SSH + parted isn't persistent.
  12. Exclude /raid from image syncs so routine updates don't wipe the cache.
  13. DCGM and nvidia-smi don't manage disks.
  14. Keep storage traffic on the storage network, not the GPU compute fabric.
  15. The DGX OS lives on the M.2 RAID 1 mirror, not on /raid. /raid is cache and scratch.
  16. $HOME is NFS over in-band. It's not the place for datasets, checkpoints, or model weights.
  17. With tensor/pipeline parallelism each GPU loads only its shard. Duplicate reads come from data-parallel replicas, which is what local caching fixes.
  18. Object storage (S3) isn't a POSIX working directory: stage or stream from it.
  19. GDS: no errors ≠ GDS active. Compatibility mode silently uses the CPU path; check gdscheck -p for nvfs/dmabuf/p2pdma.
  20. GDS prerequisites beyond nvidia-fs: IOMMU off/pt on x86, ACS disabled, ext4 with explicit data=ordered or XFS, RAID 0 only, and a cuFile-using app.

32. Practice quiz (34 questions)

Score: 0 / 0

33. Glossary

TermMeaning
Partition / filesystemA slice of a disk / the structure inside it that stores files (ext4, xfs).
NVMe / namespaceFlash storage protocol over PCIe / a logical disk exposed by an NVMe controller.
M.2 / U.2NVMe form factors: small internal stick (DGX OS) / 2.5" hot-swap drive (DGX data).
DWPD / TBWSSD endurance ratings: drive writes per day / total terabytes written.
RAID 0 / 1 / 5 / 6 / 10Stripe / mirror / single parity / double parity / striped mirrors.
mdadm / mdLinux software RAID tool / kernel driver (/dev/mdX).
/raidDGX local data array (RAID 0 of U.2 NVMe), used as cache/scratch.
FS-Cache / cachefilesdKernel caching layer for network filesystems / the daemon managing the on-disk cache.
Page cacheFile data cached in spare RAM by the Linux kernel.
Parallel filesystemStorage striped across many servers for aggregate bandwidth (Lustre, Storage Scale, WEKA, BeeGFS).
NVMe-oFNVMe over Fabrics (RDMA or TCP).
GPUDirect Storage / cuFile / nvidia-fsDirect storage↔GPU DMA / its API / its kernel module.
fioFlexible I/O tester for storage benchmarks.
DALINVIDIA Data Loading Library: GPU-accelerated decode and augmentation.
BCM / head node / software image / categoryCluster manager / its central server / master OS tree / group of nodes sharing image and settings.
Disk setupBCM's XML definition of a node's partitions, filesystems, mount points, and RAID.
AUTO / FULL install, nextinstallmodeSync if layout matches / repartition and copy everything; the setting forcing the next mode.
Exclude listsBCM category settings that keep node-local paths (like /raid) from being overwritten by image sync.
Configuration driftNodes becoming different from each other because of manual, local changes.
Drain (Slurm)Stop scheduling new jobs on a node so it can be safely maintained.