📄 ftape-write.c
字号:
TRACE(1, "wrong header signature found, aborting"); result = -EIO; } if (result >= 0) { result = _write_segment(segment, buffer, 0); if (result >= 0 && runner_status == idle) { /* Force flush for single segment instead of relying on * flush in read_segment for multiple segments. */ result = start_writing(WRITE_SINGLE); if (result >= 0 && ftape_state == writing) { result = loop_until_writes_done(); prevent_flush(); } }#ifdef VERIFY_HEADERS if (result >= 0) { /* read back and verify */ result = read_segment(segment, scratch_buffer, &status, 0); /* Should retry if soft error during read ! * TO BE IMPLEMENTED */ if (result >= 0) { if (memcmp(buffer, scratch_buffer, sizeof(buffer)) == 0) { result = 0; /* verified */ TRACE(5, "verified"); } else { result = -EIO; /* verify failed */ TRACE(5, "verify failed"); } } }#endif } TRACE_EXIT; return result;}int ftape_write_header_segments(byte * buffer){ TRACE_FUN(5, "ftape_write_header_segments"); int result = 0; int retry = 0; int header_1_ok = 0; int header_2_ok = 0; do { if (!header_1_ok) { result = update_header_segment(header_segment_1, buffer); if (result < 0) { continue; } header_1_ok = 1; } if (!header_2_ok) { result = update_header_segment(header_segment_2, buffer); if (result < 0) { continue; } header_2_ok = 1; } } while (result < 0 && retry++ < 3); if (result < 0) { if (!header_1_ok) { TRACE(1, "update of first header segment failed"); } if (!header_2_ok) { TRACE(1, "update of second header segment failed"); } result = -EIO; } TRACE_EXIT; return result;}int ftape_update_header_segments(byte * buffer, int update){ TRACE_FUN(5, "ftape_update_header_segments"); int result = 0; int dummy; int header_changed = 1; if (ftape_state == writing) { result = loop_until_writes_done(); } if (read_only) { result = 0; /* exit and fake success */ TRACE(4, "Tape set read-only: no update"); } else if (result >= 0) { result = ftape_abort_operation(); if (result >= 0) { if (buffer == NULL) { if (bad_sector_map_changed || failed_sector_log_changed) { ftape_seek_to_bot(); /* prevents extra rewind */ buffer = deblock_buffer; result = read_segment(used_header_segment, buffer, &dummy, 0); if (result < 0) { TRACE_EXIT; return result; } } header_changed = 0; } if (update) { if (bad_sector_map_changed) { store_bad_sector_map(buffer); header_changed = 1; } if (failed_sector_log_changed) { update_failed_sector_log(buffer); header_changed = 1; } } if (header_changed) { ftape_seek_to_bot(); /* prevents extra rewind */ result = ftape_write_header_segments(buffer); } } } TRACE_EXIT; return result;}int ftape_flush_buffers(void){ TRACE_FUN(5, "ftape_flush_buffers"); int result; int pad_count; int data_remaining; static int active = 0; if (active) { TRACE(5, "nested call, abort"); TRACE_EXIT; return 0; } active = 1; TRACEi(5, "entered, ftape_state =", ftape_state); if (ftape_state != writing && !need_flush) { active = 0; TRACE(5, "no need for flush"); TRACE_EXIT; return 0; } data_remaining = buf_pos_wr; buf_pos_wr = 0; /* prevent further writes if this fails */ TRACE(5, "flushing write buffers"); if (last_write_failed) { ftape_zap_write_buffers(); active = 0; TRACE_EXIT; return write_protected ? -EROFS : -EIO; } /* * If there is any data not written to tape yet, append zero's * up to the end of the sector. Then write the segment(s) to tape. */ if (data_remaining > 0) { int written; do { TRACEi(4, "remaining in buffer:", data_remaining); pad_count = sizeof(deblock_buffer) - data_remaining; TRACEi(7, "flush, padding count:", pad_count); memset(deblock_buffer + data_remaining, 0, pad_count); /* pad buffer */ result = _write_segment(ftape_seg_pos, deblock_buffer, 1); if (result < 0) { if (result != -ENOSPC) { last_write_failed = 1; } active = 0; TRACE_EXIT; return result; } written = result; clear_eof_mark_if_set(ftape_seg_pos, written); TRACEi(7, "flush, moved out buffer:", written); if (written > 0) { data_remaining -= written; if (data_remaining > 0) { /* Need another segment for remaining data, move the remainder * to the beginning of the buffer */ memmove(deblock_buffer, deblock_buffer + written, data_remaining); } } ++ftape_seg_pos; } while (data_remaining > 0); /* Data written to last segment == data_remaining + written * value is in range [1..29K]. */ TRACEx2(4, "last write: %d, netto pad-count: %d", data_remaining + written, -data_remaining); if (-1024 < data_remaining && data_remaining <= 0) { /* Last sector of segment was used for data, so put eof mark * in next segment and position at second file mark. */ if (ftape_weof(2, ftape_seg_pos, 1) >= 0) { ++ftape_seg_pos; /* position between file marks */ } } else { /* Put eof mark in previous segment after data and position * at second file mark. */ ftape_weof(2, ftape_seg_pos - 1, 1 + ((SECTOR_SIZE - 1 + result + data_remaining) / SECTOR_SIZE)); } } else { TRACE(7, "deblock_buffer empty"); if (ftape_weof(2, ftape_seg_pos, 1) >= 0) { ++ftape_seg_pos; /* position between file marks */ } start_writing(WRITE_MULTI); } TRACE(7, "waiting"); result = loop_until_writes_done(); if (result < 0) { TRACE(1, "flush buffers failed"); } ftape_state = idle; last_write_failed = 0; need_flush = 0; active = 0; TRACE_EXIT; return result;}int _ftape_write(const char *buff, int req_len){ TRACE_FUN(5, "_ftape_write"); int result = 0; int cnt; int written = 0; if (write_protected) { TRACE(1, "error: cartridge write protected"); last_write_failed = 1; result = -EROFS; } else if (ftape_offline || !formatted || no_tape) { result = -EIO; } else if (first_data_segment == -1) { /* * If we haven't read the header segment yet, do it now. * This will verify the configuration, get the eof markers * and the bad sector table. * We'll use the deblock buffer for scratch. */ result = read_header_segment(deblock_buffer); if (result >= 0 && ftape_seg_pos > ftape_last_segment.id) { result = -ENOSPC; /* full is full */ } } if (result < 0) { TRACE_EXIT; return result; } /* * This part writes data blocks to tape until the * requested amount is written. * The data will go in a buffer until it's enough * for a segment without bad sectors. Then we'll write * that segment to tape. * The bytes written will be removed from the buffer * and the process is repeated until there is less * than one segment to write left in the buffer. */ while (req_len > 0) { int space_left = sizeof(deblock_buffer) - buf_pos_wr; TRACEi(7, "remaining req_len:", req_len); TRACEi(7, " buf_pos:", buf_pos_wr); cnt = (req_len < space_left) ? req_len : space_left; if (cnt > 0) { result = verify_area(VERIFY_READ, buff, cnt); if (result) { TRACE(1, "verify_area failed"); last_write_failed = 1; TRACE_EXIT; return result; } memcpy_fromfs(deblock_buffer + buf_pos_wr, buff, cnt); buff += cnt; req_len -= cnt; buf_pos_wr += cnt; } TRACEi(7, "moved into blocking buffer:", cnt); while (buf_pos_wr >= sizeof(deblock_buffer)) { /* If this is the last buffer to be written, let flush handle it. */ if (ftape_seg_pos >= ftape_last_segment.id) { TRACEi(7, "remaining in blocking buffer:", buf_pos_wr); TRACEi(7, "just written bytes:", written + cnt); TRACE_EXIT; return written + cnt; } /* Got one full buffer, write it to disk */ result = _write_segment(ftape_seg_pos, deblock_buffer, 0); TRACEi(5, "_write_segment result =", result); if (result < 0) { if (result == -EAGAIN) { TRACE(5, "retry..."); continue; /* failed, retry same segment */ } last_write_failed = 1; TRACE_EXIT; return result; } else { clear_eof_mark_if_set(ftape_seg_pos, result); } if (result > 0 && result < buf_pos_wr) { /* Partial write: move remainder in lower part of buffer */ memmove(deblock_buffer, deblock_buffer + result, buf_pos_wr - result); } TRACEi(7, "moved out of blocking buffer:", result); buf_pos_wr -= result; /* remainder */ ++ftape_seg_pos; /* Allow us to escape from this loop with a signal ! */ if (current->signal & _DONT_BLOCK) { TRACE(2, "interrupted by signal"); last_write_failed = 1; TRACE_EXIT; return -EINTR; /* is this the right return value ? */ } } written += cnt; } TRACEi(7, "remaining in blocking buffer:", buf_pos_wr); TRACEi(7, "just written bytes:", written); last_write_failed = 0; if (!need_flush && written > 0) { need_flush = 1; } TRACE_EXIT; return written; /* bytes written */}int ftape_fix(void){ TRACE_FUN(5, "ftape_fix"); int result = 0; int dummy; int status; if (write_protected) { result = -EROFS; } else { /* This will copy header segment 2 to header segment 1 * Spares us a tape format operation if header 2 is still good. */ header_segment_1 = 0; header_segment_2 = 1; first_data_segment = 2; result = read_segment(header_segment_2, scratch_buffer, &dummy, 0); result = ftape_ready_wait(timeout.pause, &status); result = ftape_write_header_segments(scratch_buffer); } TRACE_EXIT; return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -