user/sync.c
About this file
sync waits until every file system change made so far is safely on disk. It is a single
system call, sync(), whose kernel side is sys_sync in kernel/log.c.
Why is there anything to wait for? xv6 makes every file system system call part of a
transaction in the write-ahead log. Several calls running at the same time
share one transaction, and it is written to disk (commit) only when the last
of them finishes (end_op). So when your write returns, its changes may
still be waiting for some other process’s operation to end. sync waits for the commit
that includes them: if any operation is in progress or a commit is running,
sys_sync sleeps until the commit counter ncommit goes up by one; if nothing
is in progress, everything is already on disk and it returns at once.
This is different from Unix, where sync asks the kernel to write out dirty buffers
that would otherwise be written later. xv6 never holds committed changes back:
commit writes the log, then installs the blocks at their home locations,
before it returns.
Read before: kernel/log.c (the commit path). Read next:
user/logstress.c, which exercises the log.
Headers
user/user.h declares int sync(void); the stub in user/usys.S loads
SYS_sync (22, kernel/syscall.h) into a7 and executes ecall.
kernel/stat.h is not used.
main(): wait for the log, then exit
argc and argv are accepted and ignored. sync() cannot fail; sys_sync
always returns 0. When it returns, the commit path in commit has run to
completion for every operation that had started: the changed blocks were written to
the log, the log header was written (the commit point), and the blocks were copied to
their home locations (install_trans). A crash after this point loses
nothing that was done before sync was called.
Block until the next log commit has finished, if one is pending
(sys_sync, kernel/log.c:247).
Exit with status 0 (exit status).