Using dd Safely: Swap Files, Large Test Files, and Disk Images

· Published · 18 min read

Separate storage workflows show large-file allocation, protected swap activity, and a hazard-bounded raw block-device copy

dd can create a test file, populate a swap file, capture a disk image, or overwrite the wrong device with equal efficiency. The safe way to use it is to identify the job first, choose the tool that matches that job, verify every path, and define how success and rollback will be proved.

The examples use /var/tmp/nw-storage-lab, documentation device names, and small sizes where possible. Commands that write a block device are retained because they are useful, but they are marked Unsafe and must never be pasted before the source and destination have been independently verified.

Choose the operation before choosing the command

GoalGood starting toolWhat it proves
Create a logical file quicklytruncateApplication handling of a stated file length; it may allocate almost no disk blocks.
Reserve filesystem space quicklyfallocatePreallocation on a supporting filesystem; it does not write realistic payload data.
Create a fully written zero-filled filedd if=/dev/zeroSequential write path and actual allocation, subject to filesystem and storage behavior.
Create incompressible test datahead or dd from /dev/urandomBehavior with high-entropy bytes; generation can consume substantial CPU and storage bandwidth.
Create a portable swap-file backing areadd from /dev/zero, then mkswapA populated, non-sparse file on filesystems that support file-backed swap.
Measure storage performancefio with a reviewed workloadDefined block size, queue depth, read/write mix, duration, and durability policy.
Measure network capacityiperf3 between approved endpointsNetwork throughput without mixing disk, filesystem, encryption, and application limits.
Recover a failing deviceGNU ddrescueRetry-aware recovery with a map file; ordinary dd is not the first-choice recovery tool.

A large file can be useful for upload limits, download handling, storage alerts, backup tests, LAN transfers, and development workflows. Do not assume one file is suitable for every test. A sparse zero-filled file may compress or deduplicate almost completely, while random data may stress CPU and entropy generation more than the target application does.

Read a dd command from left to right

OperandMeaningFailure to avoid
if=FILEInput file or device; standard input when omittedReversing input and output during a disk copy
of=FILEOutput file or device; standard output when omittedOverwriting an existing file, filesystem, partition, or whole disk
bs=SIZEInput and output block sizeAssuming block size changes the final byte count independently of count
count=NCopy N input blocksForgetting that total bytes are normally bs × count
skip=NSkip N input blocksUsing the wrong input block-size unit
seek=NSkip N output blocks before writingDamaging data at the wrong output offset
iflag=fullblockAccumulate short input reads into complete blocksCounting read calls instead of full blocks when input can return short reads
status=progressPeriodically print bytes and rate to standard errorTreating the displayed rate as a complete benchmark
conv=fdatasyncFlush output data before finishingTiming only cached writes
conv=fsyncFlush output data and metadata before finishingAssuming command completion always means durable storage without a sync conversion
conv=exclFail if the output file already existsSilently truncating an existing regular file
conv=sparseSeek over all-zero output blocks where supportedUsing the resulting holey file as swap or as proof of allocated capacity
conv=noerror,syncContinue after read errors and pad bad input blocksUsing it as a substitute for a recovery tool with a persistent retry map

GNU size suffixes matter. bs=1M count=1024 writes 1 GiB because GNU M represents 1,048,576 bytes. A copied command such as bs=1024 count=1024000 writes 1,048,576,000 bytes, which is 1.048576 GB but only 0.9765625 GiB. State whether a requirement uses decimal GB or binary GiB.

Prepare a safe working directory

sudo install -d -m 0750 -o root -g root /var/tmp/nw-storage-lab
cd /var/tmp/nw-storage-lab
pwd
df -hT .
df -i .
findmnt -T . -o TARGET,SOURCE,FSTYPE,OPTIONS
ls -la

Confirm available bytes and inodes, filesystem type, quotas, encryption, snapshots, thin provisioning, and the cleanup owner. A successful 10 GiB allocation on a thin or deduplicating layer does not prove that 10 GiB of physical capacity is safely available.

Create large files with the right allocation behavior

Logical sparse file with truncate

