ArchWizard

DGD/

source navigation ]
diff markup ]
identifier search ]
file search ]
Version: [ 1.0.a0 ] [ 1.1 ] [ 1.2 ] [ 1.2p1 ] [ 1.2p2 ] [ 1.2p3 ] [ 1.2p4 ] [ 1.2.151 ]

  1 # define INCLUDE_FILE_IO
  2 # include "dgd.h"
  3 # include "swap.h"
  4 
  5 typedef struct _header_ {       /* swap slot header */
  6     struct _header_ *prev;      /* previous in swap slot list */
  7     struct _header_ *next;      /* next in swap slot list */
  8     sector sec;                 /* the sector that uses this slot */
  9     sector swap;                /* the swap sector (if any) */
 10     bool dirty;                 /* has the swap slot been written to? */
 11 } header;
 12 
 13 static char *swapfile;                  /* swap file name */
 14 static int swap;                        /* swap file descriptor */
 15 static int dump;                        /* dump file descriptor */
 16 static int restore;                     /* restore file descriptor */
 17 static char *mem;                       /* swap slots in memory */
 18 static sector *map, *smap;              /* sector map, swap free map */
 19 static sector mfree, sfree;             /* free sector lists */
 20 static char *bmap;                      /* sector bitmap */
 21 static char *cbuf;                      /* sector buffer */
 22 static sector cached;                   /* sector currently cached in cbuf */
 23 static header *first, *last;            /* first and last swap slot */
 24 static header *lfree;                   /* free swap slot list */
 25 static long slotsize;                   /* sizeof(header) + size of sector */
 26 static unsigned int sectorsize;         /* size of sector */
 27 static unsigned int restoresecsize;     /* size of sector in restore file */
 28 static sector swapsize, cachesize;      /* # of sectors in swap and cache */
 29 static sector nsectors;                 /* total swap sectors */
 30 static sector nfree;                    /* # free sectors */
 31 static sector ssectors;                 /* sectors actually in swap file */
 32 static sector dsectors, dcursec;        /* dump sectors */
 33 
 34 /*
 35  * NAME:        swap->init()
 36  * DESCRIPTION: initialize the swap device
 37  */
 38 void sw_init(file, total, cache, secsize)
 39 char *file;
 40 register unsigned int total, cache;
 41 unsigned int secsize;
 42 {
 43     register header *h;
 44     register sector i;
 45 
 46     /* allocate and initialize all tables */
 47     swapfile = file;
 48     swapsize = total;
 49     cachesize = cache;
 50     sectorsize = secsize;
 51     slotsize = sizeof(header) + secsize;
 52     mem = ALLOC(char, slotsize * cache);
 53     map = ALLOC(sector, total);
 54     smap = ALLOC(sector, total);
 55     bmap = ALLOC(char, (total + 7) >> 3);
 56     cbuf = ALLOC(char, secsize);
 57     cached = SW_UNUSED;
 58 
 59     /* 0 sectors allocated */
 60     nsectors = 0;
 61     ssectors = 0;
 62     nfree = 0;
 63     dsectors = 0;
 64 
 65     /* init free sector maps */
 66     mfree = SW_UNUSED;
 67     sfree = SW_UNUSED;
 68     lfree = h = (header *) mem;
 69     for (i = cache - 1; i > 0; --i) {
 70         h->sec = SW_UNUSED;
 71         h->next = (header *) ((char *) h + slotsize);
 72         h = h->next;
 73     }
 74     h->sec = SW_UNUSED;
 75     h->next = (header *) NULL;
 76 
 77     /* no swap slots in use yet */
 78     first = (header *) NULL;
 79     last = (header *) NULL;
 80 
 81     swap = dump = -1;
 82 }
 83 
 84 /*
 85  * NAME:        swap->finish()
 86  * DESCRIPTION: clean up swapfile
 87  */
 88 void sw_finish()
 89 {
 90     if (swap >= 0) {
 91         char buf[STRINGSZ];
 92 
 93         P_close(swap);
 94         P_unlink(path_native(buf, swapfile));
 95     }
 96     if (dump >= 0) {
 97         P_close(dump);
 98     }
 99 }
