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