truncate -s 10G logical-10g.bin
ls -lh logical-10g.bin
du -h logical-10g.bin
stat --format='logical=%s bytes allocated=%b blocks block_unit=%B' logical-10g.bin

The file reports a 10 GiB logical length, but its holes consume few data blocks. This is useful for code paths that inspect length. It is unsuitable for proving free-space consumption, sustained writes, backup volume, or a valid swap file.

Preallocated file with fallocate

fallocate -l 10G allocated-10g.bin
ls -lh allocated-10g.bin
du -h allocated-10g.bin
stat --format='logical=%s bytes allocated=%b blocks block_unit=%B' allocated-10g.bin

fallocate reserves blocks quickly on supporting filesystems, usually without writing ten GiB of zeroes through the storage stack. Its exact behavior and swap suitability depend on the filesystem and kernel. Do not use it as a universal substitute for the portable dd swap-file method.

Fully written zero-filled file with dd

dd if=/dev/zero of=zero-10g.bin \
  bs=1M count=10240 \
  status=progress conv=excl,fsync

ls -lh zero-10g.bin
du -h zero-10g.bin
sha256sum zero-10g.bin

conv=excl refuses to replace an existing regular file, and conv=fsync includes a final data-and-metadata flush before completion. Zeroes can still be compressed, deduplicated, or optimized by lower layers, so document the storage path before interpreting the rate.

High-entropy file for transfer and compression tests

head -c 10G </dev/urandom > random-10g.bin
sync -f random-10g.bin
ls -lh random-10g.bin
du -h random-10g.bin
sha256sum random-10g.bin

Unsafe at scale: this command intentionally writes ten GiB and may consume significant CPU, storage bandwidth, quota, snapshot capacity, replication bandwidth, and backup space. Start with 100M in a development environment and increase only after confirming headroom and cleanup.

XFS utility when xfs_mkfile is installed

xfs_mkfile -v 10g xfs-written-10g.bin
xfs_mkfile -n -v 10g xfs-sparse-10g.bin
ls -lh xfs-*.bin
du -h xfs-*.bin

The normal command pads with zeroes. The -n form intentionally creates a holey file. Use the explicit filename and allocation checks rather than inferring behavior from the utility name.

Know why /dev/zero and /dev/null are different

Special fileRead behaviorWrite behavior
/dev/zeroReturns zero bytes continuouslyAccepts and discards data
/dev/nullImmediately returns end-of-fileAccepts and discards data
/dev/urandomReturns pseudorandom bytesNot a normal output target for this workflow
dd if=/dev/null of=empty.bin bs=1M count=10 status=progress
stat --format='size=%s bytes' empty.bin

dd if=/dev/zero of=ten-mebibytes.bin \
  bs=1M count=10 status=progress conv=excl,fsync

The first command creates or truncates the output but copies zero bytes because the input is already at EOF. It cannot be used to populate a large file or swap file.

Prove logical size, allocation, and content separately

One command rarely answers all three questions. ls normally reports the apparent length seen by an application. du reports allocated filesystem space. stat exposes both the byte length and allocated block count. filefrag can show extents and holes on supporting Linux filesystems.

EvidenceQuestion answeredWhat it cannot prove alone
ls -lh fileWhat logical size does the directory entry report?How many physical or filesystem blocks are allocated
du -h fileHow much filesystem space is charged to the file?Physical backend allocation under thin provisioning, compression, or deduplication
stat fileExact length, allocated blocks, block unit, mode, owner, and timestampsApplication readability or content integrity
filefrag -v fileExtent layout and possible holes where the filesystem exposes themBackend array placement or cloud-provider physical media
sha256sum fileWhether two complete byte streams have the same digestThat either copy is semantically correct or safely retained
Storage telemetryBackend usage, latency, queue, thin-pool, snapshot, or replication behaviorThe file's expected application content
for test_file in logical-10g.bin allocated-10g.bin zero-10g.bin random-10g.bin; do
  test -e "$test_file" || continue
  printf '\nfile=%s\n' "$test_file"
  ls -lh -- "$test_file"
  du -h -- "$test_file"
  stat --format='size=%s blocks=%b block_unit=%B mode=%a owner=%U:%G' \
    -- "$test_file"