100 
101 /*
102  * NAME:        create()
103  * DESCRIPTION: create the swap file
104  */
105 static void sw_create()
106 {
107     char buf[STRINGSZ], *p;
108 
109     memset(cbuf, '\0', sectorsize);
110     p = path_native(buf, swapfile);
111     P_unlink(p);
112     swap = P_open(p, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
113     if (swap < 0 || P_write(swap, cbuf, sectorsize) < 0) {
114         fatal("cannot create swap file \"%s\"", swapfile);
115     }
116 }
117 
118 /*
119  * NAME:        copy()
120  * DESCRIPTION: copy sectors from dump to swap
121  */
122 static void copy(sec, n)
123 register sector sec, n;
124 {
125     dsectors -= n;
126 
127     if (swap < 0) {
128         sw_create();
129     }
130 
131     while (n > 0) {
132         while (!BTST(bmap, dcursec)) {
133             dcursec++;
134         }
135         P_lseek(dump, (map[dcursec] + 1L) * sectorsize, SEEK_SET);
136         if (P_read(dump, cbuf, sectorsize) <= 0) {
137             fatal("cannot read dump file");
138         }
139         P_lseek(swap, (sec + 1L) * sectorsize, SEEK_SET);
140         if (P_write(swap, cbuf, sectorsize) < 0) {
141             fatal("cannot write swap file");
142         }
143 
144         BCLR(bmap, dcursec);
145         map[dcursec++] = sec++;
146         --n;
147     }
148 }
149 
150 /*
151  * NAME:        swap->newv()
152  * DESCRIPTION: initialize a new vector of sectors
153  */
154 void sw_newv(vec, size)
155 register sector *vec;
156 register unsigned int size;
157 {
158     while (mfree != SW_UNUSED) {
159         /* reuse a previously deleted sector */
160         if (size == 0) {
161             return;
162         }
163         mfree = map[*vec = mfree];
164         map[*vec++] = SW_UNUSED;
165         --nfree;
166         --size;
167     }
168 
169     while (size > 0) {
170         /* allocate a new sector */
171         if (nsectors == swapsize) {
172             fatal("out of sectors");
173         }
174         BCLR(bmap, nsectors);
175         map[*vec++ = nsectors++] = SW_UNUSED;
176         --size;
177     }
178 }
179 
180 /*
181  * NAME:        swap->wipev()
182  * DESCRIPTION: wipe a vector of sectors
183  */
184 void sw_wipev(vec, size)
185 register sector *vec;
186 register unsigned int size;
187 {
188     register sector sec, i;
189     register header *h;
190 
191     while (dsectors > 0) {
192         if (size == 0) {
193             return;
194         }
195         sec = *vec++;
196         i = map[sec];
197         if (i < cachesize && (h=(header *) (mem + i * slotsize))->sec == sec) {
198             i = h->swap;
199             h->swap = SW_UNUSED;
200         } else {
201             map[sec] = SW_UNUSED;
202         }
203         if (i != SW_UNUSED) {
204             if (BTST(bmap, sec)) {
205                 /*
206                  * free sector in dump file
207                  */
208                 BCLR(bmap, sec);
209                 --dsectors;
210             } else {
211                 /*
212                  * replace by sector from dump file
213                  */
214                 copy(i, (sector) 1);
215             }
216         }
217         --size;
218     }
219 
220     vec += size;
221     while (size > 0) {
222         sec = *--vec;
223         i = map[sec];
224         if (i < cachesize && (h=(header *) (mem + i * slotsize))->sec == sec) {
225             i = h->swap;
226             h->swap = SW_UNUSED;
227         } else {
228             map[sec] = SW_UNUSED;
229         }
230         if (i != SW_UNUSED) {
231             /*
232              * free sector in swap file
233              */
234             smap[i] = sfree;
235             sfree = i;
236         }
237         --size;
238     }
239 }
240 
241 /*
242  * NAME:        swap->delv()
243  * DESCRIPTION: delete a vector of swap sectors
244  */
245 void sw_delv(vec, size)
246 register sector *vec;
247 register unsigned int size;
248 {
249     register sector sec, i;
250     register header *h;
251 
252     /*
253      * note: sectors must have been wiped before being deleted!
254      */
255     vec += size;
256     while (size > 0) {
257         sec = *--vec;
258         i = map[sec];
259         if (i < cachesize && (h=(header *) (mem + i * slotsize))->sec == sec) {
260             /*
261              * remove the swap slot from the first-last list
262              */
263             if (h != first) {
264                 h->prev->next = h->next;
265             } else {
266                 first = h->next;
267                 if (first != (header *) NULL) {
268                     first->prev = (header *) NULL;
269                 }
270             }
271             if (h != last) {
272                 h->next->prev = h->prev;
273             } else {
274                 last = h->prev;
275                 if (last != (header *) NULL) {
276                     last->next = (header *) NULL;
277                 }
278             }
279             /*
280              * put the cache slot in the free cache slot list
281              */
282             h->sec = SW_UNUSED;
283             h->next = lfree;
284             lfree = h;
285         }
286 
287         /*
288          * put sec in free sector list
289          */
290         map[sec] = mfree;
291         mfree = sec;
292         nfree++;
293 
294         --size;
295     }
296 }
297 
298 /*
299  * NAME:        swap->load()
300  * DESCRIPTION: reserve a swap slot for sector sec. If fill == TRUE, load it
301  *              from the swap file if appropriate.
302  */
303 static header *sw_load(sec, fill)
304 sector sec;
305 bool fill;
306 {
307     register header *h;
308     register sector load, save;
309 
310     load = map[sec];
311     if (load >= cachesize ||
312         (h=(header *) (mem + load * slotsize))->sec != sec) {
313         /*
314          * the sector is either unused or in the swap file
315          */
316         if (lfree != (header *) NULL) {
317             /*
318              * get swap slot from the free swap slot list
319              */
320             h = lfree;
321             lfree = h->next;
322         } else {
323             /*
324              * No free slot available, use the last one in the swap slot list
325              * instead.
326              */
327             h = last;
328             last = h->prev;
329             if (last != (header *) NULL) {
330                 last->next = (header *) NULL;
331             }
332             save = h->swap;
333             if (h->dirty) {
334                 /*
335                  * Dump the sector to swap file
336                  */
337 
338                 if (save == SW_UNUSED) {
339                     /*
340                      * allocate new sector in swap file
341                      */
342                     if (sfree == SW_UNUSED) {
343                         save = ssectors++;
344                     } else {
345                         save = sfree;
346                         sfree = smap[save];
347                     }
348                 }
349 
350                 if (swap < 0) {
351                     sw_create();
352                 }
353                 P_lseek(swap, (save + 1L) * sectorsize, SEEK_SET);
354                 if (P_write(swap, (char *) (h + 1), sectorsize) < 0) {
355                     fatal("cannot write swap file");
356                 }
357             }
358             map[h->sec] = save;
359         }
360         h->sec = sec;
361         h->swap = load;
362         h->dirty = FALSE;
363         /*
364          * The slot has been reserved. Update map.
365          */
366         map[sec] = ((long) h - (long) mem) / slotsize;
367 
368         if (load != SW_UNUSED) {
369             if (dsectors > 0 && BTST(bmap, sec)) {
370                 if (fill) {
371                     /*
372                      * load the sector from the dump file
373                      */
374                     P_lseek(dump, (load + 1L) * sectorsize, SEEK_SET);
375                     if (P_read(dump, (char *) (h + 1), sectorsize) <= 0) {
376                         fatal("cannot read dump file");
377                     }
378                 }
379 
380                 BCLR(bmap, sec);
381                 --dsectors;
382 
383                 h->swap = SW_UNUSED;
384                 h->dirty = TRUE;
385             } else if (fill) {
386                 /*
387                  * load the sector from the swap file
388                  */
389                 P_lseek(swap, (load + 1L) * sectorsize, SEEK_SET);
390                 if (P_read(swap, (char *) (h + 1), sectorsize) <= 0) {
391                     fatal("cannot read swap file");
392                 }
393             }
394         } else if (fill) {
395             /* zero-fill new sector */
396             memset(h + 1, '\0', sectorsize);
397         }
398     } else {
399         /*
400          * The sector already had a slot. Remove it from the first-last list.
401          */
402         if (h != first) {
403             h->prev->next = h->next;
404         } else {
405             first = h->next;
406         }
407         if (h != last) {
408             h->next->prev = h->prev;
409         } else {
410             last = h->prev;
411             if (last != (header *) NULL) {
412                 last->next = (header *) NULL;
413             }
414         }
415     }
416     /*
417      * put the sector at the head of the first-last list
418      */
419     h->prev = (header *) NULL;
420     h->next = first;
421     if (first != (header *) NULL) {
422         first->prev = h;
423     } else {
424         last = h;       /* last was NULL too */
425     }
426     first = h;
427 
428     return h;
429 }
430 
431 /*
432  * NAME:        swap->readv()
433  * DESCRIPTION: read bytes from a vector of sectors
434  */
435 void sw_readv(m, vec, size, idx)
436 register char *m;
437 register sector *vec;
438 register Uint size, idx;
439 {
440     register unsigned int len;
441 
442     vec += idx / sectorsize;
443     idx %= sectorsize;
444     do {
445         len = (size > sectorsize - idx) ? sectorsize - idx : size;
446         memcpy(m, (char *) (sw_load(*vec++, TRUE) + 1) + idx, len);
447         idx = 0;
448         m += len;
449     } while ((size -= len) > 0);
450 }
451 
452 /*
453  * NAME:        swap->writev()
454  * DESCRIPTION: write bytes to a vector of sectors
455  */
456 void sw_writev(m, vec, size, idx)
457 register char *m;
458 register sector *vec;
459 register Uint size, idx;
460 {
461     register header *h;
462     register unsigned int len;
463 
464     vec += idx / sectorsize;
465     idx %= sectorsize;
466     do {
467         len = (size > sectorsize - idx) ? sectorsize - idx : size;
468         h = sw_load(*vec++, (len != sectorsize));
469         h->dirty = TRUE;
470         memcpy((char *) (h + 1) + idx, m, len);
471         idx = 0;
472         m += len;
473     } while ((size -= len) > 0);
474 }
475 
476 /*
477  * NAME:        swap->dreadv()
478  * DESCRIPTION: restore bytes from a vector of sectors in dump file
479  */
480 void sw_dreadv(m, vec, size, idx)
481 register char *m;
482 register sector *vec;
483 register Uint size, idx;
484 {
485     register unsigned int len;
486 
487     vec += idx / restoresecsize;
488     idx %= restoresecsize;
489     do {
490         len = (size > restoresecsize - idx) ? restoresecsize - idx : size;
491         if (*vec != cached) {
492             P_lseek(restore, (smap[*vec] + 1L) * restoresecsize, SEEK_SET);
493             if (P_read(restore, cbuf, restoresecsize) <= 0) {
494                 fatal("cannot read dump file");
495             }
496             cached = *vec;
497         }
498         vec++;
499         memcpy(m, cbuf + idx, len);
500         idx = 0;
501         m += len;
502     } while ((size -= len) > 0);
503 }
504 
505 /*
506  * NAME:        swap->mapsize()
507  * DESCRIPTION: count the number of sectors required for size bytes + a map
508  */
509 sector sw_mapsize(size)
510 unsigned int size;
511 {
512     register sector i, n;
513 
514     /* calculate the number of sectors required */
515     n = 0;
516     for (;;) {
517         i = (size + n * sizeof(sector) + sectorsize - 1) / sectorsize;
518         if (n == i) {
519             return n;
520         }
521         n = i;
522     }
523 }
524 
525 /*
526  * NAME:        swap->count()
527  * DESCRIPTION: return the number of sectors presently in use
528  */
529 sector sw_count()
530 {
531     return nsectors - nfree;
532 }
533 
534 /*
535  * NAME:        swap->copy()
536  * DESCRIPTION: copy sectors from dumpfile to swapfile
537  */
538 bool sw_copy()
539 {
540     if (dump >= 0) {
541         if (dsectors > 0) {
542             register sector n;
543 
544             n = SWAPCHUNKSZ;
545             if (n > dsectors) {
546                 n = dsectors;
547             }
548             copy(ssectors, n);
549             ssectors += n;
550         }
551         if (dsectors == 0) {
552             P_close(dump);
553             dump = -1;
554             return FALSE;
555         }
556         return TRUE;
557     }
558     return FALSE;
559 }
560 
561 
562 typedef struct {
563     Uint secsize;               /* size of swap sector */
564     sector nsectors;            /* # sectors */
565     sector ssectors;            /* # swap sectors */
566     sector nfree;               /* # free sectors */
567     sector mfree;               /* free sector list */
568 } dump_header;
569 
570 static char dh_layout[] = "idddd";
571 
572 /*
573  * NAME:        swap->dump()
574  * DESCRIPTION: dump swap file
575  */
576 int sw_dump(dumpfile)
577 char *dumpfile;
578 {
579     register header *h;
580     register sector sec;
581     char buffer[STRINGSZ + 4], buf1[STRINGSZ], buf2[STRINGSZ], *p, *q;
582     register sector n;
583     dump_header dh;
584 
585     if (dump >= 0) {
586         if (dsectors > 0) {
587             /* copy remaining dump sectors */
588             n = dsectors;
589             copy(ssectors, n);
590             ssectors += n;
591         }
592         P_close(dump);
593     }
594     p = path_native(buf1, dumpfile);
595     sprintf(buffer, "%s.old", dumpfile);
596     q = path_native(buf2, buffer);
597     P_unlink(q);
598     P_rename(p, q);
599     if (swap < 0) {
600         sw_create();
601     }
602 
603     /* flush the cache and adjust sector map */
604     for (h = last; h != (header *) NULL; h = h->prev) {
605         sec = h->swap;
606         if (h->dirty) {
607             /*
608              * Dump the sector to swap file
609              */
610             if (sec == SW_UNUSED) {
611                 /*
612                  * allocate new sector in swap file
613                  */
614                 if (sfree == SW_UNUSED) {
615                     sec = ssectors++;
616                 } else {
617                     sec = sfree;
618                     sfree = smap[sec];
619                 }
620                 h->swap = sec;
621             }
622             P_lseek(swap, (sec + 1L) * sectorsize, SEEK_SET);
623             if (P_write(swap, (char *) (h + 1), sectorsize) < 0) {
624                 fatal("cannot write swap file");
625             }
626         }
627         map[h->sec] = sec;
628     }
629 
630     /* move to dumpfile */
631     P_close(swap);
632     q = path_native(buf2, swapfile);
633     if (P_rename(q, p) < 0) {
634         /*
635          * The rename failed.  Attempt to copy the dumpfile instead.
636          * This will take a long, long while, so keep the swapfile and
637          * dumpfile on the same file system if at all possible.
638          */
639         swap = P_open(q, O_RDWR | O_BINARY, 0);
640         dump = P_open(p, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
641         if (swap < 0 || dump < 0) {
642             fatal("cannot move swap file");
643         }
644         /* copy initial sector */
645         if (P_read(swap, cbuf, sectorsize) <= 0) {
646             fatal("cannot read swap file");
647         }
648         if (P_write(dump, cbuf, sectorsize) < 0) {
649             fatal("cannot write dump file");
650         }
651         /* copy swap sectors */
652         for (n = ssectors; n > 0; --n) {
653             if (P_read(swap, cbuf, sectorsize) <= 0) {
654                 fatal("cannot read swap file");
655             }
656             if (P_write(dump, cbuf, sectorsize) < 0) {
657                 fatal("cannot write dump file");
658             }
659         }
660     } else {
661         /*
662          * The rename succeeded; reopen the new dumpfile.
663          */
664         dump = P_open(p, O_RDWR | O_BINARY, 0);
665         if (dump < 0) {
666             fatal("cannot reopen dump file");
667         }
668         swap = -1;
669     }
670 
671     /* write header */
672     dh.secsize = sectorsize;
673     dh.nsectors = nsectors;
674     dh.ssectors = ssectors;
675     dh.nfree = nfree;
676     dh.mfree = mfree;
677     P_lseek(dump, sectorsize - (long) sizeof(dump_header), SEEK_SET);
678     if (P_write(dump, (char *) &dh, sizeof(dump_header)) < 0) {
679         fatal("cannot write swap header to dump file");
680     }
681 
682     /* write map */
683     P_lseek(dump, (ssectors + 1L) * sectorsize, SEEK_SET);
684     if (P_write(dump, (char *) map, nsectors * sizeof(sector)) < 0) {
685         fatal("cannot write sector map to dump file");
686     }
687 
688 
689     if (swap < 0) {
690         /*
691          * the swapfile was moved
692          */
693 
694         /* create bitmap */
695         dsectors = nsectors;
696         dcursec = 0;
697         memset(bmap, -1, (dsectors + 7) >> 3);
698         for (sec = mfree; sec != SW_UNUSED; sec = map[sec]) {
699             BCLR(bmap, sec);
700             --dsectors;
701         }
702 
703         /* fix the sector map and bitmap */
704         for (h = last; h != (header *) NULL; h = h->prev) {
705             map[h->sec] = ((long) h - (long) mem) / slotsize;
706             h->swap = SW_UNUSED;
707             h->dirty = TRUE;
708             BCLR(bmap, h->sec);
709             --dsectors;
710         }
711 
712         ssectors = 0;
713         sfree = SW_UNUSED;
714     } else {
715         /*
716          * the swapfile was copied
717          */
718 
719         /* fix the sector map */
720         for (h = last; h != (header *) NULL; h = h->prev) {
721             map[h->sec] = ((long) h - (long) mem) / slotsize;
722             h->dirty = FALSE;
723         }
724     }
725 
726     return dump;
727 }
728 
729 /*
730  * NAME:        swap->restore()
731  * DESCRIPTION: restore dump file
732  */
733 void sw_restore(fd, secsize)
734 int fd;
735 unsigned int secsize;
736 {
737     dump_header dh;
738 
739     /* restore swap header */
740     P_lseek(fd, (long) secsize - (conf_dsize(dh_layout) & 0xff), SEEK_SET);
741     conf_dread(fd, (char *) &dh, dh_layout, (Uint) 1);
742     if (dh.secsize != secsize || dh.nsectors > swapsize) {
743         error("Wrong sector size or too many sectors in restore file");
744     }
745     restoresecsize = secsize;
746 
747     /* seek beyond swap sectors */
748     P_lseek(fd, (dh.ssectors + 1L) * secsize, SEEK_SET);
749 
750     /* restore swap map */
751     conf_dread(fd, (char *) smap, "d", (Uint) dh.nsectors);
752 
753     restore = fd;
754 }
755 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.