--- /dev/null
+Copyright 2000, International Business Machines Corporation and others.
+All Rights Reserved.
+
+This software has been released under the terms of the IBM Public
+License. For details, see the LICENSE file in the top-level source
+directory or online at http://www.openafs.org/dl/license10.html
+
+Here's a quick guide to understanding the AFS 3 VM integration. This
+will help you do AFS 3 ports, since one of the trickiest parts of an
+AFS 3 port is the integration of the virtual memory system with the
+file system.
+
+The issues arise because in AFS, as in any network file system,
+changes may be made from any machine while references are being made
+to a file on your own machine. Data may be cached in your local
+machine's VM system, and when the data changes remotely, the cache
+manager must invalidate the old information in the VM system.
+
+Furthermore, in some systems, there are pages of virtual memory
+containing changes to the files that need to be written back to the
+server at some time. In these systems, it is important not to
+invalidate those pages before the data has made it to the file system.
+In addition, such systems often provide mapped file support, with read
+and write system calls affecting the same shared virtual memory as is
+used by the file should it be mapped.
+
+As you may have guessed from the above, there are two general styles
+of VM integration done in AFS 3: one for systems with limited VM
+system caching, and one for more modern systems where mapped files
+coexist with read and write system calls.
+
+For the older systems, the function osi_FlushText exists. Its goal is
+to invalidate, or try to invalidate, caches where VM pages might cache
+file information that's now obsolete. Even if the invalidation is
+impossible at the time the call is made, things should be setup so
+that the invalidation happens afterwards.
+
+I'm not going to say more about this type of system, since fewer and
+fewer exist, and since I'm low on time. If I get back to this paper
+later, I'll remove this paragraph. The rest of this note talks about
+the more modern mapped file systems.
+
+For mapped file systems, the function osi_FlushPages is called from
+various parts of the AFS cache manager. We assume that this function
+must be called without holding any vnode locks, since it may call back
+to the file system to do part of its work.
+
+The function osi_FlushPages has a relatively complex specification.
+If the file is open for writing, or if the data version of the pages
+that could be in memory (vp->mapDV) is the current data version number
+of the file, then this function has no work to do. The rationale is
+that if the file is open for writing, calling this function could
+destroy data written to the file but not flushed from the VM system to
+the cache file. If mapDV >= DataVersion, then flushing the VM
+system's pages won't change the fact that we can still only have pages
+from data version == mapDV in memory. That's because flushing all
+pages from the VM system results in a post condition that the only
+pages that might be in memory are from the current data version.
+
+If neither of the two conditions above occur, then we actually
+invalidate the pages, on a Sun by calling pvn_vptrunc. This discards
+the pages without writing any dirty pages to the cache file. We then
+set the mapDV field to the highest data version seen before we started
+the call to flush the pages. On systems that release the vnode lock
+while doing the page flush, the file's data version at the end of this
+procedure may be larger than the value we set mapDV to, but that's
+only conservative, since a new could have been created from the
+earlier version of the file.
+
+There are a few times that we must call osi_FlushPages. We should
+call it at the start of a read or open call, so that we raise mapDV to
+the current value, and get rid of any old data that might interfere
+with later reads. Raising mapDV to the current value is also
+important, since if we wrote data with mapDV < DataVersion, then a
+call to osi_FlushPages would discard this data if the pages were
+modified w/o having the file open for writing (e.g. using a mapped
+file). This is why we also call it in afs_map. We call it in
+afs_getattr, since afs_getattr is the only function guaranteed to be
+called between the time another client updates an executable, and the
+time that our own local client tries to exec this executable; if we
+fail to call osi_FlushPages here, we might use some pages from the
+previous version of the executable file.
+
+Also, note that we update mapDV after a store back to the server
+completes, if we're sure that no other versions were created during
+the file's storeback. The mapDV invariant (that no pages from earlier
+data versions exist in memory) remains true, since the only versions
+that existed between the old and new mapDV values all contained the
+same data.
+
+Finally, note a serious incompleteness in this system: we aren't
+really prepared to deal with mapped files correctly. In particular,
+there is no code to ensure that data stored in dirty VM pages ends up
+in a cache file, except as a side effect of the segmap_release call
+(on Sun 4s) that unmaps the data from the kernel map, and which,
+because of the SM_WRITE flag, also calls putpage synchronously to get
+rid of the data.
+
+This problem needs to be fixed for any system that uses mapped files
+seriously. Note that the NeXT port's generic write call uses mapped
+files, but that we've set a flag (close_flush) that ensures that all
+dirty pages get flushed after every write call. It is also something
+of a performance hit, since it would be better to write those pages to
+the cache asynchronously rather than after every write, as happens
+now.