done

Keep filenames fixed inside a reviewed lab directory. Do not feed filenames from an untrusted upload into an administrative shell loop. A newline or option-like filename needs safe argument handling, and an application test should use its normal validation layer rather than a root shell.

Inspect before creating swap

free -h
swapon --show --output=NAME,TYPE,SIZE,USED,PRIO
cat /proc/swaps
grep -E '^(MemTotal|MemAvailable|SwapTotal|SwapFree):' /proc/meminfo
df -hT /
findmnt -T / -o TARGET,SOURCE,FSTYPE,OPTIONS
grep -vE '^[[:space:]]*(#|$)' /etc/fstab

Swap is not additional physical RAM and is not a backup. It can absorb cold anonymous pages and change out-of-memory behavior, but heavy swap use may turn a memory shortage into severe I/O latency. Size it from workload behavior, hibernation needs, storage endurance, incident policy, and available capacity rather than a fixed RAM multiplier.

Create a portable swap file with dd

This example creates a 2 GiB file. Confirm that /swapfile does not exist and that the root filesystem has enough real space before running it.

sudo test ! -e /swapfile
df -hT /

sudo dd if=/dev/zero of=/swapfile \
  bs=1M count=2048 \
  status=progress conv=excl,fsync

sudo chmod 0600 /swapfile
sudo chown root:root /swapfile
sudo ls -lh /swapfile
sudo du -h /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

swapon --show --output=NAME,TYPE,SIZE,USED,PRIO
free -h

Unsafe if the path is wrong: mkswap writes a swap signature, and swapon allows the kernel to overwrite the area with memory pages. Never point either command at an unidentified partition, mounted filesystem, application file, or disk image.

On hosts with util-linux 2.41 or newer, mkswap --file can create and format an appropriately populated swap file in one operation. Check the installed help before choosing that workflow:

mkswap --version
mkswap --help | grep -E -- '--file|--size'

# Current util-linux workflow when supported:
sudo mkswap --file --size 2G /swapfile-current
sudo swapon /swapfile-current
swapon --show

Do not run both creation workflows for the same path. The explicit dd sequence remains useful across a wider range of installed util-linux releases.

Persist swap and test the boot-equivalent path

Back up /etc/fstab, edit it with the system's normal configuration process, and add exactly one entry:

/swapfile  none  swap  defaults  0  0
sudo cp -a /etc/fstab /etc/fstab.before-swapfile
sudo findmnt --verify --verbose
sudo systemctl daemon-reload

# Only after proving enough available memory for swapoff:
free -h
sudo swapoff /swapfile
sudo swapon -a
swapon --show
free -h

swapon -a reads swap entries from /etc/fstab. mount -a handles mountable filesystems and is not the swap activation test. On a busy or memory-constrained host, swapoff may fail or trigger intense memory pressure while pages return to RAM.

Unsafe without headroom: do not run swapoff -a merely to test configuration. It targets every active swap area and can provoke an out-of-memory event. Disable only the intended path after checking MemAvailable, swap used, workload growth, and rollback access.

Handle Btrfs swap files with Btrfs rules

Btrfs supports swap files on current kernels, but the file must be NOCOW, preallocated, and free of holes. The filesystem must use a supported single-device and single-data-profile layout. An active swap file also constrains snapshots, balance, device changes, and scrub coverage for affected block groups.

findmnt -T /swap -o TARGET,SOURCE,FSTYPE,OPTIONS
sudo btrfs filesystem mkswapfile --size 2G /swap/swapfile
sudo swapon /swap/swapfile
swapon --show

If the installed Btrfs tools do not provide filesystem mkswapfile, follow the current Btrfs documentation for chattr +C, preallocation, permissions, mkswap, and activation. Do not use truncate, a copied sparse file, or a snapshotted file as swap.

Observe swap without manufacturing an incident

watch -n 2 'free -h; echo; swapon --show'
vmstat 1 10
sar -W 1 10
cat /proc/pressure/memory
sysctl vm.swappiness

In vmstat, sustained nonzero si and so show swap-in and swap-out activity. Combine that with memory pressure, major faults, application latency, I/O latency, queue depth, and OOM logs. Swap configured but unused is not a fault.

