1
2
3
4 /*
5 * Copyright (C) 1993-1995 Bas Laarhoven.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 $Source: /home/bas/distr/ftape-2.03b/RCS/ftape-write.c,v $
22 $Author: bas $
23 *
24 $Revision: 1.26 $
25 $Date: 1995/05/27 08:55:27 $
26 $State: Beta $
27 *
28 * This file contains the writing code
29 * for the QIC-117 floppy-tape driver for Linux.
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 /* Global vars.
51 */
52
53 /* Local vars.
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)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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; /* skip entire segment */
86 result = 0; /* nothing written */
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
103 {
104 need_flush = 0;
105 ftape_state = idle;
106 }
107
108 int start_writing(int mode)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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; /* stop tape instead of pause */
119 }
120 calc_next_cluster(buff); /* prepare */
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); /* go */
131 }
132 ftape_state = writing;
133 }
134 TRACE_EXIT;
135 return result;
136 }
137
138 int loop_until_writes_done(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
139 {
140 TRACE_FUN(5, "loop_until_writes_done");
141 int i;
142 int result = 0;
143
144 /*
145 * Wait until all data is actually written to tape.
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 /* Allow escape from loop when signaled !
161 */
162 if (current->signal & _DONT_BLOCK) {
163 TRACE(2, "interrupted by signal");
164 TRACE_EXIT;
165 result = -EINTR; /* is this the right return value ? */
166 break;
167 }
168 if (buffer[head].hard_error_map != 0) {
169 /* Implement hard write error recovery here
170 */
171 }
172 buffer[head].status = waiting; /* retry this one */
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; /* normal exit status */
186 }
187 TRACE_EXIT;
188 return result;
189 }
190
191 /* Write given segment from buffer at address onto tape.
192 */
193 int write_segment(unsigned segment_id, byte * address, int flushing)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 /* if all buffers full we'll have to wait...
213 */
214 wait_segment(writing);
215 if (buffer[tail].status == error) {
216 /* setup for a retry
217 */
218 buffer[tail].status = waiting;
219 bytes_written = -EAGAIN; /* force retry */
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 /* Implement hard write error recovery here
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 /* If just passed last segment on tape: wait for BOT or EOT mark.
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 /* should runner stop ?
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; /* aborted ? */
260 }
261 }
262 /* Don't start tape if runner idle and segment empty.
263 */
264 if (result >= 0 && !(runner_status == idle &&
265 get_bad_sector_entry(segment_id) == EMPTY_SEGMENT)) {
266 if (buffer[tail].status == done) {
267 /* now at least one buffer is empty, fill it with our data.
268 * skip bad sectors and generate ecc.
269 * copy_and_gen_ecc return nr of bytes written,
270 * range 0..29 Kb inclusive !
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 /* Start tape only if all buffers full or flush mode.
282 * This will give higher probability of streaming.
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 /* Write as much as fits from buffer to the given segment on tape
294 * and handle retries.
295 * Return the number of bytes written (>= 0), or:
296 * -EIO write failed
297 * -EINTR interrupted by signal
298 * -ENOSPC device full
299 */
300 int _write_segment(unsigned int segment_id, byte * buffer, int flush)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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; /* tape full */
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; /* give up */
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 { /* success */
327 if (result == 0) { /* empty segment */
328 TRACE(4, "empty segment, nothing written");
329 }
330 break;
331 }
332 /* Allow escape from loop when signaled !
333 */
334 if (current->signal & _DONT_BLOCK) {
335 TRACE(2, "interrupted by signal");
336 TRACE_EXIT;
337 result = -EINTR; /* is this the right return value ? */
338 break;
339 }
340 }
341 TRACE_EXIT;
342 return result;
343 }
344
345 int update_header_segment(unsigned segment, byte * buffer)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 /* Force flush for single segment instead of relying on
370 * flush in read_segment for multiple segments.
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) { /* read back and verify */
380 result = read_segment(segment, scratch_buffer, &status, 0);
381 /* Should retry if soft error during read !
382 * TO BE IMPLEMENTED
383 */
384 if (result >= 0) {
385 if (memcmp(buffer, scratch_buffer, sizeof(buffer)) == 0) {
386 result = 0; /* verified */
387 TRACE(5, "verified");
388 } else {
389 result = -EIO; /* verify failed */
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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; /* exit and fake success */
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(); /* prevents extra rewind */
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(); /* prevents extra rewind */
477 result = ftape_write_header_segments(buffer);
478 }
479 }
480 }
481 TRACE_EXIT;
482 return result;
483 }
484
485 int ftape_flush_buffers(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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; /* prevent further writes if this fails */
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 * If there is any data not written to tape yet, append zero's
517 * up to the end of the sector. Then write the segment(s) to tape.
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); /* pad buffer */
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 /* Need another segment for remaining data, move the remainder
543 * to the beginning of the buffer
544 */
545 memmove(deblock_buffer, deblock_buffer + written, data_remaining);
546 }
547 }
548 ++ftape_seg_pos;
549 } while (data_remaining > 0);
550 /* Data written to last segment == data_remaining + written
551 * value is in range [1..29K].
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 /* Last sector of segment was used for data, so put eof mark
557 * in next segment and position at second file mark.
558 */
559 if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
560 ++ftape_seg_pos; /* position between file marks */
561 }
562 } else {
563 /* Put eof mark in previous segment after data and position
564 * at second file mark.
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; /* position between file marks */
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)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 * If we haven't read the header segment yet, do it now.
605 * This will verify the configuration, get the eof markers
606 * and the bad sector table.
607 * We'll use the deblock buffer for scratch.
608 */
609 result = read_header_segment(deblock_buffer);
610 if (result >= 0 && ftape_seg_pos > ftape_last_segment.id) {
611 result = -ENOSPC; /* full is full */
612 }
613 }
614 if (result < 0) {
615 TRACE_EXIT;
616 return result;
617 }
618 /*
619 * This part writes data blocks to tape until the
620 * requested amount is written.
621 * The data will go in a buffer until it's enough
622 * for a segment without bad sectors. Then we'll write
623 * that segment to tape.
624 * The bytes written will be removed from the buffer
625 * and the process is repeated until there is less
626 * than one segment to write left in the buffer.
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 /* If this is the last buffer to be written, let flush handle it.
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 /* Got one full buffer, write it to disk
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; /* failed, retry same segment */
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 /* Partial write: move remainder in lower part of buffer
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; /* remainder */
679 ++ftape_seg_pos;
680 /* Allow us to escape from this loop with a signal !
681 */
682 if (current->signal & _DONT_BLOCK) {
683 TRACE(2, "interrupted by signal");
684 last_write_failed = 1;
685 TRACE_EXIT;
686 return -EINTR; /* is this the right return value ? */
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; /* bytes written */
699 }
700
701 int ftape_fix(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
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 /* This will copy header segment 2 to header segment 1
712 * Spares us a tape format operation if header 2 is still good.
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 }