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/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 /*      Global vars.
  52  */
  53 
  54 /*      Local vars.
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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;        /* skip entire segment */
  87                 result = 0;     /* nothing written */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         need_flush = 0;
 106         ftape_state = idle;
 107 }
 108 
 109 int start_writing(int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;  /* stop tape instead of pause */
 120                 }
 121                 calc_next_cluster(buff);        /* prepare */
 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);    /* go */
 132                 }
 133                 ftape_state = writing;
 134         }
 135         TRACE_EXIT;
 136         return result;
 137 }
 138 
 139 int loop_until_writes_done(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141         TRACE_FUN(5, "loop_until_writes_done");
 142         int i;
 143         int result = 0;
 144 
 145         /*
 146          *  Wait until all data is actually written to tape.
 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                         /* Allow escape from loop when signaled !
 162                          */
 163                         if (current->signal & _DONT_BLOCK) {
 164                                 TRACE(2, "interrupted by signal");
 165                                 TRACE_EXIT;
 166                                 result = -EINTR;        /* is this the right return value ? */
 167                                 break;
 168                         }
 169                         if (buffer[head].hard_error_map != 0) {
 170                                 /*  Implement hard write error recovery here
 171                                  */
 172                         }
 173                         buffer[head].status = waiting;  /* retry this one */
 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;     /* normal exit status */
 187         }
 188         TRACE_EXIT;
 189         return result;
 190 }
 191 
 192 /*      Write given segment from buffer at address onto tape.
 193  */
 194 int write_segment(unsigned segment_id, byte * address, int flushing)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /*    if all buffers full we'll have to wait...
 214          */
 215         wait_segment(writing);
 216         if (buffer[tail].status == error) {
 217                 /*  setup for a retry
 218                  */
 219                 buffer[tail].status = waiting;
 220                 bytes_written = -EAGAIN;        /* force retry */
 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                         /*  Implement hard write error recovery here
 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         /*    If just passed last segment on tape: wait for BOT or EOT mark.
 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         /*    should runner stop ?
 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;   /* aborted ? */
 261                 }
 262         }
 263         /*  Don't start tape if runner idle and segment empty.
 264          */
 265         if (result >= 0 && !(runner_status == idle &&
 266                     get_bad_sector_entry(segment_id) == EMPTY_SEGMENT)) {
 267                 if (buffer[tail].status == done) {
 268                         /*    now at least one buffer is empty, fill it with our data.
 269                          *    skip bad sectors and generate ecc.
 270                          *    copy_and_gen_ecc return nr of bytes written,
 271                          *    range 0..29 Kb inclusive !
 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                 /*    Start tape only if all buffers full or flush mode.
 283                  *    This will give higher probability of streaming.
 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 /*  Write as much as fits from buffer to the given segment on tape
 295  *  and handle retries.
 296  *  Return the number of bytes written (>= 0), or:
 297  *      -EIO          write failed
 298  *      -EINTR        interrupted by signal
 299  *      -ENOSPC       device full
 300  */
 301 int _write_segment(unsigned int segment_id, byte * buffer, int flush)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;       /* tape full */
 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;  /* give up */
 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 {        /* success */
 328                         if (result == 0) {      /* empty segment */
 329                                 TRACE(4, "empty segment, nothing written");
 330                         }
 331                         break;
 332                 }
 333                 /* Allow escape from loop when signaled !
 334                  */
 335                 if (current->signal & _DONT_BLOCK) {
 336                         TRACE(2, "interrupted by signal");
 337                         TRACE_EXIT;
 338                         result = -EINTR;        /* is this the right return value ? */
 339                         break;
 340                 }
 341         }
 342         TRACE_EXIT;
 343         return result;
 344 }
 345 
 346 int update_header_segment(unsigned segment, byte * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                         /*  Force flush for single segment instead of relying on
 371                          *  flush in read_segment for multiple segments.
 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) {      /* read back and verify */
 381                         result = read_segment(segment, scratch_buffer, &status, 0);
 382                         /*  Should retry if soft error during read !
 383                          *  TO BE IMPLEMENTED
 384                          */
 385                         if (result >= 0) {
 386                                 if (memcmp(buffer, scratch_buffer, sizeof(buffer)) == 0) {
 387                                         result = 0;     /* verified */
 388                                         TRACE(5, "verified");
 389                                 } else {
 390                                         result = -EIO;  /* verify failed */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;     /* exit and fake success */
 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();    /* prevents extra rewind */
 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();    /* prevents extra rewind */
 478                                 result = ftape_write_header_segments(buffer);
 479                         }
 480                 }
 481         }
 482         TRACE_EXIT;
 483         return result;
 484 }
 485 
 486 int ftape_flush_buffers(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;         /* prevent further writes if this fails */
 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          *    If there is any data not written to tape yet, append zero's
 518          *    up to the end of the sector. Then write the segment(s) to tape.
 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);  /* pad buffer */
 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                                         /*  Need another segment for remaining data, move the remainder
 544                                          *  to the beginning of the buffer
 545                                          */
 546                                         memmove(deblock_buffer, deblock_buffer + written, data_remaining);
 547                                 }
 548                         }
 549                         ++ftape_seg_pos;
 550                 } while (data_remaining > 0);
 551                 /*  Data written to last segment == data_remaining + written
 552                  *  value is in range [1..29K].
 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                         /*  Last sector of segment was used for data, so put eof mark
 558                          *  in next segment and position at second file mark.
 559                          */
 560                         if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
 561                                 ++ftape_seg_pos;        /* position between file marks */
 562                         }
 563                 } else {
 564                         /*  Put eof mark in previous segment after data and position
 565                          *  at second file mark.
 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;        /* position between file marks */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                  *    If we haven't read the header segment yet, do it now.
 606                  *    This will verify the configuration, get the eof markers
 607                  *    and the bad sector table.
 608                  *    We'll use the deblock buffer for scratch.
 609                  */
 610                 result = read_header_segment(deblock_buffer);
 611                 if (result >= 0 && ftape_seg_pos > ftape_last_segment.id) {
 612                         result = -ENOSPC;       /* full is full */
 613                 }
 614         }
 615         if (result < 0) {
 616                 TRACE_EXIT;
 617                 return result;
 618         }
 619         /*
 620          *    This part writes data blocks to tape until the
 621          *    requested amount is written.
 622          *    The data will go in a buffer until it's enough
 623          *    for a segment without bad sectors. Then we'll write
 624          *    that segment to tape.
 625          *    The bytes written will be removed from the buffer
 626          *    and the process is repeated until there is less
 627          *    than one segment to write left in the buffer.
 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                         /*  If this is the last buffer to be written, let flush handle it.
 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                         /* Got one full buffer, write it to disk
 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;       /* failed, retry same segment */
 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                                 /* Partial write: move remainder in lower part of buffer
 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;   /* remainder */
 680                         ++ftape_seg_pos;
 681                         /* Allow us to escape from this loop with a signal !
 682                          */
 683                         if (current->signal & _DONT_BLOCK) {
 684                                 TRACE(2, "interrupted by signal");
 685                                 last_write_failed = 1;
 686                                 TRACE_EXIT;
 687                                 return -EINTR;  /* is this the right return value ? */
 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;         /* bytes written */
 700 }
 701 
 702 int ftape_fix(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                 /*  This will copy header segment 2 to header segment 1
 713                  *  Spares us a tape format operation if header 2 is still good.
 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 }

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