sync_file_range(2)
โจ sync_file_range โ bestie edition โจ
okay so this is sync_file_range(2) from the System Calls Manual, and it's a whole situation ๐
๐ NAME ๐
sync_file_range โ sync a file segment with disk. that's it, that's the vibe, we're syncing a segment of a file to disk ๐ฆ
๐ LIBRARY ๐
Standard C library (libc, -lc). the classic. the blueprint. no cap ๐
๐ธ SYNOPSIS ๐ธ
#define _GNU_SOURCE /* See feature_test_macros(7) */
#define _FILE_OFFSET_BITS 64
#include <fcntl.h>
int sync_file_range(int fd, off_t offset, off_t nbytes,
unsigned int flags);
like, bestie, you need those defines up top. _GNU_SOURCE is giving main character energy (peep feature_test_macros(7) for the lore), and _FILE_OFFSET_BITS 64 is there so your offsets don't get humbled on 32-bit platforms ๐ซถ
๐ DESCRIPTION ๐
sync_file_range() lets you have fine control when synchronizing the open file that the file descriptor fd points to, with disk. it's giving precision. it's giving artistry. โจ
offset is the starting byte of the file range you wanna synchronize.
nbytes is how long that range is, in bytes โ and here's the spicy part: if nbytes is zero, then literally every byte from offset all the way to the end of file gets synchronized. ๐
and the units?? synchronization happens in units of the system page size, so:
offsetgets rounded down to a page boundary(offset+nbytes-1)gets rounded up to a page boundary
periodt. math is math. ๐ง
The flags bit-mask argument can include any of these values:
SYNC_FILE_RANGE_WAIT_BEFOREโ wait for write-out of every page in the specified range that's already been submitted to the device driver for write-out, before you do any writing at all. like waiting your turn, but for pages. ๐SYNC_FILE_RANGE_WRITEโ kick off write-out of all the dirty pages in the specified range that aren't currently submitted for write-out. ngl, even this one may block if you try to write more than the request queue size ๐ญSYNC_FILE_RANGE_WAIT_AFTERโ wait for write-out of all the pages in the range after you've done any writing.
Specifying flags as 0 is permitted โ it's a no-op. literally just vibes, zero consequences ๐
โ ๏ธ Warning โ ๏ธ
okay bestie, sit down for this one because it's serious:
This system call is extremely dangerous and should not be used in portable programs.
none of these operations writes out the file's metadata. so unless your application is strictly performing overwrites of already-instantiated disk blocks, there are no guarantees your data will survive a crash. ๐ญ there's no user interface to tell you whether a write is purely an overwrite. and on filesystems using copy-on-write semantics (e.g. btrfs), an overwrite of existing allocated blocks is impossible. when writing into preallocated space, lots of filesystems also need calls into the block allocator โ and this system call does not sync that out to disk. and this system call does not flush disk write caches, so it provides no data integrity on systems with volatile disk write caches.
tl;dr: iconic? maybe. safe? absolutely not. ๐
๐ Some details ๐
SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any I/O errors or ENOSPC conditions and return them to the caller. so they're the snitches of the flag world and honestly? we respect it ๐ซถ
useful combinations of the flag bits are:
SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITEโ makes sure that all pages in the specified range which were dirty whensync_file_range()was called get placed under write-out. this is a start-write-for-data-integrity operation. โจSYNC_FILE_RANGE_WRITEโ starts write-out of all dirty pages in the specified range that aren't presently under write-out. this is an asynchronous flush-to-disk operation. and it is not suitable for data integrity operations. ๐ฉSYNC_FILE_RANGE_WAIT_BEFORE(orSYNC_FILE_RANGE_WAIT_AFTER) โ waits for completion of write-out of all pages in the specified range. you can use this after an earlierSYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITEoperation to wait for that op to finish and collect its result. it's giving follow-up text energy ๐ฑSYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTERโ this is a write-for-data-integrity operation that ensures all pages in the specified range which were dirty whensync_file_range()was called get committed to disk. the full ensemble. the whole girl group is on stage. ๐
๐ซ RETURN VALUE ๐ซ
slay: on success, sync_file_range() returns 0.
on failure, -1 is returned and errno is set to indicate the error. not slay, but informative. ๐
๐จ ERRORS ๐จ
EBADFโfdis not a valid file descriptor. bestie that's not a file ๐ซEINVALโflagsspecifies an invalid bit; oroffsetornbytesis invalid. read the room (and the arguments) ๐คEIOโ I/O error. the disk said no ๐ENOMEMโ out of memory. she's full ๐ญENOSPCโ out of disk space. she's also full ๐ญ๐ญESPIPEโfdrefers to something other than a regular file, a block device, or a directory. like... what even is that ๐
๐ VERSIONS ๐
sync_file_range2()
some architectures (e.g. PowerPC, ARM) need 64-bit arguments aligned in a suitable pair of registers. on those architectures, the call signature of sync_file_range() shown in the SYNOPSIS would force a register to be wasted as padding between the fd and offset arguments. (peep syscall(2) for the details.) so these architectures define a different system call that orders the arguments suitably:
int sync_file_range2(int fd, unsigned int flags,
off_t offset, off_t nbytes);
the behavior of this system call is otherwise exactly the same as sync_file_range(). same girl, different outfit change. ๐
โจ
๐ STANDARDS ๐
Linux. that's the standard. we're Linux-pilled. ๐ง
๐ฐ๏ธ HISTORY ๐ฐ๏ธ
Linux 2.6.17. she's been around a minute and she's still iconic ๐
sync_file_range2()
a system call with this signature first appeared on the ARM architecture in Linux 2.6.20, under the name arm_sync_file_range(). it got renamed in Linux 2.6.22, when the analogous system call was added for PowerPC. on architectures where glibc support is provided, glibc transparently wraps sync_file_range2() under the name sync_file_range(). sneaky. elegant. we love a glow-up ๐
๐ NOTES ๐
_FILE_OFFSET_BITS should be defined to be 64 in code that takes the address of sync_file_range, if that code is meant to be portable to traditional 32-bit x86 and ARM platforms where off_t's width defaults to 32 bits. protect your offsets, babe ๐ซถ
๐ SEE ALSO ๐
fdatasync(2), fsync(2), msync(2), sync(2) โ go read the whole friend group, they're all valid ๐
and that's the page, bestie!! ๐ this was pulled straight from Linux man-pages 6.20, dated 2026-02-08 โ so if you're reading this and the date's gone stale, that's a you-and-your-distro problem, not mine ๐โจ๐ฆ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 2006, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms