This source file includes following definitions.
- ftape_zap_write_buffers
- copy_and_gen_ecc
- prevent_flush
- start_writing
- loop_until_writes_done
- write_segment
- _write_segment
- update_header_segment
- ftape_write_header_segments
- ftape_update_header_segments
- ftape_flush_buffers
- _ftape_write
- ftape_fix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <linux/module.h>
33 #include <linux/string.h>
34 #include <linux/errno.h>
35 #include <linux/mm.h>
36 #include <linux/ftape.h>
37 #include <asm/segment.h>
38
39 #include "tracing.h"
40 #include "ftape-write.h"
41 #include "ftape-read.h"
42 #include "qic117.h"
43 #include "ftape-io.h"
44 #include "ftape-ctl.h"
45 #include "ftape-rw.h"
46 #include "ftape-eof.h"
47 #include "ecc.h"
48 #include "ftape-bsm.h"
49
50
51
52
53
54
55
56 static int buf_pos_wr = 0;
57 static int last_write_failed = 0;
58 static int need_flush = 0;
59
60 #define WRITE_MULTI 0
61 #define WRITE_SINGLE 1
62
63 void ftape_zap_write_buffers(void)
64 {
65 int i;
66
67 for (i = 0; i < NR_BUFFERS; ++i) {
68 buffer[i].status = done;
69 }
70 need_flush = 0;
71 }
72
73 int copy_and_gen_ecc(char *destination, byte * source,
74 unsigned int bad_sector_map)
75 {
76 TRACE_FUN(8, "copy_and_gen_ecc");
77 int result;
78 struct memory_segment mseg;
79 int bads = count_ones(bad_sector_map);
80
81 if (bads > 0) {
82 TRACEi(4, "bad sectors in map:", bads);
83 }
84 if (bads + 3 >= SECTORS_PER_SEGMENT) {
85 TRACE(4, "empty segment");
86 mseg.blocks = 0;
87 result = 0;
88 } else {
89 mseg.blocks = SECTORS_PER_SEGMENT - bads;
90 mseg.data = destination;
91 memcpy(mseg.data, source, (mseg.blocks - 3) * SECTOR_SIZE);
92 result = ecc_set_segment_parity(&mseg);
93 if (result < 0) {
94 TRACE(1, "ecc_set_segment_parity failed");
95 } else {
96 result = (mseg.blocks - 3) * SECTOR_SIZE;
97 }
98 }
99 TRACE_EXIT;
100 return result;
101 }
102
103 void prevent_flush(void)
104 {
105 need_flush = 0;
106 ftape_state = idle;
107 }
108
109 int start_writing(int mode)
110 {
111 TRACE_FUN(5, "start_writing");
112 int result = 0;
113 buffer_struct *buff = &buffer[head];
114 int segment_id = buff->segment_id;
115
116 if (ftape_state == writing && buff->status == waiting) {
117 setup_new_segment(buff, segment_id, 1);
118 if (mode == WRITE_SINGLE) {
119 buffer[head].next_segment = 0;
120 }
121 calc_next_cluster(buff);
122 buff->status = writing;
123 if (runner_status == idle) {
124 TRACEi(5, "starting runner for segment", segment_id);
125 result = ftape_start_tape(segment_id, buff->sector_offset);
126 if (result >= 0) {
127 runner_status = running;
128 }
129 }
130 if (result >= 0) {
131 result = setup_fdc_and_dma(buff, FDC_WRITE);
132 }
133 ftape_state = writing;
134 }
135 TRACE_EXIT;
136 return result;
137 }
138
139 int loop_until_writes_done(void)
140 {
141 TRACE_FUN(5, "loop_until_writes_done");
142 int i;
143 int result = 0;
144
145
146
147
148 while (ftape_state == writing && buffer[head].status != done) {
149 TRACEx2(7, "tail: %d, head: %d", tail, head);
150 for (i = 0; i < NR_BUFFERS; ++i) {
151 TRACEx3(8, "buffer[ %d] segment_id: %d, status: %d",
152 i, buffer[i].segment_id, buffer[i].status);
153 }
154 result = fdc_interrupt_wait(5 * SECOND);
155 if (result < 0) {
156 TRACE(1, "fdc_interrupt_wait failed");
157 last_write_failed = 1;
158 break;
159 }
160 if (buffer[head].status == error) {
161
162
163 if (current->signal & _DONT_BLOCK) {
164 TRACE(2, "interrupted by signal");
165 TRACE_EXIT;
166 result = -EINTR;
167 break;
168 }
169 if (buffer[head].hard_error_map != 0) {
170
171
172 }
173 buffer[head].status = waiting;
174 if (runner_status == aborting) {
175 ftape_dumb_stop();
176 runner_status = idle;
177 }
178 if (runner_status != idle) {
179 TRACE(1, "unexpected state: runner_status != idle");
180 result = -EIO;
181 break;
182 }
183 start_writing(WRITE_MULTI);
184 }
185 TRACE(5, "looping until writes done");
186 result = 0;
187 }
188 TRACE_EXIT;
189 return result;
190 }
191
192
193
194 int write_segment(unsigned segment_id, byte * address, int flushing)
195 {
196 TRACE_FUN(5, "write_segment");
197 int result = 0;
198 int bytes_written = 0;
199
200 TRACEi(5, "segment_id =", segment_id);
201 if (ftape_state != writing) {
202 if (ftape_state == reading) {
203 TRACE(5, "calling ftape_abort_operation");
204 result = ftape_abort_operation();
205 if (result < 0) {
206 TRACE(1, "ftape_abort_operation failed");
207 }
208 }
209 ftape_zap_read_buffers();
210 ftape_zap_write_buffers();
211 ftape_state = writing;
212 }
213
214
215 wait_segment(writing);
216 if (buffer[tail].status == error) {
217
218
219 buffer[tail].status = waiting;
220 bytes_written = -EAGAIN;
221 if (buffer[tail].hard_error_map != 0) {
222 TRACEx1(1, "warning: %d hard error(s) in written segment",
223 count_ones(buffer[tail].hard_error_map));
224 TRACEx1(4, "hard_error_map = 0x%08lx", buffer[tail].hard_error_map);
225
226
227 }
228 } else if (buffer[tail].status == done) {
229 history.defects += count_ones(buffer[tail].hard_error_map);
230 } else {
231 TRACE(1, "wait for empty segment failed");
232 result = -EIO;
233 }
234
235
236 if (result >= 0 && runner_status == logical_eot) {
237 int status;
238
239 result = ftape_ready_wait(timeout.seek, &status);
240 if (result < 0 || (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
241 TRACE(1, "eot/bot not reached");
242 } else {
243 runner_status = end_of_tape;
244 }
245 }
246
247
248 if (result >= 0 &&
249 (runner_status == aborting || runner_status == buffer_underrun ||
250 runner_status == end_of_tape)) {
251 if (runner_status != end_of_tape) {
252 result = ftape_dumb_stop();
253 }
254 if (result >= 0) {
255 if (runner_status == aborting) {
256 if (buffer[head].status == writing) {
257 buffer[head].status = done;
258 }
259 }
260 runner_status = idle;
261 }
262 }
263
264
265 if (result >= 0 && !(runner_status == idle &&
266 get_bad_sector_entry(segment_id) == EMPTY_SEGMENT)) {
267 if (buffer[tail].status == done) {
268
269
270
271
272
273 result = copy_and_gen_ecc(buffer[tail].address, address,
274 get_bad_sector_entry(segment_id));
275 if (result >= 0) {
276 bytes_written = result;
277 buffer[tail].segment_id = segment_id;
278 buffer[tail].status = waiting;
279 next_buffer(&tail);
280 }
281 }
282
283
284
285 if (result >= 0 && runner_status != running &&
286 ((head == tail && buffer[tail].status == waiting) || flushing)) {
287 result = start_writing(WRITE_MULTI);
288 }
289 }
290 TRACE_EXIT;
291 return (result < 0) ? result : bytes_written;
292 }
293
294
295
296
297
298
299
300
301 int _write_segment(unsigned int segment_id, byte * buffer, int flush)
302 {
303 TRACE_FUN(5, "_write_segment");
304 int retry = 0;
305 int result;
306
307 history.used |= 2;
308 for (;;) {
309 if (segment_id > ftape_last_segment.id && !flush) {
310 result = -ENOSPC;
311 break;
312 }
313 result = write_segment(segment_id, buffer, flush);
314 if (result < 0) {
315 if (result == -EAGAIN) {
316 if (++retry > 100) {
317 TRACE(1, "write failed, >100 retries in segment");
318 result = -EIO;
319 break;
320 } else {
321 TRACEx1(2, "write error, retry %d", retry);
322 }
323 } else {
324 TRACEi(1, "write_segment failed, error:", -result);
325 break;
326 }
327 } else {
328 if (result == 0) {
329 TRACE(4, "empty segment, nothing written");
330 }
331 break;
332 }
333
334
335 if (current->signal & _DONT_BLOCK) {
336 TRACE(2, "interrupted by signal");
337 TRACE_EXIT;
338 result = -EINTR;
339 break;
340 }
341 }
342 TRACE_EXIT;
343 return result;
344 }
345
346 int update_header_segment(unsigned segment, byte * buffer)
347 {
348 TRACE_FUN(5, "update_header_segment");
349 int result = 0;
350 int status;
351
352 if (buffer == NULL) {
353 TRACE(5, "no input buffer specified");
354 buffer = deblock_buffer;
355 result = read_segment(used_header_segment, buffer, &status, 0);
356 if (bad_sector_map_changed) {
357 store_bad_sector_map(buffer);
358 }
359 if (failed_sector_log_changed) {
360 update_failed_sector_log(buffer);
361 }
362 }
363 if (result >= 0 && GET4(buffer, 0) != 0xaa55aa55) {
364 TRACE(1, "wrong header signature found, aborting");
365 result = -EIO;
366 }
367 if (result >= 0) {
368 result = _write_segment(segment, buffer, 0);
369 if (result >= 0 && runner_status == idle) {
370
371
372
373 result = start_writing(WRITE_SINGLE);
374 if (result >= 0 && ftape_state == writing) {
375 result = loop_until_writes_done();
376 prevent_flush();
377 }
378 }
379 #ifdef VERIFY_HEADERS
380 if (result >= 0) {
381 result = read_segment(segment, scratch_buffer, &status, 0);
382
383
384
385 if (result >= 0) {
386 if (memcmp(buffer, scratch_buffer, sizeof(buffer)) == 0) {
387 result = 0;
388 TRACE(5, "verified");
389 } else {
390 result = -EIO;
391 TRACE(5, "verify failed");
392 }
393 }
394 }
395 #endif
396 }
397 TRACE_EXIT;
398 return result;
399 }
400
401 int ftape_write_header_segments(byte * buffer)
402 {
403 TRACE_FUN(5, "ftape_write_header_segments");
404 int result = 0;
405 int retry = 0;
406 int header_1_ok = 0;
407 int header_2_ok = 0;
408
409 do {
410 if (!header_1_ok) {
411 result = update_header_segment(header_segment_1, buffer);
412 if (result < 0) {
413 continue;
414 }
415 header_1_ok = 1;
416 }
417 if (!header_2_ok) {
418 result = update_header_segment(header_segment_2, buffer);
419 if (result < 0) {
420 continue;
421 }
422 header_2_ok = 1;
423 }
424 } while (result < 0 && retry++ < 3);
425 if (result < 0) {
426 if (!header_1_ok) {
427 TRACE(1, "update of first header segment failed");
428 }
429 if (!header_2_ok) {
430 TRACE(1, "update of second header segment failed");
431 }
432 result = -EIO;
433 }
434 TRACE_EXIT;
435 return result;
436 }
437
438 int ftape_update_header_segments(byte * buffer, int update)
439 {
440 TRACE_FUN(5, "ftape_update_header_segments");
441 int result = 0;
442 int dummy;
443 int header_changed = 1;
444
445 if (ftape_state == writing) {
446 result = loop_until_writes_done();
447 }
448 if (read_only) {
449 result = 0;
450 TRACE(4, "Tape set read-only: no update");
451 } else if (result >= 0) {
452 result = ftape_abort_operation();
453 if (result >= 0) {
454 if (buffer == NULL) {
455 if (bad_sector_map_changed || failed_sector_log_changed) {
456 ftape_seek_to_bot();
457 buffer = deblock_buffer;
458 result = read_segment(used_header_segment, buffer, &dummy, 0);
459 if (result < 0) {
460 TRACE_EXIT;
461 return result;
462 }
463 }
464 header_changed = 0;
465 }
466 if (update) {
467 if (bad_sector_map_changed) {
468 store_bad_sector_map(buffer);
469 header_changed = 1;
470 }
471 if (failed_sector_log_changed) {
472 update_failed_sector_log(buffer);
473 header_changed = 1;
474 }
475 }
476 if (header_changed) {
477 ftape_seek_to_bot();
478 result = ftape_write_header_segments(buffer);
479 }
480 }
481 }
482 TRACE_EXIT;
483 return result;
484 }
485
486 int ftape_flush_buffers(void)
487 {
488 TRACE_FUN(5, "ftape_flush_buffers");
489 int result;
490 int pad_count;
491 int data_remaining;
492 static int active = 0;
493
494 if (active) {
495 TRACE(5, "nested call, abort");
496 TRACE_EXIT;
497 return 0;
498 }
499 active = 1;
500 TRACEi(5, "entered, ftape_state =", ftape_state);
501 if (ftape_state != writing && !need_flush) {
502 active = 0;
503 TRACE(5, "no need for flush");
504 TRACE_EXIT;
505 return 0;
506 }
507 data_remaining = buf_pos_wr;
508 buf_pos_wr = 0;
509 TRACE(5, "flushing write buffers");
510 if (last_write_failed) {
511 ftape_zap_write_buffers();
512 active = 0;
513 TRACE_EXIT;
514 return write_protected ? -EROFS : -EIO;
515 }
516
517
518
519
520 if (data_remaining > 0) {
521 int written;
522
523 do {
524 TRACEi(4, "remaining in buffer:", data_remaining);
525 pad_count = sizeof(deblock_buffer) - data_remaining;
526 TRACEi(7, "flush, padding count:", pad_count);
527 memset(deblock_buffer + data_remaining, 0, pad_count);
528 result = _write_segment(ftape_seg_pos, deblock_buffer, 1);
529 if (result < 0) {
530 if (result != -ENOSPC) {
531 last_write_failed = 1;
532 }
533 active = 0;
534 TRACE_EXIT;
535 return result;
536 }
537 written = result;
538 clear_eof_mark_if_set(ftape_seg_pos, written);
539 TRACEi(7, "flush, moved out buffer:", written);
540 if (written > 0) {
541 data_remaining -= written;
542 if (data_remaining > 0) {
543
544
545
546 memmove(deblock_buffer, deblock_buffer + written, data_remaining);
547 }
548 }
549 ++ftape_seg_pos;
550 } while (data_remaining > 0);
551
552
553
554 TRACEx2(4, "last write: %d, netto pad-count: %d",
555 data_remaining + written, -data_remaining);
556 if (-1024 < data_remaining && data_remaining <= 0) {
557
558
559
560 if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
561 ++ftape_seg_pos;
562 }
563 } else {
564
565
566
567 ftape_weof(2, ftape_seg_pos - 1, 1 +
568 ((SECTOR_SIZE - 1 + result + data_remaining) / SECTOR_SIZE));
569 }
570 } else {
571 TRACE(7, "deblock_buffer empty");
572 if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
573 ++ftape_seg_pos;
574 }
575 start_writing(WRITE_MULTI);
576 }
577 TRACE(7, "waiting");
578 result = loop_until_writes_done();
579 if (result < 0) {
580 TRACE(1, "flush buffers failed");
581 }
582 ftape_state = idle;
583 last_write_failed = 0;
584 need_flush = 0;
585 active = 0;
586 TRACE_EXIT;
587 return result;
588 }
589
590 int _ftape_write(const char *buff, int req_len)
591 {
592 TRACE_FUN(5, "_ftape_write");
593 int result = 0;
594 int cnt;
595 int written = 0;
596
597 if (write_protected) {
598 TRACE(1, "error: cartridge write protected");
599 last_write_failed = 1;
600 result = -EROFS;
601 } else if (ftape_offline || !formatted || no_tape) {
602 result = -EIO;
603 } else if (first_data_segment == -1) {
604
605
606
607
608
609
610 result = read_header_segment(deblock_buffer);
611 if (result >= 0 && ftape_seg_pos > ftape_last_segment.id) {
612 result = -ENOSPC;
613 }
614 }
615 if (result < 0) {
616 TRACE_EXIT;
617 return result;
618 }
619
620
621
622
623
624
625
626
627
628
629 while (req_len > 0) {
630 int space_left = sizeof(deblock_buffer) - buf_pos_wr;
631
632 TRACEi(7, "remaining req_len:", req_len);
633 TRACEi(7, " buf_pos:", buf_pos_wr);
634 cnt = (req_len < space_left) ? req_len : space_left;
635 if (cnt > 0) {
636 result = verify_area(VERIFY_READ, buff, cnt);
637 if (result) {
638 TRACE(1, "verify_area failed");
639 last_write_failed = 1;
640 TRACE_EXIT;
641 return result;
642 }
643 memcpy_fromfs(deblock_buffer + buf_pos_wr, buff, cnt);
644 buff += cnt;
645 req_len -= cnt;
646 buf_pos_wr += cnt;
647 }
648 TRACEi(7, "moved into blocking buffer:", cnt);
649 while (buf_pos_wr >= sizeof(deblock_buffer)) {
650
651
652 if (ftape_seg_pos >= ftape_last_segment.id) {
653 TRACEi(7, "remaining in blocking buffer:", buf_pos_wr);
654 TRACEi(7, "just written bytes:", written + cnt);
655 TRACE_EXIT;
656 return written + cnt;
657 }
658
659
660 result = _write_segment(ftape_seg_pos, deblock_buffer, 0);
661 TRACEi(5, "_write_segment result =", result);
662 if (result < 0) {
663 if (result == -EAGAIN) {
664 TRACE(5, "retry...");
665 continue;
666 }
667 last_write_failed = 1;
668 TRACE_EXIT;
669 return result;
670 } else {
671 clear_eof_mark_if_set(ftape_seg_pos, result);
672 }
673 if (result > 0 && result < buf_pos_wr) {
674
675
676 memmove(deblock_buffer, deblock_buffer + result, buf_pos_wr - result);
677 }
678 TRACEi(7, "moved out of blocking buffer:", result);
679 buf_pos_wr -= result;
680 ++ftape_seg_pos;
681
682
683 if (current->signal & _DONT_BLOCK) {
684 TRACE(2, "interrupted by signal");
685 last_write_failed = 1;
686 TRACE_EXIT;
687 return -EINTR;
688 }
689 }
690 written += cnt;
691 }
692 TRACEi(7, "remaining in blocking buffer:", buf_pos_wr);
693 TRACEi(7, "just written bytes:", written);
694 last_write_failed = 0;
695 if (!need_flush && written > 0) {
696 need_flush = 1;
697 }
698 TRACE_EXIT;
699 return written;
700 }
701
702 int ftape_fix(void)
703 {
704 TRACE_FUN(5, "ftape_fix");
705 int result = 0;
706 int dummy;
707 int status;
708
709 if (write_protected) {
710 result = -EROFS;
711 } else {
712
713
714
715 header_segment_1 = 0;
716 header_segment_2 = 1;
717 first_data_segment = 2;
718 result = read_segment(header_segment_2, scratch_buffer, &dummy, 0);
719 result = ftape_ready_wait(timeout.pause, &status);
720 result = ftape_write_header_segments(scratch_buffer);
721 }
722 TRACE_EXIT;
723 return result;
724 }