1 /* CCKDDASD.C   (c) Copyright Greg Smith, 2000-2009                  */
2 /*              Compressed CKD Direct Access Storage Device Handler  */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module contains device functions for compressed emulated     */
6 /* count-key-data direct access storage devices.                     */
7 /*-------------------------------------------------------------------*/
8 
9 #include "hstdinc.h"
10 
11 #define _CCKDDASD_C_
12 #define _HDASD_DLL_
13 #include "hercules.h"
14 #include "devtype.h"
15 #include "opcode.h"
16 
17 /*-------------------------------------------------------------------*/
18 /* Internal functions                                                */
19 /*-------------------------------------------------------------------*/
20 int     cckddasd_init(int argc, BYTE *argv[]);
21 int     cckddasd_term();
22 int     cckddasd_init_handler( DEVBLK *dev, int argc, char *argv[] );
23 int     cckddasd_close_device(DEVBLK *dev);
24 void    cckddasd_start(DEVBLK *dev);
25 void    cckddasd_end(DEVBLK *dev);
26 
27 int     cckd_open (DEVBLK *dev, int sfx, int flags, mode_t mode);
28 int     cckd_close (DEVBLK *dev, int sfx);
29 int     cckd_read (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len);
30 int     cckd_write (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len);
31 int     cckd_ftruncate(DEVBLK *dev, int sfx, off_t off);
32 void   *cckd_malloc(DEVBLK *dev, char *id, size_t size);
33 void   *cckd_calloc(DEVBLK *dev, char *id, size_t n, size_t size);
34 void   *cckd_free(DEVBLK *dev, char *id,void *p);
35 
36 int     cckd_read_track(DEVBLK *dev, int trk, BYTE *unitstat);
37 int     cckd_update_track(DEVBLK *dev, int trk, int off,
38                          BYTE *buf, int len, BYTE *unitstat);
39 int     cckd_used(DEVBLK *dev);
40 int     cfba_read_block(DEVBLK *dev, int blkgrp, BYTE *unitstat);
41 int     cfba_write_block(DEVBLK *dev, int blkgrp, int off,
42                          BYTE *buf, int wrlen, BYTE *unitstat);
43 int     cfba_used(DEVBLK *dev);
44 int     cckd_read_trk(DEVBLK *dev, int trk, int ra, BYTE *unitstat);
45 void    cckd_readahead(DEVBLK *dev, int trk);
46 int     cckd_readahead_scan(int *answer, int ix, int i, void *data);
47 void    cckd_ra();
48 void    cckd_flush_cache(DEVBLK *dev);
49 int     cckd_flush_cache_scan(int *answer, int ix, int i, void *data);
50 void    cckd_flush_cache_all();
51 void    cckd_purge_cache(DEVBLK *dev);
52 int     cckd_purge_cache_scan(int *answer, int ix, int i, void *data);
53 void    cckd_writer(void *arg);
54 int     cckd_writer_scan(int *o, int ix, int i, void *data);
55 off_t   cckd_get_space(DEVBLK *dev, int *size, int flags);
56 void    cckd_rel_space(DEVBLK *dev, off_t pos, int len, int size);
57 void    cckd_flush_space(DEVBLK *dev);
58 int     cckd_read_chdr(DEVBLK *dev);
59 int     cckd_write_chdr(DEVBLK *dev);
60 int     cckd_read_l1(DEVBLK *dev);
61 int     cckd_write_l1(DEVBLK *dev);
62 int     cckd_write_l1ent(DEVBLK *dev, int l1x);
63 int     cckd_read_init(DEVBLK *dev);
64 int     cckd_read_fsp(DEVBLK *dev);
65 int     cckd_write_fsp(DEVBLK *dev);
66 int     cckd_read_l2(DEVBLK *dev, int sfx, int l1x);
67 void    cckd_purge_l2(DEVBLK *dev);
68 int     cckd_purge_l2_scan(int *answer, int ix, int i, void *data);
69 int     cckd_steal_l2();
70 int     cckd_steal_l2_scan(int *answer, int ix, int i, void *data);
71 int     cckd_write_l2(DEVBLK *dev);
72 int     cckd_read_l2ent(DEVBLK *dev, CCKD_L2ENT *l2, int trk);
73 int     cckd_write_l2ent(DEVBLK *dev,   CCKD_L2ENT *l2, int trk);
74 int     cckd_read_trkimg(DEVBLK *dev, BYTE *buf, int trk, BYTE *unitstat);
75 int     cckd_write_trkimg(DEVBLK *dev, BYTE *buf, int len, int trk, int flags);
76 int     cckd_harden(DEVBLK *dev);
77 int     cckd_trklen(DEVBLK *dev, BYTE *buf);
78 int     cckd_null_trk(DEVBLK *dev, BYTE *buf, int trk, int nullfmt);
79 int     cckd_check_null_trk (DEVBLK *dev, BYTE *buf, int trk, int len);
80 int     cckd_cchh(DEVBLK *dev, BYTE *buf, int trk);
81 int     cckd_validate(DEVBLK *dev, BYTE *buf, int trk, int len);
82 char   *cckd_sf_name(DEVBLK *dev, int sfx);
83 int     cckd_sf_init(DEVBLK *dev);
84 int     cckd_sf_new(DEVBLK *dev);
85 DLL_EXPORT void   *cckd_sf_add(void *data);
86 DLL_EXPORT void   *cckd_sf_remove(void *data);
87 DLL_EXPORT void   *cckd_sf_comp(void *data);
88 DLL_EXPORT void   *cckd_sf_chk(void *data);
89 DLL_EXPORT void   *cckd_sf_stats(void *data);
90 int     cckd_disable_syncio(DEVBLK *dev);
91 void    cckd_lock_devchain(int flag);
92 void    cckd_unlock_devchain();
93 void    cckd_gcol();
94 int     cckd_gc_percolate(DEVBLK *dev, unsigned int size);
95 int     cckd_gc_l2(DEVBLK *dev, BYTE *buf);
96 DEVBLK *cckd_find_device_by_devnum (U16 devnum);
97 BYTE   *cckd_uncompress(DEVBLK *dev, BYTE *from, int len, int maxlen, int trk);
98 int     cckd_uncompress_zlib(DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen);
99 int     cckd_uncompress_bzip2(DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen);
100 int     cckd_compress(DEVBLK *dev, BYTE **to, BYTE *from, int len, int comp, int parm);
101 int     cckd_compress_none(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm);
102 int     cckd_compress_zlib(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm);
103 int     cckd_compress_bzip2(DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm);
104 void    cckd_command_help();
105 void    cckd_command_opts();
106 void    cckd_command_stats();
107 void    cckd_command_debug();
108 int     cckd_command(char *op, int cmd);
109 DLL_EXPORT void    cckd_print_itrace();
110 void    cckd_trace(DEVBLK *dev, char *msg, ...);
111 
112 /*-------------------------------------------------------------------*/
113 /* Definitions for sense data format codes and message codes         */
114 /*-------------------------------------------------------------------*/
115 #define FORMAT_0                0       /* Program or System Checks  */
116 #define FORMAT_1                1       /* Device Equipment Checks   */
117 #define FORMAT_2                2       /* 3990 Equipment Checks     */
118 #define FORMAT_3                3       /* 3990 Control Checks       */
119 #define FORMAT_4                4       /* Data Checks               */
120 #define FORMAT_5                5       /* Data Check + Displacement */
121 #define FORMAT_6                6       /* Usage Stats/Overrun Errors*/
122 #define FORMAT_7                7       /* Device Control Checks     */
123 #define FORMAT_8                8       /* Device Equipment Checks   */
124 #define FORMAT_9                9       /* Device Rd/Wrt/Seek Checks */
125 #define FORMAT_F                15      /* Cache Storage Checks      */
126 #define MESSAGE_0               0       /* Message 0                 */
127 #define MESSAGE_1               1       /* Message 1                 */
128 #define MESSAGE_2               2       /* Message 2                 */
129 #define MESSAGE_3               3       /* Message 3                 */
130 #define MESSAGE_4               4       /* Message 4                 */
131 #define MESSAGE_5               5       /* Message 5                 */
132 #define MESSAGE_6               6       /* Message 6                 */
133 #define MESSAGE_7               7       /* Message 7                 */
134 #define MESSAGE_8               8       /* Message 8                 */
135 #define MESSAGE_9               9       /* Message 9                 */
136 #define MESSAGE_A               10      /* Message A                 */
137 #define MESSAGE_B               11      /* Message B                 */
138 #define MESSAGE_C               12      /* Message C                 */
139 #define MESSAGE_D               13      /* Message D                 */
140 #define MESSAGE_E               14      /* Message E                 */
141 #define MESSAGE_F               15      /* Message F                 */
142 
143 /*-------------------------------------------------------------------*/
144 /* Data areas                                                        */
145 /*-------------------------------------------------------------------*/
146 static  CCKD_L2ENT empty_l2[CKDDASD_NULLTRK_FMTMAX+1][256];
147 static  BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
148 DEVHND  cckddasd_device_hndinfo;
149 DEVHND  cfbadasd_device_hndinfo;
150 DLL_EXPORT CCKDBLK cckdblk;                        /* cckd global area          */
151 
152 /*-------------------------------------------------------------------*/
153 /* CCKD global initialization                                        */
154 /*-------------------------------------------------------------------*/
cckddasd_init(int argc,BYTE * argv[])155 int cckddasd_init (int argc, BYTE *argv[])
156 {
157 int             i, j;                   /* Loop indexes              */
158 
159     UNREFERENCED(argc);
160     UNREFERENCED(argv);
161 
162     if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)) == 0)
163         return 0;
164 
165     /* Clear the cckdblk */
166     memset(&cckdblk, 0, sizeof(CCKDBLK));
167 
168     /* Initialize locks and conditions */
169     memcpy (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id));
170     initialize_lock (&cckdblk.gclock);
171     initialize_lock (&cckdblk.ralock);
172     initialize_lock (&cckdblk.wrlock);
173     initialize_lock (&cckdblk.devlock);
174     initialize_condition (&cckdblk.gccond);
175     initialize_condition (&cckdblk.racond);
176     initialize_condition (&cckdblk.wrcond);
177     initialize_condition (&cckdblk.devcond);
178     initialize_condition (&cckdblk.termcond);
179 
180     /* Initialize some variables */
181     cckdblk.wrprio     = 16;
182     cckdblk.ranbr      = CCKD_DEFAULT_RA_SIZE;
183     cckdblk.ramax      = CCKD_DEFAULT_RA;
184     cckdblk.wrmax      = CCKD_DEFAULT_WRITER;
185     cckdblk.gcmax      = CCKD_DEFAULT_GCOL;
186     cckdblk.gcwait     = CCKD_DEFAULT_GCOLWAIT;
187     cckdblk.gcparm     = CCKD_DEFAULT_GCOLPARM;
188     cckdblk.readaheads = CCKD_DEFAULT_READAHEADS;
189     cckdblk.freepend   = CCKD_DEFAULT_FREEPEND;
190 #ifdef HAVE_LIBZ
191     cckdblk.comps     |= CCKD_COMPRESS_ZLIB;
192 #endif
193 #ifdef CCKD_BZIP2
194     cckdblk.comps     |= CCKD_COMPRESS_BZIP2;
195 #endif
196     cckdblk.comp       = 0xff;
197     cckdblk.compparm   = -1;
198 
199     /* Initialize the readahead queue */
200     cckdblk.ra1st = cckdblk.ralast = -1;
201     cckdblk.rafree = 0;
202     for (i = 0; i < cckdblk.ranbr; i++) cckdblk.ra[i].next = i + 1;
203     cckdblk.ra[cckdblk.ranbr - 1].next = -1;
204 
205     /* Clear the empty L2 tables */
206     for (i = 0; i <= CKDDASD_NULLTRK_FMTMAX; i++)
207         for (j = 0; j < 256; j++)
208         {
209             empty_l2[i][j].pos = 0;
210             empty_l2[i][j].len = empty_l2[i][j].size = i;
211         }
212 
213     return 0;
214 
215 } /* end function cckddasd_init */
216 
217 /*-------------------------------------------------------------------*/
218 /* CCKD dasd global termination                                      */
219 /*-------------------------------------------------------------------*/
cckddasd_term()220 int cckddasd_term ()
221 {
222     /* Terminate the readahead threads */
223     obtain_lock (&cckdblk.ralock);
224     cckdblk.ramax = 0;
225     if (cckdblk.ras)
226     {
227         broadcast_condition (&cckdblk.racond);
228         wait_condition (&cckdblk.termcond, &cckdblk.ralock);
229     }
230     release_lock (&cckdblk.ralock);
231 
232     /* Terminate the garbage collection threads */
233     obtain_lock (&cckdblk.gclock);
234     cckdblk.gcmax = 0;
235     if (cckdblk.gcs)
236     {
237         broadcast_condition (&cckdblk.gccond);
238         wait_condition (&cckdblk.termcond, &cckdblk.gclock);
239     }
240     release_lock (&cckdblk.gclock);
241 
242     /* Terminate the writer threads */
243     obtain_lock (&cckdblk.wrlock);
244     cckdblk.wrmax = 0;
245     if (cckdblk.wrs)
246     {
247         broadcast_condition (&cckdblk.wrcond);
248         wait_condition (&cckdblk.termcond, &cckdblk.wrlock);
249     }
250     release_lock (&cckdblk.wrlock);
251 
252     memset(&cckdblk, 0, sizeof(CCKDBLK));
253 
254     return 0;
255 
256 } /* end function cckddasd_term */
257 
258 /*-------------------------------------------------------------------*/
259 /* CKD dasd initialization                                           */
260 /*-------------------------------------------------------------------*/
cckddasd_init_handler(DEVBLK * dev,int argc,char * argv[])261 int cckddasd_init_handler ( DEVBLK *dev, int argc, char *argv[] )
262 {
263 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
264 DEVBLK         *dev2;                   /* -> device in cckd queue   */
265 int             i;                      /* Counter                   */
266 int             fdflags;                /* File flags                */
267 
268     UNREFERENCED(argc);
269     UNREFERENCED(argv);
270 
271     /* Initialize the global cckd block if necessary */
272     if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)))
273         cckddasd_init (0, NULL);
274 
275     /* Obtain area for cckd extension */
276     dev->cckd_ext = cckd = cckd_calloc (dev, "ext", 1, sizeof(CCKDDASD_EXT));
277     if (cckd == NULL)
278         return -1;
279 
280     /* Initialize locks and conditions */
281     initialize_lock (&cckd->iolock);
282     initialize_lock (&cckd->filelock);
283     initialize_condition (&cckd->iocond);
284 
285     /* Initialize some variables */
286     obtain_lock (&cckd->filelock);
287     cckd->l1x = cckd->sfx = cckd->l2active = -1;
288     dev->cache = cckd->free1st = -1;
289     cckd->fd[0] = dev->fd;
290     fdflags = get_file_accmode_flags( dev->fd );
291     cckd->open[0] = (fdflags & O_RDWR) ? CCKD_OPEN_RW : CCKD_OPEN_RO;
292     for (i = 1; i <= CCKD_MAX_SF; i++)
293     {
294         cckd->fd[i] = -1;
295         cckd->open[i] = CCKD_OPEN_NONE;
296     }
297     cckd->maxsize = sizeof(off_t) > 4 ? 0xffffffffll : 0x7fffffffll;
298 
299     /* call the chkdsk function */
300     if (cckd_chkdsk (dev, 0) < 0)
301         return -1;
302 
303     /* Perform initial read */
304     if (cckd_read_init (dev) < 0)
305         return -1;
306     if (cckd->fbadasd) dev->ckdtrksz = CFBA_BLOCK_SIZE;
307 
308     /* open the shadow files */
309     if (cckd_sf_init (dev) < 0)
310     {
311         logmsg (_("HHCCD101E %4.4X error initializing shadow files\n"), dev->devnum);
312         return -1;
313     }
314 
315     /* Update the device handler routines */
316     if (cckd->ckddasd)
317         dev->hnd = &cckddasd_device_hndinfo;
318     else
319         dev->hnd = &cfbadasd_device_hndinfo;
320     release_lock (&cckd->filelock);
321 
322     /* Insert the device into the cckd device queue */
323     cckd_lock_devchain(1);
324     for (cckd = NULL, dev2 = cckdblk.dev1st; dev2; dev2 = cckd->devnext)
325         cckd = dev2->cckd_ext;
326     if (cckd) cckd->devnext = dev;
327     else cckdblk.dev1st = dev;
328     cckd_unlock_devchain();
329 
330     cckdblk.batch = dev->batch;
331     if (cckdblk.batch)
332     {
333         cckdblk.nostress = 1;
334         cckdblk.freepend = 0;
335         cckdblk.linuxnull = 1;
336     }
337 
338     return 0;
339 } /* end function cckddasd_init_handler */
340 
341 /*-------------------------------------------------------------------*/
342 /* Close a Compressed CKD Device                                     */
343 /*-------------------------------------------------------------------*/
cckddasd_close_device(DEVBLK * dev)344 int cckddasd_close_device (DEVBLK *dev)
345 {
346 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
347 int             i;                      /* Index                     */
348 
349     cckd = dev->cckd_ext;
350 
351     /* Wait for readaheads to finish */
352     obtain_lock(&cckdblk.ralock);
353     cckd->stopping = 1;
354     while (cckd->ras)
355     {
356         release_lock(&cckdblk.ralock);
357         usleep(1);
358         obtain_lock(&cckdblk.ralock);
359     }
360     release_lock(&cckdblk.ralock);
361 
362     /* Flush the cache and wait for the writes to complete */
363     obtain_lock (&cckd->iolock);
364     cckd->stopping = 1;
365     cckd_flush_cache (dev);
366     while (cckd->wrpending || cckd->ioactive)
367     {
368         cckd->iowaiters++;
369         wait_condition (&cckd->iocond, &cckd->iolock);
370         cckd->iowaiters--;
371         cckd_flush_cache (dev);
372     }
373     broadcast_condition (&cckd->iocond);
374     cckd_purge_cache (dev); cckd_purge_l2 (dev);
375     dev->bufcur = dev->cache = -1;
376     if (cckd->newbuf) cckd_free (dev, "newbuf", cckd->newbuf);
377     release_lock (&cckd->iolock);
378 
379     /* Remove the device from the cckd queue */
380     cckd_lock_devchain(1);
381     if (dev == cckdblk.dev1st) cckdblk.dev1st = cckd->devnext;
382     else
383     {
384         DEVBLK *dev2 = cckdblk.dev1st;
385         CCKDDASD_EXT *cckd2 = dev2->cckd_ext;
386         while (cckd2->devnext != dev)
387         {
388            dev2 = cckd2->devnext; cckd2 = dev2->cckd_ext;
389         }
390         cckd2->devnext = cckd->devnext;
391     }
392     cckd_unlock_devchain();
393 
394     /* harden the file */
395     obtain_lock (&cckd->filelock);
396     cckd_harden (dev);
397 
398     /* close the shadow files */
399     for (i = 1; i <= cckd->sfn; i++)
400     {
401         cckd_close (dev, i);
402         cckd->open[i] = 0;
403     }
404 
405     /* free the level 1 tables */
406     for (i = 0; i <= cckd->sfn; i++)
407         cckd->l1[i] = cckd_free (dev, "l1", cckd->l1[i]);
408 
409     /* reset the device handler */
410     if (cckd->ckddasd)
411         dev->hnd = &ckddasd_device_hndinfo;
412     else
413         dev->hnd = &fbadasd_device_hndinfo;
414 
415     /* write some statistics */
416     if (!dev->batch)
417         cckd_sf_stats (dev);
418     release_lock (&cckd->filelock);
419 
420     /* free the cckd extension */
421     dev->cckd_ext= cckd_free (dev, "ext", cckd);
422 
423     if (dev->dasdsfn) free (dev->dasdsfn);
424     dev->dasdsfn = NULL;
425 
426     close (dev->fd);
427     dev->fd = -1;
428 
429     /* If no more devices then perform global termination */
430     if (cckdblk.dev1st == NULL) cckddasd_term ();
431 
432     return 0;
433 } /* end function cckddasd_close_device */
434 
435 /*-------------------------------------------------------------------*/
436 /* Compressed ckd start/resume channel program                       */
437 /*-------------------------------------------------------------------*/
cckddasd_start(DEVBLK * dev)438 void cckddasd_start (DEVBLK *dev)
439 {
440 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
441 U16             devnum = 0;             /* Last active device number */
442 int             trk = 0;                /* Last active track         */
443 
444     cckd = dev->cckd_ext;
445 
446     cckd_trace (dev, "start i/o file[%d] bufcur %d cache[%d]\n",
447                 cckd->sfn, dev->bufcur, dev->cache);
448 
449     /* Reset buffer offsets */
450     dev->bufoff = 0;
451     dev->bufoffhi = cckd->ckddasd ? dev->ckdtrksz : CFBA_BLOCK_SIZE;
452 
453     /* Check for merge - synchronous i/o should be disabled */
454     obtain_lock(&cckd->iolock);
455     if (cckd->merging)
456     {
457         cckd_trace (dev, "start i/o waiting for merge%s\n","");
458         while (cckd->merging)
459         {
460             cckd->iowaiters++;
461             wait_condition (&cckd->iocond, &cckd->iolock);
462             cckd->iowaiters--;
463         }
464         dev->bufcur = dev->cache = -1;
465     }
466     cckd->ioactive = 1;
467 
468     cache_lock(CACHE_DEVBUF);
469 
470     if (dev->cache >= 0)
471         CCKD_CACHE_GETKEY(dev->cache, devnum, trk);
472 
473     /* Check if previous active entry is still valid and not busy */
474     if (dev->cache >= 0 && dev->devnum == devnum && dev->bufcur == trk
475      && !(cache_getflag(CACHE_DEVBUF, dev->cache) & CCKD_CACHE_IOBUSY))
476     {
477         /* Make the entry active again */
478         cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_ACTIVE);
479 
480         /* If the entry is pending write then change it to `updated' */
481         if (cache_getflag(CACHE_DEVBUF, dev->cache) & CCKD_CACHE_WRITE)
482         {
483             cache_setflag (CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_WRITE, CCKD_CACHE_UPDATED);
484             cckd->wrpending--;
485             if (cckd->iowaiters && !cckd->wrpending)
486                 broadcast_condition (&cckd->iocond);
487         }
488     }
489     else
490         dev->bufcur = dev->cache = -1;
491 
492     cache_unlock (CACHE_DEVBUF);
493 
494     release_lock (&cckd->iolock);
495 
496     return;
497 
498 } /* end function cckddasd_start */
499 
500 /*-------------------------------------------------------------------*/
501 /* Compressed ckd end/suspend channel program                        */
502 /*-------------------------------------------------------------------*/
cckddasd_end(DEVBLK * dev)503 void cckddasd_end (DEVBLK *dev)
504 {
505 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
506 
507     cckd = dev->cckd_ext;
508 
509     /* Update length if previous image was updated */
510     if (dev->bufupd && dev->bufcur >= 0 && dev->cache >= 0)
511     {
512         dev->buflen = cckd_trklen (dev, dev->buf);
513         cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen);
514     }
515 
516     dev->bufupd = 0;
517 
518     cckd_trace (dev, "end i/o bufcur %d cache[%d] waiters %d\n",
519                 dev->bufcur, dev->cache, cckd->iowaiters);
520 
521     obtain_lock (&cckd->iolock);
522 
523     cckd->ioactive = 0;
524 
525     /* Make the current entry inactive */
526     if (dev->cache >= 0)
527     {
528         cache_lock (CACHE_DEVBUF);
529         cache_setflag (CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_ACTIVE, 0);
530         cache_unlock (CACHE_DEVBUF);
531     }
532 
533     /* Cause writers to start after first update */
534     if (cckd->updated && (cckdblk.wrs == 0 || cckd->iowaiters != 0))
535         cckd_flush_cache (dev);
536     else if (cckd->iowaiters)
537         broadcast_condition (&cckd->iocond);
538 
539     release_lock (&cckd->iolock);
540 
541 } /* end function cckddasd_end */
542 
543 /*-------------------------------------------------------------------*/
544 /* Open a cckd file                                                  */
545 /*                                                                   */
546 /* If O_CREAT is not set and mode is non-zero then the error message */
547 /* will be supressed.                                                */
548 /*-------------------------------------------------------------------*/
cckd_open(DEVBLK * dev,int sfx,int flags,mode_t mode)549 int cckd_open (DEVBLK *dev, int sfx, int flags, mode_t mode)
550 {
551 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
552 int             err;                    /* 1 = issue error message   */
553 char            pathname[MAX_PATH];     /* file path in host format  */
554 
555     cckd = dev->cckd_ext;
556 
557     err = !((flags & O_CREAT) == 0 && mode != 0);
558 
559     if (cckd->fd[sfx] >= 0)
560         cckd_close (dev, sfx);
561 
562     hostpath(pathname, cckd_sf_name (dev, sfx), sizeof(pathname));
563     cckd->fd[sfx] = hopen(pathname, flags, mode);
564     if (sfx == 0) dev->fd = cckd->fd[sfx];
565 
566     if (cckd->fd[sfx] >= 0)
567         cckd->open[sfx] = flags & O_RDWR ? CCKD_OPEN_RW :
568                           cckd->open[sfx] == CCKD_OPEN_RW ?
569                           CCKD_OPEN_RD : CCKD_OPEN_RO;
570     else
571     {
572         if (err)
573         {
574             logmsg (_("HHCCD130E %4.4X file[%d] %s open error: %s\n"),
575                     dev->devnum, sfx, cckd_sf_name (dev, sfx),
576                     strerror(errno));
577             cckd_trace (dev, "file[%d] fd[%d] open %s error flags %8.8x mode %8.8x\n",
578                         sfx, cckd->fd[sfx], cckd_sf_name (dev, sfx), flags, mode);
579             cckd_print_itrace ();
580         }
581         cckd->open[sfx] = CCKD_OPEN_NONE;
582     }
583 
584     cckd_trace (dev, "file[%d] fd[%d] open %s, flags %8.8x mode %8.8x\n",
585                 sfx, cckd->fd[sfx], cckd_sf_name (dev, sfx), flags, mode);
586 
587     return cckd->fd[sfx];
588 
589 } /* end function cckd_open */
590 
591 /*-------------------------------------------------------------------*/
592 /* Close a cckd file                                                 */
593 /*-------------------------------------------------------------------*/
cckd_close(DEVBLK * dev,int sfx)594 int cckd_close (DEVBLK *dev, int sfx)
595 {
596 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
597 int             rc = 0;                 /* Return code               */
598 
599     cckd = dev->cckd_ext;
600 
601     cckd_trace (dev, "file[%d] fd[%d] close %s\n",
602                 sfx, cckd->fd[sfx], cckd_sf_name(dev, sfx));
603 
604     if (cckd->fd[sfx] >= 0)
605         rc = close (cckd->fd[sfx]);
606 
607     if (rc < 0)
608     {
609         logmsg (_("HHCCD130E %4.4X file[%d] close error: %s\n"),
610                 dev->devnum, sfx, strerror(errno));
611         cckd_print_itrace ();
612     }
613 
614     cckd->fd[sfx] = -1;
615     if (sfx == 0) dev->fd = -1;
616 
617     return rc;
618 
619 } /* end function cckd_close */
620 
621 /*-------------------------------------------------------------------*/
622 /* Read from a cckd file                                             */
623 /*-------------------------------------------------------------------*/
cckd_read(DEVBLK * dev,int sfx,off_t off,void * buf,size_t len)624 int cckd_read (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len)
625 {
626 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
627 int             rc;                     /* Return code               */
628 
629     cckd = dev->cckd_ext;
630 
631     cckd_trace (dev, "file[%d] fd[%d] read, off 0x%" I64_FMT "x len %ld\n",
632                 sfx, cckd->fd[sfx], (long long)off, (long)len);
633 
634     /* Seek to specified offset */
635     if (lseek (cckd->fd[sfx], off, SEEK_SET) < 0)
636     {
637         logmsg (_("HHCCD130E %4.4X file[%d] lseek error, offset 0x%" I64_FMT "x: %s\n"),
638                 dev->devnum, sfx, (long long)off, strerror(errno));
639         cckd_print_itrace ();
640         return -1;
641     }
642 
643     /* Read the data */
644     rc = read (cckd->fd[sfx], buf, len);
645     if (rc < (int)len)
646     {
647         if (rc < 0)
648             logmsg (_("HHCCD130E %4.4X file[%d] read error, offset 0x%" I64_FMT "x: %s\n"),
649                     dev->devnum, sfx, (long long)off, strerror(errno));
650         else
651             logmsg (_("HHCCD130E %4.4X file[%d] read incomplete, offset 0x%" I64_FMT "x: "
652                       "read %d expected %d\n"),
653                     dev->devnum, sfx, (long long)off, rc, len);
654         cckd_print_itrace ();
655         return -1;
656     }
657 
658     return rc;
659 
660 } /* end function cckd_read */
661 
662 /*-------------------------------------------------------------------*/
663 /* Write to a cckd file                                              */
664 /*-------------------------------------------------------------------*/
cckd_write(DEVBLK * dev,int sfx,off_t off,void * buf,size_t len)665 int cckd_write (DEVBLK *dev, int sfx, off_t off, void *buf, size_t len)
666 {
667 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
668 int             rc = 0;                 /* Return code               */
669 
670     cckd = dev->cckd_ext;
671 
672     cckd_trace (dev, "file[%d] fd[%d] write, off 0x%" I64_FMT "x len %ld\n",
673                 sfx, cckd->fd[sfx], (long long)off, (long)len);
674 
675     /* Seek to specified offset */
676     if (lseek (cckd->fd[sfx], off, SEEK_SET) < 0)
677     {
678         logmsg (_("HHCCD130E %4.4X file[%d] lseek error, offset 0x%" I64_FMT "x: %s\n"),
679                 dev->devnum, sfx, (long long)off, strerror(errno));
680         return -1;
681     }
682 
683     /* Write the data */
684     rc = write (cckd->fd[sfx], buf, len);
685     if (rc < (int)len)
686     {
687         if (rc < 0)
688             logmsg (_("HHCCD130E %4.4X file[%d] write error, offset 0x%" I64_FMT "x: %s\n"),
689                     dev->devnum, sfx, (long long)off, strerror(errno));
690         else
691             logmsg (_("HHCCD130E %4.4X file[%d] write incomplete, offset 0x%" I64_FMT "x: "
692                       "wrote %d expected %d\n"),
693                     dev->devnum, sfx, (long long)off, rc, len);
694         cckd_print_itrace ();
695         return -1;
696     }
697 
698     return rc;
699 
700 } /* end function cckd_write */
701 
702 /*-------------------------------------------------------------------*/
703 /* Truncate a cckd file                                              */
704 /*-------------------------------------------------------------------*/
cckd_ftruncate(DEVBLK * dev,int sfx,off_t off)705 int cckd_ftruncate(DEVBLK *dev, int sfx, off_t off)
706 {
707 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
708 
709     cckd = dev->cckd_ext;
710 
711     cckd_trace (dev, "file[%d] fd[%d] ftruncate, off 0x%" I64_FMT "x\n",
712                 sfx, cckd->fd[sfx], (long long)off);
713 
714     /* Truncate the file */
715     if (ftruncate (cckd->fd[sfx], off) < 0)
716     {
717         logmsg (_("HHCCD130E %4.4X file[%d] ftruncate error, offset 0x%" I64_FMT "x: %s\n"),
718                 dev->devnum, sfx, (long long)off, strerror(errno));
719         cckd_print_itrace ();
720         return -1;
721     }
722 
723     return 0;
724 
725 } /* end function cckd_ftruncate */
726 
727 /*-------------------------------------------------------------------*/
728 /* malloc                                                            */
729 /*-------------------------------------------------------------------*/
cckd_malloc(DEVBLK * dev,char * id,size_t size)730 void *cckd_malloc (DEVBLK *dev, char *id, size_t size)
731 {
732 void           *p;                      /* Pointer                   */
733 
734     p = malloc (size);
735     cckd_trace (dev, "%s malloc %p len %ld\n", id, p, (long)size);
736 
737     if (p == NULL)
738     {
739         logmsg (_("HHCCD130E %4.4X malloc error, size %d: %s\n"),
740                 dev ? dev->devnum : 0, size, strerror(errno));
741         cckd_print_itrace ();
742     }
743 
744     return p;
745 
746 } /* end function cckd_malloc */
747 
748 /*-------------------------------------------------------------------*/
749 /* calloc                                                            */
750 /*-------------------------------------------------------------------*/
cckd_calloc(DEVBLK * dev,char * id,size_t n,size_t size)751 void *cckd_calloc (DEVBLK *dev, char *id, size_t n, size_t size)
752 {
753 void           *p;                      /* Pointer                   */
754 
755     p = calloc (n, size);
756     cckd_trace (dev, "%s calloc %p len %ld\n", id, p, n*(long)size);
757 
758     if (p == NULL)
759     {
760         logmsg (_("HHCCD130E %4.4X calloc error, size %d: %s\n"),
761                 dev ? dev->devnum : 0, n*size, strerror(errno));
762         cckd_print_itrace ();
763     }
764 
765     return p;
766 
767 } /* end function cckd_calloc */
768 
769 /*-------------------------------------------------------------------*/
770 /* free                                                              */
771 /*-------------------------------------------------------------------*/
cckd_free(DEVBLK * dev,char * id,void * p)772 void *cckd_free (DEVBLK *dev, char *id, void *p)
773 {
774     cckd_trace (dev, "%s free %p\n", id, p);
775     if (p) free (p);
776     return NULL;
777 } /* end function cckd_free */
778 
779 /*-------------------------------------------------------------------*/
780 /* Compressed ckd read track image                                   */
781 /*-------------------------------------------------------------------*/
cckd_read_track(DEVBLK * dev,int trk,BYTE * unitstat)782 int cckd_read_track (DEVBLK *dev, int trk, BYTE *unitstat)
783 {
784 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
785 int             rc;                     /* Return code               */
786 int             len;                    /* Compressed length         */
787 BYTE           *newbuf;                 /* Uncompressed buffer       */
788 int             cache;                  /* New active cache entry    */
789 int             syncio;                 /* Syncio indicator          */
790 
791     cckd = dev->cckd_ext;
792 
793     /* Update length if previous image was updated */
794     if (dev->bufupd && dev->bufcur >= 0 && dev->cache >= 0)
795     {
796         dev->buflen = cckd_trklen (dev, dev->buf);
797         cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen);
798     }
799 
800     /* Turn off the synchronous I/O bit if trk overflow or trk 0 */
801     syncio = dev->syncio_active;
802     if (dev->ckdtrkof || trk == 0)
803         dev->syncio_active = 0;
804 
805     /* Reset buffer offsets */
806     dev->bufoff = 0;
807     dev->bufoffhi = dev->ckdtrksz;
808 
809     /* Check if reading the same track image */
810     if (trk == dev->bufcur && dev->cache >= 0)
811     {
812         /* Track image may be compressed */
813         if ((dev->buf[0] & CCKD_COMPRESS_MASK) != 0
814          && (dev->buf[0] & dev->comps) == 0)
815         {
816 #if 0
817             /* Return if synchronous i/o */
818             if (dev->syncio_active)
819             {
820                 cckd_trace (dev, "read  trk   %d syncio compressed\n", trk);
821                 cckdblk.stats_synciomisses++;
822                 dev->syncio_retry = 1;
823                 return -1;
824             }
825 #endif
826             len = cache_getval(CACHE_DEVBUF, dev->cache);
827             newbuf = cckd_uncompress (dev, dev->buf, len, dev->ckdtrksz, trk);
828             if (newbuf == NULL) {
829                 ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
830                 *unitstat = CSW_CE | CSW_DE | CSW_UC;
831                 dev->bufcur = dev->cache = -1;
832                 dev->syncio_active = syncio;
833                 return -1;
834             }
835             cache_setbuf (CACHE_DEVBUF, dev->cache, newbuf, dev->ckdtrksz);
836             dev->buf     = newbuf;
837             dev->buflen  = cckd_trklen (dev, newbuf);
838             cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen);
839             dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache);
840             dev->bufupd  = 0;
841             cckd_trace (dev, "read  trk   %d uncompressed len %d\n",
842                         trk, dev->buflen);
843         }
844 
845         dev->comp = dev->buf[0] & CCKD_COMPRESS_MASK;
846         if (dev->comp != 0) dev->compoff = CKDDASD_TRKHDR_SIZE;
847 
848         return 0;
849     }
850 
851     cckd_trace (dev, "read  trk   %d (%s)\n", trk,
852                 dev->syncio_active ? "synchronous" : "asynchronous");
853 
854     /* read the new track */
855     dev->bufupd = 0;
856     *unitstat = 0;
857     cache = cckd_read_trk (dev, trk, 0, unitstat);
858     if (cache < 0)
859     {
860         dev->bufcur = dev->cache = -1;
861         return -1;
862     }
863 
864     dev->cache    = cache;
865     dev->buf      = cache_getbuf (CACHE_DEVBUF, dev->cache, 0);
866     dev->bufcur   = trk;
867     dev->bufoff   = 0;
868     dev->bufoffhi = dev->ckdtrksz;
869     dev->buflen   = cache_getval (CACHE_DEVBUF, dev->cache);
870     dev->bufsize  = cache_getlen (CACHE_DEVBUF, dev->cache);
871 
872     dev->comp = dev->buf[0] & CCKD_COMPRESS_MASK;
873     if (dev->comp != 0) dev->compoff = CKDDASD_TRKHDR_SIZE;
874 
875     /* If the image is compressed then call ourself recursively
876        to cause the image to get uncompressed */
877     if (dev->comp != 0 && (dev->comp & dev->comps) == 0)
878         rc = cckd_read_track (dev, trk, unitstat);
879     else
880         rc = 0;
881 
882     dev->syncio_active = syncio;
883     return rc;
884 } /* end function cckd_read_track */
885 
886 /*-------------------------------------------------------------------*/
887 /* Compressed ckd update track image                                 */
888 /*-------------------------------------------------------------------*/
cckd_update_track(DEVBLK * dev,int trk,int off,BYTE * buf,int len,BYTE * unitstat)889 int cckd_update_track (DEVBLK *dev, int trk, int off,
890                        BYTE *buf, int len, BYTE *unitstat)
891 {
892 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
893 int             rc;                     /* Return code               */
894 
895     cckd = dev->cckd_ext;
896 
897     /* Error if opened read-only */
898     if (dev->ckdrdonly && cckd->sfn == 0)
899     {
900         ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0,FORMAT_1, MESSAGE_0);
901         *unitstat = CSW_CE | CSW_DE | CSW_UC;
902         dev->bufcur = dev->cache = -1;
903         return -1;
904     }
905 
906     /* If the track is not current or compressed then read it.
907        `dev->comps' is set to zero forcing the read routine to
908        uncompress the image.                                     */
909     if (trk != dev->bufcur || (dev->buf[0] & CCKD_COMPRESS_MASK) != 0)
910     {
911         dev->comps = 0;
912         rc = (dev->hnd->read) (dev, trk, unitstat);
913         if (rc < 0)
914         {
915             dev->bufcur = dev->cache = -1;
916             return -1;
917         }
918     }
919 
920     /* Invalid track format if going past buffer end */
921     if (off + len > dev->ckdtrksz)
922     {
923         ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0);
924         *unitstat = CSW_CE | CSW_DE | CSW_UC;
925         dev->bufcur = dev->cache = -1;
926         return -1;
927     }
928 
929     /* Copy the data into the buffer */
930     if (buf && len > 0) memcpy (dev->buf + off, buf, len);
931 
932     cckd_trace (dev, "updt  trk   %d offset %d length %d\n",
933                 trk, off, len);
934 
935     /* Update the cache entry */
936     cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_UPDATED | CCKD_CACHE_USED);
937     cckd->updated = 1;
938 
939     /* Notify the shared server of the update */
940     if (!dev->bufupd)
941     {
942         dev->bufupd = 1;
943         shared_update_notify (dev, trk);
944     }
945 
946     return len;
947 
948 } /* end function cckd_update_track */
949 
950 /*-------------------------------------------------------------------*/
951 /* Return used cylinders                                             */
952 /*-------------------------------------------------------------------*/
cckd_used(DEVBLK * dev)953 int cckd_used (DEVBLK *dev)
954 {
955 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
956 int             rc;                     /* Return code               */
957 int             l1x, l2x;               /* Lookup table indexes      */
958 int             sfx;                    /* Shadow file suffix        */
959 CCKD_L2ENT      l2;                     /* Copied level 2 entry      */
960 
961     cckd = dev->cckd_ext;
962     obtain_lock (&cckd->filelock);
963 
964     /* Find the last used level 1 table entry */
965     for (l1x = cckd->cdevhdr[0].numl1tab - 1; l1x > 0; l1x--)
966     {
967         sfx = cckd->sfn;
968         while (cckd->l1[sfx][l1x] == 0xffffffff && sfx > 0) sfx--;
969         if (cckd->l1[sfx][l1x]) break;
970     }
971 
972     /* Find the last used level 2 table entry */
973     for (l2x = 255; l2x >= 0; l2x--)
974     {
975         rc = cckd_read_l2ent (dev, &l2, l1x * 256 + l2x);
976         if (rc < 0 || l2.pos != 0) break;
977     }
978 
979     release_lock (&cckd->filelock);
980     return (l1x * 256 + l2x + dev->ckdheads) / dev->ckdheads;
981 }
982 
983 /*-------------------------------------------------------------------*/
984 /* Compressed fba read block(s)                                      */
985 /*-------------------------------------------------------------------*/
cfba_read_block(DEVBLK * dev,int blkgrp,BYTE * unitstat)986 int cfba_read_block (DEVBLK *dev, int blkgrp, BYTE *unitstat)
987 {
988 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
989 int             rc;                     /* Return code               */
990 int             cache;                  /* New active cache entry    */
991 BYTE           *cbuf;                   /* -> cache buffer           */
992 BYTE           *newbuf;                 /* Uncompressed buffer       */
993 int             len;                    /* Compressed length         */
994 int             maxlen;                 /* Size for cache entry      */
995 
996     cckd = dev->cckd_ext;
997 
998     if (dev->cache >= 0)
999         cbuf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0);
1000     else
1001         cbuf = NULL;
1002     maxlen = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE;
1003 
1004     /* Return if reading the same track image */
1005     if (blkgrp == dev->bufcur && dev->cache >= 0)
1006     {
1007         /* Block group image may be compressed */
1008         if ((cbuf[0] & CCKD_COMPRESS_MASK) != 0
1009          && (cbuf[0] & dev->comps) == 0)
1010         {
1011 #if 0
1012             /* Return if synchronous i/o */
1013             if (dev->syncio_active)
1014             {
1015                 cckd_trace (dev, "read blkgrp  %d syncio compressed\n",
1016                             blkgrp);
1017                 cckdblk.stats_synciomisses++;
1018                 dev->syncio_retry = 1;
1019                 return -1;
1020             }
1021 #endif
1022             len = cache_getval(CACHE_DEVBUF, dev->cache) + CKDDASD_TRKHDR_SIZE;
1023             newbuf = cckd_uncompress (dev, cbuf, len, maxlen, blkgrp);
1024             if (newbuf == NULL) {
1025                 dev->sense[0] = SENSE_EC;
1026                 *unitstat = CSW_CE | CSW_DE | CSW_UC;
1027                 dev->bufcur = dev->cache = -1;
1028                 return -1;
1029             }
1030             cache_setbuf (CACHE_DEVBUF, dev->cache, newbuf, maxlen);
1031             cbuf = newbuf;
1032             dev->buf     = newbuf + CKDDASD_TRKHDR_SIZE;
1033             dev->buflen  = CFBA_BLOCK_SIZE;
1034             cache_setval (CACHE_DEVBUF, dev->cache, dev->buflen);
1035             dev->bufsize = cache_getlen (CACHE_DEVBUF, dev->cache);
1036             dev->bufupd  = 0;
1037             cckd_trace (dev, "read bkgrp  %d uncompressed len %d\n",
1038                         blkgrp, dev->buflen);
1039         }
1040 
1041         dev->comp = cbuf[0] & CCKD_COMPRESS_MASK;
1042 
1043         return 0;
1044     }
1045 
1046     cckd_trace (dev, "read blkgrp  %d (%s)\n", blkgrp,
1047                 dev->syncio_active ? "synchronous" : "asynchronous");
1048 
1049     /* Read the new blkgrp */
1050     dev->bufupd = 0;
1051     *unitstat = 0;
1052     cache = cckd_read_trk (dev, blkgrp, 0, unitstat);
1053     if (cache < 0)
1054     {
1055         dev->bufcur = dev->cache = -1;
1056         return -1;
1057     }
1058     dev->cache    = cache;
1059     cbuf          = cache_getbuf (CACHE_DEVBUF, dev->cache, 0);
1060     dev->buf      = cbuf + CKDDASD_TRKHDR_SIZE;
1061     dev->bufcur   = blkgrp;
1062     dev->bufoff   = 0;
1063     dev->bufoffhi = CFBA_BLOCK_SIZE;
1064     dev->buflen   = CFBA_BLOCK_SIZE;
1065     cache_setval  (CACHE_DEVBUF, dev->cache, dev->buflen);
1066     dev->bufsize  = cache_getlen (CACHE_DEVBUF, dev->cache);
1067     dev->comp     = cbuf[0] & CCKD_COMPRESS_MASK;
1068 
1069     /* If the image is compressed then call ourself recursively
1070        to cause the image to get uncompressed.  This is because
1071       `bufcur' will match blkgrp and `comps' won't match `comp' */
1072     if (dev->comp != 0 && (dev->comp & dev->comps) == 0)
1073         rc = cfba_read_block (dev, blkgrp, unitstat);
1074     else
1075         rc = 0;
1076 
1077     return rc;
1078 } /* end function cfba_read_block */
1079 
1080 /*-------------------------------------------------------------------*/
1081 /* Compressed fba write block(s)                                     */
1082 /*-------------------------------------------------------------------*/
cfba_write_block(DEVBLK * dev,int blkgrp,int off,BYTE * buf,int len,BYTE * unitstat)1083 int cfba_write_block (DEVBLK *dev, int blkgrp, int off,
1084                       BYTE *buf, int len, BYTE *unitstat)
1085 {
1086 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1087 int             rc;                     /* Return code               */
1088 BYTE           *cbuf;                   /* -> cache buffer           */
1089 
1090     cckd = dev->cckd_ext;
1091 
1092     if (dev->cache >= 0)
1093         cbuf = cache_getbuf (CACHE_DEVBUF, dev->cache, 0);
1094     else
1095         cbuf = NULL;
1096 
1097     /* Read the block group if it's not current or compressed.
1098        `dev->comps' is set to zero forcing the read routine to
1099        uncompress the image.                                   */
1100     if (blkgrp != dev->bufcur || (cbuf[0] & CCKD_COMPRESS_MASK) != 0)
1101     {
1102         dev->comps = 0;
1103         rc = (dev->hnd->read) (dev, blkgrp, unitstat);
1104         if (rc < 0)
1105         {
1106             dev->bufcur = dev->cache = -1;
1107             return -1;
1108         }
1109     }
1110 
1111     /* Copy the data into the buffer */
1112     if (buf) memcpy (dev->buf + off, buf, len);
1113 
1114     /* Update the cache entry */
1115     cache_setflag (CACHE_DEVBUF, dev->cache, ~0, CCKD_CACHE_UPDATED|CCKD_CACHE_USED);
1116     cckd->updated = 1;
1117 
1118     /* Notify the shared server of the update */
1119     if (!dev->bufupd)
1120     {
1121         dev->bufupd = 1;
1122         shared_update_notify (dev, blkgrp);
1123     }
1124 
1125     return len;
1126 
1127 } /* end function cfba_write_block */
1128 
1129 /*-------------------------------------------------------------------*/
1130 /* Return used blocks                                                */
1131 /*-------------------------------------------------------------------*/
cfba_used(DEVBLK * dev)1132 int cfba_used (DEVBLK *dev)
1133 {
1134 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1135 int             rc;                     /* Return code               */
1136 int             l1x, l2x;               /* Lookup table indexes      */
1137 int             sfx;                    /* Shadow file suffix        */
1138 CCKD_L2ENT      l2;                     /* Copied level 2 entry      */
1139 
1140     cckd = dev->cckd_ext;
1141     obtain_lock (&cckd->filelock);
1142 
1143     /* Find the last used level 1 table entry */
1144     for (l1x = cckd->cdevhdr[0].numl1tab - 1; l1x > 0; l1x--)
1145     {
1146         sfx = cckd->sfn;
1147         while (cckd->l1[sfx][l1x] == 0xffffffff && sfx > 0) sfx--;
1148         if (cckd->l1[sfx][l1x]) break;
1149     }
1150 
1151     /* Find the last used level 2 table entry */
1152     for (l2x = 255; l2x >= 0; l2x--)
1153     {
1154         rc = cckd_read_l2ent (dev, &l2, l1x * 256 + l2x);
1155         if (rc < 0 || l2.pos != 0) break;
1156     }
1157 
1158     release_lock (&cckd->filelock);
1159     return (l1x * 256 + l2x + CFBA_BLOCK_NUM) / CFBA_BLOCK_NUM;
1160 }
1161 
1162 /*-------------------------------------------------------------------*/
1163 /* Read a track image                                                */
1164 /*                                                                   */
1165 /* This routine can be called by the i/o thread (`ra' == 0) or       */
1166 /* by readahead threads (0 < `ra' <= cckdblk.ramax).                 */
1167 /*                                                                   */
1168 /*-------------------------------------------------------------------*/
cckd_read_trk(DEVBLK * dev,int trk,int ra,BYTE * unitstat)1169 int cckd_read_trk(DEVBLK *dev, int trk, int ra, BYTE *unitstat)
1170 {
1171 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1172 int             fnd;                    /* Cache index for hit       */
1173 int             lru;                    /* Oldest unused cache index */
1174 int             len;                    /* Length of track image     */
1175 int             maxlen;                 /* Length for buffer         */
1176 int             curtrk = -1;            /* Current track (at entry)  */
1177 U16             devnum;                 /* Device number             */
1178 U32             oldtrk;                 /* Stolen track number       */
1179 U32             flag;                   /* Cache flag                */
1180 BYTE           *buf;                    /* Read buffer               */
1181 
1182     cckd = dev->cckd_ext;
1183 
1184     cckd_trace (dev, "%d rdtrk     %d\n", ra, trk);
1185 
1186     maxlen = cckd->ckddasd ? dev->ckdtrksz
1187                            : CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE;
1188 
1189     if (!ra) obtain_lock (&cckd->iolock);
1190 
1191     cache_lock (CACHE_DEVBUF);
1192 
1193     /* Inactivate the old entry */
1194     if (!ra)
1195     {
1196         curtrk = dev->bufcur;
1197         if (dev->cache >= 0)
1198             cache_setflag(CACHE_DEVBUF, dev->cache, ~CCKD_CACHE_ACTIVE, 0);
1199         dev->bufcur = dev->cache = -1;
1200     }
1201 
1202 cckd_read_trk_retry:
1203 
1204     /* scan the cache array for the track */
1205     fnd = cache_lookup (CACHE_DEVBUF, CCKD_CACHE_SETKEY(dev->devnum, trk), &lru);
1206 
1207     /* check for cache hit */
1208     if (fnd >= 0)
1209     {
1210         if (ra) /* readahead doesn't care about a cache hit */
1211         {   cache_unlock (CACHE_DEVBUF);
1212             return fnd;
1213         }
1214 
1215         /* If synchronous I/O and I/O is active then return
1216            with syncio_retry bit on */
1217         if (dev->syncio_active)
1218         {
1219             if (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_IOBUSY)
1220             {
1221                 cckd_trace (dev, "%d rdtrk[%d] %d syncio %s\n", ra, fnd, trk,
1222                             cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_READING ?
1223                             "reading" : "writing");
1224                 cckdblk.stats_synciomisses++;
1225                 dev->syncio_retry = 1;
1226                 cache_unlock (CACHE_DEVBUF);
1227                 release_lock (&cckd->iolock);
1228                 return -1;
1229             }
1230             else cckdblk.stats_syncios++;
1231         }
1232 
1233         /* Mark the new entry active */
1234         cache_setflag(CACHE_DEVBUF, fnd, ~0, CCKD_CACHE_ACTIVE | CCKD_CACHE_USED);
1235         cache_setage(CACHE_DEVBUF, fnd);
1236 
1237         /* If the entry is pending write then change it to `updated' */
1238         if (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_WRITE)
1239         {
1240             cache_setflag(CACHE_DEVBUF, fnd, ~CCKD_CACHE_WRITE, CCKD_CACHE_UPDATED);
1241             cckd->wrpending--;
1242             if (cckd->iowaiters && !cckd->wrpending)
1243                 broadcast_condition (&cckd->iocond);
1244         }
1245         buf = cache_getbuf(CACHE_DEVBUF, fnd, 0);
1246 
1247         cache_unlock (CACHE_DEVBUF);
1248 
1249         cckd_trace (dev, "%d rdtrk[%d] %d cache hit buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n",
1250                     ra, fnd, trk, buf, buf[0], buf[1], buf[2], buf[3], buf[4]);
1251 
1252         cckdblk.stats_switches++;  cckd->switches++;
1253         cckdblk.stats_cachehits++; cckd->cachehits++;
1254 
1255         /* if read/write is in progress then wait for it to finish */
1256         while (cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_IOBUSY)
1257         {
1258             cckdblk.stats_iowaits++;
1259             cckd_trace (dev, "%d rdtrk[%d] %d waiting for %s\n", ra, fnd, trk,
1260                         cache_getflag(CACHE_DEVBUF, fnd) & CCKD_CACHE_READING ?
1261                         "read" : "write");
1262             cache_setflag (CACHE_DEVBUF, fnd, ~0, CCKD_CACHE_IOWAIT);
1263             cckd->iowaiters++;
1264             wait_condition (&cckd->iocond, &cckd->iolock);
1265             cckd->iowaiters--;
1266             cache_setflag (CACHE_DEVBUF, fnd, ~CCKD_CACHE_IOWAIT, 0);
1267             cckd_trace (dev, "%d rdtrk[%d] %d io wait complete\n",
1268                         ra, fnd, trk);
1269         }
1270 
1271         release_lock (&cckd->iolock);
1272 
1273         /* Asynchrously schedule readaheads */
1274         if (curtrk > 0 && trk > curtrk && trk <= curtrk + 2)
1275             cckd_readahead (dev, trk);
1276 
1277         return fnd;
1278 
1279     } /* cache hit */
1280 
1281     /* If not readahead and synchronous I/O then retry */
1282     if (!ra && dev->syncio_active)
1283     {
1284         cache_unlock(CACHE_DEVBUF);
1285         release_lock (&cckd->iolock);
1286         cckd_trace (dev, "%d rdtrk[%d] %d syncio cache miss\n", ra, lru, trk);
1287         cckdblk.stats_synciomisses++;
1288         dev->syncio_retry = 1;
1289         return -1;
1290     }
1291 
1292     cckd_trace (dev, "%d rdtrk[%d] %d cache miss\n", ra, lru, trk);
1293 
1294     /* If no cache entry was stolen, then flush all outstanding writes.
1295        This requires us to release our locks.  cache_wait should be
1296        called with only the cache_lock held.  Fortunately, cache waits
1297        occur very rarely. */
1298     if (lru < 0) /* No available entry to be stolen */
1299     {
1300         cckd_trace (dev, "%d rdtrk[%d] %d no available cache entry\n",
1301                     ra, lru, trk);
1302         cache_unlock (CACHE_DEVBUF);
1303         if (!ra) release_lock (&cckd->iolock);
1304         cckd_flush_cache_all();
1305         cache_lock (CACHE_DEVBUF);
1306         cckdblk.stats_cachewaits++;
1307         cache_wait (CACHE_DEVBUF);
1308         if (!ra)
1309         {
1310             cache_unlock (CACHE_DEVBUF);
1311             obtain_lock (&cckd->iolock);
1312             cache_lock (CACHE_DEVBUF);
1313         }
1314         goto cckd_read_trk_retry;
1315     }
1316 
1317     CCKD_CACHE_GETKEY(lru, devnum, oldtrk);
1318     if (devnum != 0)
1319     {
1320         cckd_trace (dev, "%d rdtrk[%d] %d dropping %4.4X:%d from cache\n",
1321                     ra, lru, trk, devnum, oldtrk);
1322         if (!(cache_getflag(CACHE_DEVBUF, lru) & CCKD_CACHE_USED))
1323         {
1324             cckdblk.stats_readaheadmisses++;  cckd->misses++;
1325         }
1326     }
1327 
1328     /* Initialize the entry */
1329     cache_setkey(CACHE_DEVBUF, lru, CCKD_CACHE_SETKEY(dev->devnum, trk));
1330     cache_setflag(CACHE_DEVBUF, lru, 0, CCKD_CACHE_READING);
1331     cache_setage(CACHE_DEVBUF, lru);
1332     cache_setval(CACHE_DEVBUF, lru, 0);
1333     if (!ra)
1334     {
1335         cckdblk.stats_switches++; cckd->switches++;
1336         cckdblk.stats_cachemisses++;
1337         cache_setflag(CACHE_DEVBUF, lru, ~0, CCKD_CACHE_ACTIVE|CCKD_CACHE_USED);
1338     }
1339     cache_setflag(CACHE_DEVBUF, lru, ~CACHE_TYPE,
1340                   cckd->ckddasd ? DEVBUF_TYPE_CCKD : DEVBUF_TYPE_CFBA);
1341     buf = cache_getbuf(CACHE_DEVBUF, lru, maxlen);
1342 
1343     cckd_trace (dev, "%d rdtrk[%d] %d buf %p len %d\n",
1344                 ra, lru, trk, buf, cache_getlen(CACHE_DEVBUF, lru));
1345 
1346     cache_unlock (CACHE_DEVBUF);
1347 
1348     if (!ra) release_lock (&cckd->iolock);
1349 
1350     /* Asynchronously schedule readaheads */
1351     if (!ra && curtrk > 0 && trk > curtrk && trk <= curtrk + 2)
1352         cckd_readahead (dev, trk);
1353 
1354     /* Clear the buffer if batch mode */
1355     if (dev->batch) memset(buf, 0, maxlen);
1356 
1357     /* Read the track image */
1358     obtain_lock (&cckd->filelock);
1359     len = cckd_read_trkimg (dev, buf, trk, unitstat);
1360     release_lock (&cckd->filelock);
1361     cache_setval (CACHE_DEVBUF, lru, len);
1362 
1363     obtain_lock (&cckd->iolock);
1364 
1365     /* Turn off the READING bit */
1366     cache_lock (CACHE_DEVBUF);
1367     flag = cache_setflag(CACHE_DEVBUF, lru, ~CCKD_CACHE_READING, 0);
1368     cache_unlock (CACHE_DEVBUF);
1369 
1370     /* Wakeup other thread waiting for this read */
1371     if (cckd->iowaiters && (flag & CCKD_CACHE_IOWAIT))
1372     {   cckd_trace (dev, "%d rdtrk[%d] %d signalling read complete\n",
1373                     ra, lru, trk);
1374         broadcast_condition (&cckd->iocond);
1375     }
1376 
1377     release_lock (&cckd->iolock);
1378 
1379     if (ra)
1380     {
1381         cckdblk.stats_readaheads++; cckd->readaheads++;
1382     }
1383 
1384     cckd_trace (dev, "%d rdtrk[%d] %d complete buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n",
1385                 ra, lru, trk, buf, buf[0], buf[1], buf[2], buf[3], buf[4]);
1386 
1387     if (cache_busy_percent(CACHE_DEVBUF) > 80) cckd_flush_cache_all();
1388 
1389     return lru;
1390 
1391 } /* end function cckd_read_trk */
1392 
1393 /*-------------------------------------------------------------------*/
1394 /* Schedule asynchronous readaheads                                  */
1395 /*-------------------------------------------------------------------*/
cckd_readahead(DEVBLK * dev,int trk)1396 void cckd_readahead (DEVBLK *dev, int trk)
1397 {
1398 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1399 int             i, r;                   /* Indexes                   */
1400 TID             tid;                    /* Readahead thread id       */
1401 
1402     cckd = dev->cckd_ext;
1403 
1404     if (cckdblk.ramax < 1 || cckdblk.readaheads < 1)
1405         return;
1406 
1407     obtain_lock (&cckdblk.ralock);
1408 
1409     /* Scan the cache to see if the tracks are already there */
1410     memset(cckd->ralkup, 0, sizeof(cckd->ralkup));
1411     cckd->ratrk = trk;
1412     cache_lock(CACHE_DEVBUF);
1413     cache_scan(CACHE_DEVBUF, cckd_readahead_scan, dev);
1414     cache_unlock(CACHE_DEVBUF);
1415 
1416     /* Scan the queue to see if the tracks are already there */
1417     for (r = cckdblk.ra1st; r >= 0; r = cckdblk.ra[r].next)
1418         if (cckdblk.ra[r].dev == dev)
1419         {
1420             i = cckdblk.ra[r].trk - trk;
1421             if (i > 0 && i <= cckdblk.readaheads)
1422                 cckd->ralkup[i-1] = 1;
1423         }
1424 
1425     /* Queue the tracks to the readahead queue */
1426     for (i = 1; i <= cckdblk.readaheads && cckdblk.rafree >= 0; i++)
1427     {
1428         if (cckd->ralkup[i-1]) continue;
1429         if (trk + i >= dev->ckdtrks) break;
1430         r = cckdblk.rafree;
1431         cckdblk.rafree = cckdblk.ra[r].next;
1432         if (cckdblk.ralast < 0)
1433         {
1434             cckdblk.ra1st = cckdblk.ralast = r;
1435             cckdblk.ra[r].prev = cckdblk.ra[r].next = -1;
1436         }
1437         else
1438         {
1439             cckdblk.ra[cckdblk.ralast].next = r;
1440             cckdblk.ra[r].prev = cckdblk.ralast;
1441             cckdblk.ra[r].next = -1;
1442             cckdblk.ralast = r;
1443         }
1444         cckdblk.ra[r].trk = trk + i;
1445         cckdblk.ra[r].dev = dev;
1446     }
1447 
1448     /* Schedule the readahead if any are pending */
1449     if (cckdblk.ra1st >= 0)
1450     {
1451         if (cckdblk.rawaiting)
1452             signal_condition (&cckdblk.racond);
1453         else if (cckdblk.ras < cckdblk.ramax)
1454             create_thread (&tid, JOINABLE, cckd_ra, NULL, "cckd_ra");
1455     }
1456 
1457     release_lock (&cckdblk.ralock);
1458 
1459 } /* end function cckd_readahead */
1460 
cckd_readahead_scan(int * answer,int ix,int i,void * data)1461 int cckd_readahead_scan (int *answer, int ix, int i, void *data)
1462 {
1463 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1464 U16             devnum;                 /* Cached device number      */
1465 U32             trk;                    /* Cached track              */
1466 DEVBLK         *dev = data;             /* -> device block           */
1467 int             k;                      /* Index                     */
1468 
1469     UNREFERENCED(answer);
1470     UNREFERENCED(ix);
1471     cckd = dev->cckd_ext;
1472     CCKD_CACHE_GETKEY(i, devnum, trk);
1473     if (devnum == dev->devnum)
1474     {
1475         k = (int)trk - cckd->ratrk;
1476         if (k > 0 && k <= cckdblk.readaheads)
1477             cckd->ralkup[k-1] = 1;
1478     }
1479     return 0;
1480 }
1481 
1482 /*-------------------------------------------------------------------*/
1483 /* Asynchronous readahead thread                                     */
1484 /*-------------------------------------------------------------------*/
cckd_ra()1485 void cckd_ra ()
1486 {
1487 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1488 DEVBLK         *dev;                    /* Readahead devblk          */
1489 int             trk;                    /* Readahead track           */
1490 int             ra;                     /* Readahead index           */
1491 int             r;                      /* Readahead queue index     */
1492 TID             tid;                    /* Readahead thread id       */
1493 
1494     obtain_lock (&cckdblk.ralock);
1495     ra = ++cckdblk.ras;
1496 
1497     /* Return without messages if too many already started */
1498     if (ra > cckdblk.ramax)
1499     {
1500         --cckdblk.ras;
1501         release_lock (&cckdblk.ralock);
1502         return;
1503     }
1504 
1505     if (!cckdblk.batch)
1506     {
1507         logmsg (_("HHCCD001I Readahead thread %d started: tid="TIDPAT", pid=%d\n"),
1508             ra, thread_id(), getpid());
1509     }
1510 
1511     while (ra <= cckdblk.ramax)
1512     {
1513         if (cckdblk.ra1st < 0)
1514         {
1515             cckdblk.rawaiting++;
1516             wait_condition (&cckdblk.racond, &cckdblk.ralock);
1517             cckdblk.rawaiting--;
1518         }
1519 
1520         /* Possibly shutting down if no writes pending */
1521         if (cckdblk.ra1st < 0) continue;
1522 
1523         r = cckdblk.ra1st;
1524         trk = cckdblk.ra[r].trk;
1525         dev = cckdblk.ra[r].dev;
1526         cckd = dev->cckd_ext;
1527 
1528         /* Requeue the 1st entry to the readahead free queue */
1529         cckdblk.ra1st = cckdblk.ra[r].next;
1530         if (cckdblk.ra[r].next > -1)
1531             cckdblk.ra[cckdblk.ra[r].next].prev = -1;
1532         else cckdblk.ralast = -1;
1533         cckdblk.ra[r].next = cckdblk.rafree;
1534         cckdblk.rafree = r;
1535 
1536         /* Schedule the other readaheads if any are still pending */
1537         if (cckdblk.ra1st)
1538         {
1539             if (cckdblk.rawaiting)
1540                 signal_condition (&cckdblk.racond);
1541             else if (cckdblk.ras < cckdblk.ramax)
1542                 create_thread (&tid, JOINABLE, cckd_ra, dev, "cckd_ra");
1543         }
1544 
1545         if (!cckd || cckd->stopping || cckd->merging) continue;
1546 
1547         cckd->ras++;
1548         release_lock (&cckdblk.ralock);
1549 
1550         /* Read the readahead track */
1551         cckd_read_trk (dev, trk, ra, NULL);
1552 
1553         obtain_lock (&cckdblk.ralock);
1554         cckd->ras--;
1555     }
1556 
1557     if (!cckdblk.batch)
1558     logmsg (_("HHCCD011I Readahead thread %d stopping: tid="TIDPAT", pid=%d\n"),
1559             ra, thread_id(), getpid());
1560     --cckdblk.ras;
1561     if (!cckdblk.ras) signal_condition(&cckdblk.termcond);
1562     release_lock(&cckdblk.ralock);
1563 
1564 } /* end thread cckd_ra_thread */
1565 
1566 /*-------------------------------------------------------------------*/
1567 /* Flush updated cache entries for a device                          */
1568 /*                                                                   */
1569 /* Caller holds the cckd->iolock                                     */
1570 /* cckdblk.wrlock then cache_lock is obtained and released           */
1571 /*-------------------------------------------------------------------*/
cckd_flush_cache(DEVBLK * dev)1572 void cckd_flush_cache(DEVBLK *dev)
1573 {
1574 int             rc;                     /* Return code               */
1575 TID             tid;                    /* Writer thread id          */
1576 
1577     /* Scan cache for updated cache entries */
1578     obtain_lock (&cckdblk.wrlock);
1579     cache_lock (CACHE_DEVBUF);
1580     rc = cache_scan (CACHE_DEVBUF, cckd_flush_cache_scan, dev);
1581     cache_unlock (CACHE_DEVBUF);
1582 
1583     /* Schedule the writer if any writes are pending */
1584     if (cckdblk.wrpending)
1585     {
1586         if (cckdblk.wrwaiting)
1587             signal_condition (&cckdblk.wrcond);
1588         else if (cckdblk.wrs < cckdblk.wrmax)
1589         {
1590             create_thread (&tid, JOINABLE, cckd_writer, NULL, "cckd_writer");
1591         }
1592     }
1593     release_lock (&cckdblk.wrlock);
1594 }
cckd_flush_cache_scan(int * answer,int ix,int i,void * data)1595 int cckd_flush_cache_scan (int *answer, int ix, int i, void *data)
1596 {
1597 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1598 U16             devnum;                 /* Cached device number      */
1599 U32             trk;                    /* Cached track              */
1600 DEVBLK         *dev = data;             /* -> device block           */
1601 
1602     UNREFERENCED(answer);
1603     cckd = dev->cckd_ext;
1604     CCKD_CACHE_GETKEY(i, devnum, trk);
1605     if ((cache_getflag(ix,i) & CACHE_BUSY) == CCKD_CACHE_UPDATED
1606      && dev->devnum == devnum)
1607     {
1608         cache_setflag (ix, i, ~CCKD_CACHE_UPDATED, CCKD_CACHE_WRITE);
1609         ++cckd->wrpending;
1610         ++cckdblk.wrpending;
1611         cckd_trace (dev, "flush file[%d] cache[%d] %4.4X trk %d\n",
1612                     cckd->sfn, i, devnum, trk);
1613     }
1614     return 0;
1615 }
cckd_flush_cache_all()1616 void cckd_flush_cache_all()
1617 {
1618 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1619 DEVBLK         *dev = NULL;             /* -> device block           */
1620 
1621     cckd_lock_devchain(0);
1622     for (dev = cckdblk.dev1st; dev; dev = cckd->devnext)
1623     {
1624         cckd = dev->cckd_ext;
1625         obtain_lock (&cckd->iolock);
1626         if (!cckd->merging && !cckd->stopping)
1627             cckd_flush_cache(dev);
1628         release_lock (&cckd->iolock);
1629     }
1630     cckd_unlock_devchain();
1631 }
1632 
1633 /*-------------------------------------------------------------------*/
1634 /* Purge cache entries for a device                                  */
1635 /*                                                                   */
1636 /* Caller holds the iolock                                           */
1637 /* cache_lock is obtained and released                               */
1638 /*-------------------------------------------------------------------*/
cckd_purge_cache(DEVBLK * dev)1639 void cckd_purge_cache(DEVBLK *dev)
1640 {
1641 
1642     /* Scan cache and purge entries */
1643     cache_lock (CACHE_DEVBUF);
1644     cache_scan (CACHE_DEVBUF, cckd_purge_cache_scan, dev);
1645     cache_unlock (CACHE_DEVBUF);
1646 }
cckd_purge_cache_scan(int * answer,int ix,int i,void * data)1647 int cckd_purge_cache_scan (int *answer, int ix, int i, void *data)
1648 {
1649 U16             devnum;                 /* Cached device number      */
1650 U32             trk;                    /* Cached track              */
1651 DEVBLK         *dev = data;             /* -> device block           */
1652 
1653     UNREFERENCED(answer);
1654     CCKD_CACHE_GETKEY(i, devnum, trk);
1655     if (dev->devnum == devnum)
1656     {
1657         cache_release (ix, i, 0);
1658         cckd_trace (dev, "purge cache[%d] %4.4X trk %d purged\n",
1659                     i, devnum, trk);
1660     }
1661     return 0;
1662 }
1663 
1664 /*-------------------------------------------------------------------*/
1665 /* Writer thread                                                     */
1666 /*-------------------------------------------------------------------*/
cckd_writer(void * arg)1667 void cckd_writer(void *arg)
1668 {
1669 DEVBLK         *dev;                    /* Device block              */
1670 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1671 int             writer;                 /* Writer identifier         */
1672 int             o;                      /* Cache entry found         */
1673 U16             devnum;                 /* Device number             */
1674 BYTE           *buf;                    /* Buffer                    */
1675 BYTE           *bufp;                   /* Buffer to be written      */
1676 int             len, bufl;              /* Buffer lengths            */
1677 int             trk;                    /* Track number              */
1678 int             comp;                   /* Compression algorithm     */
1679 int             parm;                   /* Compression parameter     */
1680 TID             tid;                    /* Writer thead id           */
1681 U32             flag;                   /* Cache flag                */
1682 static char    *compress[] = {"none", "zlib", "bzip2"};
1683 BYTE            buf2[65536];            /* Compress buffer           */
1684 
1685     UNREFERENCED(arg);
1686 
1687 #ifndef WIN32
1688     /* Set writer priority just below cpu priority to mimimize the
1689        compression effect */
1690     if(cckdblk.wrprio >= 0)
1691         setpriority (PRIO_PROCESS, 0, cckdblk.wrprio);
1692 #endif
1693 
1694     obtain_lock (&cckdblk.wrlock);
1695 
1696     writer = ++cckdblk.wrs;
1697 
1698     /* Return without messages if too many already started */
1699     if (writer > cckdblk.wrmax)
1700     {
1701         --cckdblk.wrs;
1702         release_lock (&cckdblk.wrlock);
1703         return;
1704     }
1705 
1706     if (!cckdblk.batch)
1707     {
1708         logmsg (_("HHCCD002I Writer thread %d started: tid="TIDPAT", pid=%d\n"),
1709             writer, thread_id(), getpid());
1710     }
1711 
1712     while (writer <= cckdblk.wrmax || cckdblk.wrpending)
1713     {
1714         /* Wait for work */
1715         if (cckdblk.wrpending == 0)
1716         {
1717             cckdblk.wrwaiting++;
1718             wait_condition (&cckdblk.wrcond, &cckdblk.wrlock);
1719             cckdblk.wrwaiting--;
1720         }
1721 
1722         /* Scan the cache for the oldest pending write */
1723         cache_lock (CACHE_DEVBUF);
1724         o = cache_scan (CACHE_DEVBUF, cckd_writer_scan, NULL);
1725 
1726         /* Possibly shutting down if no writes pending */
1727         if (o < 0)
1728         {
1729             cache_unlock (CACHE_DEVBUF);
1730             cckdblk.wrpending = 0;
1731             continue;
1732         }
1733         cache_setflag (CACHE_DEVBUF, o, ~CCKD_CACHE_WRITE, CCKD_CACHE_WRITING);
1734         cache_unlock (CACHE_DEVBUF);
1735 
1736         /* Schedule the other writers if any writes are still pending */
1737         cckdblk.wrpending--;
1738         if (cckdblk.wrpending)
1739         {
1740             if (cckdblk.wrwaiting)
1741                 signal_condition (&cckdblk.wrcond);
1742             else if (cckdblk.wrs < cckdblk.wrmax)
1743             {
1744                 create_thread (&tid, JOINABLE, cckd_writer, NULL, "cckd_writer");
1745             }
1746         }
1747         release_lock (&cckdblk.wrlock);
1748 
1749         /* Prepare to compress */
1750         CCKD_CACHE_GETKEY(o, devnum, trk);
1751         dev = cckd_find_device_by_devnum (devnum);
1752         cckd = dev->cckd_ext;
1753         buf = cache_getbuf(CACHE_DEVBUF, o, 0);
1754         len = cckd_trklen (dev, buf);
1755         comp = len < CCKD_COMPRESS_MIN ? CCKD_COMPRESS_NONE
1756              : cckdblk.comp == 0xff ? cckd->cdevhdr[cckd->sfn].compress
1757              : cckdblk.comp;
1758         parm = cckdblk.compparm < 0
1759              ? cckd->cdevhdr[cckd->sfn].compress_parm
1760              : cckdblk.compparm;
1761 
1762         cckd_trace (dev, "%d wrtrk[%d] %d len %d buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n",
1763                     writer, o, trk, len, buf, buf[0], buf[1],buf[2],buf[3],buf[4]);
1764 
1765         /* Compress the image if not null */
1766         if ((len = cckd_check_null_trk (dev, buf, trk, len)) > CKDDASD_NULLTRK_FMTMAX)
1767         {
1768             /* Stress adjustments */
1769             if ((cache_waiters(CACHE_DEVBUF) || cache_busy(CACHE_DEVBUF) > 90)
1770              && !cckdblk.nostress)
1771             {
1772                 cckdblk.stats_stresswrites++;
1773                 comp = len < CCKD_STRESS_MINLEN ?
1774                        CCKD_COMPRESS_NONE : CCKD_STRESS_COMP;
1775                 parm = cache_busy(CACHE_DEVBUF) <= 95 ?
1776                        CCKD_STRESS_PARM1 : CCKD_STRESS_PARM2;
1777             }
1778 
1779             /* Compress the track image */
1780             cckd_trace (dev, "%d wrtrk[%d] %d comp %s parm %d\n",
1781                         writer, o, trk, compress[comp], parm);
1782             bufp = (BYTE *)&buf2;
1783             bufl = cckd_compress(dev, &bufp, buf, len, comp, parm);
1784             cckd_trace (dev, "%d wrtrk[%d] %d compressed length %d\n",
1785                         writer, o, trk, bufl);
1786         }
1787         else
1788         {
1789             bufp = buf;
1790             bufl = len;
1791         }
1792 
1793         obtain_lock (&cckd->filelock);
1794 
1795         /* Turn on read-write header bits if not already on */
1796         if (!(cckd->cdevhdr[cckd->sfn].options & CCKD_OPENED))
1797         {
1798             cckd->cdevhdr[cckd->sfn].options |= (CCKD_OPENED | CCKD_ORDWR);
1799             cckd_write_chdr (dev);
1800         }
1801 
1802         /* Write the track image */
1803         cckd_write_trkimg (dev, bufp, bufl, trk, CCKD_SIZE_ANY);
1804 
1805         release_lock (&cckd->filelock);
1806 
1807         /* Schedule the garbage collector */
1808         if (cckdblk.gcs < cckdblk.gcmax)
1809             create_thread (&tid, JOINABLE, cckd_gcol, NULL, "cckd_gcol");
1810 
1811         obtain_lock (&cckd->iolock);
1812         cache_lock (CACHE_DEVBUF);
1813         flag = cache_setflag (CACHE_DEVBUF, o, ~CCKD_CACHE_WRITING, 0);
1814         cache_unlock (CACHE_DEVBUF);
1815         cckd->wrpending--;
1816         if (cckd->iowaiters && ((flag & CCKD_CACHE_IOWAIT) || !cckd->wrpending))
1817         {   cckd_trace (dev, "writer[%d] cache[%2.2d] %d signalling write complete\n",
1818                         writer, o, trk);
1819             broadcast_condition (&cckd->iocond);
1820         }
1821         release_lock(&cckd->iolock);
1822 
1823         cckd_trace (dev, "%d wrtrk[%2.2d] %d complete flags:%8.8x\n",
1824                     writer, o, trk, cache_getflag(CACHE_DEVBUF,o));
1825 
1826         obtain_lock(&cckdblk.wrlock);
1827     }
1828 
1829     if (!cckdblk.batch)
1830     logmsg (_("HHCCD012I Writer thread %d stopping: tid="TIDPAT", pid=%d\n"),
1831             writer, thread_id(), getpid());
1832     cckdblk.wrs--;
1833     if (cckdblk.wrs == 0) signal_condition(&cckdblk.termcond);
1834     release_lock(&cckdblk.wrlock);
1835 } /* end thread cckd_writer */
1836 
cckd_writer_scan(int * o,int ix,int i,void * data)1837 int cckd_writer_scan (int *o, int ix, int i, void *data)
1838 {
1839     UNREFERENCED(data);
1840     if ((cache_getflag(ix,i) & DEVBUF_TYPE_COMP)
1841      && (cache_getflag(ix,i) & CCKD_CACHE_WRITE)
1842      && (*o == -1 || cache_getage(ix, i) < cache_getage(ix, *o)))
1843         *o = i;
1844     return 0;
1845 }
1846 
1847 /*-------------------------------------------------------------------*/
1848 /* Debug routine for checking the free space array                   */
1849 /*-------------------------------------------------------------------*/
1850 
cckd_chk_space(DEVBLK * dev)1851 void cckd_chk_space(DEVBLK *dev)
1852 {
1853 #if 1
1854 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1855 int             sfx;                    /* Shadow file index         */
1856 int             err = 0, n = 0, i, p;
1857 size_t  largest=0;
1858 size_t  total=0;
1859 off_t           fpos;
1860 
1861     cckd = dev->cckd_ext;
1862     sfx = cckd->sfn;
1863 
1864     p = -1;
1865     fpos = cckd->cdevhdr[sfx].free;
1866     for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
1867     {
1868         n++; total += cckd->free[i].len;
1869         if (n > cckd->freenbr) break;
1870         if (cckd->free[i].prev != p)
1871             err = 1;
1872         if (cckd->free[i].next >= 0)
1873         {
1874             if (fpos + cckd->free[i].len > cckd->free[i].pos)
1875                 err = 1;
1876         }
1877         else
1878         {
1879             if (fpos + cckd->free[i].len > cckd->cdevhdr[sfx].size)
1880                 err = 1;
1881         }
1882         if (cckd->free[i].pending == 0 && cckd->free[i].len > largest)
1883             largest = cckd->free[i].len;
1884         fpos = cckd->free[i].pos;
1885         p = i;
1886     }
1887 
1888     if (err
1889      || (cckd->cdevhdr[sfx].free != 0 && cckd->cdevhdr[sfx].free_number == 0)
1890      || (cckd->cdevhdr[sfx].free == 0 && cckd->cdevhdr[sfx].free_number != 0)
1891      || (n != cckd->cdevhdr[sfx].free_number)
1892      || (total != cckd->cdevhdr[sfx].free_total - cckd->cdevhdr[sfx].free_imbed)
1893      || (cckd->freelast != p)
1894      || (largest != cckd->cdevhdr[sfx].free_largest)
1895        )
1896     {
1897         cckd_trace (dev, "cdevhdr[%d] size   %10d used   %10d free   0x%8.8x\n",
1898                     sfx,cckd->cdevhdr[sfx].size,cckd->cdevhdr[sfx].used,
1899                     cckd->cdevhdr[sfx].free);
1900         cckd_trace (dev, "           nbr   %10d total  %10d imbed  %10d largest %10d\n",
1901                     cckd->cdevhdr[sfx].free_number,
1902                     cckd->cdevhdr[sfx].free_total,cckd->cdevhdr[sfx].free_imbed,
1903                     cckd->cdevhdr[sfx].free_largest);
1904         cckd_trace (dev, "free %p nbr %d 1st %d last %d avail %d\n",
1905                     cckd->free,cckd->freenbr,cckd->free1st,
1906                     cckd->freelast,cckd->freeavail);
1907         cckd_trace (dev, "found nbr %d total %ld largest %ld\n",n,(long)total,(long)largest);
1908         fpos = cckd->cdevhdr[sfx].free;
1909         for (n = 0, i = cckd->free1st; i >= 0; i = cckd->free[i].next)
1910         {
1911             if (++n > cckd->freenbr) break;
1912             cckd_trace (dev, "%4d: [%4d] prev[%4d] next[%4d] pos %8.8" I64_FMT "x len %8d %8.8" I64_FMT "x pend %d\n",
1913                         n, i, cckd->free[i].prev, cckd->free[i].next,
1914                         (long long)fpos, cckd->free[i].len,
1915                         (long long)fpos + cckd->free[i].len, cckd->free[i].pending);
1916             fpos = cckd->free[i].pos;
1917         }
1918         cckd_print_itrace();
1919     }
1920 #endif
1921 } /* end function cckd_chk_space */
1922 
1923 /*-------------------------------------------------------------------*/
1924 /* Get file space                                                    */
1925 /*-------------------------------------------------------------------*/
cckd_get_space(DEVBLK * dev,int * size,int flags)1926 off_t cckd_get_space(DEVBLK *dev, int *size, int flags)
1927 {
1928 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
1929 int             i,p,n;                  /* Free space indexes        */
1930 int             len2;                   /* Other lengths             */
1931 off_t           fpos;                   /* Free space offset         */
1932 unsigned int    flen;                   /* Free space size           */
1933 int             sfx;                    /* Shadow file index         */
1934 int             len;                    /* Requested length          */
1935 
1936     cckd = dev->cckd_ext;
1937     sfx = cckd->sfn;
1938 
1939     len = *size;
1940 
1941     if (flags & CCKD_L2SPACE)
1942     {
1943         flags |= CCKD_SIZE_EXACT;
1944         len = *size = CCKD_L2TAB_SIZE;
1945     }
1946 
1947     cckd_trace (dev, "get_space len %d largest %d flags 0x%2.2x\n",
1948                 len, cckd->cdevhdr[sfx].free_largest, flags);
1949 
1950     if (len <= CKDDASD_NULLTRK_FMTMAX)
1951         return 0;
1952 
1953     if (!cckd->free)
1954         cckd_read_fsp (dev);
1955 
1956     len2 = len + CCKD_FREEBLK_SIZE;
1957 
1958     /* Get space at the end if no space is large enough */
1959     if (len2 > (int)cckd->cdevhdr[sfx].free_largest
1960      && len != (int)cckd->cdevhdr[sfx].free_largest)
1961     {
1962 
1963 cckd_get_space_atend:
1964 
1965         fpos = (off_t)cckd->cdevhdr[sfx].size;
1966         if ((long long)(fpos + len) > cckd->maxsize)
1967         {
1968             logmsg (_("HHCCD102E %4.4X file[%d] get space error, size exceeds %lldM\n"),
1969                     dev->devnum, sfx, (cckd->maxsize >> 20) + 1);
1970             return -1;
1971         }
1972         cckd->cdevhdr[sfx].size += len;
1973         cckd->cdevhdr[sfx].used += len;
1974 
1975         cckd_trace (dev, "get_space atend 0x%" I64_FMT "x len %d\n",(long long)fpos, len);
1976 
1977         return fpos;
1978     }
1979 
1980     /* Scan free space chain */
1981     fpos = (off_t)cckd->cdevhdr[sfx].free;
1982     for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
1983     {
1984         if (cckd->free[i].pending == 0
1985          && (len2 <= (int)cckd->free[i].len || len == (int)cckd->free[i].len)
1986          && ((flags & CCKD_L2SPACE) || fpos >= cckd->l2bounds))
1987             break;
1988         fpos = (off_t)cckd->free[i].pos;
1989     }
1990 
1991     /* This can happen if largest comes before l2bounds */
1992     if (i < 0) goto cckd_get_space_atend;
1993 
1994     flen = cckd->free[i].len;
1995     p = cckd->free[i].prev;
1996     n = cckd->free[i].next;
1997 
1998     /*
1999      * If `CCKD_SIZE_ANY' bit is set and the left over space is small
2000      * enough, then use the entire free space
2001      */
2002     if ((flags & CCKD_SIZE_ANY) && flen <= cckd->freemin)
2003         *size = (int)flen;
2004 
2005     /* Remove the new space from free space */
2006     if (*size < (int)flen)
2007     {
2008         cckd->free[i].len -= *size;
2009         if (p >= 0)
2010             cckd->free[p].pos += *size;
2011         else
2012             cckd->cdevhdr[sfx].free += *size;
2013     }
2014     else
2015     {
2016         cckd->cdevhdr[sfx].free_number--;
2017 
2018         /* Remove the free space entry from the chain */
2019         if (p >= 0)
2020         {
2021             cckd->free[p].pos = cckd->free[i].pos;
2022             cckd->free[p].next = n;
2023         }
2024         else
2025         {
2026             cckd->cdevhdr[sfx].free = cckd->free[i].pos;
2027             cckd->free1st = n;
2028         }
2029 
2030         if (n >= 0)
2031             cckd->free[n].prev = p;
2032         else
2033             cckd->freelast = p;
2034 
2035         /* Add entry to the available queue */
2036         cckd->free[i].next = cckd->freeavail;
2037         cckd->freeavail = i;
2038     }
2039 
2040     /* Find the largest free space if we got the largest */
2041     if (flen >= cckd->cdevhdr[sfx].free_largest)
2042     {
2043         int i;
2044         cckd->cdevhdr[sfx].free_largest = 0;
2045         for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
2046             if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest
2047              && cckd->free[i].pending == 0)
2048                 cckd->cdevhdr[sfx].free_largest = cckd->free[i].len;
2049     }
2050 
2051     /* Update free space stats */
2052     cckd->cdevhdr[sfx].used += len;
2053     cckd->cdevhdr[sfx].free_total -= len;
2054 
2055     cckd->cdevhdr[sfx].free_imbed += *size - len;
2056 
2057     cckd_trace (dev, "get_space found 0x%" I64_FMT "x len %d size %d\n",
2058                 (long long)fpos, len, *size);
2059 
2060     return fpos;
2061 
2062 } /* end function cckd_get_space */
2063 
2064 /*-------------------------------------------------------------------*/
2065 /* Release file space                                                */
2066 /*-------------------------------------------------------------------*/
cckd_rel_space(DEVBLK * dev,off_t pos,int len,int size)2067 void cckd_rel_space(DEVBLK *dev, off_t pos, int len, int size)
2068 {
2069 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2070 int             sfx;                    /* Shadow file index         */
2071 off_t           ppos, npos;             /* Prev/next free offsets    */
2072 int             i, p, n;                /* Free space indexes        */
2073 int             pending;                /* Calculated pending value  */
2074 int             fsize = size;           /* Free space size           */
2075 
2076     if (len <= CKDDASD_NULLTRK_FMTMAX || pos == 0 || pos == 0xffffffff)
2077         return;
2078 
2079     cckd = dev->cckd_ext;
2080     sfx = cckd->sfn;
2081 
2082     cckd_trace (dev, "rel_space offset %" I64_FMT "x len %d size %d\n",
2083                 (long long)pos, len, size);
2084 
2085     if (!cckd->free) cckd_read_fsp (dev);
2086 
2087 //  cckd_chk_space(dev);
2088 
2089     /* Scan free space chain */
2090     ppos = -1;
2091     npos = cckd->cdevhdr[sfx].free;
2092     for (p = -1, n = cckd->free1st; n >= 0; n = cckd->free[n].next)
2093     {
2094         if (pos < npos) break;
2095         ppos = npos;
2096         npos = cckd->free[n].pos;
2097         p = n;
2098     }
2099 
2100     /* Calculate the `pending' value */
2101     pending = cckdblk.freepend >= 0 ? cckdblk.freepend : 1 + (1 - cckdblk.fsync);
2102 
2103     /* If possible use previous adjacent free space otherwise get an available one */
2104     if (p >= 0 && ppos + cckd->free[p].len == pos && cckd->free[p].pending == pending)
2105     {
2106         cckd->free[p].len += size;
2107         fsize = cckd->free[p].len;
2108     }
2109     else
2110     {
2111         /* Increase the size of the free space array if necessary */
2112         if (cckd->freeavail < 0)
2113         {
2114             cckd->freeavail = cckd->freenbr;
2115             cckd->freenbr += 1024;
2116             cckd->free = realloc ( cckd->free, cckd->freenbr * CCKD_FREEBLK_ISIZE);
2117             for (i = cckd->freeavail; i < cckd->freenbr; i++)
2118                 cckd->free[i].next = i + 1;
2119             cckd->free[i-1].next = -1;
2120             cckd->freemin = CCKD_FREE_MIN_SIZE + ((cckd->freenbr >> 10) * CCKD_FREE_MIN_INCR);
2121         }
2122 
2123         /* Get an available free space entry */
2124         i = cckd->freeavail;
2125         cckd->freeavail = cckd->free[i].next;
2126         cckd->cdevhdr[sfx].free_number++;
2127 
2128         /* Update the new entry */
2129         cckd->free[i].prev = p;
2130         cckd->free[i].next = n;
2131         cckd->free[i].len = size;
2132         cckd->free[i].pending = pending;
2133 
2134         /* Update the previous entry */
2135         if (p >= 0)
2136         {
2137             cckd->free[i].pos = cckd->free[p].pos;
2138             cckd->free[p].pos = pos;
2139             cckd->free[p].next = i;
2140         }
2141         else
2142         {
2143             cckd->free[i].pos = cckd->cdevhdr[sfx].free;
2144             cckd->cdevhdr[sfx].free = pos;
2145             cckd->free1st = i;
2146         }
2147 
2148         /* Update the next entry */
2149         if (n >= 0)
2150             cckd->free[n].prev = i;
2151         else
2152             cckd->freelast = i;
2153     }
2154 
2155     /* Update the free space statistics */
2156     cckd->cdevhdr[sfx].used -= len;
2157     cckd->cdevhdr[sfx].free_total += len;
2158     cckd->cdevhdr[sfx].free_imbed -= size - len;
2159     if (!pending && (U32)fsize > cckd->cdevhdr[sfx].free_largest)
2160         cckd->cdevhdr[sfx].free_largest = (U32)fsize;
2161 
2162 //  cckd_chk_space(dev);
2163 
2164 } /* end function cckd_rel_space */
2165 
2166 /*-------------------------------------------------------------------*/
2167 /* Flush pending free space                                          */
2168 /*-------------------------------------------------------------------*/
cckd_flush_space(DEVBLK * dev)2169 void cckd_flush_space(DEVBLK *dev)
2170 {
2171 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2172 int             p,i,n;                  /* Free free space indexes   */
2173 int             sfx;                    /* Shadow file index         */
2174 U32             ppos, pos;              /* Free space offsets        */
2175 
2176     cckd = dev->cckd_ext;
2177     sfx = cckd->sfn;
2178 
2179     cckd_trace (dev, "flush_space nbr %d\n",cckd->cdevhdr[sfx].free_number);
2180 
2181     /* Make sure the free space chain is built */
2182     if (!cckd->free) cckd_read_fsp (dev);
2183 
2184 //  cckd_chk_space(dev);
2185 
2186     if (cckd->cdevhdr[sfx].free_number == 0 || cckd->cdevhdr[sfx].free == 0)
2187     {
2188         cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free = 0;
2189         cckd->free1st = cckd->freelast = cckd->freeavail = -1;
2190     }
2191 
2192     pos = cckd->cdevhdr[sfx].free;
2193     ppos = p = -1;
2194     cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free_largest = 0;
2195     for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
2196     {
2197         /* Decrement the pending count */
2198         if (cckd->free[i].pending)
2199             --cckd->free[i].pending;
2200 
2201         /* Combine adjacent free spaces */
2202         while (pos + cckd->free[i].len == cckd->free[i].pos)
2203         {
2204             n = cckd->free[i].next;
2205             if (cckd->free[n].pending > cckd->free[i].pending + 1
2206              || cckd->free[n].pending < cckd->free[i].pending)
2207                 break;
2208             cckd->free[i].pos = cckd->free[n].pos;
2209             cckd->free[i].len += cckd->free[n].len;
2210             cckd->free[i].next = cckd->free[n].next;
2211             cckd->free[n].next = cckd->freeavail;
2212             cckd->freeavail = n;
2213             n = cckd->free[i].next;
2214             if (n >= 0)
2215                 cckd->free[n].prev = i;
2216 
2217         }
2218         ppos = pos;
2219         pos = cckd->free[i].pos;
2220         cckd->cdevhdr[sfx].free_number++;
2221         if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest
2222          && !cckd->free[i].pending)
2223             cckd->cdevhdr[sfx].free_largest = cckd->free[i].len;
2224         p = i;
2225     }
2226     cckd->freelast = p;
2227 
2228     cckd_trace (dev, "rel_flush_space nbr %d (after merge)\n",
2229                 cckd->cdevhdr[sfx].free_number);
2230 
2231     /* If the last free space is at the end of the file then release it */
2232     if (p >= 0 && ppos + cckd->free[p].len == cckd->cdevhdr[sfx].size
2233      && !cckd->free[p].pending)
2234     {
2235         i = p;
2236         p = cckd->free[i].prev;
2237 
2238         cckd_trace (dev, "file[%d] rel_flush_space atend 0x%" I64_FMT "x len %d\n",
2239                     sfx, (long long)ppos, cckd->free[i].len);
2240 
2241         /* Remove the entry from the chain */
2242         if (p >= 0)
2243         {
2244             cckd->free[p].pos = 0;
2245             cckd->free[p].next = -1;
2246         }
2247         else
2248         {
2249             cckd->cdevhdr[sfx].free = 0;
2250             cckd->free1st = -1;
2251         }
2252         cckd->freelast = p;
2253 
2254         /* Add the entry to the available chain */
2255         cckd->free[i].next = cckd->freeavail;
2256         cckd->freeavail = i;
2257 
2258         /* Update the device header */
2259         cckd->cdevhdr[sfx].size -= cckd->free[i].len;
2260         cckd->cdevhdr[sfx].free_total -= cckd->free[i].len;
2261         cckd->cdevhdr[sfx].free_number--;
2262         if (cckd->free[i].len >= cckd->cdevhdr[sfx].free_largest)
2263         {
2264             cckd->cdevhdr[sfx].free_largest = 0;
2265             for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
2266                 if (cckd->free[i].len > cckd->cdevhdr[sfx].free_largest
2267                  && cckd->free[i].pending == 0)
2268                     cckd->cdevhdr[sfx].free_largest = cckd->free[i].len;
2269         }
2270 
2271         /* Truncate the file */
2272         cckd_ftruncate (dev, sfx, (off_t)cckd->cdevhdr[sfx].size);
2273 
2274     } /* Release space at end of the file */
2275 
2276 //  cckd_chk_space(dev);
2277 
2278 } /* end function cckd_flush_space */
2279 
2280 /*-------------------------------------------------------------------*/
2281 /* Read compressed dasd header                                       */
2282 /*-------------------------------------------------------------------*/
cckd_read_chdr(DEVBLK * dev)2283 int cckd_read_chdr (DEVBLK *dev)
2284 {
2285 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2286 int             sfx;                    /* File index                */
2287 
2288     cckd = dev->cckd_ext;
2289     sfx = cckd->sfn;
2290 
2291     cckd_trace (dev, "file[%d] read_chdr\n", sfx);
2292 
2293     memset (&cckd->cdevhdr[sfx], 0, CCKDDASD_DEVHDR_SIZE);
2294 
2295     /* Read the device header */
2296     if (cckd_read (dev, sfx, CKDDASD_DEVHDR_SIZE, &cckd->cdevhdr[sfx], CCKDDASD_DEVHDR_SIZE) < 0)
2297         return -1;
2298 
2299     /* Check endian format */
2300     cckd->swapend[sfx] = 0;
2301     if ((cckd->cdevhdr[sfx].options & CCKD_BIGENDIAN) != cckd_endian())
2302     {
2303         if (cckd->open[sfx] == CCKD_OPEN_RW)
2304         {
2305             if (cckd_swapend (dev) < 0)
2306                 return -1;
2307             cckd_swapend_chdr (&cckd->cdevhdr[sfx]);
2308         }
2309         else
2310         {
2311             cckd->swapend[sfx] = 1;
2312             cckd_swapend_chdr (&cckd->cdevhdr[sfx]);
2313         }
2314     }
2315 
2316     /* Set default null format */
2317     if (cckd->cdevhdr[sfx].nullfmt > CKDDASD_NULLTRK_FMTMAX)
2318         cckd->cdevhdr[sfx].nullfmt = 0;
2319 
2320     if (cckd->cdevhdr[sfx].nullfmt == 0 && dev->oslinux && dev->devtype == 0x3390)
2321         cckd->cdevhdr[sfx].nullfmt = CKDDASD_NULLTRK_FMT2;
2322 
2323     if (cckd->cdevhdr[sfx].nullfmt == CKDDASD_NULLTRK_FMT2)
2324         dev->oslinux = 1;
2325 
2326     return 0;
2327 
2328 } /* end function cckd_read_chdr */
2329 
2330 /*-------------------------------------------------------------------*/
2331 /* Write compressed dasd header                                      */
2332 /*-------------------------------------------------------------------*/
cckd_write_chdr(DEVBLK * dev)2333 int cckd_write_chdr (DEVBLK *dev)
2334 {
2335 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2336 int             sfx;                    /* File index                */
2337 
2338     cckd = dev->cckd_ext;
2339     sfx = cckd->sfn;
2340 
2341     cckd_trace (dev, "file[%d] write_chdr\n", sfx);
2342 
2343     /* Set version.release.modlvl */
2344     cckd->cdevhdr[sfx].vrm[0] = CCKD_VERSION;
2345     cckd->cdevhdr[sfx].vrm[1] = CCKD_RELEASE;
2346     cckd->cdevhdr[sfx].vrm[2] = CCKD_MODLVL;
2347 
2348     if (cckd_write (dev, sfx, CCKD_DEVHDR_POS, &cckd->cdevhdr[sfx], CCKD_DEVHDR_SIZE) < 0)
2349         return -1;
2350 
2351     return 0;
2352 
2353 } /* end function cckd_write_chdr */
2354 
2355 /*-------------------------------------------------------------------*/
2356 /* Read the level 1 table                                            */
2357 /*-------------------------------------------------------------------*/
cckd_read_l1(DEVBLK * dev)2358 int cckd_read_l1 (DEVBLK *dev)
2359 {
2360 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2361 int             sfx;                    /* File index                */
2362 int             len;                    /* Length of level 1 table   */
2363 int             i;                      /* Work integer              */
2364 
2365     cckd = dev->cckd_ext;
2366     sfx = cckd->sfn;
2367 
2368     cckd_trace (dev, "file[%d] read_l1 offset 0x%"I64_FMT"x\n",
2369                 sfx, (U64)CCKD_L1TAB_POS);
2370 
2371     /* Free the old level 1 table if it exists */
2372     cckd->l1[sfx] = cckd_free (dev, "l1", cckd->l1[sfx]);
2373 
2374     /* Allocate the level 1 table */
2375     len = cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE;
2376     if ((cckd->l1[sfx] = cckd_malloc (dev, "l1", len)) == NULL)
2377         return -1;
2378     memset(cckd->l1[sfx], sfx ? 0xFF : 0, len);
2379 
2380     /* Read the level 1 table */
2381     if (cckd_read (dev, sfx, CCKD_L1TAB_POS, cckd->l1[sfx], len) < 0)
2382         return -1;
2383 
2384     /* Fix endianess */
2385     if (cckd->swapend[sfx])
2386         cckd_swapend_l1 (cckd->l1[sfx], cckd->cdevhdr[sfx].numl1tab);
2387 
2388     /* Determine bounds */
2389     cckd->l2bounds = CCKD_L1TAB_POS + len;
2390     for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++)
2391         if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff)
2392             cckd->l2bounds += CCKD_L2TAB_SIZE;
2393 
2394     /* Check if all l2 tables are within bounds */
2395     cckd->l2ok = 1;
2396     for (i = 0; i < cckd->cdevhdr[sfx].numl1tab && cckd->l2ok; i++)
2397         if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff)
2398             if (cckd->l1[sfx][i] > cckd->l2bounds - CCKD_L2TAB_SIZE)
2399                 cckd->l2ok = 0;
2400 
2401     return 0;
2402 
2403 } /* end function cckd_read_l1 */
2404 
2405 /*-------------------------------------------------------------------*/
2406 /* Write the level 1 table                                           */
2407 /*-------------------------------------------------------------------*/
cckd_write_l1(DEVBLK * dev)2408 int cckd_write_l1 (DEVBLK *dev)
2409 {
2410 CCKDDASD_EXT    *cckd;                  /* -> cckd extension         */
2411 int             sfx;                    /* File index                */
2412 int             len;                    /* Length of level 1 table   */
2413 
2414     cckd = dev->cckd_ext;
2415     sfx = cckd->sfn;
2416     len = cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE;
2417 
2418     cckd_trace (dev, "file[%d] write_l1 0x%"I64_FMT"x len %d\n",
2419                 sfx, (U64)CCKD_L1TAB_POS, len);
2420 
2421     if (cckd_write (dev, sfx, CCKD_L1TAB_POS, cckd->l1[sfx], len) < 0)
2422         return -1;
2423 
2424     return 0;
2425 
2426 } /* end function cckd_write_l1 */
2427 
2428 /*-------------------------------------------------------------------*/
2429 /* Update a level 1 table entry                                      */
2430 /*-------------------------------------------------------------------*/
cckd_write_l1ent(DEVBLK * dev,int l1x)2431 int cckd_write_l1ent (DEVBLK *dev, int l1x)
2432 {
2433 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2434 int             sfx;                    /* File index                */
2435 off_t           off;                    /* Offset to l1 entry        */
2436 
2437     cckd = dev->cckd_ext;
2438     sfx = cckd->sfn;
2439     off = (off_t)(CCKD_L1TAB_POS + l1x * CCKD_L1ENT_SIZE);
2440 
2441     cckd_trace (dev, "file[%d] write_l1ent[%d] , 0x%" I64_FMT "x\n",
2442                 sfx, l1x, (long long)off);
2443 
2444     if (cckd_write (dev, sfx, off, &cckd->l1[sfx][l1x], CCKD_L1ENT_SIZE) < 0)
2445         return -1;
2446 
2447     return 0;
2448 
2449 } /* end function cckd_write_l1ent */
2450 
2451 /*-------------------------------------------------------------------*/
2452 /* Initial read                                                      */
2453 /*-------------------------------------------------------------------*/
cckd_read_init(DEVBLK * dev)2454 int cckd_read_init (DEVBLK *dev)
2455 {
2456 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2457 int             sfx;                    /* File index                */
2458 CKDDASD_DEVHDR  devhdr;                 /* Device header             */
2459 
2460     cckd = dev->cckd_ext;
2461     sfx = cckd->sfn;
2462 
2463     cckd_trace (dev, "file[%d] read_init\n", sfx);
2464 
2465     /* Read the device header */
2466     if (cckd_read (dev, sfx, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0)
2467         return -1;
2468 
2469     /* Check the device hdr */
2470     if (sfx == 0 && memcmp (&devhdr.devid, "CKD_C370", 8) == 0)
2471         cckd->ckddasd = 1;
2472     else if (sfx == 0 && memcmp (&devhdr.devid, "FBA_C370", 8) == 0)
2473         cckd->fbadasd = 1;
2474     else if (!(sfx && memcmp (&devhdr.devid, "CKD_S370", 8) == 0 && cckd->ckddasd)
2475           && !(sfx && memcmp (&devhdr.devid, "FBA_S370", 8) == 0 && cckd->fbadasd))
2476     {
2477         logmsg (_("HHCCD110E %4.4X file[%d] devhdr id error\n"),
2478                 dev->devnum, sfx);
2479         return -1;
2480     }
2481 
2482     /* Read the compressed header */
2483     if (cckd_read_chdr (dev) < 0)
2484         return -1;
2485 
2486     /* Read the level 1 table */
2487     if (cckd_read_l1 (dev) < 0)
2488         return -1;
2489 
2490     return 0;
2491 } /* end function cckd_read_init */
2492 
2493 /*-------------------------------------------------------------------*/
2494 /* Read free space                                                   */
2495 /*-------------------------------------------------------------------*/
cckd_read_fsp(DEVBLK * dev)2496 int cckd_read_fsp (DEVBLK *dev)
2497 {
2498 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2499 off_t           fpos;                   /* Free space offset         */
2500 int             sfx;                    /* File index                */
2501 int             i;                      /* Index                     */
2502 CCKD_FREEBLK    freeblk;                /* First freeblk read        */
2503 
2504     cckd = dev->cckd_ext;
2505     sfx = cckd->sfn;
2506 
2507     cckd_trace (dev, "file[%d] read_fsp number %d\n",
2508                 sfx, cckd->cdevhdr[sfx].free_number);
2509 
2510     cckd->free = cckd_free (dev, "free", cckd->free);
2511     cckd->free1st = cckd->freelast = cckd->freeavail = -1;
2512 
2513     /* Get storage for the internal free space chain
2514      * in a multiple of 1024 entries
2515      */
2516     cckd->freenbr = (cckd->cdevhdr[sfx].free_number + 1023) & ~0x3FF;
2517     if (cckd->freenbr)
2518         if ((cckd->free = cckd_calloc (dev, "free", cckd->freenbr, CCKD_FREEBLK_ISIZE)) == NULL)
2519             return -1;
2520 
2521     /* Build the doubly linked internal free space chain */
2522     if (cckd->cdevhdr[sfx].free_number)
2523     {
2524         cckd->free1st = 0;
2525 
2526         /* Read the first freeblk to determine old/new format */
2527         fpos = (off_t)cckd->cdevhdr[sfx].free;
2528         if (cckd_read (dev, sfx, fpos, &freeblk, CCKD_FREEBLK_SIZE) < 0)
2529             return -1;
2530 
2531         if (memcmp(&freeblk, "FREE_BLK", 8) == 0)
2532         {
2533             /* new format free space */
2534             CCKD_FREEBLK *fsp;
2535             U32 ofree = cckd->cdevhdr[sfx].free;
2536             int n = cckd->cdevhdr[sfx].free_number * CCKD_FREEBLK_SIZE;
2537             if ((fsp = cckd_malloc (dev, "fsp", n)) == NULL)
2538                 return -1;
2539             fpos += CCKD_FREEBLK_SIZE;
2540             if (cckd_read (dev, sfx, fpos, fsp, n) < 0)
2541                 return -1;
2542             for (i = 0; i < cckd->cdevhdr[sfx].free_number; i++)
2543             {
2544                 if (i == 0)
2545                     cckd->cdevhdr[sfx].free = fsp[i].pos;
2546                 else
2547                     cckd->free[i-1].pos = fsp[i].pos;
2548                 cckd->free[i].pos  = 0;
2549                 cckd->free[i].len  = fsp[i].len;
2550                 cckd->free[i].prev = i - 1;
2551                 cckd->free[i].next = i + 1;
2552             }
2553             cckd->free[i-1].next = -1;
2554             cckd->freelast = i-1;
2555             fsp = cckd_free (dev, "fsp", fsp);
2556 
2557             /* truncate if new format free space was at the end */
2558             if (ofree == cckd->cdevhdr[sfx].size)
2559             {
2560                 fpos = (off_t)cckd->cdevhdr[sfx].size;
2561                 cckd_ftruncate(dev, sfx, fpos);
2562             }
2563         } /* new format free space */
2564         else
2565         {
2566             /* old format free space */
2567             fpos = (off_t)cckd->cdevhdr[sfx].free;
2568             for (i = 0; i < cckd->cdevhdr[sfx].free_number; i++)
2569             {
2570                 if (cckd_read (dev, sfx, fpos, &cckd->free[i], CCKD_FREEBLK_SIZE) < 0)
2571                     return -1;
2572                 cckd->free[i].prev = i - 1;
2573                 cckd->free[i].next = i + 1;
2574                 fpos = (off_t)cckd->free[i].pos;
2575             }
2576             cckd->free[i-1].next = -1;
2577             cckd->freelast = i-1;
2578         } /* old format free space */
2579     } /* if (cckd->cdevhdr[sfx].free_number) */
2580 
2581     /* Build singly linked chain of available free space entries */
2582     if (cckd->cdevhdr[sfx].free_number < cckd->freenbr)
2583     {
2584         cckd->freeavail = cckd->cdevhdr[sfx].free_number;
2585         for (i = cckd->freeavail; i < cckd->freenbr; i++)
2586             cckd->free[i].next = i + 1;
2587         cckd->free[i-1].next = -1;
2588     }
2589 
2590     /* Set minimum free space size */
2591     cckd->freemin = CCKD_FREE_MIN_SIZE + ((cckd->freenbr >> 10) * CCKD_FREE_MIN_INCR);
2592     return 0;
2593 
2594 } /* end function cckd_read_fsp */
2595 
2596 /*-------------------------------------------------------------------*/
2597 /* Write the free space                                              */
2598 /*-------------------------------------------------------------------*/
cckd_write_fsp(DEVBLK * dev)2599 int cckd_write_fsp (DEVBLK *dev)
2600 {
2601 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2602 off_t           fpos;                   /* Free space offset         */
2603 U32             ppos;                   /* Previous free space offset*/
2604 int             sfx;                    /* File index                */
2605 int             i, j, n;                /* Work variables            */
2606 int             rc;                     /* Return code               */
2607 CCKD_FREEBLK   *fsp = NULL;             /* -> new format free space  */
2608 
2609     cckd = dev->cckd_ext;
2610     sfx = cckd->sfn;
2611 
2612     if (cckd->free == NULL)
2613         return 0;
2614 
2615     cckd_trace (dev, "file[%d] write_fsp number %d\n",
2616                 sfx, cckd->cdevhdr[sfx].free_number);
2617 
2618     /* get rid of pending free space */
2619     for (i = 0; i < CCKD_MAX_FREEPEND; i++)
2620         cckd_flush_space(dev);
2621 
2622     /* sanity checks */
2623     if (cckd->cdevhdr[sfx].free_number == 0 || cckd->cdevhdr[sfx].free == 0)
2624     {
2625         cckd->cdevhdr[sfx].free_number = cckd->cdevhdr[sfx].free = 0;
2626         cckd->free1st = cckd->freelast = cckd->freeavail = -1;
2627     }
2628 
2629     /* Write any free spaces */
2630     if (cckd->cdevhdr[sfx].free)
2631     {
2632         /* size needed for new format free space */
2633         n = (cckd->cdevhdr[sfx].free_number+1) * CCKD_FREEBLK_SIZE;
2634 
2635         /* look for existing free space to fit new format free space */
2636         fpos = 0;
2637         for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
2638             if (n <= (int)cckd->free[i].len)
2639                 break;
2640         if (i >= 0)
2641             fpos = cckd->free[i].prev < 0
2642                  ? (off_t)cckd->cdevhdr[sfx].free
2643                  : (off_t)cckd->free[cckd->free[i].prev].pos;
2644 
2645         /* if no applicable space see if we can append to the file */
2646         if (fpos == 0 && cckd->maxsize - cckd->cdevhdr[sfx].size >= n)
2647             fpos = (off_t)cckd->cdevhdr[sfx].size;
2648 
2649         if (fpos && (fsp = cckd_malloc (dev, "fsp", n)) == NULL)
2650             fpos = 0;
2651 
2652         if (fpos)
2653         {
2654             /* New format free space */
2655             memcpy (&fsp[0], "FREE_BLK", 8);
2656             ppos = cckd->cdevhdr[sfx].free;
2657             for (i = cckd->free1st, j = 1; i >= 0; i = cckd->free[i].next)
2658             {
2659                 fsp[j].pos = ppos;
2660                 fsp[j++].len = cckd->free[i].len;
2661                 ppos = cckd->free[i].pos;
2662             }
2663             rc = cckd_write (dev, sfx, fpos, fsp, n);
2664             fsp = cckd_free (dev, "fsp", fsp);
2665             if (rc < 0)
2666                 return -1;
2667             cckd->cdevhdr[sfx].free = (U32)fpos;
2668         } /* new format free space */
2669         else
2670         {
2671             /* Old format free space */
2672             for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
2673             {
2674                 if (cckd_write (dev, sfx, fpos, &cckd->free[i], CCKD_FREEBLK_SIZE) < 0)
2675                     return -1;
2676                 fpos = (off_t)cckd->free[i].pos;
2677             }
2678         } /* old format free space */
2679     } /* if (cckd->cdevhdr[sfx].free) */
2680 
2681     /* Free the free space array */
2682     cckd->free = cckd_free (dev, "free", cckd->free);
2683     cckd->freenbr = 0;
2684     cckd->free1st = cckd->freelast = cckd->freeavail = -1;
2685 
2686     return 0;
2687 
2688 } /* end function cckd_write_fsp */
2689 
2690 /*-------------------------------------------------------------------*/
2691 /* Read a new level 2 table                                          */
2692 /*-------------------------------------------------------------------*/
cckd_read_l2(DEVBLK * dev,int sfx,int l1x)2693 int cckd_read_l2 (DEVBLK *dev, int sfx, int l1x)
2694 {
2695 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2696 off_t           off;                    /* L2 file offset            */
2697 int             fnd;                    /* Found cache               */
2698 int             lru;                    /* Oldest available cache    */
2699 CCKD_L2ENT     *buf;                    /* -> Cache buffer           */
2700 int             i;                      /* Loop index                */
2701 int             nullfmt;                /* Null track format         */
2702 
2703     cckd = dev->cckd_ext;
2704     nullfmt = cckd->cdevhdr[cckd->sfn].nullfmt;
2705 
2706     cckd_trace (dev, "file[%d] read_l2 %d active %d %d %d\n",
2707                 sfx, l1x, cckd->sfx, cckd->l1x, cckd->l2active);
2708 
2709     /* Return if table is already active */
2710     if (sfx == cckd->sfx && l1x == cckd->l1x) return 0;
2711 
2712     cache_lock(CACHE_L2);
2713 
2714     /* Inactivate the previous entry */
2715     if (cckd->l2active >= 0)
2716         cache_setflag(CACHE_L2, cckd->l2active, ~L2_CACHE_ACTIVE, 0);
2717     cckd->l2 = NULL;
2718     cckd->l2active = cckd->sfx = cckd->l1x = -1;
2719 
2720     /* scan the cache array for the l2tab */
2721     fnd = cache_lookup (CACHE_L2, L2_CACHE_SETKEY(sfx, dev->devnum, l1x), &lru);
2722 
2723     /* check for level 2 cache hit */
2724     if (fnd >= 0)
2725     {
2726         cckd_trace (dev, "l2[%d,%d] cache[%d] hit\n", sfx, l1x, fnd);
2727         cache_setflag (CACHE_L2, fnd, 0, L2_CACHE_ACTIVE);
2728         cache_setage (CACHE_L2, fnd);
2729         cckdblk.stats_l2cachehits++;
2730         cache_unlock (CACHE_L2);
2731         cckd->sfx = sfx;
2732         cckd->l1x = l1x;
2733         cckd->l2 = cache_getbuf(CACHE_L2, fnd, 0);
2734         cckd->l2active = fnd;
2735         return 1;
2736     }
2737 
2738     cckd_trace (dev, "l2[%d,%d] cache[%d] miss\n", sfx, l1x, lru);
2739 
2740     /* Steal an entry if all are busy */
2741     if (lru < 0) lru = cckd_steal_l2();
2742 
2743     /* Make the entry active */
2744     cache_setkey (CACHE_L2, lru, L2_CACHE_SETKEY(sfx, dev->devnum, l1x));
2745     cache_setflag (CACHE_L2, lru, 0, L2_CACHE_ACTIVE);
2746     cache_setage (CACHE_L2, lru);
2747     buf = cache_getbuf(CACHE_L2, lru, CCKD_L2TAB_SIZE);
2748     cckdblk.stats_l2cachemisses++;
2749     cache_unlock (CACHE_L2);
2750     if (buf == NULL) return -1;
2751 
2752     /* Check for null table */
2753     if (cckd->l1[sfx][l1x] == 0)
2754     {
2755         memset(buf, 0, CCKD_L2TAB_SIZE);
2756         if (nullfmt)
2757             for (i = 0; i < 256; i++)
2758                 buf[i].len = buf[i].size = nullfmt;
2759         cckd_trace (dev, "l2[%d,%d] cache[%d] null fmt[%d]\n", sfx, l1x, lru, nullfmt);
2760     }
2761     else if (cckd->l1[sfx][l1x] == 0xffffffff)
2762     {
2763         memset(buf, 0xff, CCKD_L2TAB_SIZE);
2764         cckd_trace (dev, "l2[%d,%d] cache[%d] null 0xff\n", sfx, l1x, lru);
2765     }
2766     /* Read the new level 2 table */
2767     else
2768     {
2769         off = (off_t)cckd->l1[sfx][l1x];
2770         if (cckd_read (dev, sfx, off, buf, CCKD_L2TAB_SIZE) < 0)
2771         {
2772             cache_lock(CACHE_L2);
2773             cache_setflag(CACHE_L2, lru, 0, 0);
2774             cache_unlock(CACHE_L2);
2775             return -1;
2776         }
2777 
2778         if (cckd->swapend[sfx])
2779             cckd_swapend_l2 (buf);
2780 
2781         cckd_trace (dev, "file[%d] cache[%d] l2[%d] read offset 0x%" I64_FMT "x\n",
2782                     sfx, lru, l1x, (long long)cckd->l1[sfx][l1x]);
2783 
2784         cckd->l2reads[sfx]++;
2785         cckd->totl2reads++;
2786         cckdblk.stats_l2reads++;
2787     }
2788 
2789     cckd->sfx = sfx;
2790     cckd->l1x = l1x;
2791     cckd->l2 = buf;
2792     cckd->l2active = lru;
2793 
2794     return 0;
2795 
2796 } /* end function cckd_read_l2 */
2797 
2798 /*-------------------------------------------------------------------*/
2799 /* Purge all l2tab cache entries for a given device                  */
2800 /*-------------------------------------------------------------------*/
cckd_purge_l2(DEVBLK * dev)2801 void cckd_purge_l2 (DEVBLK *dev)
2802 {
2803 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2804 
2805     cckd = dev->cckd_ext;
2806 
2807     cckd_trace (dev, "purge_l2%s\n", "");
2808 
2809     cache_lock (CACHE_L2);
2810     cckd->l2active = cckd->sfx = cckd->l1x = -1;
2811     cckd->l2 = NULL;
2812     cache_scan (CACHE_L2, cckd_purge_l2_scan, dev);
2813     cache_unlock (CACHE_L2);
2814 }
cckd_purge_l2_scan(int * answer,int ix,int i,void * data)2815 int cckd_purge_l2_scan (int *answer, int ix, int i, void *data)
2816 {
2817 U16             sfx;                    /* Cached suffix             */
2818 U16             devnum;                 /* Cached device number      */
2819 U32             l1x;                    /* Cached level 1 index      */
2820 DEVBLK         *dev = data;             /* -> device block           */
2821 
2822     UNREFERENCED(answer);
2823     L2_CACHE_GETKEY(i, sfx, devnum, l1x);
2824     if (dev == NULL || devnum == dev->devnum)
2825     {
2826         cckd_trace (dev, "purge l2cache[%d] %4.4X sfx %d ix %d purged\n",
2827                     i, devnum, sfx, l1x);
2828         cache_release(ix, i, 0);
2829     }
2830     return 0;
2831 }
2832 
2833 /*-------------------------------------------------------------------*/
2834 /* Steal an l2tab cache entry                                        */
2835 /*-------------------------------------------------------------------*/
cckd_steal_l2()2836 int cckd_steal_l2 ()
2837 {
2838 DEVBLK         *dev;                    /* -> device block           */
2839 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2840 int             i;                      /* Stolen cache index        */
2841 U16             sfx;                    /* Cached suffix             */
2842 U16             devnum;                 /* Cached device number      */
2843 U32             l1x;                    /* Cached level 1 index      */
2844 
2845     i = cache_scan (CACHE_L2, cckd_steal_l2_scan, NULL);
2846     L2_CACHE_GETKEY(i, sfx, devnum, l1x);
2847     dev = cckd_find_device_by_devnum(devnum);
2848     cckd = dev->cckd_ext;
2849     cckd->l2active = cckd->sfx = cckd->l1x = -1;
2850     cckd->l2 = NULL;
2851     cache_release(CACHE_L2, i, 0);
2852     return i;
2853 }
cckd_steal_l2_scan(int * answer,int ix,int i,void * data)2854 int cckd_steal_l2_scan (int *answer, int ix, int i, void *data)
2855 {
2856     UNREFERENCED(data);
2857     if (*answer < 0) *answer = i;
2858     else if (cache_getage(ix, i) < cache_getage(ix, *answer))
2859         *answer = i;
2860     return 0;
2861 }
2862 
2863 /*-------------------------------------------------------------------*/
2864 /* Write the current level 2 table                                   */
2865 /*-------------------------------------------------------------------*/
cckd_write_l2(DEVBLK * dev)2866 int cckd_write_l2 (DEVBLK *dev)
2867 {
2868 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2869 int             sfx,l1x;                /* Lookup table indices      */
2870 off_t           off, old_off;           /* New/old L2 file offsets   */
2871 int             size = CCKD_L2TAB_SIZE; /* L2 table size             */
2872 int             fix;                    /* Null format type          */
2873 
2874     cckd = dev->cckd_ext;
2875     sfx = cckd->sfn;
2876     l1x = cckd->l1x;
2877     fix = cckd->cdevhdr[sfx].nullfmt;
2878     cckd->l2ok = 0;
2879 
2880     cckd_trace (dev, "file[%d] write_l2 %d\n", sfx, l1x);
2881 
2882     if (sfx < 0 || l1x < 0) return -1;
2883 
2884     old_off = (off_t)cckd->l1[sfx][l1x];
2885 
2886     if (cckd->l1[sfx][l1x] == 0 || cckd->l1[sfx][l1x] == 0xffffffff)
2887         cckd->l2bounds += CCKD_L2TAB_SIZE;
2888 
2889     /* Write the L2 table if it's not empty */
2890     if (memcmp(cckd->l2, &empty_l2[fix], CCKD_L2TAB_SIZE))
2891     {
2892         if ((off = cckd_get_space (dev, &size, CCKD_L2SPACE)) < 0)
2893             return -1;
2894         if (cckd_write (dev, sfx, off, cckd->l2, CCKD_L2TAB_SIZE) < 0)
2895             return -1;
2896     }
2897     else
2898     {
2899         off = 0;
2900         cckd->l2bounds -= CCKD_L2TAB_SIZE;
2901     }
2902 
2903     /* Free the old L2 space */
2904     cckd_rel_space (dev, old_off, CCKD_L2TAB_SIZE, CCKD_L2TAB_SIZE);
2905 
2906     /* Update level 1 table */
2907     cckd->l1[sfx][l1x] = (U32)off;
2908     if (cckd_write_l1ent (dev, l1x) < 0)
2909         return -1;
2910 
2911     return 0;
2912 
2913 } /* end function cckd_write_l2 */
2914 
2915 /*-------------------------------------------------------------------*/
2916 /* Return a level 2 entry                                            */
2917 /*-------------------------------------------------------------------*/
cckd_read_l2ent(DEVBLK * dev,CCKD_L2ENT * l2,int trk)2918 int cckd_read_l2ent (DEVBLK *dev, CCKD_L2ENT *l2, int trk)
2919 {
2920 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2921 int             sfx,l1x,l2x;            /* Lookup table indices      */
2922 
2923     cckd = dev->cckd_ext;
2924 
2925     l1x = trk >> 8;
2926     l2x = trk & 0xff;
2927 
2928     if (l2 != NULL) l2->pos = l2->len = l2->size = 0;
2929 
2930     for (sfx = cckd->sfn; sfx >= 0; sfx--)
2931     {
2932         cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] read_l2ent 0x%x\n",
2933                     sfx, l1x, l2x, trk, cckd->l1[sfx][l1x]);
2934 
2935         /* Continue if l2 table not in this file */
2936         if (cckd->l1[sfx][l1x] == 0xffffffff)
2937             continue;
2938 
2939         /* Read l2 table from this file */
2940         if (cckd_read_l2 (dev, sfx, l1x) < 0)
2941             return -1;
2942 
2943         /* Exit loop if track is in this file */
2944         if (cckd->l2[l2x].pos != 0xffffffff)
2945             break;
2946     }
2947 
2948     cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] read_l2ent 0x%x %d %d\n",
2949                 sfx, l1x, l2x, trk, sfx >= 0 ? cckd->l2[l2x].pos : 0,
2950                 sfx >= 0 ? cckd->l2[l2x].len : 0,
2951                 sfx >= 0 ? cckd->l2[l2x].size : 0);
2952 
2953     if (l2 != NULL && sfx >= 0)
2954     {
2955         l2->pos = cckd->l2[l2x].pos;
2956         l2->len = cckd->l2[l2x].len;
2957         l2->size = cckd->l2[l2x].size;
2958     }
2959 
2960     return sfx;
2961 
2962 } /* end function cckd_read_l2ent */
2963 
2964 /*-------------------------------------------------------------------*/
2965 /* Update a level 2 entry                                            */
2966 /*-------------------------------------------------------------------*/
cckd_write_l2ent(DEVBLK * dev,CCKD_L2ENT * l2,int trk)2967 int cckd_write_l2ent (DEVBLK *dev,  CCKD_L2ENT *l2, int trk)
2968 {
2969 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
2970 int             sfx,l1x,l2x;            /* Lookup table indices      */
2971 off_t           off;                    /* L2 entry offset           */
2972 
2973     cckd = dev->cckd_ext;
2974 
2975     /* Error return if no available level 2 table */
2976     if (!cckd->l2) return -1;
2977 
2978     sfx = cckd->sfn;
2979     l1x = trk >> 8;
2980     l2x = trk & 0xff;
2981 
2982     /* Copy the new entry if passed */
2983     if (l2) memcpy (&cckd->l2[l2x], l2, CCKD_L2ENT_SIZE);
2984 
2985     cckd_trace (dev, "file[%d] l2[%d,%d] trk[%d] write_l2ent 0x%x %d %d\n",
2986                 sfx, l1x, l2x, trk,
2987                 cckd->l2[l2x].pos, cckd->l2[l2x].len, cckd->l2[l2x].size);
2988 
2989     /* If no level 2 table for this file, then write a new one */
2990     if (cckd->l1[sfx][l1x] == 0 || cckd->l1[sfx][l1x] == 0xffffffff)
2991         return cckd_write_l2 (dev);
2992 
2993     /* Write the level 2 table entry */
2994     off = (off_t)(cckd->l1[sfx][l1x] + l2x * CCKD_L2ENT_SIZE);
2995     if (cckd_write (dev, sfx, off, &cckd->l2[l2x], CCKD_L2ENT_SIZE) < 0)
2996         return -1;
2997 
2998     return 0;
2999 } /* end function cckd_write_l2ent */
3000 
3001 /*-------------------------------------------------------------------*/
3002 /* Read a track image                                                */
3003 /*-------------------------------------------------------------------*/
cckd_read_trkimg(DEVBLK * dev,BYTE * buf,int trk,BYTE * unitstat)3004 int cckd_read_trkimg (DEVBLK *dev, BYTE *buf, int trk, BYTE *unitstat)
3005 {
3006 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3007 int             rc;                     /* Return code               */
3008 int             sfx;                    /* File index                */
3009 CCKD_L2ENT      l2;                     /* Level 2 entry             */
3010 
3011     cckd = dev->cckd_ext;
3012 
3013     cckd_trace (dev, "trk[%d] read_trkimg\n", trk);
3014 
3015     /* Read level 2 entry for the track */
3016     if ((sfx = cckd_read_l2ent (dev, &l2, trk)) < 0)
3017         goto cckd_read_trkimg_error;
3018 
3019     /* Read the track image or build a null track image */
3020     if (l2.pos != 0)
3021     {
3022         rc = cckd_read (dev, sfx, (off_t)l2.pos, buf, (size_t)l2.len);
3023         if (rc < 0)
3024             goto cckd_read_trkimg_error;
3025 
3026         cckd->reads[sfx]++;
3027         cckd->totreads++;
3028         cckdblk.stats_reads++;
3029         cckdblk.stats_readbytes += rc;
3030         if (cckd->notnull == 0 && trk > 1) cckd->notnull = 1;
3031     }
3032     else
3033         rc = cckd_null_trk (dev, buf, trk, l2.len);
3034 
3035     /* Validate the track image */
3036     if (cckd_cchh (dev, buf, trk) < 0)
3037         goto cckd_read_trkimg_error;
3038 
3039     return rc;
3040 
3041 cckd_read_trkimg_error:
3042 
3043     if (unitstat)
3044     {
3045         ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
3046         *unitstat = CSW_CE | CSW_DE | CSW_UC;
3047     }
3048 
3049     return cckd_null_trk (dev, buf, trk, 0);
3050 
3051 } /* end function cckd_read_trkimg */
3052 
3053 /*-------------------------------------------------------------------*/
3054 /* Write a track image                                               */
3055 /*-------------------------------------------------------------------*/
cckd_write_trkimg(DEVBLK * dev,BYTE * buf,int len,int trk,int flags)3056 int cckd_write_trkimg (DEVBLK *dev, BYTE *buf, int len, int trk, int flags)
3057 {
3058 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3059 int             rc;                     /* Return code               */
3060 off_t           off;                    /* File offset               */
3061 CCKD_L2ENT      l2, oldl2;              /* Level 2 entries           */
3062 int             sfx,l1x,l2x;            /* Lookup table indices      */
3063 int             after = 0;              /* 1=New track after old     */
3064 int             size;                   /* Size of new track         */
3065 
3066     cckd = dev->cckd_ext;
3067 
3068     sfx = cckd->sfn;
3069     l1x = trk >> 8;
3070     l2x = trk & 0xff;
3071 
3072     cckd_trace (dev, "file[%d] trk[%d] write_trkimg len %d buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n",
3073                 sfx, trk, len, buf, buf[0], buf[1], buf[2], buf[3], buf[4]);
3074 
3075     /* Validate the new track image */
3076     if (cckd_cchh (dev, buf, trk) < 0)
3077         return -1;
3078 
3079     /* Get the level 2 table for the track in the active file */
3080     if (cckd_read_l2 (dev, sfx, l1x) < 0)
3081         return -1;
3082 
3083     /* Save the level 2 entry for the track */
3084     oldl2.pos = cckd->l2[l2x].pos;
3085     oldl2.len = cckd->l2[l2x].len;
3086     oldl2.size = cckd->l2[l2x].size;
3087     cckd_trace (dev, "file[%d] trk[%d] write_trkimg oldl2 0x%x %d %d\n",
3088                 sfx, trk, oldl2.pos,oldl2.len,oldl2.size);
3089 
3090     /* Check if writing a null track */
3091     len = cckd_check_null_trk(dev, buf, trk, len);
3092 
3093     if (len > CKDDASD_NULLTRK_FMTMAX)
3094     {
3095         /* Get space for the track image */
3096         size = len;
3097         if ((off = cckd_get_space (dev, &size, flags)) < 0)
3098             return -1;
3099 
3100         l2.pos = (U32)off;
3101         l2.len = (U16)len;
3102         l2.size = (U16)size;
3103 
3104         if (oldl2.pos != 0 && oldl2.pos != 0xffffffff && oldl2.pos < l2.pos)
3105             after = 1;
3106 
3107         /* Write the track image */
3108         if ((rc = cckd_write (dev, sfx, off, buf, len)) < 0)
3109             return -1;
3110 
3111         cckd->writes[sfx]++;
3112         cckd->totwrites++;
3113         cckdblk.stats_writes++;
3114         cckdblk.stats_writebytes += rc;
3115     }
3116     else
3117     {
3118         l2.pos = 0;
3119         l2.len = l2.size = (U16)len;
3120     }
3121 
3122     /* Update the level 2 entry */
3123     if (cckd_write_l2ent (dev, &l2, trk) < 0)
3124         return -1;
3125 
3126     /* Release the previous space */
3127     cckd_rel_space (dev, (off_t)oldl2.pos, (int)oldl2.len, (int)oldl2.size);
3128 
3129     /* `after' is 1 if the new offset is after the old offset */
3130     return after;
3131 
3132 } /* end function cckd_write_trkimg */
3133 
3134 /*-------------------------------------------------------------------*/
3135 /* Harden the file                                                   */
3136 /*-------------------------------------------------------------------*/
cckd_harden(DEVBLK * dev)3137 int cckd_harden(DEVBLK *dev)
3138 {
3139 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3140 int             rc=0;                   /* Return code               */
3141 
3142     cckd = dev->cckd_ext;
3143 
3144     if ((dev->ckdrdonly && cckd->sfn == 0)
3145      || cckd->open[cckd->sfn] != CCKD_OPEN_RW)
3146         return 0;
3147 
3148     cckd_trace (dev, "file[%d] harden\n", cckd->sfn);
3149 
3150     /* Write the compressed device header */
3151     if (cckd_write_chdr (dev) < 0)
3152         rc = -1;
3153 
3154     /* Write the level 1 table */
3155     if (cckd_write_l1 (dev) < 0)
3156         rc = -1;
3157 
3158     /* Write the free space chain */
3159     if (cckd_write_fsp (dev) < 0)
3160         rc = -1;
3161 
3162     /* Re-write the compressed device header */
3163     cckd->cdevhdr[cckd->sfn].options &= ~CCKD_OPENED;
3164     if (cckd_write_chdr (dev) < 0)
3165         rc = -1;
3166 
3167     if (cckdblk.fsync)
3168         fdatasync (cckd->fd[cckd->sfn]);
3169 
3170     return rc;
3171 } /* cckd_harden */
3172 
3173 /*-------------------------------------------------------------------*/
3174 /* Return length of an uncompressed track image                      */
3175 /*-------------------------------------------------------------------*/
cckd_trklen(DEVBLK * dev,BYTE * buf)3176 int cckd_trklen (DEVBLK *dev, BYTE *buf)
3177 {
3178 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3179 int             size;                   /* Track size                */
3180 
3181     cckd = dev->cckd_ext;
3182 
3183     if (cckd->fbadasd)
3184         return CKDDASD_TRKHDR_SIZE + CFBA_BLOCK_SIZE;
3185 
3186     for (size = CKDDASD_TRKHDR_SIZE;
3187          memcmp (&buf[size], &eighthexFF, 8) != 0; )
3188     {
3189         if (size > dev->ckdtrksz) break;
3190 
3191         /* add length of count, key, and data fields */
3192         size += CKDDASD_RECHDR_SIZE +
3193                 buf[size+5] +
3194                 (buf[size+6] << 8) + buf[size+7];
3195     }
3196 
3197     /* add length for end-of-track indicator */
3198     size += CKDDASD_RECHDR_SIZE;
3199 
3200     /* check for missing end-of-track indicator */
3201     if (size > dev->ckdtrksz ||
3202         memcmp (&buf[size-CKDDASD_RECHDR_SIZE], &eighthexFF, 8) != 0)
3203     {
3204         logmsg (_("HHCCD121E %4.4X file[%d] trklen err for %2.2x%2.2x%2.2x%2.2x%2.2x\n"),
3205                 dev->devnum, cckd->sfn, buf[0], buf[1], buf[2], buf[3], buf[4]);
3206         size = -1;
3207     }
3208 
3209     return size;
3210 }
3211 
3212 /*-------------------------------------------------------------------*/
3213 /* Build a null track                                                */
3214 /*-------------------------------------------------------------------*/
cckd_null_trk(DEVBLK * dev,BYTE * buf,int trk,int nullfmt)3215 int cckd_null_trk(DEVBLK *dev, BYTE *buf, int trk, int nullfmt)
3216 {
3217 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3218 int             i;                      /* Loop counter              */
3219 CKDDASD_TRKHDR *trkhdr;                 /* -> Track header           */
3220 CKDDASD_RECHDR *rechdr;                 /* -> Record header          */
3221 U32             cyl;                    /* Cylinder number           */
3222 U32             head;                   /* Head number               */
3223 BYTE            r;                      /* Record number             */
3224 BYTE           *pos;                    /* -> Next position in buffer*/
3225 int             len;                    /* Length of null track      */
3226 
3227     cckd = dev->cckd_ext;
3228 
3229     if (nullfmt < 0 || nullfmt > CKDDASD_NULLTRK_FMTMAX)
3230         nullfmt = cckd->cdevhdr[cckd->sfn].nullfmt;
3231 
3232     // FIXME
3233     // Compatibility check for nullfmt bug and linux -- 18 May 2005
3234     // Remove at some reasonable date in the future
3235     else if (nullfmt == 0
3236      && cckd->cdevhdr[cckd->sfn].nullfmt == CKDDASD_NULLTRK_FMT2)
3237         nullfmt = CKDDASD_NULLTRK_FMT2;
3238 
3239     if (cckd->ckddasd)
3240     {
3241 
3242         /* cylinder and head calculations */
3243         cyl = trk / dev->ckdheads;
3244         head = trk % dev->ckdheads;
3245 
3246         /* Build the track header */
3247         trkhdr = (CKDDASD_TRKHDR*)buf;
3248         trkhdr->bin = 0;
3249         store_hw(&trkhdr->cyl, cyl);
3250         store_hw(&trkhdr->head, head);
3251         pos = buf + CKDDASD_TRKHDR_SIZE;
3252 
3253         /* Build record zero */
3254         r = 0;
3255         rechdr = (CKDDASD_RECHDR*)pos;
3256         pos += CKDDASD_RECHDR_SIZE;
3257         store_hw(&rechdr->cyl, cyl);
3258         store_hw(&rechdr->head, head);
3259         rechdr->rec = r;
3260         rechdr->klen = 0;
3261         store_hw(&rechdr->dlen, 8);
3262         memset (pos, 0, 8);
3263         pos += 8;
3264         r++;
3265 
3266         /* Specific null track formatting */
3267         if (nullfmt == CKDDASD_NULLTRK_FMT0)
3268         {
3269             rechdr = (CKDDASD_RECHDR*)pos;
3270             pos += CKDDASD_RECHDR_SIZE;
3271 
3272             store_hw(&rechdr->cyl, cyl);
3273             store_hw(&rechdr->head, head);
3274             rechdr->rec = r;
3275             rechdr->klen = 0;
3276             store_hw(&rechdr->dlen, 0);
3277             r++;
3278         }
3279         else if (nullfmt == CKDDASD_NULLTRK_FMT2)
3280         {
3281             for (i = 0; i < 12; i++)
3282             {
3283                 rechdr = (CKDDASD_RECHDR*)pos;
3284                 pos += CKDDASD_RECHDR_SIZE;
3285 
3286                 store_hw(&rechdr->cyl, cyl);
3287                 store_hw(&rechdr->head, head);
3288                 rechdr->rec = r;
3289                 rechdr->klen = 0;
3290                 store_hw(&rechdr->dlen, 4096);
3291                 r++;
3292                 memset(pos, 0, 4096);
3293                 pos += 4096;
3294             }
3295         }
3296 
3297         /* Build the end of track marker */
3298         memcpy (pos, eighthexFF, 8);
3299         pos += 8;
3300         len = (int)(pos - buf);
3301     }
3302     else
3303     {
3304         memset (buf, 0, CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE);
3305         store_fw(buf+1, trk);
3306         len = CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE;
3307     }
3308 
3309     cckd_trace (dev, "null_trk %s %d format %d size %d\n",
3310                 cckd->ckddasd ? "trk" : "blkgrp", trk, nullfmt, len);
3311 
3312     return len;
3313 
3314 } /* end function cckd_null_trk */
3315 
3316 /*-------------------------------------------------------------------*/
3317 /* Return a number 0 .. CKDDASD_NULLTRK_FMTMAX if track is null      */
3318 /* else return the original length                                   */
3319 /*-------------------------------------------------------------------*/
cckd_check_null_trk(DEVBLK * dev,BYTE * buf,int trk,int len)3320 int cckd_check_null_trk (DEVBLK *dev, BYTE *buf, int trk, int len)
3321 {
3322 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3323 int             rc;                     /* Return code               */
3324 BYTE            buf2[65536];            /* Null track buffer         */
3325 
3326     cckd = dev->cckd_ext;
3327     rc = len;
3328 
3329     if (len == CKDDASD_NULLTRK_SIZE0)
3330         rc = CKDDASD_NULLTRK_FMT0;
3331     else if (len == CKDDASD_NULLTRK_SIZE1)
3332         rc = CKDDASD_NULLTRK_FMT1;
3333     else if (len == CKDDASD_NULLTRK_SIZE2 && dev->oslinux
3334           && (!cckd->notnull || cckdblk.linuxnull))
3335     {
3336          cckd_null_trk (dev, buf2, trk, 0);
3337          if (memcmp(buf, buf2, len) == 0)
3338             rc = CKDDASD_NULLTRK_FMT2;
3339     }
3340 
3341     return rc;
3342 }
3343 
3344 /*-------------------------------------------------------------------*/
3345 /* Verify a track/block header and return track/block number         */
3346 /*-------------------------------------------------------------------*/
cckd_cchh(DEVBLK * dev,BYTE * buf,int trk)3347 int cckd_cchh (DEVBLK *dev, BYTE *buf, int trk)
3348 {
3349 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3350 U16             cyl;                    /* Cylinder                  */
3351 U16             head;                   /* Head                      */
3352 int             t;                      /* Calculated track          */
3353 BYTE            badcomp=0;              /* 1=Unsupported compression */
3354 static char    *comp[] = {"none", "zlib", "bzip2"};
3355 
3356     cckd = dev->cckd_ext;
3357 
3358     /* CKD dasd header verification */
3359     if (cckd->ckddasd)
3360     {
3361         cyl = fetch_hw (buf + 1);
3362         head = fetch_hw (buf + 3);
3363         t = cyl * dev->ckdheads + head;
3364 
3365         if (cyl < dev->ckdcyls && head < dev->ckdheads
3366          && (trk == -1 || t == trk))
3367         {
3368             if (buf[0] & ~cckdblk.comps)
3369             {
3370                 if (buf[0] & ~CCKD_COMPRESS_MASK)
3371                 {
3372                     if (cckdblk.bytemsgs++ < 10)
3373                         logmsg (_("HHCCD122E %4.4X file[%d] invalid byte 0 trk %d: "
3374                             "buf %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn,
3375                             t, buf[0],buf[1],buf[2],buf[3],buf[4]);
3376                     buf[0] &= CCKD_COMPRESS_MASK;
3377                 }
3378             }
3379             if (buf[0] & ~cckdblk.comps)
3380                 badcomp = 1;
3381             else
3382                 return t;
3383         }
3384     }
3385     /* FBA dasd header verification */
3386     else
3387     {
3388         t = fetch_fw (buf + 1);
3389         if (t < dev->fbanumblk && (trk == -1 || t == trk))
3390         {
3391             if (buf[0] & ~cckdblk.comps)
3392             {
3393                 if (buf[0] & ~CCKD_COMPRESS_MASK)
3394                 {
3395                     logmsg (_("HHCCD123E %4.4X file[%d] invalid byte 0 blkgrp %d: "
3396                             "buf %2.2x%2.2x%2.2x%2.2x%2.2x\n"), dev->devnum, cckd->sfn,
3397                             t, buf[0],buf[1],buf[2],buf[3],buf[4]);
3398                     buf[0] &= CCKD_COMPRESS_MASK;
3399                 }
3400             }
3401             if (buf[0] & ~cckdblk.comps)
3402                 badcomp = 1;
3403             else
3404                 return t;
3405         }
3406     }
3407 
3408     if (badcomp)
3409     {
3410         logmsg (_("HHCCD124E %4.4X file[%d] invalid %s hdr %s %d: "
3411                 "%s compression unsupported\n"),
3412                 dev->devnum, cckd->sfn,
3413                 cckd->ckddasd ? "trk" : "blk",
3414                 cckd->ckddasd ? "trk" : "blk", t, comp[buf[0]]);
3415     }
3416     else
3417     {
3418         logmsg (_("HHCCD125E %4.4X file[%d] invalid %s hdr %s %d "
3419                 "buf %p:%2.2x%2.2x%2.2x%2.2x%2.2x\n"),
3420                 dev->devnum, cckd->sfn,
3421                 cckd->ckddasd ? "trk" : "blk",
3422                 cckd->ckddasd ? "trk" : "blk", trk,
3423                 buf, buf[0], buf[1], buf[2], buf[3], buf[4]);
3424         cckd_print_itrace ();
3425     }
3426 
3427     return -1;
3428 } /* end function cckd_cchh */
3429 
3430 /*-------------------------------------------------------------------*/
3431 /* Validate a track image                                            */
3432 /*-------------------------------------------------------------------*/
cckd_validate(DEVBLK * dev,BYTE * buf,int trk,int len)3433 int cckd_validate (DEVBLK *dev, BYTE *buf, int trk, int len)
3434 {
3435 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3436 int             cyl;                    /* Cylinder                  */
3437 int             head;                   /* Head                      */
3438 char            cchh[4],cchh2[4];       /* Cyl, head big-endian      */
3439 int             r;                      /* Record number             */
3440 int             sz;                     /* Track size                */
3441 int             vlen;                   /* Validation length         */
3442 int             kl,dl;                  /* Key/Data lengths          */
3443 
3444     cckd = dev->cckd_ext;
3445 
3446     if (buf == NULL || len < 0) return -1;
3447 
3448     cckd_trace (dev, "validating %s %d len %d %2.2x%2.2x%2.2x%2.2x%2.2x "
3449                 "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
3450                 cckd->ckddasd ? "trk" : "blkgrp", trk, len,
3451                 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
3452                 buf[7], buf[8], buf[9], buf[10], buf[11], buf[12]);
3453 
3454     /* FBA dasd check */
3455     if (cckd->fbadasd)
3456     {
3457         if (len == CFBA_BLOCK_SIZE + CKDDASD_TRKHDR_SIZE || len == 0)
3458             return len;
3459         cckd_trace (dev, "validation failed: bad length%s\n","");
3460         return -1;
3461     }
3462 
3463     /* cylinder and head calculations */
3464     cyl = trk / dev->ckdheads;
3465     head = trk % dev->ckdheads;
3466     cchh[0] = cyl >> 8;
3467     cchh[1] = cyl & 0xFF;
3468     cchh[2] = head >> 8;
3469     cchh[3] = head & 0xFF;
3470 
3471     /* validate record 0 */
3472     memcpy (cchh2, &buf[5], 4); cchh2[0] &= 0x7f; /* fix for ovflow */
3473     if (/* memcmp (cchh, cchh2, 4) != 0 || */ buf[9]  != 0 ||
3474         buf[10] != 0 || buf[11] != 0 || buf[12] != 8)
3475     {
3476         cckd_trace (dev, "validation failed: bad r0%s\n","");
3477         return -1;
3478     }
3479 
3480     /* validate records 1 thru n */
3481     vlen = len > 0 ? len : dev->ckdtrksz;
3482     for (r = 1, sz = 21; sz + 8 <= vlen; sz += 8 + kl + dl, r++)
3483     {
3484         if (memcmp (&buf[sz], eighthexFF, 8) == 0) break;
3485         kl = buf[sz+5];
3486         dl = buf[sz+6] * 256 + buf[sz+7];
3487         /* fix for track overflow bit */
3488         memcpy (cchh2, &buf[sz], 4); cchh2[0] &= 0x7f;
3489 
3490         /* fix for funny formatted vm disks */
3491         /*
3492         if (r == 1) memcpy (cchh, cchh2, 4);
3493         */
3494 
3495         if (/*memcmp (cchh, cchh2, 4) != 0 ||*/ buf[sz+4] == 0 ||
3496             sz + 8 + kl + dl >= vlen)
3497         {
3498             cckd_trace (dev, "validation failed: bad r%d "
3499                         "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
3500                         r, buf[sz], buf[sz+1], buf[sz+2], buf[sz+3],
3501                         buf[sz+4], buf[sz+5], buf[sz+6], buf[sz+7]);
3502              return -1;
3503         }
3504     }
3505     sz += 8;
3506 
3507     if ((sz != len && len > 0) || sz > vlen)
3508     {
3509         cckd_trace (dev, "validation failed: no eot%s\n","");
3510         return -1;
3511     }
3512 
3513     return sz;
3514 
3515 } /* end function cckd_validate */
3516 
3517 /*-------------------------------------------------------------------*/
3518 /* Return shadow file name                                           */
3519 /*-------------------------------------------------------------------*/
cckd_sf_name(DEVBLK * dev,int sfx)3520 char *cckd_sf_name (DEVBLK *dev, int sfx)
3521 {
3522     /* Return base file name if index is 0 */
3523     if (sfx == 0)
3524         return dev->filename;
3525 
3526     /* Error if no shadow file name specified or number exceeded */
3527     if (dev->dasdsfn == NULL || sfx > CCKD_MAX_SF)
3528         return NULL;
3529 
3530     /* Set the suffix character in the shadow file name */
3531     if (sfx > 0)
3532         *dev->dasdsfx = '0' + sfx;
3533     else
3534         *dev->dasdsfx = '*';
3535 
3536     return dev->dasdsfn;
3537 
3538 } /* end function cckd_sf_name */
3539 
3540 /*-------------------------------------------------------------------*/
3541 /* Initialize shadow files                                           */
3542 /*-------------------------------------------------------------------*/
cckd_sf_init(DEVBLK * dev)3543 int cckd_sf_init (DEVBLK *dev)
3544 {
3545 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3546 int             rc;                     /* Return code               */
3547 int             i;                      /* Index                     */
3548 struct stat     st;                     /* stat() buffer             */
3549 char            pathname[MAX_PATH];     /* file path in host format  */
3550 
3551     cckd = dev->cckd_ext;
3552 
3553     /* return if no shadow files */
3554     if (dev->dasdsfn == NULL) return 0;
3555 
3556 #if 1
3557     /* Check for shadow file name collision */
3558     for (i = 1; i <= CCKD_MAX_SF && dev->dasdsfn != NULL; i++)
3559     {
3560      DEVBLK       *dev2;
3561      CCKDDASD_EXT *cckd2;
3562      int           j;
3563 
3564         for (dev2 = cckdblk.dev1st; dev2; dev2 = cckd2->devnext)
3565         {
3566             cckd2 = dev2->cckd_ext;
3567             if (dev2 == dev) continue;
3568             for (j = 0; j <= CCKD_MAX_SF && dev2->dasdsfn != NULL; j++)
3569             {
3570                 if (strcmp (cckd_sf_name(dev, i),cckd_sf_name(dev2, j)) == 0)
3571                 {
3572                     logmsg (_("HHCCD142E %4.4X file[%d] shadow file name %s\n"
3573                             "      collides with %4.4X file[%d] name %s\n"),
3574                             dev->devnum, i, cckd_sf_name(dev, i),
3575                             dev2->devnum, j, cckd_sf_name(dev2, j));
3576                     return -1;
3577                 }
3578             }
3579         }
3580     }
3581 #endif
3582 
3583     /* open all existing shadow files */
3584     for (cckd->sfn = 1; cckd->sfn <= CCKD_MAX_SF; cckd->sfn++)
3585     {
3586         hostpath(pathname, cckd_sf_name (dev, cckd->sfn), sizeof(pathname));
3587         if (stat (pathname, &st) < 0)
3588             break;
3589 
3590         /* Try to open the shadow file read-write then read-only */
3591         if (cckd_open (dev, cckd->sfn, O_RDWR|O_BINARY, 1) < 0)
3592             if (cckd_open (dev, cckd->sfn, O_RDONLY|O_BINARY, 0) < 0)
3593                 break;
3594 
3595         /* Call the chkdsk function */
3596         rc = cckd_chkdsk (dev, 0);
3597         if (rc < 0) return -1;
3598 
3599         /* Perform initial read */
3600         rc = cckd_read_init (dev);
3601     }
3602 
3603     /* Backup to the last opened file number */
3604     cckd->sfn--;
3605 
3606     /* If the last file was opened read-only then create a new one   */
3607     if (cckd->open[cckd->sfn] == CCKD_OPEN_RO)
3608         if (cckd_sf_new(dev) < 0)
3609             return -1;
3610 
3611     /* Re-open previous rdwr files rdonly */
3612     for (i = 0; i < cckd->sfn; i++)
3613     {
3614         if (cckd->open[i] == CCKD_OPEN_RO) continue;
3615         if (cckd_open (dev, i, O_RDONLY|O_BINARY, 0) < 0)
3616         {
3617             logmsg (_("HHCCD151E %4.4X file[%d] error re-opening %s readonly\n  %s\n"),
3618                     dev->devnum, i, cckd_sf_name(dev, i), strerror(errno));
3619             return -1;
3620         }
3621     }
3622 
3623     return 0;
3624 
3625 } /* end function cckd_sf_init */
3626 
3627 /*-------------------------------------------------------------------*/
3628 /* Create a new shadow file                                          */
3629 /*-------------------------------------------------------------------*/
cckd_sf_new(DEVBLK * dev)3630 int cckd_sf_new (DEVBLK *dev)
3631 {
3632 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3633 int             l1size;                 /* Size of level 1 table     */
3634 CKDDASD_DEVHDR  devhdr;                 /* Device header             */
3635 
3636     cckd = dev->cckd_ext;
3637 
3638     cckd_trace (dev, "file[%d] sf_new %s\n", cckd->sfn+1,
3639                 cckd_sf_name(dev, cckd->sfn+1) ?
3640                 (char *)cckd_sf_name(dev, cckd->sfn+1) : "(none)");
3641 
3642     /* Error if no shadow file name */
3643     if (dev->dasdsfn == NULL)
3644     {
3645         logmsg (_("HHCCD161E %4.4X file[%d] no shadow file name\n"),
3646                 dev->devnum, cckd->sfn+1);
3647         return -1;
3648     }
3649 
3650     /* Error if max number of shadow files exceeded */
3651     if (cckd->sfn+1 == CCKD_MAX_SF)
3652     {
3653         logmsg (_("HHCCD161E %4.4X file[%d] max shadow files exceeded\n"),
3654                 dev->devnum, cckd->sfn+1);
3655         return -1;
3656     }
3657 
3658     /* Harden the current file */
3659     cckd_harden (dev);
3660 
3661     /* Open the new shadow file */
3662     if (cckd_open(dev, cckd->sfn+1, O_RDWR|O_CREAT|O_EXCL|O_BINARY,
3663                                       S_IRUSR | S_IWUSR | S_IRGRP) < 0)
3664         return -1;
3665 
3666     /* Read previous file's device header */
3667     if (cckd_read (dev, cckd->sfn, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0)
3668         goto sf_new_error;
3669 
3670     /* Make sure identifier is CKD_S370 or FBA_S370 */
3671     devhdr.devid[4] = 'S';
3672 
3673     /* Write new file's device header */
3674     if (cckd_write (dev, cckd->sfn+1, 0, &devhdr, CKDDASD_DEVHDR_SIZE) < 0)
3675         goto sf_new_error;
3676 
3677     /* Build the compressed device header */
3678     memcpy (&cckd->cdevhdr[cckd->sfn+1], &cckd->cdevhdr[cckd->sfn], CCKDDASD_DEVHDR_SIZE);
3679     l1size = cckd->cdevhdr[cckd->sfn+1].numl1tab * CCKD_L1ENT_SIZE;
3680     cckd->cdevhdr[cckd->sfn+1].size =
3681     cckd->cdevhdr[cckd->sfn+1].used = CKDDASD_DEVHDR_SIZE + CCKDDASD_DEVHDR_SIZE + l1size;
3682     cckd->cdevhdr[cckd->sfn+1].free =
3683     cckd->cdevhdr[cckd->sfn+1].free_total =
3684     cckd->cdevhdr[cckd->sfn+1].free_largest =
3685     cckd->cdevhdr[cckd->sfn+1].free_number =
3686     cckd->cdevhdr[cckd->sfn+1].free_imbed = 0;
3687 
3688     /* Init the level 1 table */
3689     if ((cckd->l1[cckd->sfn+1] = cckd_malloc (dev, "l1", l1size)) == NULL)
3690         goto sf_new_error;
3691     memset (cckd->l1[cckd->sfn+1], 0xff, l1size);
3692 
3693     /* Make the new file active */
3694     cckd->sfn++;
3695 
3696     /* Harden the new file */
3697     if (cckd_harden (dev) < 0)
3698     {
3699         cckd->sfn--;
3700         goto sf_new_error;
3701     }
3702 
3703     /* Re-read the l1 to set l2bounds, l2ok */
3704     cckd_read_l1 (dev);
3705 
3706     return 0;
3707 
3708 sf_new_error:
3709     cckd->l1[cckd->sfn+1] = cckd_free(dev, "l1", cckd->l1[cckd->sfn+1]);
3710     cckd_close (dev, cckd->sfn+1);
3711     cckd->open[cckd->sfn+1] = CCKD_OPEN_NONE;
3712     unlink (cckd_sf_name (dev, cckd->sfn+1));
3713 
3714     /* Re-read the l1 to set l2bounds, l2ok */
3715     cckd_read_l1 (dev);
3716 
3717     return -1;
3718 
3719 } /* end function cckd_sf_new */
3720 
3721 /*-------------------------------------------------------------------*/
3722 /* Add a shadow file  (sf+)                                          */
3723 /*-------------------------------------------------------------------*/
cckd_sf_add(void * data)3724 void *cckd_sf_add (void *data)
3725 {
3726 DEVBLK         *dev = data;             /* -> DEVBLK                 */
3727 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3728 int             syncio;                 /* Saved syncio bit          */
3729 
3730     if (dev == NULL)
3731     {
3732     int n = 0;
3733         for (dev=sysblk.firstdev; dev; dev=dev->nextdev)
3734             if (dev->cckd_ext)
3735             {
3736                 logmsg( _("HHCCD207I Adding device %d:%4.4X\n"),
3737                           SSID_TO_LCSS(dev->ssid), dev->devnum );
3738                 cckd_sf_add (dev);
3739                 n++;
3740             }
3741         logmsg( _("HHCCD092I %d devices processed\n"), n );
3742         return NULL;
3743     }
3744 
3745     cckd = dev->cckd_ext;
3746     if (!cckd)
3747     {
3748         logmsg (_("HHCCD160E %4.4X not a cckd device\n"), dev->devnum);
3749         return NULL;
3750     }
3751 
3752     /* Disable synchronous I/O for the device */
3753     syncio = cckd_disable_syncio(dev);
3754 
3755     /* Schedule updated track entries to be written */
3756     obtain_lock (&cckd->iolock);
3757     if (cckd->merging)
3758     {
3759         dev->syncio = syncio;
3760         release_lock (&cckd->iolock);
3761         logmsg (_("HHCCD165W %4.4X error adding shadow file, "
3762                   "sf command busy on device\n"),
3763                 dev->devnum,cckd->sfn);
3764         return NULL;
3765     }
3766     cckd->merging = 1;
3767     cckd_flush_cache (dev);
3768     while (cckd->wrpending || cckd->ioactive)
3769     {
3770         cckd->iowaiters++;
3771         wait_condition (&cckd->iocond, &cckd->iolock);
3772         cckd->iowaiters--;
3773         cckd_flush_cache (dev);
3774     }
3775     cckd_purge_cache (dev); cckd_purge_l2 (dev);
3776     dev->bufcur = dev->cache = -1;
3777     release_lock (&cckd->iolock);
3778 
3779     /* Obtain control of the file */
3780     obtain_lock (&cckd->filelock);
3781 
3782     /* Harden the current file */
3783     cckd_harden (dev);
3784 
3785     /* Create a new shadow file */
3786     if (cckd_sf_new (dev) < 0) {
3787         logmsg (_("HHCCD161E %4.4X file[%d] error adding shadow file\n"),
3788                 dev->devnum, cckd->sfn+1);
3789         goto cckd_sf_add_exit;
3790     }
3791 
3792     /* Re-open the previous file if opened read-write */
3793     if (cckd->open[cckd->sfn-1] == CCKD_OPEN_RW)
3794         cckd_open (dev, cckd->sfn-1, O_RDONLY|O_BINARY, 0);
3795 
3796     logmsg (_("HHCCD162I %4.4X file[%d] %s added\n"),
3797             dev->devnum, cckd->sfn, cckd_sf_name (dev, cckd->sfn));
3798 
3799 cckd_sf_add_exit:
3800 
3801     /* Re-read the l1 to set l2bounds, l2ok */
3802     cckd_read_l1 (dev);
3803 
3804     release_lock (&cckd->filelock);
3805 
3806     obtain_lock (&cckd->iolock);
3807     cckd->merging = 0;
3808     if (cckd->iowaiters)
3809         broadcast_condition (&cckd->iocond);
3810     dev->syncio = syncio;
3811     release_lock (&cckd->iolock);
3812 
3813     cckd_sf_stats (dev);
3814     return NULL;
3815 } /* end function cckd_sf_add */
3816 
3817 /*-------------------------------------------------------------------*/
3818 /* Remove a shadow file  (sf-)                                       */
3819 /*-------------------------------------------------------------------*/
cckd_sf_remove(void * data)3820 void *cckd_sf_remove (void *data)
3821 {
3822 DEVBLK         *dev = data;             /* -> DEVBLK                 */
3823 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
3824 int             syncio;                 /* Saved syncio bit          */
3825 int             rc;                     /* Return code               */
3826 int             from_sfx, to_sfx;       /* From/to file index        */
3827 int             fix;                    /* nullfmt index             */
3828 int             add = 0;                /* 1=Add shadow file back    */
3829 int             l2updated = 0;          /* 1=L2 table was updated    */
3830 int             i,j;                    /* Loop indexes              */
3831 int             merge, force;           /* Flags                     */
3832 off_t           pos;                    /* File offset               */
3833 size_t          len;                    /* Length to read/write      */
3834 int             size;                   /* Image size                */
3835 int             trk = -1;               /* Track being read/written  */
3836 CCKD_L2ENT      from_l2[256],           /* Level 2 tables            */
3837                 to_l2[256];
3838 CCKD_L2ENT      new_l2;                 /* New level 2 table entry   */
3839 BYTE            buf[65536];             /* Buffer                    */
3840 
3841     if (dev == NULL)
3842     {
3843     int n = 0;
3844         merge = cckdblk.sfmerge;
3845         force = cckdblk.sfforce;
3846         cckdblk.sfmerge = cckdblk.sfforce = 0;
3847         for (dev=sysblk.firstdev; dev; dev=dev->nextdev)
3848             if ((cckd = dev->cckd_ext))
3849             {
3850                 logmsg( _("HHCCD179I Merging device %d:%4.4X\n"),
3851                           SSID_TO_LCSS(dev->ssid), dev->devnum );
3852                 cckd->sfmerge = merge;
3853                 cckd->sfforce = force;
3854                 cckd_sf_remove (dev);
3855                 n++;
3856             }
3857         logmsg( _("HHCCD092I %d devices processed\n"), n );
3858         return NULL;
3859     }
3860 
3861     cckd = dev->cckd_ext;
3862     if (!cckd)
3863     {
3864         logmsg (_("HHCCD170E %4.4X not a cckd device\n"),
3865                 dev ? dev->devnum : 0);
3866         return NULL;
3867     }
3868 
3869     /* Set flags */
3870     merge = cckd->sfmerge || cckd->sfforce;
3871     force = cckd->sfforce;
3872     cckd->sfmerge = cckd->sfforce = 0;
3873 
3874     cckd_trace (dev, "merge starting: %s %s\n",
3875                 merge ? "merge" : "nomerge", force ? "force" : "");
3876 
3877     /* Disable synchronous I/O for the device */
3878     syncio = cckd_disable_syncio(dev);
3879 
3880     /* Schedule updated track entries to be written */
3881     obtain_lock (&cckd->iolock);
3882     if (cckd->merging)
3883     {
3884         dev->syncio = syncio;
3885         release_lock (&cckd->iolock);
3886         logmsg (_("HHCCD175W %4.4X file[%d] merge failed, "
3887                   "sf command busy on device\n"),
3888                 dev->devnum,cckd->sfn);
3889         return NULL;
3890     }
3891     cckd->merging = 1;
3892     cckd_flush_cache (dev);
3893     while (cckd->wrpending || cckd->ioactive)
3894     {
3895         cckd->iowaiters++;
3896         wait_condition (&cckd->iocond, &cckd->iolock);
3897         cckd->iowaiters--;
3898         cckd_flush_cache (dev);
3899     }
3900     cckd_purge_cache (dev); cckd_purge_l2 (dev);
3901     dev->bufcur = dev->cache = -1;
3902     release_lock (&cckd->iolock);
3903 
3904     obtain_lock (&cckd->filelock);
3905 
3906     if (cckd->sfn == 0)
3907     {
3908         dev->syncio = syncio;
3909         release_lock (&cckd->filelock);
3910         logmsg (_("HHCCD171E %4.4X file[%d] cannot remove base file\n"),
3911                 dev->devnum,cckd->sfn);
3912         cckd->merging = 0;
3913         return NULL;
3914     }
3915 
3916     from_sfx = cckd->sfn;
3917     to_sfx = cckd->sfn - 1;
3918     fix = cckd->cdevhdr[to_sfx].nullfmt;
3919 
3920     /* Harden the `from' file */
3921     if (cckd_harden (dev) < 0)
3922     {
3923         logmsg (_("HHCCD174E %4.4X file[%d] not merged, "
3924                 "file[%d] not hardened\n"),
3925                 dev->devnum, from_sfx, from_sfx);
3926         goto sf_remove_exit;
3927     }
3928 
3929     /* Attempt to re-open the `to' file read-write */
3930     cckd_close (dev, to_sfx);
3931     if (to_sfx > 0 || !dev->ckdrdonly || force)
3932         cckd_open (dev, to_sfx, O_RDWR|O_BINARY, 1);
3933     if (cckd->fd[to_sfx] < 0)
3934     {
3935         /* `from' file can't be opened read-write */
3936         cckd_open (dev, to_sfx, O_RDONLY|O_BINARY, 0);
3937         if (merge)
3938         {
3939             logmsg (_("HHCCD172E %4.4X file[%d] not merged, "
3940                     "file[%d] cannot be opened read-write%s\n"),
3941                     dev->devnum, from_sfx, to_sfx,
3942                     to_sfx == 0 && dev->ckdrdonly && !force
3943                     ? ", try `force'" : "");
3944             goto sf_remove_exit;
3945         }
3946         else
3947            add = 1;
3948     }
3949     else
3950     {
3951         /* `from' file opened read-write */
3952         cckd->sfn = to_sfx;
3953         if (cckd_chkdsk (dev, 0) < 0)
3954         {
3955             cckd->sfn = from_sfx;
3956             logmsg (_("HHCCD173E %4.4X file[%d] not merged, "
3957                     "file[%d] check failed\n"),
3958                     dev->devnum, to_sfx, to_sfx);
3959             goto sf_remove_exit;
3960         }
3961     }
3962 
3963     cckd->sfn = to_sfx;
3964 
3965     /* Perform backwards merge */
3966     if (merge)
3967     {
3968         cckd_trace (dev, "merging to file[%d]\n", to_sfx);
3969 
3970         /* Make the target file the active file */
3971         cckd->sfn = to_sfx;
3972         cckd->cdevhdr[to_sfx].options |= (CCKD_OPENED | CCKD_ORDWR);
3973 
3974         /* Loop for each level 1 table entry */
3975         for (i = 0; i < cckd->cdevhdr[from_sfx].numl1tab; i++)
3976         {
3977             l2updated = 0;
3978             /* Continue if from L2 doesn't exist */
3979             if (cckd->l1[from_sfx][i] == 0xffffffff
3980              || (cckd->l1[from_sfx][i] == 0 && cckd->l1[to_sfx][i] == 0))
3981                 continue;
3982 
3983             trk = i*256;
3984 
3985             /* Read `from' l2 table */
3986             if (cckd->l1[from_sfx][i] == 0)
3987                 memset (&from_l2, 0, CCKD_L2TAB_SIZE);
3988             else
3989             {
3990                 pos = (off_t)cckd->l1[from_sfx][i];
3991                 if (cckd_read(dev, from_sfx, pos, &from_l2, CCKD_L2TAB_SIZE) < 0)
3992                     goto sf_merge_error;
3993             }
3994 
3995             /* Read `to' l2 table */
3996             if (cckd->l1[to_sfx][i] == 0)
3997                 memset (&to_l2, 0, CCKD_L2TAB_SIZE);
3998             else if (cckd->l1[to_sfx][i] == 0xffffffff)
3999                 memset (&to_l2, 0xff, CCKD_L2TAB_SIZE);
4000             else
4001             {
4002                 pos = (off_t)cckd->l1[to_sfx][i];
4003                 if (cckd_read(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE) < 0)
4004                     goto sf_merge_error;
4005             }
4006 
4007             /* Loop for each level 2 table entry */
4008             for (j = 0; j < 256; j++)
4009             {
4010                 trk = i*256 + j;
4011                 /* Continue if from L2 entry doesn't exist */
4012                 if (from_l2[j].pos == 0xffffffff
4013                  || (from_l2[j].pos == 0 && to_l2[j].pos == 0))
4014                     continue;
4015 
4016                 /* Read the `from' track/blkgrp image */
4017                 len = (int)from_l2[j].len;
4018                 if (len > CKDDASD_NULLTRK_FMTMAX)
4019                 {
4020                     pos = (off_t)from_l2[j].pos;
4021                     if (cckd_read (dev, from_sfx, pos, buf, len) < 0)
4022                         goto sf_merge_error;
4023 
4024                     /* Get space for the `to' track/blkgrp image */
4025                     size = len;
4026                     if ((pos = cckd_get_space (dev, &size, CCKD_SIZE_EXACT)) < 0)
4027                         goto sf_merge_error;
4028 
4029                     new_l2.pos = (U32)pos;
4030                     new_l2.len = (U16)len;
4031                     new_l2.size = (U16)size;
4032 
4033                     /* Write the `to' track/blkgrp image */
4034                     if (cckd_write(dev, to_sfx, pos, buf, len) < 0)
4035                         goto sf_merge_error;
4036                 }
4037                 else
4038                 {
4039                     new_l2.pos = 0;
4040                     new_l2.len = new_l2.size = (U16)len;
4041                 }
4042 
4043                 /* Release space occupied by old `to' entry */
4044                 cckd_rel_space (dev, (off_t)to_l2[j].pos, (int)to_l2[j].len,
4045                                                           (int)to_l2[j].size);
4046 
4047                 /* Update `to' l2 table entry */
4048                 l2updated = 1;
4049                 to_l2[j].pos = new_l2.pos;
4050                 to_l2[j].len = new_l2.len;
4051                 to_l2[j].size = new_l2.size;
4052             } /* for each level 2 table entry */
4053 
4054             /* Update the `to' level 2 table */
4055             if (l2updated)
4056             {
4057                 l2updated = 0;
4058                 pos = (off_t)cckd->l1[to_sfx][i];
4059                 if (memcmp (&to_l2, &empty_l2[fix], CCKD_L2TAB_SIZE) == 0)
4060                 {
4061                     cckd_rel_space (dev, pos, CCKD_L2TAB_SIZE, CCKD_L2TAB_SIZE);
4062                     pos = 0;
4063                 }
4064                 else
4065                 {
4066                     size = CCKD_L2TAB_SIZE;
4067                     if (pos == 0 || pos == (off_t)0xffffffff)
4068                         if ((pos = cckd_get_space (dev, &size, CCKD_L2SPACE)) < 0)
4069                             goto sf_merge_error;
4070                     if (cckd_write(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE) < 0)
4071                         goto sf_merge_error;
4072                 } /* `to' level 2 table not null */
4073 
4074                 /* Update the level 1 table index */
4075                 cckd->l1[to_sfx][i] = (U32)pos;
4076 
4077                 /* Flush free space */
4078                 cckd_flush_space (dev);
4079 
4080             } /* Update level 2 table */
4081 
4082         } /* For each level 1 table entry */
4083 
4084         /* Validate the merge */
4085         cckd_harden (dev);
4086         cckd_chkdsk (dev, 0);
4087         cckd_read_init (dev);
4088 
4089     } /* if merge */
4090 
4091     /* Remove the old file */
4092     cckd_close (dev, from_sfx);
4093     cckd->l1[from_sfx] = cckd_free (dev, "l1", cckd->l1[from_sfx]);
4094     memset (&cckd->cdevhdr[from_sfx], 0, CCKDDASD_DEVHDR_SIZE);
4095     rc = unlink (cckd_sf_name (dev, from_sfx));
4096 
4097     /* Add the file back if necessary */
4098     if (add) rc = cckd_sf_new (dev) ;
4099 
4100     logmsg (_("HHCCD181I %4.4X shadow file [%d] successfully %s\n"),
4101             dev->devnum, from_sfx, merge ? "merged" : add ? "re-added" : "removed");
4102 
4103 sf_remove_exit:
4104 
4105     /* Re-read the l1 to set l2bounds, l2ok */
4106     cckd_read_l1 (dev);
4107 
4108     release_lock (&cckd->filelock);
4109 
4110     obtain_lock (&cckd->iolock);
4111     cckd_purge_cache (dev); cckd_purge_l2 (dev);
4112     dev->bufcur = dev->cache = -1;
4113     cckd->merging = 0;
4114     if (cckd->iowaiters)
4115         broadcast_condition (&cckd->iocond);
4116     dev->syncio = syncio;
4117     cckd_trace (dev, "merge complete%s\n","");
4118     release_lock (&cckd->iolock);
4119 
4120     cckd_sf_stats (dev);
4121     return NULL;
4122 
4123 sf_merge_error:
4124 
4125     if (trk < 0)
4126         logmsg (_("HHCCD180E %4.4X file[%d] not merged, error during merge\n"),
4127                 dev->devnum, from_sfx);
4128     else
4129         logmsg (_("HHCCD180E %4.4X file[%d] not merged, error processing trk %d\n"),
4130                 dev->devnum, from_sfx, trk);
4131 
4132     if (l2updated && cckd->l1[to_sfx][i] && cckd->l1[to_sfx][i] != 0xffffffff)
4133     {
4134         l2updated = 0;
4135         pos = (off_t)cckd->l1[to_sfx][i];
4136         cckd_write(dev, to_sfx, pos, &to_l2, CCKD_L2TAB_SIZE);
4137     }
4138     cckd_harden(dev);
4139     cckd_chkdsk (dev, 2);
4140     cckd->sfn = from_sfx;
4141     cckd_harden(dev);
4142     cckd_chkdsk (dev, 2);
4143     goto sf_remove_exit;
4144 
4145 } /* end function cckd_sf_remove */
4146 
4147 /*-------------------------------------------------------------------*/
4148 /* Check and compress a shadow file  (sfc)                           */
4149 /*-------------------------------------------------------------------*/
cckd_sf_comp(void * data)4150 void *cckd_sf_comp (void *data)
4151 {
4152 DEVBLK         *dev = data;             /* -> DEVBLK                 */
4153 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4154 int             syncio;                 /* Saved syncio bit          */
4155 int             rc;                     /* Return code               */
4156 
4157     if (dev == NULL)
4158     {
4159     int n = 0;
4160         for (dev=sysblk.firstdev; dev; dev=dev->nextdev)
4161             if (dev->cckd_ext)
4162             {
4163                 logmsg( _("HHCCD207I Compressing device %d:%4.4X\n"),
4164                           SSID_TO_LCSS(dev->ssid), dev->devnum );
4165                 cckd_sf_comp (dev);
4166                 n++;
4167             }
4168         logmsg( _("HHCCD092I %d devices processed\n"), n );
4169         return NULL;
4170     }
4171 
4172     cckd = dev->cckd_ext;
4173     if (!cckd)
4174     {
4175         logmsg (_("HHCCD205W %4.4X device is not a cckd device\n"), dev->devnum);
4176         return NULL;
4177     }
4178 
4179     /* Disable synchronous I/O for the device */
4180     syncio = cckd_disable_syncio(dev);
4181 
4182     /* schedule updated track entries to be written */
4183     obtain_lock (&cckd->iolock);
4184     if (cckd->merging)
4185     {
4186         dev->syncio = syncio;
4187         release_lock (&cckd->iolock);
4188         logmsg (_("HHCCD206W %4.4X file[%d] compress failed, "
4189                   "sf command busy on device\n"),
4190                 dev->devnum,cckd->sfn);
4191         return NULL;
4192     }
4193     cckd->merging = 1;
4194     cckd_flush_cache (dev);
4195     while (cckd->wrpending || cckd->ioactive)
4196     {
4197         cckd->iowaiters++;
4198         wait_condition (&cckd->iocond, &cckd->iolock);
4199         cckd->iowaiters--;
4200         cckd_flush_cache (dev);
4201     }
4202     cckd_purge_cache (dev); cckd_purge_l2 (dev);
4203     dev->bufcur = dev->cache = -1;
4204     release_lock (&cckd->iolock);
4205 
4206     /* obtain control of the file */
4207     obtain_lock (&cckd->filelock);
4208 
4209     /* harden the current file */
4210     cckd_harden (dev);
4211 
4212     /* Call the compress function */
4213     rc = cckd_comp (dev);
4214 
4215     /* Perform initial read */
4216     rc = cckd_read_init (dev);
4217 
4218     release_lock (&cckd->filelock);
4219 
4220     obtain_lock (&cckd->iolock);
4221     cckd->merging = 0;
4222     if (cckd->iowaiters)
4223         broadcast_condition (&cckd->iocond);
4224     dev->syncio = syncio;
4225     release_lock (&cckd->iolock);
4226 
4227     /* Display the shadow file statistics */
4228     cckd_sf_stats (dev);
4229 
4230     return NULL;
4231 } /* end function cckd_sf_comp */
4232 
4233 /*-------------------------------------------------------------------*/
4234 /* Check a shadow file  (sfk)                                        */
4235 /*-------------------------------------------------------------------*/
cckd_sf_chk(void * data)4236 void *cckd_sf_chk (void *data)
4237 {
4238 DEVBLK         *dev = data;             /* -> DEVBLK                 */
4239 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4240 int             syncio;                 /* Saved syncio bit          */
4241 int             rc;                     /* Return code               */
4242 int             level = 2;              /* Check level               */
4243 
4244     if (dev == NULL)
4245     {
4246     int n = 0;
4247         level = cckdblk.sflevel;
4248         cckdblk.sflevel = 0;
4249         for (dev=sysblk.firstdev; dev; dev=dev->nextdev)
4250             if ((cckd = dev->cckd_ext))
4251             {
4252                 logmsg( _("HHCCD207I Checking device %d:%4.4X level %d\n"),
4253                           SSID_TO_LCSS(dev->ssid), dev->devnum, level );
4254                 cckd->sflevel = level;
4255                 cckd_sf_chk (dev);
4256                 n++;
4257             }
4258         logmsg( _("HHCCD092I %d devices processed\n"), n );
4259         return NULL;
4260     }
4261 
4262     cckd = dev->cckd_ext;
4263     if (!cckd)
4264     {
4265         logmsg (_("HHCCD205W %4.4X device is not a cckd device\n"), dev->devnum);
4266         return NULL;
4267     }
4268 
4269     level = cckd->sflevel;
4270     cckd->sflevel = 0;
4271 
4272     /* Disable synchronous I/O for the device */
4273     syncio = cckd_disable_syncio(dev);
4274 
4275     /* schedule updated track entries to be written */
4276     obtain_lock (&cckd->iolock);
4277     if (cckd->merging)
4278     {
4279         dev->syncio = syncio;
4280         release_lock (&cckd->iolock);
4281         logmsg (_("HHCCD206W %4.4X file[%d] check failed, "
4282                   "sf command busy on device\n"),
4283                 dev->devnum,cckd->sfn);
4284         return NULL;
4285     }
4286     cckd->merging = 1;
4287     cckd_flush_cache (dev);
4288     while (cckd->wrpending || cckd->ioactive)
4289     {
4290         cckd->iowaiters++;
4291         wait_condition (&cckd->iocond, &cckd->iolock);
4292         cckd->iowaiters--;
4293         cckd_flush_cache (dev);
4294     }
4295     cckd_purge_cache (dev); cckd_purge_l2 (dev);
4296     dev->bufcur = dev->cache = -1;
4297     release_lock (&cckd->iolock);
4298 
4299     /* obtain control of the file */
4300     obtain_lock (&cckd->filelock);
4301 
4302     /* harden the current file */
4303     cckd_harden (dev);
4304 
4305     /* Call the chkdsk function */
4306     rc = cckd_chkdsk (dev, level);
4307 
4308     /* Perform initial read */
4309     rc = cckd_read_init (dev);
4310 
4311     release_lock (&cckd->filelock);
4312 
4313     obtain_lock (&cckd->iolock);
4314     cckd->merging = 0;
4315     if (cckd->iowaiters)
4316         broadcast_condition (&cckd->iocond);
4317     dev->syncio = syncio;
4318     release_lock (&cckd->iolock);
4319 
4320     /* Display the shadow file statistics */
4321     cckd_sf_stats (dev);
4322 
4323     return NULL;
4324 } /* end function cckd_sf_chk */
4325 
4326 /*-------------------------------------------------------------------*/
4327 /* Display shadow file statistics   (sfd)                            */
4328 /*-------------------------------------------------------------------*/
cckd_sf_stats(void * data)4329 void *cckd_sf_stats (void *data)
4330 {
4331 DEVBLK         *dev = data;             /* -> DEVBLK                 */
4332 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4333 struct stat     st;                     /* File information          */
4334 int             i;                      /* Index                     */
4335 int             rc;                     /* Return code               */
4336 char           *ost[] = {"  ", "ro", "rd", "rw"};
4337 unsigned long long size=0,free=0;       /* Total size, free space    */
4338 int             freenbr=0;              /* Total number free spaces  */
4339 
4340     if (dev == NULL)
4341     {
4342     int n = 0;
4343         for (dev=sysblk.firstdev; dev; dev=dev->nextdev)
4344             if (dev->cckd_ext)
4345             {
4346                 logmsg( _("HHCCD208I Displaying device %d:%4.4X\n"),
4347                           SSID_TO_LCSS(dev->ssid), dev->devnum );
4348                 cckd_sf_stats (dev);
4349                 n++;
4350             }
4351         logmsg( _("HHCCD092I %d devices processed\n"), n );
4352         return NULL;
4353     }
4354 
4355     cckd = dev->cckd_ext;
4356     if (!cckd)
4357     {
4358         logmsg (_("HHCCD209W %4.4X device is not a cckd device\n"));
4359         return NULL;
4360     }
4361 
4362 //  obtain_lock (&cckd->filelock);
4363 
4364     /* Calculate totals */
4365     rc = fstat (cckd->fd[0], &st);
4366     for (i = 0; i <= cckd->sfn; i++)
4367     {
4368         if (!i) size = st.st_size;
4369         else size += cckd->cdevhdr[i].size;
4370         free += cckd->cdevhdr[i].free_total;
4371         freenbr += cckd->cdevhdr[i].free_number;
4372     }
4373 
4374     /* header */
4375     logmsg (_("HHCCD210I           size free  nbr st   reads  writes l2reads    hits switches\n"));
4376     if (cckd->readaheads || cckd->misses)
4377     logmsg (_("HHCCD211I                                                  readaheads   misses\n"));
4378     logmsg (_("HHCCD212I --------------------------------------------------------------------\n"));
4379 
4380     /* total statistics */
4381     logmsg (_("HHCCD213I [*] %10" I64_FMT "d %3" I64_FMT "d%% %4d    %7d %7d %7d %7d  %7d\n"),
4382             size, (free * 100) / size, freenbr,
4383             cckd->totreads, cckd->totwrites, cckd->totl2reads,
4384             cckd->cachehits, cckd->switches);
4385     if (cckd->readaheads || cckd->misses)
4386     logmsg (_("HHCCD214I                                                     %7d  %7d\n"),
4387             cckd->readaheads, cckd->misses);
4388 
4389     /* base file statistics */
4390     logmsg (_("HHCCD215I %s\n"), dev->filename);
4391     logmsg (_("HHCCD216I [0] %10" I64_FMT "d %3" I64_FMT "d%% %4d %s %7d %7d %7d\n"),
4392             (long long)st.st_size,
4393             (long long)((long long)((long long)cckd->cdevhdr[0].free_total * 100) / st.st_size),
4394             cckd->cdevhdr[0].free_number, ost[cckd->open[0]],
4395             cckd->reads[0], cckd->writes[0], cckd->l2reads[0]);
4396 
4397     if (dev->dasdsfn != NULL && CCKD_MAX_SF > 0)
4398         logmsg (_("HHCCD217I %s\n"), cckd_sf_name(dev, -1));
4399 
4400     /* shadow file statistics */
4401     for (i = 1; i <= cckd->sfn; i++)
4402     {
4403         logmsg (_("HHCCD218I [%d] %10" I64_FMT "d %3" I64_FMT "d%% %4d %s %7d %7d %7d\n"),
4404                 i, (long long)cckd->cdevhdr[i].size,
4405                 (long long)((long long)((long long)cckd->cdevhdr[i].free_total * 100) / cckd->cdevhdr[i].size),
4406                 cckd->cdevhdr[i].free_number, ost[cckd->open[i]],
4407                 cckd->reads[i], cckd->writes[i], cckd->l2reads[i]);
4408     }
4409 //  release_lock (&cckd->filelock);
4410     return NULL;
4411 } /* end function cckd_sf_stats */
4412 
4413 /*-------------------------------------------------------------------*/
4414 /* Disable synchronous I/O for a device                              */
4415 /*-------------------------------------------------------------------*/
cckd_disable_syncio(DEVBLK * dev)4416 int cckd_disable_syncio(DEVBLK *dev)
4417 {
4418     if (!dev->syncio) return 0;
4419     obtain_lock(&dev->lock);
4420     while (dev->syncio_active)
4421     {
4422         release_lock(&dev->lock);
4423         usleep(500);
4424         obtain_lock(&dev->lock);
4425     }
4426     dev->syncio = 0;
4427     release_lock(&dev->lock);
4428     cckd_trace (dev, "syncio disabled%s\n","");
4429     return 1;
4430 }
4431 
4432 /*-------------------------------------------------------------------*/
4433 /* Lock/unlock the device chain                                      */
4434 /*-------------------------------------------------------------------*/
cckd_lock_devchain(int flag)4435 void cckd_lock_devchain(int flag)
4436 {
4437 //struct timespec tm;
4438 //struct timeval  now;
4439 //int             timeout;
4440 
4441     obtain_lock(&cckdblk.devlock);
4442     while ((flag && cckdblk.devusers != 0)
4443         || (!flag && cckdblk.devusers < 0))
4444     {
4445 //gettimeofday(&now,NULL);
4446 //tm.tv_sec = now.tv_sec + 2;
4447 //tm.tv_nsec = now.tv_usec * 1000;
4448         cckdblk.devwaiters++;
4449         wait_condition(&cckdblk.devcond, &cckdblk.devlock);
4450 //timeout = timed_wait_condition(&cckdblk.devcond, &cckdblk.devlock, &tm);
4451 //if (timeout) cckd_print_itrace();
4452         cckdblk.devwaiters--;
4453     }
4454     if (flag) cckdblk.devusers--;
4455     else cckdblk.devusers++;
4456     release_lock(&cckdblk.devlock);
4457 }
cckd_unlock_devchain()4458 void cckd_unlock_devchain()
4459 {
4460     obtain_lock(&cckdblk.devlock);
4461     if (cckdblk.devusers < 0) cckdblk.devusers++;
4462     else cckdblk.devusers--;
4463     if (cckdblk.devusers == 0 && cckdblk.devwaiters)
4464         signal_condition(&cckdblk.devcond);
4465     release_lock(&cckdblk.devlock);
4466 }
4467 
4468 /*-------------------------------------------------------------------*/
4469 /* Garbage Collection thread                                         */
4470 /*-------------------------------------------------------------------*/
cckd_gcol()4471 void cckd_gcol()
4472 {
4473 int             gcol;                   /* Identifier                */
4474 int             rc;                     /* Return code               */
4475 DEVBLK         *dev;                    /* -> device block           */
4476 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4477 long long       size, fsiz;             /* File size, free size      */
4478 struct timeval  tv_now;                 /* Time-of-day (as timeval)  */
4479 time_t          tt_now;                 /* Time-of-day (as time_t)   */
4480 struct timespec tm;                     /* Time-of-day to wait       */
4481 int             gc;                     /* Garbage collection state  */
4482 int             gctab[5]= {             /* default gcol parameters   */
4483                            4096,        /* critical  50%   - 100%    */
4484                            2048,        /* severe    25%   -  50%    */
4485                            1024,        /* moderate  12.5% -  25%    */
4486                             512,        /* light      6.3% -  12.5%  */
4487                             256};       /* none       0%   -   6.3%  */
4488 //char *gcstates[] = {"critical","severe","moderate","light","none"};
4489 
4490     obtain_lock (&cckdblk.gclock);
4491     gcol = ++cckdblk.gcs;
4492 
4493     /* Return without messages if too many already started */
4494     if (gcol > cckdblk.gcmax)
4495     {
4496         --cckdblk.gcs;
4497         release_lock (&cckdblk.gclock);
4498         return;
4499     }
4500 
4501     if (!cckdblk.batch)
4502     {
4503         logmsg (_("HHCCD003I Garbage collector thread started: tid="TIDPAT", pid=%d \n"),
4504               thread_id(), getpid());
4505     }
4506 
4507     while (gcol <= cckdblk.gcmax)
4508     {
4509         cckd_lock_devchain(0);
4510         /* Perform collection on each device */
4511         for (dev = cckdblk.dev1st; dev; dev = cckd->devnext)
4512         {
4513             cckd = dev->cckd_ext;
4514             obtain_lock (&cckd->iolock);
4515 
4516             /* Bypass if merging or stopping */
4517             if (cckd->merging || cckd->stopping)
4518             {
4519                 release_lock (&cckd->iolock);
4520                 continue;
4521             }
4522 
4523             /* Bypass if not opened read-write */
4524             if (cckd->open[cckd->sfn] != CCKD_OPEN_RW)
4525             {
4526                 release_lock (&cckd->iolock);
4527                 continue;
4528             }
4529 
4530             /* Free newbuf if it hasn't been used */
4531             if (!cckd->ioactive && !cckd->bufused && cckd->newbuf)
4532                 cckd->newbuf = cckd_free (dev, "newbuf", cckd->newbuf);
4533             cckd->bufused = 0;
4534 
4535             /* If OPENED bit not on then flush if updated */
4536             if (!(cckd->cdevhdr[cckd->sfn].options & CCKD_OPENED))
4537             {
4538                 if (cckd->updated) cckd_flush_cache (dev);
4539                 release_lock (&cckd->iolock);
4540                 continue;
4541             }
4542 
4543             /* Determine garbage state */
4544             size = (long long)cckd->cdevhdr[cckd->sfn].size;
4545             fsiz = (long long)cckd->cdevhdr[cckd->sfn].free_total;
4546             if      (fsiz >= (size = size/2)) gc = 0;
4547             else if (fsiz >= (size = size/2)) gc = 1;
4548             else if (fsiz >= (size = size/2)) gc = 2;
4549             else if (fsiz >= (size = size/2)) gc = 3;
4550             else gc = 4;
4551 
4552             /* Adjust the state based on the number of free spaces */
4553             if (cckd->cdevhdr[cckd->sfn].free_number >  800 && gc > 0) gc--;
4554             if (cckd->cdevhdr[cckd->sfn].free_number > 1800 && gc > 0) gc--;
4555             if (cckd->cdevhdr[cckd->sfn].free_number > 3000)           gc = 0;
4556 
4557             /* Set the size */
4558             if (cckdblk.gcparm > 0) size = gctab[gc] << cckdblk.gcparm;
4559             else if (cckdblk.gcparm < 0) size = gctab[gc] >> abs(cckdblk.gcparm);
4560             else size = gctab[gc];
4561             if (size > cckd->cdevhdr[cckd->sfn].used >> 10)
4562                 size = cckd->cdevhdr[cckd->sfn].used >> 10;
4563             if (size < 64) size = 64;
4564 
4565             release_lock (&cckd->iolock);
4566 
4567             /* Call the garbage collector */
4568             cckd_gc_percolate (dev, (unsigned int)size);
4569 
4570             /* Schedule any updated tracks to be written */
4571             obtain_lock (&cckd->iolock);
4572             cckd_flush_cache (dev);
4573             while (cckdblk.fsync && cckd->wrpending)
4574             {
4575                 cckd->iowaiters++;
4576                 wait_condition (&cckd->iocond, &cckd->iolock);
4577                 cckd->iowaiters--;
4578             }
4579             release_lock (&cckd->iolock);
4580 
4581             /* Sync the file */
4582             if (cckdblk.fsync && cckd->lastsync + 10 <= tv_now.tv_sec)
4583             {
4584                 obtain_lock (&cckd->filelock);
4585                 rc = fdatasync (cckd->fd[cckd->sfn]);
4586                 cckd->lastsync = tv_now.tv_sec;
4587                 release_lock (&cckd->filelock);
4588             }
4589 
4590             /* Flush the free space */
4591             if (cckd->cdevhdr[cckd->sfn].free_number)
4592             {
4593                 obtain_lock (&cckd->filelock);
4594                 cckd_flush_space (dev);
4595                 release_lock (&cckd->filelock);
4596             }
4597 
4598         } /* for each cckd device */
4599         cckd_unlock_devchain();
4600 
4601         /* wait a bit */
4602         gettimeofday (&tv_now, NULL);
4603         tm.tv_sec = tv_now.tv_sec + cckdblk.gcwait;
4604         tm.tv_nsec = tv_now.tv_usec * 1000;
4605         tt_now = tv_now.tv_sec + ((tv_now.tv_usec + 500000)/1000000);
4606         cckd_trace (dev, "gcol wait %d seconds at %s",
4607                     cckdblk.gcwait, ctime (&tt_now));
4608         timed_wait_condition (&cckdblk.gccond, &cckdblk.gclock, &tm);
4609     }
4610 
4611     if (!cckdblk.batch)
4612     logmsg (_("HHCCD013I Garbage collector thread stopping: tid="TIDPAT", pid=%d\n"),
4613             thread_id(), getpid());
4614 
4615     cckdblk.gcs--;
4616     if (!cckdblk.gcs) signal_condition (&cckdblk.termcond);
4617     release_lock (&cckdblk.gclock);
4618 } /* end thread cckd_gcol */
4619 
4620 /*-------------------------------------------------------------------*/
4621 /* Garbage Collection -- Percolate algorithm                         */
4622 /*-------------------------------------------------------------------*/
cckd_gc_percolate(DEVBLK * dev,unsigned int size)4623 int cckd_gc_percolate(DEVBLK *dev, unsigned int size)
4624 {
4625 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4626 int             rc;                     /* Return code               */
4627 size_t          moved = 0;              /* Space moved               */
4628 int             after = 0, a;           /* New space after old       */
4629 int             sfx;                    /* File index                */
4630 int             i, j, l;                /* Indexes                   */
4631 int             flags;                  /* Write trkimg flags        */
4632 off_t           fpos, upos;             /* File offsets              */
4633 size_t          flen, ulen, len;        /* Lengths                   */
4634 int             trk;                    /* Track number              */
4635 int             l1x,l2x;                /* Table Indexes             */
4636 CCKD_L2ENT      l2;                     /* Copied level 2 entry      */
4637 BYTE            buf[256*1024];          /* Buffer                    */
4638 
4639     cckd = dev->cckd_ext;
4640     size = size << 10;
4641 
4642     /* Debug */
4643     if (cckdblk.itracen)
4644     {
4645         cckd_trace (dev, "gcperc size %d 1st 0x%x nbr %d largest %u\n",
4646                     size, cckd->cdevhdr[cckd->sfn].free,
4647                     cckd->cdevhdr[cckd->sfn].free_number,
4648                     cckd->cdevhdr[cckd->sfn].free_largest);
4649         fpos = (off_t)cckd->cdevhdr[cckd->sfn].free;
4650         for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
4651         {
4652             cckd_trace (dev, "gcperc free[%4d]:%8.8x end %8.8x len %10d%cpend %d\n",
4653                         i,(int)fpos,(int)(fpos+cckd->free[i].len),(int)cckd->free[i].len,
4654                         fpos+(int)cckd->free[i].len == (int)cckd->free[i].pos ?
4655                                 '*' : ' ',cckd->free[i].pending);
4656             fpos = cckd->free[i].pos;
4657         }
4658     }
4659 
4660     if (!cckd->l2ok)
4661         cckd_gc_l2(dev, buf);
4662 
4663     /* garbage collection cycle */
4664     while (moved < size && after < 4)
4665     {
4666         obtain_lock (&cckd->filelock);
4667         sfx = cckd->sfn;
4668 
4669         /* Exit if no more free space */
4670         if (cckd->cdevhdr[sfx].free_total == 0)
4671         {
4672             release_lock (&cckd->filelock);
4673             return moved;
4674         }
4675 
4676         /* Make sure the free space chain is built */
4677         if (!cckd->free) cckd_read_fsp (dev);
4678 
4679         /* Find a space to start with */
4680         l = -1;
4681         upos = ulen = flen = 0;
4682         fpos = cckd->cdevhdr[sfx].free;
4683 
4684         /* First non-pending free space */
4685         for (i = cckd->free1st; i >= 0; i = cckd->free[i].next)
4686         {
4687             if (!cckd->free[i].pending)
4688             {
4689                 flen += cckd->free[i].len;
4690                 break;
4691             }
4692             fpos = cckd->free[i].pos;
4693         }
4694 
4695         /* Continue to largest if non-zero `after' */
4696         for ( ; i >= 0 && after; i = cckd->free[i].next)
4697         {
4698             l = i;
4699             if (!cckd->free[i].pending) flen += cckd->free[i].len;
4700             if (cckd->free[i].len == cckd->cdevhdr[sfx].free_largest)
4701                 break;
4702             fpos = cckd->free[i].pos;
4703         }
4704 
4705         /* Skip following free spaces */
4706         for ( ; i >= 0; i = cckd->free[i].next)
4707         {
4708             if (!cckd->free[i].pending) flen += cckd->free[i].len;
4709             if (fpos + cckd->free[i].len != cckd->free[i].pos) break;
4710             fpos = cckd->free[i].pos;
4711         }
4712 
4713         /* Space preceding largest if largest is at the end */
4714         if (i < 0 && l >= 0)
4715         {
4716             if (!cckd->free[l].pending) flen -= cckd->free[i].len;
4717             for (i = cckd->free[l].prev; i >= 0; i = cckd->free[i].prev)
4718             {
4719                 fpos = cckd->free[i].prev >= 0
4720                      ? cckd->free[cckd->free[i].prev].pos
4721                      : cckd->cdevhdr[sfx].free;
4722                 if (fpos + cckd->free[i].len < cckd->free[i].pos) break;
4723                 if (!cckd->free[i].pending) flen -= cckd->free[i].len;
4724             }
4725         }
4726 
4727         /* Calculate the offset/length of the used space.
4728          * If only imbedded free space is left, then start
4729          * with the first used space that is not an l2 table.
4730          */
4731         if (i >= 0)
4732         {
4733             upos = fpos + cckd->free[i].len;
4734             ulen = (cckd->free[i].pos ? cckd->free[i].pos : cckd->cdevhdr[sfx].size) - upos;
4735         }
4736         else if (!cckd->cdevhdr[sfx].free_number && cckd->cdevhdr[sfx].free_imbed)
4737         {
4738             upos = (off_t)(CCKD_L1TAB_POS + cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE);
4739             while (1)
4740             {
4741                 for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++)
4742                     if (cckd->l1[sfx][i] == (U32)upos)
4743                        break;
4744                 if (i >= cckd->cdevhdr[sfx].numl1tab)
4745                     break;
4746                 upos += CCKD_L2TAB_SIZE;
4747             }
4748             ulen = cckd->cdevhdr[sfx].size - upos;
4749         }
4750 
4751         /* Return if no applicable used space */
4752         if (ulen == 0)
4753         {
4754             cckd_trace (dev, "gcperc no applicable space, moved %ld\n",(long)moved);
4755             release_lock (&cckd->filelock);
4756             return moved;
4757         }
4758 
4759         /* Reduce ulen size to minimize `after' relocations */
4760         if (ulen > flen + 65536) ulen = flen + 65536;
4761         if (ulen > sizeof(buf))  ulen = sizeof(buf);
4762 
4763         cckd_trace (dev, "gcperc selected space 0x%" I64_FMT "x len %ld\n",
4764                     (long long)upos, (long)ulen);
4765 
4766         if (cckd_read (dev, sfx, upos, buf, ulen) < 0)
4767             goto cckd_gc_perc_error;
4768 
4769         /* Process each space in the buffer */
4770         flags = cckd->cdevhdr[sfx].free_number < 100 ? CCKD_SIZE_EXACT : CCKD_SIZE_ANY;
4771         for (i = a = 0; i + CKDDASD_TRKHDR_SIZE <= (int)ulen; i += len)
4772         {
4773             /* Check for level 2 table */
4774             for (j = 0; j < cckd->cdevhdr[sfx].numl1tab; j++)
4775                 if (cckd->l1[sfx][j] == (U32)(upos + i)) break;
4776 
4777             if (j < cckd->cdevhdr[sfx].numl1tab)
4778             {
4779                 /* Moving a level 2 table */
4780                 len = CCKD_L2TAB_SIZE;
4781                 if (i + len > ulen) break;
4782                 cckd_trace (dev, "gcperc move l2tab[%d] at pos 0x%" I64_FMT "x len %ld\n",
4783                             j, (unsigned long long)(upos + i), (long)len);
4784 
4785                 /* Make the level 2 table active */
4786                 if (cckd_read_l2 (dev, sfx, j) < 0)
4787                     goto cckd_gc_perc_error;
4788 
4789                 /* Write the level 2 table */
4790                 if (cckd_write_l2 (dev) < 0)
4791                     goto cckd_gc_perc_error;
4792             }
4793             else
4794             {
4795                 /* Moving a track image */
4796                 if ((trk = cckd_cchh (dev, buf + i, -1)) < 0)
4797                     goto cckd_gc_perc_space_error;
4798 
4799                 l1x = trk >> 8;
4800                 l2x = trk & 0xff;
4801 
4802                 /* Read the lookup entry for the track */
4803                 if (cckd_read_l2ent (dev, &l2, trk) < 0)
4804                     goto cckd_gc_perc_error;
4805                 if (l2.pos != (U32)(upos + i))
4806                     goto cckd_gc_perc_space_error;
4807                 len = (int)l2.size;
4808                 if (i + l2.len > (int)ulen) break;
4809 
4810                 cckd_trace (dev, "gcperc move trk %d at pos 0x%" I64_FMT "x len %d\n",
4811                             trk, (long long)(upos + i), (int)l2.len);
4812 
4813                 /* Relocate the track image somewhere else */
4814                 if ((rc = cckd_write_trkimg (dev, buf + i, (int)l2.len, trk, flags)) < 0)
4815                     goto cckd_gc_perc_error;
4816                 a += rc;
4817             }
4818         } /* for each space in the used space */
4819 
4820         /* Set `after' to 1 if first time space was relocated after */
4821         after += after ? a : (a > 0);
4822         moved += i;
4823 
4824         cckdblk.stats_gcolmoves++;
4825         cckdblk.stats_gcolbytes += i;
4826 
4827         release_lock (&cckd->filelock);
4828 
4829     } /* while (moved < size) */
4830 
4831     cckd_trace (dev, "gcperc moved %ld 1st 0x%x nbr %d\n", (long)moved,
4832                 cckd->cdevhdr[cckd->sfn].free,cckd->cdevhdr[cckd->sfn].free_number);
4833     return moved;
4834 
4835 cckd_gc_perc_space_error:
4836 
4837     logmsg (_("HHCCD190E %4.4X file[%d] offset 0x%" I64_FMT "x unknown space: "
4838               "%2.2x%2.2x%2.2x%2.2x%2.2x\n"),
4839             dev->devnum,cckd->sfn,(long long)(upos + i),
4840             buf[i], buf[i+1],buf[i+2], buf[i+3], buf[i+4]);
4841     cckd->cdevhdr[cckd->sfn].options |= CCKD_SPERRS;
4842     cckd_print_itrace();
4843 
4844 cckd_gc_perc_error:
4845 
4846     cckd_trace (dev, "gcperc exiting due to error, moved %ld\n", (long)moved);
4847     release_lock (&cckd->filelock);
4848     return moved;
4849 
4850 } /* end function cckd_gc_percolate */
4851 
4852 /*-------------------------------------------------------------------*/
4853 /* Garbage Collection -- Reposition level 2 tables                   */
4854 /*                                                                   */
4855 /* General idea is to relocate all level 2 tables as close to the    */
4856 /* beginning of the file as possible.  This can help speed up, for   */
4857 /* example, chkdsk processing.                                       */
4858 /*                                                                   */
4859 /* If any level 2 tables reside outside of the bounds (that is, if   */
4860 /* any level 2 table could be moved closer to the beginning of the   */
4861 /* file) then first we relocate all track images within the bounds.  */
4862 /* Note that cckd_get_space will not allocate space within the       */
4863 /* the bounds for track images.  Next we try to relocate all level 2 */
4864 /* tables outside the bounds.  This may take a few iterations for    */
4865 /* the freed space within the bounds to become non-pending.          */
4866 /*                                                                   */
4867 /* The bounds can change as level 2 tables are added or removed.     */
4868 /* cckd_read_l1 sets the bounds and they are adjusted by             */
4869 /* cckd_write_l2.                                                    */
4870 /*-------------------------------------------------------------------*/
cckd_gc_l2(DEVBLK * dev,BYTE * buf)4871 int cckd_gc_l2(DEVBLK *dev, BYTE *buf)
4872 {
4873 CCKDDASD_EXT   *cckd;                   /* -> cckd extension         */
4874 int             sfx;                    /* Shadow file index         */
4875 int             i, j;                   /* Work variables            */
4876 int             trk;                    /* Track number              */
4877 int             len;                    /* Track length              */
4878 off_t           pos, fpos;              /* File offsets              */
4879 
4880     cckd = dev->cckd_ext;
4881 
4882     obtain_lock (&cckd->filelock);
4883     sfx = cckd->sfn;
4884 
4885     if (cckd->l2ok || cckd->cdevhdr[cckd->sfn].free_total == 0)
4886         goto cckd_gc_l2_exit;
4887 
4888     /* Find any level 2 table out of bounds */
4889     for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++)
4890         if (cckd->l1[sfx][i] != 0 && cckd->l1[sfx][i] != 0xffffffff
4891          && cckd->l2bounds - CCKD_L2TAB_SIZE < (off_t)cckd->l1[sfx][i])
4892             break;
4893 
4894     /* Return OK if no l2 tables out of bounds */
4895     if (i >= cckd->cdevhdr[sfx].numl1tab)
4896         goto cckd_gc_l2_exit_ok;
4897 
4898     /* Relocate all track images within the bounds */
4899     pos = CCKD_L1TAB_POS + (cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE);
4900     i = cckd->free1st;
4901     fpos = (off_t)cckd->cdevhdr[sfx].free;
4902     while (pos < cckd->l2bounds)
4903     {
4904         if (i >= 0 && pos == fpos)
4905         {
4906             pos += cckd->free[i].len;
4907             fpos = (off_t)cckd->free[i].pos;
4908             i = cckd->free[i].next;
4909             j = 0;
4910         }
4911         else
4912         {
4913             for (j = 0; j < cckd->cdevhdr[sfx].numl1tab; j++)
4914                 if (pos == (off_t)cckd->l1[sfx][j])
4915                 {
4916                     pos += CCKD_L2TAB_SIZE;
4917                     break;
4918                 }
4919         }
4920         if (j >= cckd->cdevhdr[sfx].numl1tab)
4921         {
4922             /* Found a track to relocate */
4923             if (cckd_read (dev, sfx, pos, buf, CKDDASD_TRKHDR_SIZE) < 0)
4924                 goto cckd_gc_l2_exit;
4925             if ((trk = cckd_cchh (dev, buf, -1)) < 0)
4926                 goto cckd_gc_l2_exit;
4927             cckd_trace (dev, "gc_l2 relocate trk[%d] offset 0x%x\n", trk, pos);
4928             if ((len = cckd_read_trkimg (dev, buf, trk, NULL)) < 0)
4929                goto cckd_gc_l2_exit;
4930             if (cckd_write_trkimg (dev, buf, len, trk, CCKD_SIZE_EXACT) < 0)
4931                goto cckd_gc_l2_exit;
4932             /* Start over */
4933             pos = CCKD_L1TAB_POS + (cckd->cdevhdr[sfx].numl1tab * CCKD_L1ENT_SIZE);
4934             i = cckd->free1st;
4935             fpos = (off_t)cckd->cdevhdr[sfx].free;
4936         }
4937     }
4938 
4939     do {
4940         /* Find a level 2 table to relocate */
4941         i = cckd->free1st;
4942         fpos = (off_t)cckd->cdevhdr[sfx].free;
4943         cckd_trace (dev, "gc_l2 first free[%d] pos 0x%x len %d pending %d\n",
4944                     i, (int)fpos, i >= 0 ? (int)cckd->free[i].len : -1,
4945                     i >= 0 ? cckd->free[i].pending : -1);
4946         if (i < 0 || fpos >= cckd->l2bounds || cckd->free[i].pending)
4947             goto cckd_gc_l2_exit;
4948 
4949         if (cckd->free[i].len < CCKD_L2TAB_SIZE
4950          || (cckd->free[i].len != CCKD_L2TAB_SIZE
4951           && cckd->free[i].len < CCKD_L2TAB_SIZE + CCKD_FREEBLK_SIZE
4952             )
4953            )
4954         {
4955             for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++)
4956                 if (fpos + cckd->free[i].len == (off_t)cckd->l1[sfx][i])
4957                     break;
4958         }
4959         else
4960         {
4961             for (i = 0; i < cckd->cdevhdr[sfx].numl1tab; i++)
4962                 if (cckd->l2bounds - CCKD_L2TAB_SIZE < (off_t)cckd->l1[sfx][i]
4963                  && cckd->l1[sfx][i] != 0xffffffff)
4964                     break;
4965         }
4966 
4967         if (i < cckd->cdevhdr[sfx].numl1tab)
4968         {
4969             cckd_trace (dev, "gc_l2 relocate l2[%d] pos 0x%x\n",
4970                         i, cckd->l1[sfx][i]);
4971             if (cckd_read_l2 (dev, sfx, i) < 0)
4972                 goto cckd_gc_l2_exit;
4973             if (cckd_write_l2 (dev) < 0)
4974                 goto cckd_gc_l2_exit;
4975         }
4976     } while (i < cckd->cdevhdr[sfx].numl1tab);
4977 
4978 cckd_gc_l2_exit:
4979     release_lock (&cckd->filelock);
4980     return 0;
4981 
4982 cckd_gc_l2_exit_ok:
4983     cckd_trace (dev, "gc_l2 ok%s\n", "");
4984     cckd->l2ok = 1;
4985     goto cckd_gc_l2_exit;
4986 }
4987 
4988 /*-------------------------------------------------------------------*/
4989 /* Find device by devnum                                             */
4990 /*-------------------------------------------------------------------*/
cckd_find_device_by_devnum(U16 devnum)4991 DEVBLK *cckd_find_device_by_devnum (U16 devnum)
4992 {
4993 DEVBLK       *dev;
4994 CCKDDASD_EXT *cckd;
4995 
4996     cckd_lock_devchain (0);
4997     for (dev = cckdblk.dev1st; dev; dev = cckd->devnext)
4998     {
4999         if (dev->devnum == devnum) break;
5000         cckd = dev->cckd_ext;
5001     }
5002     cckd_unlock_devchain ();
5003     return dev;
5004 } /* end function cckd_find_device_by_devnum */
5005 
5006 /*-------------------------------------------------------------------*/
5007 /* Uncompress a track image                                          */
5008 /*-------------------------------------------------------------------*/
cckd_uncompress(DEVBLK * dev,BYTE * from,int len,int maxlen,int trk)5009 BYTE *cckd_uncompress (DEVBLK *dev, BYTE *from, int len, int maxlen,
5010                        int trk)
5011 {
5012 CCKDDASD_EXT   *cckd;
5013 BYTE           *to = NULL;                /* Uncompressed buffer     */
5014 int             newlen;                   /* Uncompressed length     */
5015 BYTE            comp;                     /* Compression type        */
5016 static char    *compress[] = {"none", "zlib", "bzip2"};
5017 
5018     cckd = dev->cckd_ext;
5019 
5020     cckd_trace (dev, "uncompress comp %d len %d maxlen %d trk %d\n",
5021                 from[0] & CCKD_COMPRESS_MASK, len, maxlen, trk);
5022 
5023     /* Extract compression type */
5024     comp = (from[0] & CCKD_COMPRESS_MASK);
5025 
5026     /* Get a buffer to uncompress into */
5027     if (comp != CCKD_COMPRESS_NONE && cckd->newbuf == NULL)
5028     {
5029         cckd->newbuf = cckd_malloc (dev, "newbuf", maxlen);
5030         if (cckd->newbuf == NULL)
5031             return NULL;
5032     }
5033 
5034     /* Uncompress the track image */
5035     switch (comp) {
5036 
5037     case CCKD_COMPRESS_NONE:
5038         newlen = cckd_trklen (dev, from);
5039         to = from;
5040         break;
5041     case CCKD_COMPRESS_ZLIB:
5042         to = cckd->newbuf;
5043         newlen = cckd_uncompress_zlib (dev, to, from, len, maxlen);
5044         break;
5045     case CCKD_COMPRESS_BZIP2:
5046         to = cckd->newbuf;
5047         newlen = cckd_uncompress_bzip2 (dev, to, from, len, maxlen);
5048         break;
5049     default:
5050         newlen = -1;
5051         break;
5052     }
5053 
5054     /* Validate the uncompressed track image */
5055     newlen = cckd_validate (dev, to, trk, newlen);
5056 
5057     /* Return if successful */
5058     if (newlen > 0)
5059     {
5060         if (to != from)
5061         {
5062             cckd->newbuf = from;
5063             cckd->bufused = 1;
5064         }
5065         return to;
5066     }
5067 
5068     /* Get a buffer now if we haven't gotten one */
5069     if (cckd->newbuf == NULL)
5070     {
5071         cckd->newbuf = cckd_malloc (dev, "newbuf2", maxlen);
5072         if (cckd->newbuf == NULL)
5073             return NULL;
5074     }
5075 
5076     /* Try each uncompression routine in turn */
5077 
5078     /* uncompressed */
5079     newlen = cckd_trklen (dev, from);
5080     newlen = cckd_validate (dev, from, trk, newlen);
5081     if (newlen > 0)
5082         return from;
5083 
5084     /* zlib compression */
5085     to = cckd->newbuf;
5086     newlen = cckd_uncompress_zlib (dev, to, from, len, maxlen);
5087     newlen = cckd_validate (dev, to, trk, newlen);
5088     if (newlen > 0)
5089     {
5090         cckd->newbuf = from;
5091         cckd->bufused = 1;
5092         return to;
5093     }
5094 
5095     /* bzip2 compression */
5096     to = cckd->newbuf;
5097     newlen = cckd_uncompress_bzip2 (dev, to, from, len, maxlen);
5098     newlen = cckd_validate (dev, to, trk, newlen);
5099     if (newlen > 0)
5100     {
5101         cckd->newbuf = from;
5102         cckd->bufused = 1;
5103         return to;
5104     }
5105 
5106     /* Unable to uncompress */
5107     logmsg (_("HHCCD193E %4.4X file[%d] uncompress error trk %d: %2.2x%2.2x%2.2x%2.2x%2.2x\n"),
5108             dev->devnum, cckd->sfn, trk, from[0], from[1], from[2], from[3], from[4]);
5109     if (comp & ~cckdblk.comps)
5110         logmsg (_("HHCCD194E %4.4X file[%d] %s compression not supported\n"),
5111                 dev->devnum, cckd->sfn, compress[comp]);
5112     return NULL;
5113 }
5114 
cckd_uncompress_zlib(DEVBLK * dev,BYTE * to,BYTE * from,int len,int maxlen)5115 int cckd_uncompress_zlib (DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen)
5116 {
5117 #if defined(HAVE_LIBZ)
5118 unsigned long newlen;
5119 int rc;
5120 
5121     UNREFERENCED(dev);
5122     memcpy (to, from, CKDDASD_TRKHDR_SIZE);
5123     newlen = maxlen - CKDDASD_TRKHDR_SIZE;
5124     rc = uncompress(&to[CKDDASD_TRKHDR_SIZE], &newlen,
5125                 &from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE);
5126     if (rc == Z_OK)
5127     {
5128         newlen += CKDDASD_TRKHDR_SIZE;
5129         to[0] = 0;
5130     }
5131     else
5132         newlen = -1;
5133 
5134     cckd_trace (dev, "uncompress zlib newlen %d rc %d\n",(int)newlen,rc);
5135 
5136     return (int)newlen;
5137 #else
5138     UNREFERENCED(dev);
5139     UNREFERENCED(to);
5140     UNREFERENCED(from);
5141     UNREFERENCED(len);
5142     UNREFERENCED(maxlen);
5143     return -1;
5144 #endif
5145 }
cckd_uncompress_bzip2(DEVBLK * dev,BYTE * to,BYTE * from,int len,int maxlen)5146 int cckd_uncompress_bzip2 (DEVBLK *dev, BYTE *to, BYTE *from, int len, int maxlen)
5147 {
5148 #if defined(CCKD_BZIP2)
5149 unsigned int newlen;
5150 int rc;
5151 
5152     UNREFERENCED(dev);
5153     memcpy (to, from, CKDDASD_TRKHDR_SIZE);
5154     newlen = maxlen - CKDDASD_TRKHDR_SIZE;
5155     rc = BZ2_bzBuffToBuffDecompress (
5156                 (void *)&to[CKDDASD_TRKHDR_SIZE], &newlen,
5157                 (void *)&from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE,
5158                 0, 0);
5159     if (rc == BZ_OK)
5160     {
5161         newlen += CKDDASD_TRKHDR_SIZE;
5162         to[0] = 0;
5163     }
5164     else
5165         newlen = -1;
5166 
5167     cckd_trace (dev, "uncompress bz2 newlen %d rc %d\n",newlen,rc);
5168 
5169     return (int)newlen;
5170 #else
5171     UNREFERENCED(dev);
5172     UNREFERENCED(to);
5173     UNREFERENCED(from);
5174     UNREFERENCED(len);
5175     UNREFERENCED(maxlen);
5176     return -1;
5177 #endif
5178 }
5179 
5180 /*-------------------------------------------------------------------*/
5181 /* Compress a track image                                            */
5182 /*-------------------------------------------------------------------*/
cckd_compress(DEVBLK * dev,BYTE ** to,BYTE * from,int len,int comp,int parm)5183 int cckd_compress (DEVBLK *dev, BYTE **to, BYTE *from, int len,
5184                    int comp, int parm)
5185 {
5186 int newlen;
5187 
5188     switch (comp) {
5189     case CCKD_COMPRESS_NONE:
5190         newlen = cckd_compress_none (dev, to, from, len, parm);
5191         break;
5192     case CCKD_COMPRESS_ZLIB:
5193         newlen = cckd_compress_zlib (dev, to, from, len, parm);
5194         break;
5195     case CCKD_COMPRESS_BZIP2:
5196         newlen = cckd_compress_bzip2 (dev, to, from, len, parm);
5197         break;
5198     default:
5199         newlen = cckd_compress_bzip2 (dev, to, from, len, parm);
5200         break;
5201     }
5202     return newlen;
5203 }
cckd_compress_none(DEVBLK * dev,BYTE ** to,BYTE * from,int len,int parm)5204 int cckd_compress_none (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm)
5205 {
5206     UNREFERENCED(dev);
5207     UNREFERENCED(parm);
5208     *to = from;
5209     from[0] = CCKD_COMPRESS_NONE;
5210     return len;
5211 }
cckd_compress_zlib(DEVBLK * dev,BYTE ** to,BYTE * from,int len,int parm)5212 int cckd_compress_zlib (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm)
5213 {
5214 #if defined(HAVE_LIBZ)
5215 unsigned long newlen;
5216 int rc;
5217 BYTE *buf;
5218 
5219     UNREFERENCED(dev);
5220     buf = *to;
5221     from[0] = CCKD_COMPRESS_NONE;
5222     memcpy (buf, from, CKDDASD_TRKHDR_SIZE);
5223     buf[0] = CCKD_COMPRESS_ZLIB;
5224     newlen = 65535 - CKDDASD_TRKHDR_SIZE;
5225     rc = compress2 (&buf[CKDDASD_TRKHDR_SIZE], &newlen,
5226                     &from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE,
5227                     parm);
5228     newlen += CKDDASD_TRKHDR_SIZE;
5229     if (rc != Z_OK || (int)newlen >= len)
5230     {
5231         *to = from;
5232         newlen = len;
5233     }
5234     return (int)newlen;
5235 #else
5236 
5237 #if defined(CCKD_BZIP2)
5238     return cckd_compress_bzip2 (dev, to, from, len, parm);
5239 #else
5240     return cckd_compress_none (dev, to, from, len, parm);
5241 #endif
5242 
5243 #endif
5244 }
cckd_compress_bzip2(DEVBLK * dev,BYTE ** to,BYTE * from,int len,int parm)5245 int cckd_compress_bzip2 (DEVBLK *dev, BYTE **to, BYTE *from, int len, int parm)
5246 {
5247 #if defined(CCKD_BZIP2)
5248 unsigned int newlen;
5249 int rc;
5250 BYTE *buf;
5251 
5252     UNREFERENCED(dev);
5253     buf = *to;
5254     from[0] = CCKD_COMPRESS_NONE;
5255     memcpy (buf, from, CKDDASD_TRKHDR_SIZE);
5256     buf[0] = CCKD_COMPRESS_BZIP2;
5257     newlen = 65535 - CKDDASD_TRKHDR_SIZE;
5258     rc = BZ2_bzBuffToBuffCompress (
5259                     (void *)&buf[CKDDASD_TRKHDR_SIZE], &newlen,
5260                     (void *)&from[CKDDASD_TRKHDR_SIZE], len - CKDDASD_TRKHDR_SIZE,
5261                     parm >= 1 && parm <= 9 ? parm : 5, 0, 0);
5262     newlen += CKDDASD_TRKHDR_SIZE;
5263     if (rc != BZ_OK || newlen >= (unsigned int)len)
5264     {
5265         *to = from;
5266         newlen = len;
5267     }
5268     return newlen;
5269 #else
5270     return cckd_compress_zlib (dev, to, from, len, parm);
5271 #endif
5272 }
5273 
5274 /*-------------------------------------------------------------------*/
5275 /* cckd command help                                                 */
5276 /*-------------------------------------------------------------------*/
cckd_command_help()5277 void cckd_command_help()
5278 {
5279     logmsg ("cckd command parameters:\n"
5280              "help\t\tDisplay help message\n"
5281              "stats\t\tDisplay cckd statistics\n"
5282              "opts\t\tDisplay cckd options\n"
5283              "comp=<n>\t\tOverride compression\t\t(-1 .. 2)\n"
5284              "compparm=<n>\tOverride compression parm\t\t(-1 .. 9)\n"
5285              "ra=<n>\t\tSet number readahead threads\t\t(1 .. 9)\n"
5286              "raq=<n>\t\tSet readahead queue size\t\t(0 .. 16)\n"
5287              "rat=<n>\t\tSet number tracks to read ahead\t\t(0 .. 16)\n"
5288              "wr=<n>\t\tSet number writer threads\t\t(1 .. 9)\n"
5289              "gcint=<n>\tSet garbage collector interval (sec)\t(1 .. 60)\n"
5290              "gcparm=<n>\tSet garbage collector parameter\t\t(-8 .. 8)\n"
5291              "\t\t    (least agressive ... most aggressive)\n"
5292              "nostress=<n>\t1=Disable stress writes\n"
5293              "freepend=<n>\tSet free pending cycles\t\t\t(-1 .. 4)\n"
5294              "fsync=<n>\t1=Enable fsync()\n"
5295              "trace=<n>\tSet trace table size\t\t\t(0 .. 200000)\n"
5296             );
5297 } /* end function cckd_command_help */
5298 
5299 /*-------------------------------------------------------------------*/
5300 /* cckd command stats                                                */
5301 /*-------------------------------------------------------------------*/
cckd_command_opts()5302 void cckd_command_opts()
5303 {
5304     logmsg ("comp=%d,compparm=%d,ra=%d,raq=%d,rat=%d,"
5305              "wr=%d,gcint=%d,gcparm=%d,nostress=%d,\n"
5306              "\tfreepend=%d,fsync=%d,trace=%d,linuxnull=%d\n",
5307              cckdblk.comp == 0xff ? -1 : cckdblk.comp,
5308              cckdblk.compparm, cckdblk.ramax,
5309              cckdblk.ranbr, cckdblk.readaheads,
5310              cckdblk.wrmax, cckdblk.gcwait,
5311              cckdblk.gcparm, cckdblk.nostress, cckdblk.freepend,
5312              cckdblk.fsync, cckdblk.itracen, cckdblk.linuxnull);
5313 } /* end function cckd_command_opts */
5314 
5315 /*-------------------------------------------------------------------*/
5316 /* cckd command stats                                                */
5317 /*-------------------------------------------------------------------*/
cckd_command_stats()5318 void cckd_command_stats()
5319 {
5320     logmsg("reads....%10" I64_FMT "d Kbytes...%10" I64_FMT "d writes...%10" I64_FMT "d Kbytes...%10" I64_FMT "d\n"
5321             "readaheads%9" I64_FMT "d misses...%10" I64_FMT "d syncios..%10" I64_FMT "d misses...%10" I64_FMT "d\n"
5322             "switches.%10" I64_FMT "d l2 reads.%10" I64_FMT "d              stress writes...%10" I64_FMT "d\n"
5323             "cachehits%10" I64_FMT "d misses...%10" I64_FMT "d l2 hits..%10" I64_FMT "d misses...%10" I64_FMT "d\n"
5324             "waits                                   i/o......%10" I64_FMT "d cache....%10" I64_FMT "d\n"
5325             "garbage collector   moves....%10" I64_FMT "d Kbytes...%10" I64_FMT "d\n",
5326             cckdblk.stats_reads, cckdblk.stats_readbytes >> 10,
5327             cckdblk.stats_writes, cckdblk.stats_writebytes >> 10,
5328             cckdblk.stats_readaheads, cckdblk.stats_readaheadmisses,
5329             cckdblk.stats_syncios, cckdblk.stats_synciomisses,
5330             cckdblk.stats_switches, cckdblk.stats_l2reads,
5331             cckdblk.stats_stresswrites,
5332             cckdblk.stats_cachehits, cckdblk.stats_cachemisses,
5333             cckdblk.stats_l2cachehits, cckdblk.stats_l2cachemisses,
5334             cckdblk.stats_iowaits, cckdblk.stats_cachewaits,
5335             cckdblk.stats_gcolmoves, cckdblk.stats_gcolbytes >> 10);
5336 } /* end function cckd_command_stats */
5337 
5338 /*-------------------------------------------------------------------*/
5339 /* cckd command debug                                                */
5340 /*-------------------------------------------------------------------*/
cckd_command_debug()5341 void cckd_command_debug()
5342 {
5343 }
5344 
5345 /*-------------------------------------------------------------------*/
5346 /* cckd command processor                                            */
5347 /*-------------------------------------------------------------------*/
cckd_command(char * op,int cmd)5348 DLL_EXPORT int cckd_command(char *op, int cmd)
5349 {
5350 char  *kw, *p, c = '\0', buf[256];
5351 int   val, opts = 0;
5352 
5353     /* Display help for null operand */
5354     if (op == NULL)
5355     {
5356         if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)) == 0 && cmd)
5357             cckd_command_help();
5358         return 0;
5359     }
5360 
5361     strcpy(buf, op);
5362     op = buf;
5363 
5364     /* Initialize the global cckd block if necessary */
5365     if (memcmp (&cckdblk.id, "CCKDBLK ", sizeof(cckdblk.id)))
5366         cckddasd_init (0, NULL);
5367 
5368     while (op)
5369     {
5370         /* Operands are delimited by commas */
5371         kw = op;
5372         op = strchr (op, ',');
5373         if (op) *op++ = '\0';
5374 
5375         /* Check for keyword = value */
5376         if ((p = strchr (kw, '=')))
5377         {
5378             *p++ = '\0';
5379             sscanf (p, "%d%c", &val, &c);
5380         }
5381         else val = -77;
5382 
5383         /* Parse the keyword */
5384         if (strcasecmp (kw, "help") == 0)
5385         {
5386             if (!cmd) return 0;
5387             cckd_command_help();
5388         }
5389         else if (strcasecmp (kw, "stats") == 0)
5390         {
5391             if (!cmd) return 0;
5392             cckd_command_stats ();
5393         }
5394         else if (strcasecmp (kw, "opts") == 0)
5395         {
5396             if (!cmd) return 0;
5397             cckd_command_opts();
5398         }
5399         else if (strcasecmp (kw, "debug") == 0)
5400         {
5401             if (!cmd) return 0;
5402             cckd_command_debug();
5403         }
5404         else if (strcasecmp (kw, "comp") == 0)
5405         {
5406             if (val < -1 || (val & ~cckdblk.comps) || c != '\0')
5407             {
5408                 logmsg ("Invalid value for comp=\n");
5409                 return -1;
5410             }
5411             else
5412             {
5413                 cckdblk.comp = val < 0 ? 0xff : val;
5414                 opts = 1;
5415             }
5416         }
5417         else if (strcasecmp (kw, "compparm") == 0)
5418         {
5419             if (val < -1 || val > 9 || c != '\0')
5420             {
5421                 logmsg ("Invalid value for compparm=\n");
5422                 return -1;
5423             }
5424             else
5425             {
5426                 cckdblk.compparm = val;
5427                 opts = 1;
5428             }
5429         }
5430         else if (strcasecmp (kw, "ra") == 0)
5431         {
5432             if (val < CCKD_MIN_RA || val > CCKD_MAX_RA || c != '\0')
5433             {
5434                 logmsg ("Invalid value for ra=\n");
5435                 return -1;
5436             }
5437             else
5438             {
5439                 cckdblk.ramax = val;
5440                 opts = 1;
5441             }
5442         }
5443         else if (strcasecmp (kw, "raq") == 0)
5444         {
5445             if (val < 0 || val > CCKD_MAX_RA_SIZE || c != '\0')
5446             {
5447                 logmsg ("Invalid value for raq=\n");
5448                 return -1;
5449             }
5450             else
5451             {
5452                 cckdblk.ranbr = val;
5453                 opts = 1;
5454             }
5455         }
5456         else if (strcasecmp (kw, "rat") == 0)
5457         {
5458             if (val < 0 || val > CCKD_MAX_RA_SIZE || c != '\0')
5459             {
5460                 logmsg ("Invalid value for rat=\n");
5461                 return -1;
5462             }
5463             else
5464             {
5465                 cckdblk.readaheads = val;
5466                 opts = 1;
5467             }
5468         }
5469         else if (strcasecmp (kw, "wr") == 0)
5470         {
5471             if (val < CCKD_MIN_WRITER || val > CCKD_MAX_WRITER || c != '\0')
5472             {
5473                 logmsg ("Invalid value for wr=\n");
5474                 return -1;
5475             }
5476             else
5477             {
5478                 cckdblk.wrmax = val;
5479                 opts = 1;
5480             }
5481         }
5482         else if (strcasecmp (kw, "gcint") == 0)
5483         {
5484             if (val < 1 || val > 60 || c != '\0')
5485             {
5486                 logmsg ("Invalid value for gcint=\n");
5487                 return -1;
5488             }
5489             else
5490             {
5491                 cckdblk.gcwait = val;
5492                 opts = 1;
5493             }
5494         }
5495         else if (strcasecmp (kw, "gcparm") == 0)
5496         {
5497             if (val < -8 || val > 8 || c != '\0')
5498             {
5499                 logmsg ("Invalid value for gcparm=\n");
5500                 return -1;
5501             }
5502             else
5503             {
5504                 cckdblk.gcparm = val;
5505                 opts = 1;
5506             }
5507         }
5508         else if (strcasecmp (kw, "nostress") == 0)
5509         {
5510             if (val < 0 || val > 1 || c != '\0')
5511             {
5512                 logmsg ("Invalid value for nostress=\n");
5513                 return -1;
5514             }
5515             else
5516             {
5517                 cckdblk.nostress = val;
5518                 opts = 1;
5519             }
5520         }
5521         else if (strcasecmp (kw, "freepend") == 0)
5522         {
5523             if (val < -1 || val > CCKD_MAX_FREEPEND || c != '\0')
5524             {
5525                 logmsg ("Invalid value for freepend=\n");
5526                 return -1;
5527             }
5528             else
5529             {
5530                 cckdblk.freepend = val;
5531                 opts = 1;
5532             }
5533         }
5534         else if (strcasecmp (kw, "fsync") == 0)
5535         {
5536             if (val < 0 || val > 1 || c != '\0')
5537             {
5538                 logmsg ("Invalid value for fsync=\n");
5539                 return -1;
5540             }
5541             else
5542             {
5543                 cckdblk.fsync = val;
5544                 opts = 1;
5545             }
5546         }
5547         else if (strcasecmp (kw, "trace") == 0)
5548         {
5549             if (val < 0 || val > CCKD_MAX_TRACE || c != '\0')
5550             {
5551                 logmsg ("Invalid value for trace=\n");
5552                 return -1;
5553             }
5554             else
5555             {
5556                 /* Disable tracing in case it's already active */
5557                 CCKD_TRACE *p = cckdblk.itrace;
5558                 cckdblk.itrace = NULL;
5559                 if (p)
5560                 {
5561                     SLEEP (1);
5562                     cckdblk.itrace = cckdblk.itracep = cckdblk.itracex = NULL;
5563                     cckdblk.itracen = 0;
5564                     cckd_free (NULL, "trace", p);
5565                 }
5566 
5567                 /* Get a new trace table */
5568                 if (val > 0)
5569                 {
5570                     p = cckd_calloc (NULL, "trace", val, sizeof(CCKD_TRACE));
5571                     if (p)
5572                     {
5573                         cckdblk.itracen = val;
5574                         cckdblk.itracex = p + val;
5575                         cckdblk.itracep = p;
5576                         cckdblk.itrace  = p;
5577                     }
5578                 }
5579                 opts = 1;
5580             }
5581         }
5582         else if (strcasecmp (kw, "linuxnull") == 0)
5583         {
5584             if (val < 0 || val > 1 || c != '\0')
5585             {
5586                 logmsg ("Invalid value for linuxnull=\n");
5587                 return -1;
5588             }
5589             else
5590             {
5591                 cckdblk.linuxnull = val;
5592                 opts = 1;
5593             }
5594         }
5595         else if (strcasecmp (kw, "gcstart") == 0)
5596         {
5597             DEVBLK *dev;
5598             CCKDDASD_EXT *cckd;
5599             TID tid;
5600             int flag = 0;
5601 
5602             cckd_lock_devchain(0);
5603             for (dev = cckdblk.dev1st; dev; dev = cckd->devnext)
5604             {
5605                 cckd = dev->cckd_ext;
5606                 obtain_lock (&cckd->filelock);
5607                 if (cckd->cdevhdr[cckd->sfn].free_total)
5608                 {
5609                     cckd->cdevhdr[cckd->sfn].options |= (CCKD_OPENED | CCKD_ORDWR);
5610                     cckd_write_chdr (dev);
5611                     flag = 1;
5612                 }
5613                 release_lock (&cckd->filelock);
5614             }
5615             cckd_unlock_devchain();
5616             if (flag && cckdblk.gcs < cckdblk.gcmax)
5617                 create_thread (&tid, JOINABLE, cckd_gcol, NULL, "cckd_gcol");
5618         }
5619         else
5620         {
5621             logmsg ("cckd invalid keyword: %s\n",kw);
5622             if (!cmd) return -1;
5623             cckd_command_help ();
5624             op = NULL;
5625         }
5626     }
5627 
5628     if (cmd && opts) cckd_command_opts();
5629     return 0;
5630 } /* end function cckd_command */
5631 
5632 /*-------------------------------------------------------------------*/
5633 /* Print internal trace                                              */
5634 /*-------------------------------------------------------------------*/
cckd_print_itrace()5635 DLL_EXPORT void cckd_print_itrace()
5636 {
5637 CCKD_TRACE     *i, *p;                  /* Trace table pointers      */
5638 
5639     if (!cckdblk.itrace) return;
5640     logmsg (_("HHCCD900I print_itrace\n"));
5641     i = cckdblk.itrace;
5642     cckdblk.itrace = NULL;
5643     SLEEP (1);
5644     p = cckdblk.itracep;
5645     if (p >= cckdblk.itracex) p = i;
5646     do
5647     {
5648         if (p[0] != '\0')
5649             logmsg ("%s", (char *)p);
5650         if (++p >= cckdblk.itracex) p = i;
5651     } while (p != cckdblk.itracep);
5652     memset (i, 0, cckdblk.itracen * sizeof(CCKD_TRACE));
5653     cckdblk.itracep = i;
5654     cckdblk.itrace  = i;
5655 } /* end function cckd_print_itrace */
5656 
5657 /*-------------------------------------------------------------------*/
5658 /* Write internal trace entry                                        */
5659 /*-------------------------------------------------------------------*/
cckd_trace(DEVBLK * dev,char * msg,...)5660 void cckd_trace(DEVBLK *dev, char *msg, ...)
5661 {
5662 va_list         vl;
5663 struct timeval  tv;
5664 time_t          t;
5665 char            tbuf[64];
5666 CCKD_TRACE     *p;
5667 int             l;
5668 
5669     if (dev && (dev->ccwtrace||dev->ccwstep))
5670     {
5671         char *bfr;
5672         int  sz=1024,rc;
5673         bfr=malloc(1024);
5674         va_start(vl,msg);
5675         while(1)
5676         {
5677             rc=vsnprintf(bfr,sz,msg,vl);
5678             if(rc<0)
5679             {
5680                 free(bfr);
5681                 bfr=NULL;
5682                 break;
5683             }
5684             if(rc<sz)
5685             {
5686                 break;
5687             }
5688             sz+=256;
5689             bfr=realloc(bfr,sz);
5690         }
5691         if(bfr)
5692         {
5693             logmsg("%4.4X:%s",dev->devnum,bfr);
5694         }
5695         va_end(vl);
5696     }
5697     /* ISW FIXME : The following code has a potential */
5698     /*             for heap overrun (vsprintf)        */
5699     if (cckdblk.itrace)
5700     {
5701         gettimeofday(&tv, NULL);
5702         t = tv.tv_sec;
5703         strcpy(tbuf, ctime(&t));
5704         tbuf[19] = '\0';
5705 
5706         va_start(vl,msg);
5707 
5708         p = cckdblk.itracep++;
5709         if (p >= cckdblk.itracex)
5710         {
5711             p = cckdblk.itrace;
5712             cckdblk.itracep = p + 1;
5713         }
5714 
5715         if (p)
5716         {
5717             l = sprintf ((char *)p, "%s" "." "%6.6ld %4.4X:",
5718                       tbuf+11, (long)(tv.tv_usec), dev ? dev->devnum : 0);
5719             vsprintf ((char *)p + l, msg, vl);
5720         }
5721     }
5722 } /* end function cckd_trace */
5723 
5724 DEVHND cckddasd_device_hndinfo = {
5725         &ckddasd_init_handler,          /* Device Initialisation      */
5726         &ckddasd_execute_ccw,           /* Device CCW execute         */
5727         &cckddasd_close_device,         /* Device Close               */
5728         &ckddasd_query_device,          /* Device Query               */
5729         &cckddasd_start,                /* Device Start channel pgm   */
5730         &cckddasd_end,                  /* Device End channel pgm     */
5731         &cckddasd_start,                /* Device Resume channel pgm  */
5732         &cckddasd_end,                  /* Device Suspend channel pgm */
5733         &cckd_read_track,               /* Device Read                */
5734         &cckd_update_track,             /* Device Write               */
5735         &cckd_used,                     /* Device Query used          */
5736         NULL,                           /* Device Reserve             */
5737         NULL,                           /* Device Release             */
5738         NULL,                           /* Device Attention           */
5739         NULL,                           /* Immediate CCW Codes        */
5740         NULL,                           /* Signal Adapter Input       */
5741         NULL,                           /* Signal Adapter Ouput       */
5742         &ckddasd_hsuspend,              /* Hercules suspend           */
5743         &ckddasd_hresume                /* Hercules resume            */
5744 };
5745 
5746 DEVHND cfbadasd_device_hndinfo = {
5747         &fbadasd_init_handler,          /* Device Initialisation      */
5748         &fbadasd_execute_ccw,           /* Device CCW execute         */
5749         &cckddasd_close_device,         /* Device Close               */
5750         &fbadasd_query_device,          /* Device Query               */
5751         &cckddasd_start,                /* Device Start channel pgm   */
5752         &cckddasd_end,                  /* Device End channel pgm     */
5753         &cckddasd_start,                /* Device Resume channel pgm  */
5754         &cckddasd_end,                  /* Device Suspend channel pgm */
5755         &cfba_read_block,               /* Device Read                */
5756         &cfba_write_block,              /* Device Write               */
5757         &cfba_used,                     /* Device Query used          */
5758         NULL,                           /* Device Reserve             */
5759         NULL,                           /* Device Release             */
5760         NULL,                           /* Device Attention           */
5761         NULL,                           /* Immediate CCW Codes        */
5762         NULL,                           /* Signal Adapter Input       */
5763         NULL,                           /* Signal Adapter Ouput       */
5764         &fbadasd_hsuspend,              /* Hercules suspend           */
5765         &fbadasd_hresume                /* Hercules resume            */
5766 };
5767