root/drivers/char/ftape/ftape-write.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ftape_zap_write_buffers
  2. copy_and_gen_ecc
  3. prevent_flush
  4. start_writing
  5. loop_until_writes_done
  6. write_segment
  7. _write_segment
  8. update_header_segment
  9. ftape_write_header_segments
  10. ftape_update_header_segments
  11. ftape_flush_buffers
  12. _ftape_write
  13. ftape_fix

   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][next][first][last][top][bottom][index][help] */
  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][next][first][last][top][bottom][index][help] */
  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][next][first][last][top][bottom][index][help] */
 103 {
 104         need_flush = 0;
 105         ftape_state = idle;
 106 }
 107 
 108 int start_writing(int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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 }

/* [previous][next][first][last][top][bottom][index][help] */