!****************************** !* file system handler * !* fsys1s/fsys1y * !* date: 30.Jun.81 * !****************************** ! STACK = 240, STREAMS = 0 !*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 x'4001' include "deimosperm" begin !********************************************************* !************* data areas &declarations ********** !********************************************************* !*system slots/disc constinteger max drives = 4 constbyteintegerarray serv(0:max drives) = 3, 3, 8, 14, 28 constbytearray myser(0:max drives) = 4, 4, 9, 15, 29 !*directory block areas/disc ownintegerarray dirblk(0:max drives) !*block descriptor base/disc ownbyteintegerarray blklst(0:max drives) !*free block start/disc ownintegerarray fblock(0:max drives) ownintegerarray first free(0:max drives) !*top of disc ownintegerarray lastbl(0:max drives) !*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 constinteger report unit = 10 constinteger report unit2 = 11 !*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 a, c (integer b or integername xa2), integer c or c byte a1, a2, b1, b2, c1, c2)) 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 ownintegerarray dum(0:20); ! compiler fault in GLA length !*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_c = bx_block; ! compiler error forces this p_service = serv(bx_drive) p_reply = id if bx_drive = 1 then p_c = p_c!k'020000' p_a = mode if mode # d read then bx_wrm = 0 ! clear the write marker p_xa2 == bx_blk(0)_x ponoff(p) if p_a # 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 = 1 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 routine do report unit(integer type) integer i, j i = p_a2 if serv(i) # p_reply then return ; ! enforce a check if type = report unit start fblock(i) = p_b; first free(i) = p_b lastbl(i) = p_c finish else start dirblk(i) = p_b blklst(i) = p_c linkin(myser(i)) finish end !***************************************************************** !************************************************************* !************************************************************* !*main control loop !*link to system slots linkin(rkser) 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 if report unit <= p_a1 <= report unit 2 then c do report unit(p_a1) and continue px_service = p_reply px_reply = p_service px_b = p_b !*get callers block no = 0 seg = p_b >> 13 if seg = 0 then -> reply; ! reject it i = map virt(p_reply, seg, my seg) if i = 0 then -> reply inf == record(msa+(p_b&k'17777')); inf2 == inf if dirblk(inf_unit) = 0 then -> reply; ! disc not present -> request(p_a) !* !** !***** examine file !** !* request(examine): !*p_b 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_a = no pon(px) continue !* !** !***** get next !** !* request(get next): !*p_b=file descriptor,p_c=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_c 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_c; !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_bhas existing,p_c 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_c >> 13 if seg2 = seg start inf2 == record(msa+(p_c&k'17777')) if inf_unit = inf2_unit start if p_a = 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