1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1984 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 
 14 quotaw: proc;
 15 
 16 /* RE Mullen, v2pl1, oct 1973 */
 17 /* Modified by Bernard Greenberg, 04/28/75 for New Storage System */
 18 /* Modified by Bernard Greenberg, 02/18/77 for online quota reconstructor */
 19 /* Modified by David Spector, 02/18/79 for 18 bit quota */
 20 /* Modified by Keith Loepere, 12/13/84 to count dirs pages against its own dir quota. */
 21 
 22 dcl (a_astep, a_astep2) ptr,
 23      a_t fixed bin (1),
 24     (csw, a_csw) fixed bin (2);
 25 dcl  a_q fixed bin (18);
 26 dcl  a_code fixed bin (17);
 27 dcl  a_uc fixed bin (18);
 28 
 29 dcl (addr, fixed, ptr) builtin;
 30 
 31 dcl (astpp, astep1, astep2, ptwp) ptr,
 32     (uchange, tchange, qchange, quota) fixed bin (34),
 33      code fixed bin,
 34     (tsw, ct, nt, qt) fixed bin (1),
 35     (a_osu, osu, a_odu, odu, a_nsu, nsu, a_ndu, ndu) fixed bin (34),
 36      new_quota fixed bin (34),
 37      pcsw bit (1),
 38      a_qt bit (1) aligned,
 39      pds$processid ext bit (36),
 40      pds$quota_inhib ext fixed bin (17),
 41      oldmask fixed bin (71),
 42      privileged_mode_ut$lock_ptl ext entry (fixed bin (71), ptr),
 43      privileged_mode_ut$unlock_ptl ext entry (fixed bin (71), ptr);
 44 
 45           % include aste;
 46 
 47 declare sst$rqover fixed bin (35) external static;
 48 declare sst_seg$ external static;
 49 declare sstp pointer;
 50 
 51 /* entry to changed used records for an active account */
 52 
 53 cu:       entry (a_astep, a_uc, a_qt, a_csw, a_code);
 54           csw = a_csw;                                      /* check switch: = 1 check only, = 0 check and make change */
 55                                                             /* 2 = make change and dont complain */
 56           pcsw = "0"b;
 57           go to cum;
 58 cu_for_pc: entry (a_astep, a_uc, a_qt);
 59                                                             /* Special side-door for pc$truncate */
 60           pcsw = "1"b;
 61           csw = 0;                                          /* Do it */
 62 cum:
 63 
 64 
 65           astep = a_astep;                                  /* ptr to AST entry of dir in which file resides */
 66           uchange = a_uc;                                   /* change to used */
 67           qt = fixed (a_qt, 1);                             /* quota type, 0 = segs, 1 = dirs */
 68           code = 0;
 69 
 70           sstp = addr (sst_seg$);
 71           if ^pcsw then call privileged_mode_ut$lock_ptl (oldmask, ptwp); /* lock, switch_stack and mask */
 72 
 73 cu1:      astpp = astep;
 74 cu2:      if csw ^= 1
 75           then astpp -> aste.used (qt) = astpp -> aste.used (qt) + uchange;
 76           if csw = 2 then do;
 77                if uchange > 0 & astpp -> aste.used (qt) > aste.quota (qt)
 78                then code = sst$rqover;
 79                go to finish;
 80           end;
 81           if astpp -> aste.tqsw (qt) = "0"b then do;
 82                astpp = ptr (sstp, astpp -> aste.par_astep); /* loop over parents */
 83                go to cu2;
 84           end;
 85           if pds$quota_inhib ^= 0
 86           then go to finish;                                /* Patch for reloader, etc */
 87           if code ^= 0
 88           then go to finish;                                /* second time thru the loop */
 89           if uchange <= 0 then go to finish;                /* don't check quota when decreasing */
 90           if csw = 1
 91           then tchange = uchange;                           /* change has not been added in */
 92           else tchange = 0;                                 /* change has been added in */
 93           if astpp -> aste.quota (qt) < (astpp -> aste.used (qt) + tchange)
 94           then do;                                          /* change is not ok */
 95                uchange = -uchange;                          /* prepare to remove change */
 96                code = sst$rqover;
 97                if csw = 0
 98                then go to cu1;                              /* loop thru and undo change if any */
 99           end;
