(FILECREATED "11-Oct-84 11:38:05" {ERIS}<STANSBURY>OS>VOLUMEALLOCATIONMAP.;1 13732  

      changes to:  (FNS \DFSVAMFreePage)
		   (VARS VOLUMEALLOCATIONMAPCOMS)
		   (RESOURCES \DFSVAMpage)

      previous date: " 5-Oct-84 23:31:30" {ERIS}<STANSBURY>VAM>VOLUMEALLOCATIONMAP.;1)


(* Copyright (c) 1984 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT VOLUMEALLOCATIONMAPCOMS)

(RPAQQ VOLUMEALLOCATIONMAPCOMS ((* Implements the 1108 file system volume file map. Very roughly 
				   translates {idun}<apilot100>pilot>private>volAllocMapImpl.mesa, 
				   but omits a number of dubious optimizations.)
				(DECLARE: EVAL@COMPILE DONTCOPY (COMS * 
								  VOLUMEMALLOCATIONMAPCOMPILECOMS))
				(DECLARE: (LOCALVARS . T))
				(* * Public routines)
				(FNS \DFSVAMAllocPageGroup \DFSVAMFreePageGroup \DFSVAMInit 
				     \DFSVAMRecomputeFreePageCount)
				(* * Private routines:)
				(FNS \DFSVAMAllocPage \DFSVAMUpdateVAM \DFSVAMFreePage 
				     \DFSVAMAdjustGroup)
				(RESOURCES \DFSVAMpage)
				(GLOBALVARS \DFSVAMmonitor)
				[INITVARS (\DFSVAMmonitor (CREATE.MONITORLOCK (QUOTE VAMmonitor]
				(* * buffer management)
				(FNS \DFSVAMGetVAMPageFor \DFSVAMBufferInit \DFSVAMBufferSave)
				(GLOBALVARS \DFSVAMbuffer \DFSVAMbufferVolume \DFSVAMbufferVolumePage)
				(* * Initialize VAM)
				(P (\DFSVAMInit))))



(* Implements the 1108 file system volume file map. Very roughly translates 
{idun}<apilot100>pilot>private>volAllocMapImpl.mesa, but omits a number of dubious 
optimizations.)

(DECLARE: EVAL@COMPILE DONTCOPY 

(RPAQQ VOLUMEMALLOCATIONMAPCOMPILECOMS ((FILES (LOADCOMP)
					       DLIONFS)
					(CONSTANTS (BITSPERPAGE 4096))))
(FILESLOAD (LOADCOMP)
	   DLIONFS)
(DECLARE: EVAL@COMPILE 

(RPAQQ BITSPERPAGE 4096)

(CONSTANTS (BITSPERPAGE 4096))
)
)
(DECLARE: 
(DECLARE: DOEVAL@COMPILE DONTCOPY

(LOCALVARS)
)
)
(* * Public routines)

(DEFINEQ

(\DFSVAMAllocPageGroup
  [LAMBDA (vol filePtr groupPtr createFile)                  (* hts: " 5-Oct-84 23:17")
                                                             (* vol: LogicalVolumeDescriptor, filePtr: 
							     FileDescriptor, groupPtr: PageGroup, createFile: 
							     BOOLEAN)

          (* * Allocates as many of the pages in groupPtr as it can in a contiguous run. Modifies groupPtr so the caller can 
	  know what pages and how many were allocated)


    (WITH.MONITOR \DFSVAMmonitor
		  (UNINTERRUPTABLY
                      (PROG ((volPage# (fetch (LogicalVolumeDescriptor lowerBound) of vol))
			     (filePage# (fetch (PageGroup filePage) of groupPtr))
			     allocated)

          (* * Find first free page and allocate it. lowerBound is supposed to be the first free page on the volume)


			    (until (PROGN (if (IGEQ volPage# (SUB1 (fetch (LogicalVolumeDescriptor
									    volumeSize)
								      of vol)))
					      then (DiskError "FILE SYSTEM RESOURCES EXCEEDED"
							      (fetch (LogicalVolumeDescriptor LVlabel)
								 of vol)))
					  (\DFSVAMAllocPage vol volPage# filePtr filePage#))
			       do (add volPage# 1))

          (* * Note in groupPtr the beginning page of the run we will allocate to this file)


			    (replace (PageGroup volumePage) of groupPtr with volPage#)

          (* * Keep allocating until either you run out of consecutive free pages or you've allocated enough)


			    [repeatuntil (PROGN (add volPage# 1)
						(add filePage# 1)
						(if (IGEQ volPage# (SUB1 (fetch (
LogicalVolumeDescriptor volumeSize) of vol)))
						    then (DiskError "FILE SYSTEM RESOURCES EXCEEDED"
								    (fetch (LogicalVolumeDescriptor
									     LVlabel)
								       of vol)))
						(OR (EQP filePage# (fetch (PageGroup nextFilePage)
								      of groupPtr))
						    (NOT (\DFSVAMAllocPage vol volPage# filePtr 
									   filePage#]
			    (SETQ allocated (IDIFFERENCE volPage# (fetch (PageGroup volumePage)
								     of groupPtr)))

          (* * Note in the PageGroup what the last page allocated actually was, so the caller will know)


			    (replace (PageGroup nextFilePage) of groupPtr
			       with (IPLUS (fetch (PageGroup filePage) of groupPtr)
					   allocated))

          (* * Update free page count and lower bound on the logical volume page and write it out)


			    (add (fetch (LogicalVolumeDescriptor freePageCount) of vol)
				 (MINUS allocated))
			    (replace (LogicalVolumeDescriptor lowerBound) of vol with volPage#)
			    (\LvPutPage vol 0 vol)

          (* * Flush last VAM page used)


			    (\DFSVAMBufferSave)))])

(\DFSVAMFreePageGroup
  [LAMBDA (vol filePtr groupPtr deleteFile)                  (* hts: " 5-Oct-84 12:28")
                                                             (* vol: LogicalVolumeDescriptor, filePtr: 
							     FileDescriptor, groupPtr: PageGroup, deleteFile: 
							     BOOLEAN)

          (* * Frees each page in groupPtr)


    (WITH.MONITOR \DFSVAMmonitor (UNINTERRUPTABLY
                                     (PROG ((group (\DFSVAMAdjustGroup groupPtr)))
                                                             (* Adjust to coincide with Pilot's silly "[0, 0)" 
							     convention)
				           (if (IGEQ (fetch (PageGroup filePage) of group)
						     (fetch (PageGroup nextFilePage) of group))
					       then (RETURN))

          (* * Free up the pages you're supposed to)


				           (for filePageNumber from (fetch (PageGroup filePage)
								       of group)
					      to (SUB1 (fetch (PageGroup nextFilePage) of group))
					      as volumePageNumber from (fetch (PageGroup volumePage)
									  of group)
					      do (\DFSVAMFreePage vol volumePageNumber filePtr 
								  filePageNumber))

          (* * Update free page count and lower bound on the logical volume page and write it out)


				           (add (fetch (LogicalVolumeDescriptor freePageCount)
						   of vol)
						(IDIFFERENCE (fetch (PageGroup nextFilePage)
								of group)
							     (fetch (PageGroup filePage)
								of group)))
                                                             (* Update free page count for the volume)
				           (replace (LogicalVolumeDescriptor lowerBound)
					      of vol with (MIN (fetch (PageGroup volumePage)
								  of group)
							       (fetch (LogicalVolumeDescriptor 
										       lowerBound)
								  of vol)))
				           (\LvPutPage vol 0 vol)

          (* * Save out buffered VAM pages)


				           (\DFSVAMBufferSave)))])

(\DFSVAMInit
  [LAMBDA NIL                                                (* hts: "25-Sep-84 18:20")

          (* * Initializes or reinitializes the volume allocation map)


    (WITH.MONITOR \DFSVAMmonitor (\DFSVAMBufferInit])

(\DFSVAMRecomputeFreePageCount
  [LAMBDA (vol)                                              (* hts: " 5-Oct-84 12:28")
                                                             (* vol: LogicalVolumeDescriptor,)
                                                             (* Recomputes the free page count for each volume from 
							     scratch; also resets the lower bound pointer)
    (WITH.MONITOR \DFSVAMmonitor [replace (LogicalVolumeDescriptor freePageCount) of vol
				    with (bind (firstFree ← T) for page from 1
					    to (fetch (LogicalVolumeDescriptor volumeSize)
						  of vol)
					    count (PROG [(free (ZEROP (\DFSVAMUpdateVAM vol NIL page
											(QUOTE read]
						        (if (AND free firstFree)
							    then (replace (LogicalVolumeDescriptor
									    lowerBound)
								    of vol with page)
								 (SETQ firstFree NIL))
						        (RETURN free]
		  (\LvPutPage vol 0 vol)
		  (fetch (LogicalVolumeDescriptor freePageCount) of vol])
)
(* * Private routines:)

(DEFINEQ

(\DFSVAMAllocPage
  [LAMBDA (vol volPage# filePtr filePage#)                   (* hts: " 5-Oct-84 12:32")
                                                             (* vol: LogicalVolumeDescriptor, filePtr: 
							     FileDescriptor, page: FIXP)

          (* * RETURNS T if successful at allocating page, otherwise NIL)


    (ZEROP (\DFSVAMUpdateVAM vol filePtr volPage# (QUOTE alloc])

(\DFSVAMUpdateVAM
  [LAMBDA (vol filePtr page allocOrFree)                     (* hts: " 5-Oct-84 23:15")
                                                             (* vol: LogicalVolumeDescriptor, filePtr: 
							     FileDescriptor, page: FIXP, allocOrFree: {alloc, free})
                                                             (* RETURNS previous value of allocation map for 
							     specified page)
                                                             (* Sets (if allocOrFree = alloc) or clears 
							     (if allocOrFree = free) the map bit for the specified 
							     page)
    (PROG ((VAMPage# (IQUOTIENT page BITSPERPAGE))
	   (VAMWord# (IQUOTIENT (IREMAINDER page BITSPERPAGE)
				BITSPERWORD))
	   (VAMBit# (IREMAINDER page BITSPERWORD))
	   VAMPage VAMWord VAMBit result)
          (SETQ VAMPage (\DFSVAMGetVAMPageFor vol VAMPage#))
          (SETQ VAMWord (\GETBASE VAMPage VAMWord#))
          (SETQ VAMBit (MASK.1'S (DIFFERENCE 15 VAMBit#)
				 1))
          (SETQ result (if (BITTEST VAMWord VAMBit)
			   then 1
			 else 0))
          (SELECTQ allocOrFree
		   (alloc (SETQ VAMWord (BITSET VAMWord VAMBit)))
		   (free (SETQ VAMWord (BITCLEAR VAMWord VAMBit)))
		   (read)
		   (SHOULDNT))
          (\PUTBASE VAMPage VAMWord# VAMWord)
          (RETURN result])

(\DFSVAMFreePage
  [LAMBDA (vol volPageNumber filePtr filePageNumber)         (* hts: "10-Oct-84 23:12")
                                                             (* vol: LogicalVolumeDescriptor, filePtr: 
							     FileDescriptor, page: FIXP)

          (* * Frees the specified page)



          (* * Zero the page and write it out)


    (WITH-RESOURCE \DFSVAMpage (\ZEROPAGE (fetch (POINTER PAGE#) of \DFSVAMpage))
		   (\LvPutPage vol volPageNumber \DFSVAMpage))

          (* * and mark it free in the allocation map)


    (\DFSVAMUpdateVAM vol filePtr volPageNumber (QUOTE free])

(\DFSVAMAdjustGroup
  [LAMBDA (groupPtr)                                         (* hts: "12-Apr-84 14:47")
    (PROG ((group (create PageGroup using groupPtr)))
          [if (ZEROP (fetch (PageGroup filePage) of group))
	      then (if (ZEROP (fetch (PageGroup nextFilePage) of group))
		       then (replace (PageGroup nextFilePage) of group with 1)
		     else (replace (PageGroup filePage) of group with 1)
			  (replace (PageGroup volumePage) of group with (ADD1 (fetch (PageGroup
										       volumePage)
										 of group]
          (RETURN group])
)
(DECLARE: EVAL@COMPILE 
[PUTDEF (QUOTE \DFSVAMpage)
	(QUOTE RESOURCES)
	(QUOTE (NEW (create Page]
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \DFSVAMmonitor)
)

(RPAQ? \DFSVAMmonitor (CREATE.MONITORLOCK (QUOTE VAMmonitor)))
(* * buffer management)

(DEFINEQ

(\DFSVAMGetVAMPageFor
  [LAMBDA (vol VAMPage#)                                     (* hts: " 5-Oct-84 12:27")
    (PROG ((volumePage (IPLUS (fetch (LogicalVolumeDescriptor vamStart) of vol)
			      VAMPage#)))
          (if (AND \DFSVAMbufferVolumePage (LVEqual \DFSVAMbufferVolume vol)
		   (EQP \DFSVAMbufferVolumePage volumePage))
	      then (RETURN \DFSVAMbuffer)                    (* If the desired VAM page is already read in, just 
							     return it)
	    else (if \DFSVAMbufferVolumePage
		     then (\LvPutPage \DFSVAMbufferVolume \DFSVAMbufferVolumePage \DFSVAMbuffer))
                                                             (* Otherwise write out the old VAM page)
		 (UNINTERRUPTABLY

          (* * Record what the new page is)


		     (SETQ \DFSVAMbufferVolume vol)
		     (SETQ \DFSVAMbufferVolumePage volumePage)

          (* * and read it in)


		     (\LvGetPage \DFSVAMbufferVolume \DFSVAMbufferVolumePage \DFSVAMbuffer)
		     (RETURN \DFSVAMbuffer))])

(\DFSVAMBufferInit
  [LAMBDA NIL                                                (* hts: "25-Sep-84 18:20")

          (* * if bufferVolumePage is NIL, GetVAMPageFor will not try to flush an old version of it)


    (SETQ \DFSVAMbuffer (create Page))
    (SETQ \DFSVAMbufferVolume)
    (SETQ \DFSVAMbufferVolumePage])

(\DFSVAMBufferSave
  [LAMBDA NIL                                                (* hts: " 5-Oct-84 12:28")

          (* * Flush last VAM page used)


    (\LvPutPage \DFSVAMbufferVolume \DFSVAMbufferVolumePage \DFSVAMbuffer])
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \DFSVAMbuffer \DFSVAMbufferVolume \DFSVAMbufferVolumePage)
)
(* * Initialize VAM)

(\DFSVAMInit)
(PUTPROPS VOLUMEALLOCATIONMAP COPYRIGHT ("Xerox Corporation" 1984))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (1895 8309 (\DFSVAMAllocPageGroup 1905 . 4821) (\DFSVAMFreePageGroup 4823 . 6959) (
\DFSVAMInit 6961 . 7205) (\DFSVAMRecomputeFreePageCount 7207 . 8307)) (8340 11544 (\DFSVAMAllocPage 
8350 . 8773) (\DFSVAMUpdateVAM 8775 . 10215) (\DFSVAMFreePage 10217 . 10862) (\DFSVAMAdjustGroup 10864
 . 11542)) (11808 13493 (\DFSVAMGetVAMPageFor 11818 . 12901) (\DFSVAMBufferInit 12903 . 13247) (
\DFSVAMBufferSave 13249 . 13491)))))
STOP