Current kernels accept vm.swappiness values from 0 through 200. The default is commonly 60, but the right value is workload-dependent and reflects the relative cost of swap I/O and filesystem paging. Do not copy a universal “set it to 10” rule into every server.

# Temporary, reviewed experiment:
sudo sysctl vm.swappiness=30

# Persist only after measuring the workload:
printf 'vm.swappiness = 30\n' \
  | sudo tee /etc/sysctl.d/60-nw-swappiness.conf
sudo sysctl --system

Use dd benchmarks as narrow evidence

cd /var/tmp/nw-storage-lab

dd if=/dev/zero of=write-test-2g.bin \
  bs=1M count=2048 \
  status=progress conv=excl,fdatasync

dd if=write-test-2g.bin of=/dev/null \
  bs=1M iflag=direct status=progress

This is a sequential test, not a database, VM, mail queue, or mixed application workload. Results depend on caches, thin provisioning, compression, deduplication, RAID, network storage, background activity, direct-I/O support, block size, and queue depth. iflag=direct may reject an unsupported alignment or filesystem.

Unsafe on production: writing a multi-gigabyte test file consumes capacity and I/O. Dropping all kernel caches with echo 3 > /proc/sys/vm/drop_caches is sometimes suggested before read tests, but it disturbs unrelated workloads and still does not create a controlled benchmark. Use an isolated test volume and a reviewed fio job instead.

Monitor a running copy without guessing its state

Use status=progress for a new GNU dd command. For an already running process, GNU dd prints statistics when it receives USR1 on Linux and then continues. Capture the exact child PID instead of using a broad pkill or a process-name search that might signal another administrator's job.

dd if=/dev/zero of=/dev/null \
  bs=1M count=4096 iflag=fullblock &
dd_pid=$!

kill -USR1 "$dd_pid"
wait "$dd_pid"
dd_status=$?
printf 'dd_exit=%s\n' "$dd_status"

This harmless example reads zero bytes and discards them, so it demonstrates process control rather than disk throughput. An exit status of zero indicates that dd completed its requested copy. Capture standard error and the final status in automation. A progress line without a successful exit is not completion evidence.

Ctrl-C sends an interrupt and normally stops a foreground copy after printing final statistics. Stopping a regular-file copy can leave a partial output. Stopping a block-device restore can leave an unbootable, partially overwritten destination. Never improvise a “resume” offset from the displayed byte count without aligning units and proving the destination state.

Copy a bounded region when that is the actual task

# Copy the first 64 MiB of a regular image into a new file.
dd if=source-device.img of=first-64m.img \
  bs=1M count=64 iflag=fullblock \
  status=progress conv=excl,fsync

# Copy 16 MiB beginning at input offset 128 MiB.
dd if=source-device.img of=region-128m-144m.img \
  bs=1M skip=128 count=16 iflag=fullblock \
  status=progress conv=excl,fsync

stat --format='size=%s bytes' first-64m.img region-128m-144m.img
sha256sum first-64m.img region-128m-144m.img

skip counts input blocks, while seek counts output blocks. Changing bs changes the offsets represented by both values. For forensic, boot-record, database, or recovery work, record byte offsets explicitly and use a tool designed for the format when one exists.

Unsafe: combining seek with conv=notrunc can modify a region inside an existing output while preserving the rest. That is useful in specialized image construction and destructive on an ordinary filesystem or disk. Keep it out of general-purpose automation unless a reviewed binary layout requires it.

Test LAN and application transfers separately

# Network-only test between approved systems:
iperf3 --server
iperf3 --client 192.0.2.20 --time 30 --parallel 4

# File-transfer integrity test:
sha256sum random-10g.bin
scp random-10g.bin [email protected]:/var/tmp/nw-storage-lab/
ssh [email protected] \
  'sha256sum /var/tmp/nw-storage-lab/random-10g.bin'

Run the server only on an approved test endpoint and restrict its firewall exposure. iperf3 isolates the network more effectively. The file transfer then tests SSH, encryption, disks, filesystem, and end-to-end integrity together. A zero-filled file can produce misleading results when transport or storage compression is active.

