Subject: Re: updating, build and install order
To: NetBSD-current Discussion List <current-users@netbsd.org>
From: Robert Elz <kre@munnari.OZ.AU>
List: current-users
Date: 06/23/2003 03:46:08
    Date:        Sun, 22 Jun 2003 15:20:00 -0400 (EDT)
    From:        "Greg A. Woods" <woods@weird.com>
    Message-ID:  <m19UANc-000B44C@proven.weird.com>

  | Yes, but IIUC that's only to schedule the write of the superblock
  | itself, and unless somehow the writes are ordered such that the
  | superblock is often/always written last then I would expect this not to
  | cause the second 'sync' to pause.

It actually causes the 3rd sync to pause, and that's why there are
three...

The process is ...

	First sync()
		write super block (for each mounted filesystem
			 that isn't read only)
		write all modified inodes
		write all dirty buffers
	Second sync()
		wait for first super block write to complete
		write super block (always done)
		(there probably isn't anything else modified)
	Third sync
		wait for second super block write to complete
		(write super block one more time)

The disc drivers did no write reordering, so when the third sync returned
you'd know for sure the 2nd super block write was done, as that had to complete
before the 3rd write could be queued, and as the 2nd write was queued after
all of the other writes to flush everything else, you also knew that all the
rest of the writes had completed as well.

So, that's why the 3 syncs (and yes, "sync;sync;sync" worked just as well
doing it on 3 lines - except it didn't start till you had finished typing,
where usually by the time the typing was finished, so would the syncs be.

  | You may be correct but I've always assumed that the second sync()
  | wouldn't find any inodes with any outstanding blocks to call free() on

Hmm - sync never (in those days) looked for inodes with outstanding
blocks, that would be an utter waste of time, it looked for blocks in
the buffer cache marked dirty - it is irrelevant which inodes they
belonged to.

  | The first call should have found all the
  | out-of-date inodes, scheduled their writes, and marked the inodes as
  | free.

And inodes don't get marked as free because of a sync() - the system just
keeps on running, the only change is that all the dirty blocks and inodes
(and all the super blocks, with updated modify time) got written.  Once
written the only change was that they were no longer listed as dirty.

  | The second and subsequent sync() calls will only schedule just
  | the re-write the superblock(s) for the mounted filesystem(s).

Yes, but to cause a write, the previous write of the same block has
to have completed first.

  | The only
  | time the second manual 'sync' should ever pause is if the one triggered
  | by 'update' was still happening.

No, if that was happening, the sync would simply return immediately, that
is what updlock was all about.   That's the case where it wouldn't pause.

  | I don't remember the second 'sync' command
  | ever pausing (and this was with a decwriter console probably at 1200bps).

Perhaps, though if it was 1200 it must have been a fairly modern system
(and so not nearly back to where sync**3 originated).   If you never saw
he 2nd sync pause, you must have been on systems where either the buffer
cache was small, or the discs quite fast (or both) or where there weren't
many dirty blocks.

The way to see it most obviously, was to modify lots of blocks (fill the
buffer cache with dirty blocks) in single user mode, so update wasn't
running - then it would be obvious.

kre