1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 
 14 /*
 15    update_vtoce        (astep)
 16    update_vtoce$deact  (astep, code)
 17 
 18 
 19 
 20 
 21 
 22    FUNCTION -
 23 
 24    The procedure "update_vtoce" updates the vtoce using the aste pointed to by  the
 25    input  argument  "astep".  The  aste  can  be  regarded  as  being  some form of
 26    associative memory for almost all the vtoce items.  Therefore,  any  vtoce  item
 27    that  has  been  copied from the vtoce into the aste at activation time, must be
 28    copied back from the aste into the vtoce at update vtoce time, if the  value  of
 29    this  item  is  different  in  the  vtoce  and the aste. These items include the
 30    maximum segment length (msl), the current segment length (csl),  the  number  of
 31    disk  records  (records)  occupied by the segment, the date and time segment was
 32    used (dtu), the date and time the segment was modified (dtm) and  the  file  map
 33    (fm).  For  directories,  these  items,  in  addition, include all quota related
 34    information.
 35 
 36    The AST is supposed to be locked before calling "update_vtoce" and unlocked upon
 37    return. The procedure "update_vtoce" does not concern  itself  with  this  lock.
 38    When  it  is  obvious  that  no race condition can occur (initializer, emergency
 39    shutdown), this procedure may be called without locking the AST.
 40 
 41    The Page Table Lock however is not supposed  to  be  locked  (and  must  not  be
 42    locked) before calling this procedure.
 43 
 44    Update_vtoce  is  called  each  time  a segment is being deactivated. It is also
 45    called for segments which are not being deactivated,  in  order  to  update  the
 46    vtoce on the disk, if they have been active for a long time.
 47 
 48 
 49    IMPLEMENTATION -
 50 
 51    Basically   the   logic   of   "update_vtoce"   is  very  simple.   First,  call
 52    pc$get_file_map in order to get a  snapshot  of  the  aste  with  the  fm.  Then
 53    determine,  from  the aste, the pvtx and the vtocx of the vtoce, read the vtoce,
 54    update it with the items returned by pc$get_file_map, and write it back  on  the
 55    disk. At last, deposit the list of disk addresses that may have been returned by
 56    pc$get_file_map.   Although  this  simple  implementation  is  correct, it would
 57    probably be very expensive in terms of I/O requests since the
 58    vtoce would be read and written each time.
 59 
 60    The simple implementation is optimized as follows. A set of criteria are used
 61    to determine whether it is necessary to read the VTOCE. If it is not, part
 62    1 is written to disk (note that this can happen only for a segment whose
 63    file map fits into part 1). If it is necessary to read the VTOCE, the entire
 64    VTOCE is read and written back.
 65 
 66 
 67 
 68 
 69 
 70 
 71    MODIFIED BY:
 72 
 73         /84   Benson Margulies - to purge users of sst.incl
 74    10/01/82   J. Bongiovanni - synchronized switch, filemap checksum
 75    8/18/82    J. Bongiovanni - new pc$get_file_map, pc$deposit_list calling
 76                                sequence
 77    7/10/82    J. Bongiovanni - to simplify the optimization by reading the
 78                                entire VTOCE if it is necessary to read it at all
 79    3/18/82    J. Bongiovanni - to return an error code if called for a hardcore  segment
 80    10/10/77   B. Greenberg - update_vtoce$deact to take code, & implications thereof.
 81    Modified by D.Vinograd 6/76 to update volume dumper bit map so tha modified objects are dumped
 82    04/23/75   A. Bensoussan - wrote the first version for the new storage system to
 83    replace updateb.
 84 
 85 */
 86 
 87 
 88 
 89 
 90 
 91 update_vtoce: procedure (a_astep);
 92           dsw = "0"b;
 93           go to join;
 94 
 95 deact: entry (a_astep, a_code);
 96           dsw = "1"b;
 97 join:
 98 
 99           dcl     a_astep                ptr;