Image a healthy device to a file

Quiesce the application and unmount the source filesystem when a crash-consistent raw image is required. Database and virtual-machine workloads may need their own snapshot or backup mechanism.

lsblk -e7 -o NAME,PATH,SIZE,MODEL,SERIAL,TYPE,FSTYPE,MOUNTPOINTS
findmnt

# Documentation names only. Replace after independent verification.
sudo dd if=/dev/disk/by-id/SOURCE_DEVICE \
  of=/mnt/backup/source-device.img \
  bs=4M iflag=fullblock \
  status=progress conv=excl,fsync

sha256sum /mnt/backup/source-device.img \
  | sudo tee /mnt/backup/source-device.img.sha256
ls -lh /mnt/backup/source-device.img*

Unsafe: a mounted, changing source can produce an inconsistent image, and a mistaken if/of reversal can destroy the device. Use stable /dev/disk/by-id/ names, record model and serial, verify the backup filesystem has capacity, and require a second-person check for important systems.

Clone or restore to a block device

lsblk -e7 -o NAME,PATH,SIZE,MODEL,SERIAL,TYPE,FSTYPE,MOUNTPOINTS
sudo blockdev --getsize64 /dev/disk/by-id/SOURCE_DEVICE
sudo blockdev --getsize64 /dev/disk/by-id/DESTINATION_DEVICE

# UNSAFE: overwrites the destination from its first block onward.
sudo dd if=/dev/disk/by-id/SOURCE_DEVICE \
  of=/dev/disk/by-id/DESTINATION_DEVICE \
  bs=4M iflag=fullblock \
  status=progress conv=fsync

Unsafe and destructive: the destination loses its partition table, filesystems, boot records, and data. Confirm the destination is not mounted or used by LVM, RAID, encryption, swap, a database, a VM, or the running system. The destination must be large enough. Keep a tested backup and console access. Do not rely on changing /dev/sdX letters.

After a planned clone, reread the partition table or reboot only according to the change plan, then validate partitions, filesystem identifiers, bootability, application integrity, and expanded capacity. Duplicate filesystem UUIDs can cause ambiguous mounting when source and clone remain attached.

Use a recovery tool for failing media

sudo ddrescue --force --no-scrape \
  /dev/disk/by-id/FAILING_SOURCE \
  /mnt/recovery/device.img \
  /mnt/recovery/device.map

sudo ddrescue --force --direct --retry-passes=3 \
  /dev/disk/by-id/FAILING_SOURCE \
  /mnt/recovery/device.img \
  /mnt/recovery/device.map

The map file lets ddrescue resume and distinguish copied, failed, and pending areas. Recovery strategy depends on device health and data value; repeated reads can worsen some failures. For important data, stop and use a qualified recovery service rather than experimenting.

Place swap at the correct virtualization boundary

On a physical server, the operating system owns the swap area and its storage path. In a virtual machine, guest swap consumes virtual-disk I/O that ultimately reaches the hypervisor and backend storage. The host may also be under memory pressure. Monitor both layers before concluding that more guest swap solves the problem.

A container normally shares the host kernel and does not own a private swap device merely because a file exists inside its filesystem view. Container memory and swap behavior is governed through cgroups and the orchestration platform. Running swapon inside an application container usually requires excessive privilege and creates an unmanaged host-level side effect. Configure memory limits, swap policy, eviction behavior, and observability at the platform boundary.

Managed Kubernetes and container services can restrict or define node swap behavior differently by version and provider. Do not enable host swap underneath a cluster by copying a standalone-server procedure. Start with the current platform policy, node image, kubelet configuration, workload class, and support boundary.

Cloud virtual disks add another layer of limits. A dd result may be constrained by provisioned IOPS, throughput caps, burst credits, instance bandwidth, attachment type, encryption, snapshots, or noisy neighbors. Record the disk and instance limits beside the command. A short burst is not sustained capacity.

Protect memory contents and plan hibernation separately

Swap can contain fragments of credentials, message bodies, application data, cryptographic material, and other memory-resident information. Apply the same data-classification and disposal policy used for memory dumps. Whole-disk encryption may protect a swap file at rest when the key lifecycle and boot path are designed correctly. An unencrypted swap partition or file can expose data after shutdown or disk removal.