100 
101 finish:   if pcsw then return;
102           call privileged_mode_ut$unlock_ptl (oldmask, ptwp); /* unlock, switch back and unmask */
103           a_code = code;
104           return;
105 
106 
107 /* * * * * * * * * * * * * * * * * * * * * * * * * */
108 
109 /* entry to set a quota and change the terminal state of an active AST */
110 
111 sq:       entry (a_astep, a_q, a_qt, a_t);
112 
113 
114           astep = a_astep;                                  /* ptr to ast entry to set quota on */
115           quota = a_q;                                      /* new quota */
116           qt = fixed (a_qt, 1);
117           tsw = a_t;                                        /* = 1 if quota is being changed from non-term to term */
118                                                             /* = 0 if quota is being changed from term to non-term */
119           sstp = addr (sst_seg$);
120 
121           call privileged_mode_ut$lock_ptl (oldmask, ptwp); /* mask, switch stack and lock */
122 
123           if tsw = 1
124           then uchange = astep -> aste.used (qt);           /* used records that will no longer be carried up */
125           else uchange = -astep -> aste.used (qt);          /* used records will be added sup acct */
126           astpp = astep;
127 sq1:      astpp = ptr (sstp, astpp -> aste.par_astep);      /* loop to find terminal account */
128           astpp -> aste.used (qt) = astpp -> aste.used (qt) - uchange; /* subtract used from parents */
129           if astpp -> aste.tqsw (qt) = "0"b
130           then go to sq1;
131 
132           astep -> aste.quota (qt) = quota;
133           astep -> aste.tqsw (qt) = (tsw = 1);
134 
135           call privileged_mode_ut$unlock_ptl (oldmask, ptwp); /* unlock, switch back and unmask */
136 
137           return;
138 
139 /* * * * * * * * * * * * * * * * * * */
140 
141 /* entry to move quota from parent ast (ast1) to inferior ast (ast2) */
142 
143 mq:       entry (a_astep, a_astep2, a_q, a_qt, a_code);
144 
145 
146           astep1 = a_astep;                                 /* ptr to parent ast entry */
147           astep2 = a_astep2;                                /* ptr to target ast entry */
148           qchange = a_q;                                    /* amount of quota to be moved from ast1 to ast2 */
149           qt = fixed (a_qt, 1);
150           code = 0;
151           sstp = addr (sst_seg$);
152 
153           call privileged_mode_ut$lock_ptl (oldmask, ptwp); /* mask, switch stack and lock */
154 
155           ct = fixed (astep2 -> aste.tqsw (qt), 1);         /* ct = 1 if ast2 currently has term quota */
156           if astep2 -> aste.quota (qt) + qchange ^= 0
157           then do;                                          /* ast2 will have terminal quota */
158                nt = 1;
159                if astep2 -> aste.quota (qt) + qchange < astep2 -> aste.used (qt)
160                then go to error;
161                                                             /* new quota must cover used */
162                if ct = 0
163                then uchange = -astep2 -> aste.used (qt);    /* subtract used from current terminal quota */
164                else uchange = 0;                            /* no change from terminal state */
165           end;
166           else do;                                          /* ast2 will not have terminal quota */
167                nt = 0;
168                if ct = 1
169                then uchange = astep2 -> aste.used (qt);     /* add used into new terminal quota */
170                else uchange = 0;
171           end;
172           new_quota = astep1 -> aste.quota (qt) - qchange;
173           if new_quota <= 0 then go to error;               /* Insure no zero terminal quota */
174           if new_quota < astep1 -> aste.used (qt)+uchange then go to error;
175           astep1 -> aste.quota (qt) = new_quota;            /* Change quota */
176           astep1 -> aste.used (qt) = astep1 -> aste.used (qt)+uchange; /* change parent used */
177           astep2 -> aste.quota (qt) = astep2 -> aste.quota (qt)+qchange; /* change target quota */
178           astep2 -> aste.tqsw (qt) = (nt = 1);
179 
180 mqfinish:
181           call privileged_mode_ut$unlock_ptl (oldmask, ptwp); /* unlock, switch back and unmask */
182 
183           a_code = code;
184           return;
185 
186 error:    code = sst$rqover;
187           go to mqfinish;
188 
189 /* * * * * * * * * * * * * * * * * * * * * * * * * */
190 
191 rvq:      entry (a_astep, a_osu, a_odu, a_nsu, a_ndu);
192 
193 /*        Entry to determine active inferior and current active quota totals for revalidator */
194 
195           astep = a_astep;
196 
197           sstp = addr (sst_seg$);
198 
199           call privileged_mode_ut$lock_ptl (oldmask, ptwp); /* mask, lock */
200 
201           osu = aste.used (0);
202           odu = aste.used (1);                              /* Copy current, incorrect totals */
203           nsu = 0;                                          /* Zero totals to be accumulated */
204           ndu = fixed (aste.records, 9);                    /* dirs records count towards itself */
205 
206           do astep = ptr (sstp, aste.infp) repeat ptr (sstp, aste.infl) while (astep ^= sstp);
207                                                             /* Map over inferiors */
208                if aste.dirsw then do;
209                     if ^aste.tqsw (0) then nsu = nsu + aste.used (0); /* Add inferior dir totals */
210                     if ^aste.tqsw (1) then ndu = ndu + aste.used (1); /* records of dir already counted in quota used */
211                end;
212                else nsu = nsu + fixed (aste.records, 9);    /* Account to right place */
213           end;
214 
215           call privileged_mode_ut$unlock_ptl (oldmask, ptwp);
216 
217           a_osu = osu;                                      /* Copy out answers */
218           a_odu = odu;
219           a_nsu = nsu;
220           a_ndu = ndu;
221 
222           return;
223      end quotaw;