100 
101 
102           dcl     1 local_vtoce          like vtoce aligned;
103           dcl     1 local_aste           like aste aligned;
104 
105           dcl     (pvtx, vtocx)          fixed bin (17);
106           dcl     dsw                    bit (1);
107           dcl     code                   fixed bin (35);
108           dcl     a_code                 fixed bin (35);
109           dcl     (n, i, pts, max)       fixed bin (17);
110           dcl     deposit_list           (0:255) bit (22) aligned;
111           dcl     pageno_list            (0:255) fixed bin aligned;
112           dcl     1 saved_fm             aligned,
113                     2 fm                 (0:255) bit (18) unaligned;
114 
115           dcl     curtime                bit (36) aligned;
116           dcl     dt                     fixed bin (35);
117           dcl     read_vtoce             bit (1) aligned;
118           dcl     parts_write            bit (3);
119 
120           dcl     ALL_PARTS              bit (3) int static options (constant) init ("111"b);
121           dcl     PART_ONE               bit (3) int static options (constant) init ("100"b);
122 
123           dcl     vtoc_man$get_vtoce     entry (bit (36) aligned, fixed bin, fixed bin, bit (3), ptr, fixed bin (35));
124           dcl     vtoc_man$put_vtoce     entry (bit (36) aligned, fixed bin, fixed bin, bit (3), ptr, fixed bin (35));
125           dcl     vtoc_man$await_vtoce   entry (bit (36) aligned, fixed bin, fixed bin, fixed bin (35));
126           dcl     pc$get_file_map        entry (ptr, ptr, ptr, fixed bin, ptr, ptr);
127           dcl     pc$deposit_list        entry (fixed bin, fixed bin, ptr, fixed bin, ptr);
128           dcl     filemap_checksum_      entry (ptr, fixed bin, bit (36) aligned);
129 
130           dcl     (addr, bin, bit, clock, fixed, unspec) builtin;
131 
132           dcl     sst$checksum_filemap   fixed bin (35) external;
133           dcl     sst$pts                (0:3) fixed bin (35) external static;
134 
135           dcl     error_table_$hardcore_sdw fixed bin (35) external;
136 
137 
138 /*        % include vtoce;              see at the end.     */
139 /*        % include aste;               see at the end.     */
140 /*        % include null_addresses;     see at the end.     */
141 ^L
142 /* INITIALIZE POINTERS */
143 
144           n = 0;                                            /* For error recovery */
145           astep = a_astep;
146           if aste.hc_sdw then do;                           /* Meaningless to update VTOCE for this type of segment */
147                     if dsw then a_code = error_table_$hardcore_sdw;
148                     return;
149                end;
150           vtocep = addr (local_vtoce);
151           pvtx = fixed (aste.pvtx); if pvtx <= 0 then return;
152           vtocx = aste.vtocx;
153           pts = sst$pts (fixed (aste.ptsi));
154 
155           read_vtoce = "0"b;
156 
157 /* DETERMINE WHETHER IT IS NECESSARY TO READ THE VTOCE */
158 
159           if aste.dirsw & (aste.tqsw (0) | aste.tqsw (1))
160           then read_vtoce = "1"b;
161           if pts > 96 & aste.fmchanged
162           then read_vtoce = "1"b;
163 
164           if read_vtoce then do;
165                     call vtoc_man$get_vtoce ("0"b, pvtx, vtocx, ALL_PARTS, vtocep, code);
166                     if code ^= 0 then go to serious_problem;
167                end;
168 
169 
170 /* GET A SNAPSHOT OF THE ASTE AND THE FILE MAP */
171 
172           if ^read_vtoce
173           then unspec (vtoce) = ""b;
174 
175           call pc$get_file_map (astep, addr (local_aste), addr (vtoce.fm), n, addr (deposit_list), addr (pageno_list));
176           if aste.fm_damaged & (sst$checksum_filemap ^= 0) then n = 0; /* Don't deposit if file map suspect */
177 
178           astep = addr (local_aste);
179 
180 /* CHECK FOR RACE (FILE MAP UPDATED SINCE WE CHECKED) */
181 
182           if ^read_vtoce & aste.fmchanged & (pts > 96)
183           then do;
184                     read_vtoce = "1"b;
185                     unspec (saved_fm.fm) = unspec (vtoce.fm);
186                     call vtoc_man$get_vtoce ("0"b, pvtx, vtocx, ALL_PARTS, vtocep, code);
187                     if code ^= 0 then goto serious_problem;
188                     unspec (vtoce.fm) = unspec (saved_fm.fm);
189                end;
190 
191 
192 
193 /* UPDATE THE VTOCE IN LOCAL STORAGE */
194 
195           curtime = bit (bin (clock (), 52), 52);
196 
197           vtoce.uid = aste.uid;
198           vtoce.msl = aste.msl;
199           vtoce.csl = aste.csl;
200           vtoce.records = aste.records;
201 
202           vtoce.dtu = aste.dtu;
203           vtoce.dtm = aste.dtm;
204 
205           vtoce.nqsw = aste.nqsw;
206           vtoce.deciduous = aste.hc_sdw;
207           vtoce.per_process = aste.per_process;
208           vtoce.damaged = aste.damaged;
209           vtoce.fm_damaged = aste.fm_damaged;
210           vtoce.synchronized = aste.synchronized;
211           vtoce.dnzp = aste.dnzp;
212           vtoce.gtpd = aste.gtpd;
213           vtoce.nid = aste.nid;
214           vtoce.dirsw = aste.dirsw;
215 
216 
217 
218 
219           if aste.dirsw then
220                do;
221                     vtoce.master_dir = aste.master_dir;
222                     do i = 0, 1;
223                          vtoce.used (i) = aste.used (i);
224                          vtoce.quota (i) = aste.quota (i);
225                          if aste.tqsw (i) then
226                               do;
227                                    dt = fixed (curtime, 36) - fixed (vtoce.trp_time (i), 36);
228                                    vtoce.trp (i) = vtoce.trp (i) + fixed (aste.used (i) * dt * .65536e-1 + .5e0, 71);
229                                    vtoce.trp_time (i) = curtime;
230                               end;
231                     end;
232                end;
233           else seg_vtoce.usage = seg_aste.usage;            /* segments have pf count instead of quota */
234 
235 
236 /* DETERMINE THE PARTS TO BE WRITTEN AND WRITE THE VTOCE */
237 
238           if read_vtoce then do;
239                     parts_write = ALL_PARTS;
240                     max = 255;
241                end;
242           else do;
243                     parts_write = PART_ONE;
244                     max = 95;
245                end;
246 
247           do i = pts to max; vtoce.fm (i) = update_vtoce_null_addr; end;
248 
249           if sst$checksum_filemap = 0 then do;
250                     vtoce.fm_checksum_valid = "0"b;
251                     vtoce.fm_checksum = ""b;
252                end;
253           else if read_vtoce | (pts <= 96) then do;
254                     vtoce.fm_checksum_valid = "1"b;
255                     call filemap_checksum_ (addr (vtoce.fm), fixed (vtoce.csl, 9), vtoce.fm_checksum);
256                end;
257 
258           call vtoc_man$put_vtoce ("0"b, pvtx, vtocx, parts_write, vtocep, code);
259           if code ^= 0 then go to serious_problem;
260 
261 
262 /* IF THERE ARE ANY DISK ADDRESSES TO BE DEPOSITED, THEN DO IT */
263 
264           if n > 0 then do;
265                     call vtoc_man$await_vtoce ("0"b, pvtx, vtocx, code);
266                     if code ^= 0 then go to serious_problem;
267                     call pc$deposit_list (pvtx, n, addr (deposit_list), vtocx, addr (pageno_list));
268                end;
269 
270 
271 /* RESET THE ASTE.FMCHANGED1 FLAG FOR PAGE CONTROL IF NECESSARY */
272 
273           if aste.fmchanged then a_astep -> aste.fmchanged1 = "0"b;
274 
275           if dsw then a_code = 0;
276           return;
277 
278 serious_problem:
279           if dsw then a_code = code;
280           a_astep -> aste.fmchanged = "1"b;                 /* Cause trickle to do it */
281           if n > 0
282           then addr (pvt$array) -> pvt_array (aste.pvtx).vol_trouble_count
283                     = addr (pvt$array) -> pvt_array (aste.pvtx).vol_trouble_count + 1; /* Couldn't deposit */
284           return;
285 ^L
286 %include vtoce;
287 %include pvte;
288 %include aste;
289 %include null_addresses;
290 
291      end update_vtoce;