Ephemeral encrypted swap, where a new key is created at boot, is useful when resume across reboot is not required. Hibernation needs the system to find and decrypt the saved memory image during early boot, so it has different key-retention and resume requirements. A swap file used for hibernation also needs a correct resume device and physical offset. Merely making the file as large as RAM is not a complete hibernation configuration.

Do not enable hibernation on servers, encrypted systems, Btrfs files, or managed images without following the distribution and bootloader procedure. Test resume after kernel, initramfs, storage, encryption, and bootloader changes. A failed resume can become a boot incident or expose stale memory contents.

When retiring swap, disable it, remove the persistent configuration, verify it is inactive, and follow the storage platform's sanitization policy. Overwriting a file once does not guarantee physical erasure on SSDs, copy-on-write filesystems, snapshots, thin pools, replicated volumes, or cloud storage. Cryptographic erasure or provider-managed destruction may be the correct control.

Remove a swap file safely

  1. Confirm swap usage, available memory, and the exact active path.
  2. Remove or comment the matching /etc/fstab entry through the normal configuration process.
  3. Reload the service manager if required.
  4. Disable only that swap file and verify it disappeared.
  5. Delete the exact inactive file only after validation.
swapon --show
free -h
grep -nF '/swapfile' /etc/fstab

sudo cp -a /etc/fstab /etc/fstab.before-swapfile-removal
# Edit only the validated /swapfile entry.
sudo systemctl daemon-reload
sudo swapoff /swapfile
swapon --show
sudo file /swapfile

# UNSAFE: irreversible regular-file deletion after all checks pass.
sudo rm -f -- /swapfile
df -hT /

Unsafe: deleting a file that is still active as swap may fail, create confusing hidden space use, or leave an inconsistent boot configuration. A broad wildcard or unresolved variable in the removal command is unacceptable.

Troubleshoot from evidence

SymptomEvidenceLikely boundary
swapon failed: Invalid argumentfilefrag -v, filesystem type, file attributes, kernel logHoles, copy-on-write, unsupported filesystem layout, or invalid swap header
Permission warning from swaponstat -c '%a %U:%G %n'Key-like swap contents exposed by a mode broader than 0600
Swap works now but not after boot/etc/fstab, swapon -a, journalWrong path, syntax, mount ordering, or service-manager configuration
Large file reports size but uses no spacels -lh, du -h, stat, filefragSparse file, reflink, compression, deduplication, or thin provisioning
dd read test is unexpectedly fastCache state, direct-I/O support, storage telemetryPage cache or lower-layer cache rather than media performance
No space left on devicedf -h, df -i, quotas, thin-pool and snapshot usageBytes, inodes, quota, reserved blocks, or backing-pool exhaustion
swapoff failsExit code, MemAvailable, swap used, OOM and pressure logsInsufficient memory or kernel/system call failure
Clone will not bootPartition table, UUIDs, boot mode, bootloader, initramfs, logsIdentity collision, boot metadata, geometry, firmware mode, or inconsistent source

Completion record

  • The goal, test size, logical-versus-allocated requirement, owner, capacity limit, duration, and cleanup time are recorded.
  • Every dd input and output was resolved to an exact regular file or stable device identity before execution.
  • The filesystem, free bytes, inodes, quotas, snapshots, thin provisioning, compression, deduplication, and backup impact were checked.
  • Swap creation used a populated non-sparse file and filesystem-specific rules.
  • Permissions, mkswap, activation, /etc/fstab, swapon -a, monitoring, and rollback passed.
  • Performance results state block size, durability, cache, allocation, storage path, concurrency, and what was not measured.
  • Images and clones have recorded source/destination identities, consistency method, capacity proof, checksums, recovery plan, and validation.
  • Temporary files and swap areas are removed only by exact path after they are inactive and their evidence is retained.

Primary references

Related technical notes

Technical review

Need this checked against your own sending system?

Share the domain, headers, bounces, provider warning, logs, or infrastructure symptom and NitWings will identify the practical next step.

Schedule a Technical Review
Advertisement