!******************************
!* file system handler *
!* fsys1s/fsys1y *
!* date: 30.Jun.81 *
!******************************
!*w.s.c. 25th august 1976
!*b.g. 27.mar.78
!*this handler is the file system utility to replace the
!*existing one in deimos to permit a file system to be
!*created on the ampex 9500 disc as well as the rk05's.
!*it is a conceptual copy of the rk05 file system handler
!*except that a buffer pool is used for block descriptors
!*and directory blocks.
!*the code is shared by 3 system slots,4 for the rk05's,
!*and 9,15 for the ampex disc.the ampex disc is logically
!*divided into two,units 2&3.
!* a further disc is catered for in slot 28
!*the clock is used to write blocks back every 10secs
!*(block descriptor blocks).directory blocks are always
!*written back as soon as possible after a change.
!*tuneable parameters
!* nbuf=number of buffers in pool-1(must be>0)
!* secs::length of time between inspecting buffer
!* pool for writing back to disc.
!*the following facilities are offered
!* examine a file
!* get next block of a file
!* destroy a file
!* create a file
!* append a block to a file
!* rename a file
!* rename a temporary file
!*stack=300 streams=0
!**********************************************************
!**********************************************************
control 1
include "deimosperm"
begin
!*********************************************************
!************* data areas &declarations **********
!*********************************************************
!*system slots/disc
constinteger max drives = 4
constbyteintegerarray serv(0:max drives) = 3, 3, 8, 14, 28
!*directory block areas/disc
constintegerarray dirblk(0:max drives) = k'220',0, k'1100'(2) c
, k'220'
!*block descriptor base/disc
constbyteintegerarray blklst(0:max drives) = k'100',0, k'100' c
(2), k'100'
!*free block start/disc
constintegerarray fblock(0:max drives) = k'400',0, k'1500'(2) c
, k'400'
ownintegerarray first free(0:max drives) = k'400',0, k'1500' c
(2), k'400'
! initially is identical to
! fblock
!*top of disc
constintegerarray lastbl(0:max drives) = 9200,0, k'175000'(2) c
, 9200
!*request types
constinteger examine = 0
constinteger get next = 1
constinteger destroy = 2
constinteger create = 3
constinteger append = 4
constinteger rename = 5
constinteger rename temp = 6
constinteger rename fsys = 7
constinteger dir blk no = 8
!*system constants
constinteger dread = 0, dwrite = 1
!modes
constinteger clock int = 0
constinteger my seg = 4, msa = k'100000'
!*system slots
constinteger rkser = 4
constinteger amp1ser = 9
constinteger amp2ser = 15
constinteger rkbser = 29
switch request(0:dir blk no)
integer id, seg, i, bk, no, nosave, pr, exit, seg2
owninteger drive, fno
!*message formats
recordformat pf(byteinteger service, reply, integer a1, c
(integer a2 or integername xa2), integer a3)
record (pf)p, px
!*disc buffer pool
constinteger secs = 5; !buffer write back time
constinteger nbuf = 3; !number of buffers-1(must be>0)
recordformat xf(integer x)
recordformat bf(integer drive, block, wrm, record (xf) c
array blk(0:255))
!*wrm is a write marker to say that block has been
!*altered and must be written back to disc.
ownrecord (bf) array b(0:nbuf)
owninteger blast = 0; !last buffer used in pool
ownrecord (bf) name bx; !points to current buffer record
!*formats for block descriptors and directory blocks
recordformat blkf(integer pr, next)
!block descriptor
recordformat n1f((byteintegerarray name(0:5) or integer a, b, c))
! two forms of the file name
recordformat inff(byteinteger unit, fsys, record (n1f)n)
! file descriptor
recordformat filef(record (n1f)n, integer first, pr)
!directory entry
ownrecord (blkf) arrayname blka
record (filef) arrayname fa
ownrecord (filef) name f
record (blkf) name blk
record (blkf)save blk
record (inff) name inf, inf2
record (inff)g
!***********************************************
!* e v e n t s
!! %on %event 15 %start; ! disc i/o fail
!! %if px_service = 0 %then -> restart; ! in timer section
!! -> reply
!! %finish
!**********************************************
!****************************************************************
!******************************************************************
!*routine da
!*calls disc handler to read in a block
!* nb: this routine assumes that bx points to the block descriptor
routine da(integer mode)
record (pf)p
p_a3 = bx_block; ! compiler error forces this
p_service = serv(bx_drive)
p_reply = id
if bx_drive = 1 then p_a3 = p_a3!k'020000'
p_a1 = mode
if mode # d read then bx_wrm = 0
! clear the write marker
p_xa2 == bx_blk(0)_x
ponoff(p)
if p_a1 # 0 thensignal 15, 15
end
!*******************************************************
!*record map load
!*loads requested block into core if it is not already there
!*and returns a pointer to the start of the record bx
!*which is set up to current entry in the buffer pool
!*drive is assumed to be set up. ********
!* the routine also sets up global bx as a side effect
record (bf) map load(integer block)
integer i, temp
!*check if block already in pool
cycle i = nbuf, -1, 0
bx == b(i)
if bx_drive = drive and bx_block = block start
result == bx
finish
repeat
!*block not in pool
bx == b(blast)
blast = blast+1
if blast > nbuf then blast = 0
if bx_wrm # 0 start ; !write back old block
da(dwrite)
finish
bx_drive = drive
bx_block = block
da(dread); !read in new block
result == bx
end
!************************************************************
!*record map exam
!*to read in correct directory block
!*and find required entry
record (filef) map exam(record (inff) name inf)
integer n, j, k, hit, t
record (n1f) name file
record (n1f) name info
record (filef) name f
!*set up drive number,0,1 rk05
!2,3 ampex
drive = inf_unit
info == inf_n; ! point to name part
!*set up directory block for scan
t = dirblk(drive)
n = t+inf_fsys; ! map to users directory
cycle ; ! system occupies 3 blocks
fa == load(n)_blk
!*look for match
cycle j = 0, 1, 50
fno = j; ! global for create
f == fa(j); ! point to target entry
if f_n_a = info_a and f_n_b = info_b and f_n_c = c
info_c thenresult == f
repeat
n = n+1
repeat until n > t+2
result == null
end
!******************************************************************
!*record map get block
!*returns pointer to correct block descriptor
!*after calling load to read it into core
record (blkf) map get block(integer block no)
blka == load(block no >> 7+blklst(drive))_blk
!block desc block
result == blka(block no&k'177')
! offset into block
end
!**********************************************************
!*integer function appendb
!*returns next free block number
integerfn appendb(integer last)
integer wrap
wrap = 0
cycle
last = last+1
if last = lastbl(drive) start
if wrap = 0 thenresult = 0
wrap = wrap+1
last = fblock(drive)
finish
blk == get block(last)
if blk_pr = 0 thenresult = last
repeat
end
routine rewrite dir
integer i
cycle i = nbuf, -1, 0
if b(i)_wrm # 0 start
bx == b(i)
da(dwrite)
finish
repeat
end
!*****************************************************************
!*************************************************************
!*************************************************************
!*main control loop
!*link to system slots
linkin(rkser); linkin(amp1ser); linkin(amp2ser); linkin(rkbser)
id = getid
alarm(secs*50); !set clock for secs seconds
restart:
cycle
p_service = 0
poff(p)
!*if clock tick check if buffer pool needs writing
if p_reply = clock int start
alarm(secs*50)
px_service = 0; ! for event 15 handling
rewrite dir
continue
finish
!*not a clock tick--request for service
px_service = p_reply
px_reply = p_service
px_a2 = p_a2
!*get callers block
no = 0
seg = p_a2 >> 13
if seg = 0 thensignal 36, 36
i = map virt(p_reply, seg, my seg)
inf == record(msa+(p_a2&k'17777')); inf2 == inf
-> request(p_a1)
!*
!**
!***** examine file
!**
!*
request(examine):
!*p_a2 has address of descriptor
!*examine finds the file entry in the directory block
!*and returns the first block's number in the file
!*to the caller.
no = 0
f == exam(inf)
unless f == null then no = f_first
if drive = 1 and no # 0 then no = no!k'020000'
-> reply
write dir: da(dwrite); !put directory block back
rewrite dir; ! put list blocks back
reply: i = map virt(0, -1, myseg); !release segment
px_a1 = no
pon(px)
continue
!*
!**
!***** get next
!**
!*
request(get next):
!*p_a2=file descriptor,p_a3=last block
!*get next is given a block of a file and returns
!*the next block in the file by looking at the link in
!*the block descriptor.it also reads the block decriptor
!*entry for the next block to check the protect code.
drive = inf_unit
bk = p_a3
if drive = 1 then bk = bk&k'17777'
blk == get block(bk); !get previous block
pr = blk_pr; no = blk_next
if no # 0 start
blk == get block(no)
if blk_pr # pr then no =- 1 elsestart
!! no = -1 is a protect code error
if drive = 1 then no = no!k'020000'
finish
finish
-> reply
!*
!**
!***** destroy
!**
!*
request(destroy):
!*destroy removes the file's name from the directory
!*block and goes down the block descriptor entries for
!*that file setting all the links and protect codes to
!*zero(checking the protect codes as it goes.)
exit = 0; !take normal exit
destf:
no = 1; ! file does not exist
f == exam(inf)
unless f == null start
no = 0
bk = f_first; pr = f_pr
f = 0; ! delete name etc
f_pr = pr; ! restore "pr"
da(dwrite); !write block back immediately
cycle
!delete all links and pr
blk == get block(bk)
if blk_pr # pr start
no =- 1; !corrupt file!!!
exit
finish
if fblock(drive) <= bk < first free(drive) then c
first free(drive) = bk
bk = blk_next
blk = 0; ! zero pr and next
bx_wrm = bx_wrm+1
repeat until bk = 0
finish
-> write dir if exit = 0
-> ren tmp; !back to rename temp
!*
!**
!***** create file
!**
!*
request(create):
!*a file is created by finding an empty slot in the directory
!*block and copying the name into it.a free block is then found
!*and is deemed to be the first block of the file.a link to
!*this block is set up and the protect code calculated and
!*inserted into the block descriptor.
drive = inf_unit
nosave = 0
nosave = appendb(first free(drive))
if nosave # 0 start
g_fsys = inf_fsys
g_unit = inf_unit
f == exam(g); !find empty slot
unless f == null start
no = nosave
f_n = inf_n; ! copy name
bx_wrm = bx_wrm+1
f_pr = ((f_pr+k'010000')&k'170000')!inf_fsys << 6!fno
f_pr = k'010000' if f_pr = 0
! in case of zero pr
f_first = no
pr = f_pr
da(d write); !put directory block back
blk == get block(no); !get block descriptor back
blk_pr = pr
bx_wrm = bx_wrm+1
first free(drive) = no
if drive = 1 then no = no!k'020000'
finish
finish
-> reply
!*
!**
!***** append block
!**
!*
request(append):
!*to append a block to a file the current last block
!*descriptor entry is inspected for the protect code.
!*the next free block's descriptor is then
!*updated with this code and a link to this block
!*is inserted in the last descriptor entry.
drive = inf_unit
bk = p_a3; !get last block
if drive = 1 then bk = bk&k'17777'
blk == get block(bk); !get last block
pr = blk_pr
no = appendb(bk); !get new last block
if no # 0 start
blk_next = 0
blk_pr = pr
bx_wrm = bx_wrm+1
first free(drive) = no
blk == get block(bk); !get previuos last block to
! insert link
blk_next = no
if drive = 1 then no = no!k'020000'
bx_wrm = bx_wrm+1
finish
-> reply
!*
!**
!***** rename file
!**
!*
request(rename):
request(rename fsys): ! files in different fsys
!*p_a2has existing,p_a3 has new file descriptor
!*if the new file does not already exist then the old
!*file name in the directory block is replaced by
!*the new.
no =- 1
seg2 = p_a3 >> 13
if seg2 = seg start
inf2 == record(msa+(p_a3&k'17777'))
if inf_unit = inf2_unit start
if p_a1 = rename fsys start
g_fsys = inf2_fsys
g_unit = inf2_unit
f == exam(g)
unless f == null start
f == exam(inf); ! get existing file
unless f == null start ; ! doesn't exist
bk = f_first; pr = f_pr
f = 0; ! zero name record
bx_wrm = bx_wrm+1
da(d write)
f == exam(g); ! get empty slot again
f_n = inf2_n; ! copy name
f_first = bk; f_pr = pr
!! bx_wrm = bx_wrm+1 (write dir writes back)
no = 0
finish
finish
else
f == exam(inf2); !check new file does not exist
if f == null start
f == exam(inf)
if f == null then no = 1 elsestart
f_n = inf2_n; ! copy name
!! bx_wrm = bx_wrm+1 (write dir writes back)
no = 0
finish
finish
finish
finish
finish
-> write dir
!*
!**
!***** rename temporary file
!**
!*
request(rename temp):
!*this renames a temporary file in the sense that it removes
!*the temp file marker and destroys the file.
exit = 1; !special exit form directory
inf_n_name(0) = inf_n_name(0)&x'ff7f'
!remove temp marker
-> destf
ren tmp:
inf_n_name(0) = inf_n_name(0)!x'0080'
!put back marker
f == exam(inf)
if f == null then no =- 1 elsestart
f_n_name(0) = f_n_name(0)&x'ff7f'
!not temp now
!! bx_wrm = bx_wrm+1 (write dir writes back)
no = 0
finish
-> write dir
request(dir blk no): ! give block no of directory
no = dirblk(inf_unit)+inf_fsys
-> reply
repeat
endofprogram
!not temp now
request(dir blk no): ! give block no of directory