Print this page
    
NEX-9532 NDMP: readdir errors when file/directory has special characters
Reviewed by: Peer Dampmann <peer.dampmann@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Revert "NEX-5801 Snapshots left over after failed backups"
This reverts commit f182fb95f09036db71fbfc6f0a6b90469b761f21.
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-2911 NDMP logging should use syslog and is too chatty
NEX-799 past last file mark returned NDMP_IO_ERR, should be NDMP_EOM_ERR (V4+)
NEX-812 NDMP backup terminate after hit the EOM in Netbackup backup
NEX-355 NDMP backup, EOF position remains on BOT side of filemark
NEX-249 NS ndmp can't write to a brand new tape with IO error (fix cstyle)
SUP-484 NDMP backup jobs error out when reaching the end of media (EOM)
NEX-249 NS ndmp can't write to a brand new tape with IO error
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/ndmpd/ndmp/ndmpd_tape.c
          +++ new/usr/src/cmd/ndmpd/ndmp/ndmpd_tape.c
   1    1  /*
   2    2   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3    3   * Use is subject to license terms.
   4    4   */
   5    5  /*
   6    6   * BSD 3 Clause License
   7    7   *
   8    8   * Copyright (c) 2007, The Storage Networking Industry Association.
   9    9   *
  10   10   * Redistribution and use in source and binary forms, with or without
  11   11   * modification, are permitted provided that the following conditions
  12   12   * are met:
  13   13   *      - Redistributions of source code must retain the above copyright
  14   14   *        notice, this list of conditions and the following disclaimer.
  15   15   *
  16   16   *      - Redistributions in binary form must reproduce the above copyright
  17   17   *        notice, this list of conditions and the following disclaimer in
  18   18   *        the documentation and/or other materials provided with the
  19   19   *        distribution.
  20   20   *
  21   21   *      - Neither the name of The Storage Networking Industry Association (SNIA)
  22   22   *        nor the names of its contributors may be used to endorse or promote
  23   23   *        products derived from this software without specific prior written
  24   24   *        permission.
  25   25   *
  26   26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27   27   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28   28   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29   29   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  
    | 
      ↓ open down ↓ | 
    29 lines elided | 
    
      ↑ open up ↑ | 
  
  30   30   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31   31   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32   32   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33   33   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34   34   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35   35   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36   36   * POSSIBILITY OF SUCH DAMAGE.
  37   37   */
  38   38  /* Copyright (c) 2007, The Storage Networking Industry Association. */
  39   39  /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  40      -/* Copyright 2014 Nexenta Systems, Inc.  All rights reserved. */
       40 +/* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
  41   41  
  42   42  #include <sys/param.h>
       43 +#include <syslog.h>
  43   44  #include <fcntl.h>
  44   45  #include <sys/mtio.h>
  45   46  #include <errno.h>
  46   47  #include <stdio.h>
  47   48  #include <string.h>
  48   49  #include <unistd.h>
  49   50  #include "ndmpd_common.h"
  50   51  #include "ndmpd.h"
  51   52  
  52   53  static void tape_open_send_reply(ndmp_connection_t *connection, int err);
  53   54  static void unbuffered_read(ndmpd_session_t *session, char *buf, long wanted,
  54   55      ndmp_tape_read_reply *reply);
  55   56  static boolean_t validmode(int mode);
  56   57  static void common_tape_open(ndmp_connection_t *connection, char *devname,
  57   58      int ndmpmode);
  58   59  static void common_tape_close(ndmp_connection_t *connection);
  59   60  
  60   61  /*
  61   62   * Configurable delay & time when the tape is
  62   63   * busy during opening the tape.
  63   64   */
  64   65  int ndmp_tape_open_retries = 5;
  65   66  int ndmp_tape_open_delay = 1000;
  66   67  
  67   68  /*
  68   69   * A few words about EOT (end-of-tape) and EOM handling on tapes with SVR4
  69   70   * semantic:
  70   71   *
  71   72   * We adhere to terminology as used in st driver.  EOT means end of recorded
  72   73   * data on a tape. This is different from EOM (somewhere referred to as LEOT)
  73   74   * which is the end of tape medium. EOT is meaningful only for reads while EOM
  74   75   * is meaningful only for writes. It's not possible to read after EOT (fails
  75   76   * with EIO), but it's possible to write data after EOM. EOM returned by st
  76   77   * driver on modern tape drives is just indication that the physical end of
  77   78   * tape medium is nearing and that writer should write just the necessary
  78   79   * minimum and stop writing. When physical end of tape is reached all writes
  79   80   * return EIO. If EOM is crossed during read operation then st driver doesn't
  80   81   * bother to report it to client and that's alright because reads don't care
  81   82   * where medium physically ends but they care about meaningful data recorded on
  82   83   * the tape and as long as there are such data reads should continue to work.
  83   84   *
  84   85   * When reading EOT is signalled by st driver by two empty consecutive reads
  85   86   * (with FSF done between them).  When writing EOM is signalled by empty write
  86   87   * (a write which writes zero bytes). Following writes succeed until physical
  87   88   * end of tape is reached in which case EIO is returned.
  88   89   */
  89   90  
  90   91  /*
  91   92   * ************************************************************************
  92   93   * NDMP V2 HANDLERS
  93   94   * ************************************************************************
  94   95   */
  95   96  
  96   97  /*
  97   98   * ndmpd_tape_open_v2
  98   99   *
  99  100   * This handler opens the specified tape device.
 100  101   *
 101  102   * Parameters:
 102  103   *   connection (input) - connection handle.
 103  104   *   body       (input) - request message body.
 104  105   *
 105  106   * Returns:
 106  107   *   void
 107  108   */
  
    | 
      ↓ open down ↓ | 
    55 lines elided | 
    
      ↑ open up ↑ | 
  
 108  109  void
 109  110  ndmpd_tape_open_v2(ndmp_connection_t *connection, void *body)
 110  111  {
 111  112          ndmp_tape_open_request_v2 *request = (ndmp_tape_open_request_v2 *) body;
 112  113          ndmpd_session_t *session = ndmp_get_client_data(connection);
 113  114          char adptnm[SCSI_MAX_NAME];
 114  115          int mode;
 115  116          int sid, lun;
 116  117          int err;
 117  118          scsi_adapter_t *sa;
 118      -        int devid;
      119 +        int devid = -1;
 119  120  
 120  121          err = NDMP_NO_ERR;
 121  122  
 122  123          if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) {
 123      -                NDMP_LOG(LOG_INFO,
      124 +                syslog(LOG_INFO,
 124  125                      "Connection already has a tape or scsi device open");
 125  126                  err = NDMP_DEVICE_OPENED_ERR;
 126  127          } else if (request->mode != NDMP_TAPE_READ_MODE &&
 127  128              request->mode != NDMP_TAPE_WRITE_MODE &&
 128  129              request->mode != NDMP_TAPE_RAW1_MODE) {
 129  130                  err = NDMP_ILLEGAL_ARGS_ERR;
 130  131          }
 131  132  
 132  133          if ((sa = scsi_get_adapter(0)) != NULL) {
 133      -                NDMP_LOG(LOG_DEBUG,
 134      -                    "Adapter device opened: %s", request->device.name);
 135  134                  (void) strlcpy(adptnm, request->device.name, SCSI_MAX_NAME-2);
 136  135                  adptnm[SCSI_MAX_NAME-1] = '\0';
 137  136                  sid = lun = -1;
 138  137          }
 139  138          /* try to get the scsi id etc.... */
 140  139          if (sa) {
 141  140                  scsi_find_sid_lun(sa, request->device.name, &sid, &lun);
 142  141                  if (ndmp_open_list_find(request->device.name, sid, lun) == 0 &&
 143  142                      (devid = tape_open(request->device.name,
 144  143                      O_RDWR | O_NDELAY)) < 0) {
 145      -                        NDMP_LOG(LOG_ERR, "Failed to open device %s: %m.",
      144 +                        syslog(LOG_ERR, "Failed to open device %s: %m.",
 146  145                              request->device.name);
 147  146                          err = NDMP_NO_DEVICE_ERR;
 148  147                  }
 149  148                  else
 150  149                          (void) close(devid);
 151  150          } else {
 152      -                NDMP_LOG(LOG_ERR, "%s: No such tape device.",
      151 +                syslog(LOG_ERR, "%s: No such tape device.",
 153  152                      request->device.name);
 154  153                  err = NDMP_NO_DEVICE_ERR;
 155  154          }
 156  155          if (err != NDMP_NO_ERR) {
 157  156                  tape_open_send_reply(connection, err);
 158  157                  return;
 159  158          }
 160  159  
 161  160          switch (ndmp_open_list_add(connection, adptnm, sid, lun, devid)) {
 162  161          case 0:
 163  162                  err = NDMP_NO_ERR;
 164  163                  break;
 165  164          case EBUSY:
 166  165                  err = NDMP_DEVICE_BUSY_ERR;
 167  166                  break;
 168  167          case ENOMEM:
 169  168                  err = NDMP_NO_MEM_ERR;
 170  169                  break;
 171  170          default:
 172  171                  err = NDMP_IO_ERR;
 173  172          }
 174  173          if (err != NDMP_NO_ERR) {
 175  174                  tape_open_send_reply(connection, err);
 176  175                  return;
 177  176          }
 178  177  
 179  178          /*
 180  179           * According to Connectathon 2001, the 0x7fffffff is a secret
 181  180           * code between "Workstartion Solutions" and * net_app.
 182  181           * If mode is set to this value, tape_open() won't fail if
 183  182           * the tape device is not ready.
 184  183           */
  
    | 
      ↓ open down ↓ | 
    22 lines elided | 
    
      ↑ open up ↑ | 
  
 185  184          if (request->mode != NDMP_TAPE_RAW1_MODE &&
 186  185              !is_tape_unit_ready(adptnm, 0)) {
 187  186                  (void) ndmp_open_list_del(adptnm, sid, lun);
 188  187                  tape_open_send_reply(connection, NDMP_NO_TAPE_LOADED_ERR);
 189  188                  return;
 190  189          }
 191  190  
 192  191          mode = (request->mode == NDMP_TAPE_READ_MODE) ? O_RDONLY : O_RDWR;
 193  192          mode |= O_NDELAY;
 194  193          if ((session->ns_tape.td_fd = open(request->device.name, mode)) < 0) {
 195      -                        NDMP_LOG(LOG_ERR, "Failed to open tape device %s: %m.",
      194 +                        syslog(LOG_ERR, "Failed to open tape device %s: %m.",
 196  195                              request->device.name);
 197  196                          switch (errno) {
 198  197                          case EACCES:
 199  198                                  err = NDMP_WRITE_PROTECT_ERR;
 200  199                                  break;
 201  200                          case ENXIO:
 202  201                          case ENOENT:
 203  202                                  err = NDMP_NO_DEVICE_ERR;
 204  203                                  break;
 205  204                          case EBUSY:
 206  205                                  err = NDMP_DEVICE_BUSY_ERR;
 207  206                                  break;
 208  207                          default:
 209  208                                  err = NDMP_IO_ERR;
 210  209                          }
 211  210  
 212  211                          (void) ndmp_open_list_del(adptnm, sid, lun);
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
 213  212                          tape_open_send_reply(connection, err);
 214  213                          return;
 215  214                  }
 216  215  
 217  216          session->ns_tape.td_mode = request->mode;
 218  217          session->ns_tape.td_sid = sid;
 219  218          session->ns_tape.td_lun = lun;
 220  219          (void) strlcpy(session->ns_tape.td_adapter_name, adptnm, SCSI_MAX_NAME);
 221  220          session->ns_tape.td_record_count = 0;
 222  221  
 223      -        NDMP_LOG(LOG_DEBUG, "Tape is opened fd: %d", session->ns_tape.td_fd);
 224      -
 225  222          tape_open_send_reply(connection, NDMP_NO_ERR);
 226  223  }
 227  224  
 228  225  
 229  226  /*
 230  227   * ndmpd_tape_close_v2
 231  228   *
 232  229   * This handler closes the currently open tape device.
 233  230   *
 234  231   * Parameters:
 235  232   *   connection (input) - connection handle.
 236  233   *   body       (input) - request message body.
 237  234   *
 238  235   * Returns:
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
 239  236   *   void
 240  237   */
 241  238  /*ARGSUSED*/
 242  239  void
 243  240  ndmpd_tape_close_v2(ndmp_connection_t *connection, void *body)
 244  241  {
 245  242          ndmp_tape_close_reply reply;
 246  243          ndmpd_session_t *session = ndmp_get_client_data(connection);
 247  244  
 248  245          if (session->ns_tape.td_fd == -1) {
 249      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      246 +                syslog(LOG_ERR, "Tape device is not open.");
 250  247                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 251  248                  ndmp_send_reply(connection, (void *) &reply,
 252  249                      "sending tape_close reply");
 253  250                  return;
 254  251          }
 255  252          common_tape_close(connection);
 256  253  
 257  254  }
 258  255  
 259  256  /*
 260  257   * ndmpd_tape_get_state_v2
 261  258   *
 262  259   * This handler handles the tape_get_state request.
 263  260   * Status information for the currently open tape device is returned.
 264  261   *
 265  262   * Parameters:
 266  263   *   connection (input) - connection handle.
 267  264   *   body       (input) - request message body.
 268  265   *
 269  266   * Returns:
 270  267   *   void
 271  268   */
 272  269  /*ARGSUSED*/
 273  270  void
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
 274  271  ndmpd_tape_get_state_v2(ndmp_connection_t *connection, void *body)
 275  272  
 276  273  {
 277  274          ndmp_tape_get_state_reply_v2 reply;
 278  275          ndmpd_session_t *session = ndmp_get_client_data(connection);
 279  276          struct mtget mtstatus;
 280  277          struct mtdrivetype_request dtpr;
 281  278          struct mtdrivetype dtp;
 282  279  
 283  280          if (session->ns_tape.td_fd == -1) {
 284      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      281 +                syslog(LOG_ERR, "Tape device is not open.");
 285  282                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 286  283                  ndmp_send_reply(connection, (void *) &reply,
 287  284                      "sending tape_get_state reply");
 288  285                  return;
 289  286          }
 290  287  
 291  288          if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) < 0) {
 292      -                NDMP_LOG(LOG_ERR, "Failed to get status from tape: %m.");
 293      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m.");
      289 +                syslog(LOG_ERR, "Failed to get status from tape: %m.");
 294  290                  reply.error = NDMP_IO_ERR;
 295  291                  ndmp_send_reply(connection, (void *)&reply,
 296  292                      "sending tape_get_state reply");
 297  293                  return;
 298  294          }
 299  295  
 300  296          dtpr.size = sizeof (struct mtdrivetype);
 301  297          dtpr.mtdtp = &dtp;
 302  298          if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) {
 303      -                NDMP_LOG(LOG_ERR,
      299 +                syslog(LOG_ERR,
 304  300                      "Failed to get drive type information from tape: %m.");
 305      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m.");
 306  301                  reply.error = NDMP_IO_ERR;
 307  302                  ndmp_send_reply(connection, (void *)&reply,
 308  303                      "sending tape_get_state reply");
 309  304                  return;
 310  305          }
 311  306  
 312  307          reply.flags = 0;
 313  308  
 314  309          reply.file_num = mtstatus.mt_fileno;
 315  310          reply.soft_errors = 0;
 316  311          reply.block_size = dtp.bsize;
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
 317  312          if (dtp.bsize == 0)
 318  313                  reply.blockno = mtstatus.mt_blkno;
 319  314          else
 320  315                  reply.blockno = mtstatus.mt_blkno *
 321  316                      (session->ns_mover.md_record_size / dtp.bsize);
 322  317  
 323  318          reply.soft_errors = 0;
 324  319          reply.total_space = long_long_to_quad(0);       /* not supported */
 325  320          reply.space_remain = long_long_to_quad(0);      /* not supported */
 326  321  
 327      -        NDMP_LOG(LOG_DEBUG,
 328      -            "flags: 0x%x, file_num: %d, block_size: %d, blockno: %d",
 329      -            reply.flags, reply.file_num, reply.block_size, reply.blockno);
 330      -
 331  322          reply.error = NDMP_NO_ERR;
 332  323          ndmp_send_reply(connection, (void *) &reply,
 333  324              "sending tape_get_state reply");
 334  325  }
 335  326  
 336  327  
 337  328  /*
 338  329   * ndmpd_tape_mtio_v2
 339  330   *
 340  331   * This handler handles tape_mtio requests.
 341  332   *
 342  333   * Parameters:
 343  334   *   connection (input) - connection handle.
 344  335   *   body       (input) - request message body.
 345  336   *
 346  337   * Returns:
 347  338   *   void
 348  339   */
 349  340  void
 350  341  ndmpd_tape_mtio_v2(ndmp_connection_t *connection, void *body)
 351  342  {
 352  343          ndmp_tape_mtio_request *request = (ndmp_tape_mtio_request *) body;
 353  344          ndmp_tape_mtio_reply reply;
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
 354  345          ndmpd_session_t *session = ndmp_get_client_data(connection);
 355  346  
 356  347          struct mtop tapeop;
 357  348          struct mtget mtstatus;
 358  349          int retry = 0;
 359  350          int rc;
 360  351  
 361  352          reply.resid_count = 0;
 362  353  
 363  354          if (session->ns_tape.td_fd == -1) {
 364      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      355 +                syslog(LOG_ERR, "Tape device is not open.");
 365  356                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 366  357                  ndmp_send_reply(connection, (void *) &reply,
 367  358                      "sending tape_mtio reply");
 368  359                  return;
 369  360          }
 370  361  
 371  362          reply.error = NDMP_NO_ERR;
 372  363          switch (request->tape_op) {
 373  364          case NDMP_MTIO_FSF:
 374  365                  tapeop.mt_op = MTFSF;
 375  366                  break;
 376  367          case NDMP_MTIO_BSF:
 377  368                  tapeop.mt_op = MTBSF;
 378  369                  break;
 379  370          case NDMP_MTIO_FSR:
 380  371                  tapeop.mt_op = MTFSR;
 381  372                  break;
 382  373          case NDMP_MTIO_BSR:
 383  374                  tapeop.mt_op = MTBSR;
 384  375                  break;
 385  376          case NDMP_MTIO_REW:
 386  377                  tapeop.mt_op = MTREW;
 387  378                  break;
 388  379          case NDMP_MTIO_EOF:
 389  380                  if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE)
 390  381                          reply.error = NDMP_PERMISSION_ERR;
 391  382                  tapeop.mt_op = MTWEOF;
 392  383                  break;
 393  384          case NDMP_MTIO_OFF:
 394  385                  tapeop.mt_op = MTOFFL;
 395  386                  break;
 396  387  
 397  388          case NDMP_MTIO_TUR: /* test unit ready */
 398  389  
 399  390                  if (is_tape_unit_ready(session->ns_tape.td_adapter_name,
 400  391                      session->ns_tape.td_fd) == 0)
 401  392                          /* tape not ready ? */
 402  393                          reply.error = NDMP_NO_TAPE_LOADED_ERR;
 403  394                  break;
 404  395  
 405  396          default:
 406  397                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
 407  398          }
 408  399  
 409  400          if (reply.error == NDMP_NO_ERR && request->tape_op != NDMP_MTIO_TUR) {
 410  401                  tapeop.mt_count = request->count;
 411  402  
 412  403                  do {
 413  404                          NS_UPD(twait, trun);
 414  405                          errno = 0;
 415  406                          rc = ioctl(session->ns_tape.td_fd, MTIOCTOP, &tapeop);
 416  407                          NS_UPD(trun, twait);
 417      -                        NDMP_LOG(LOG_DEBUG,
 418      -                            "ioctl MTIO rc:%d, cmd:%d, retry:%d, error: %d",
 419      -                            rc, tapeop.mt_op, retry, errno);
 420  408                  } while (rc < 0 && errno == EIO &&
 421  409                      retry++ < 5);
 422  410  
 423  411                  /*
 424  412                   * Ignore I/O errors since these usually are the result of
 425  413                   * attempting to position past the beginning or end of the tape.
 426  414                   * The residual count will be returned and can be used to
 427  415                   * determine that the call was not completely successful.
 428  416                   */
 429  417                  if (rc < 0) {
 430      -                        NDMP_LOG(LOG_ERR,
      418 +                        syslog(LOG_ERR,
 431  419                              "Failed to send command to tape: %m.");
 432      -                        NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCTOP) error: %m.");
 433  420  
 434  421                          /* MTWEOF doesnt have residual count */
 435  422                          if (tapeop.mt_op == MTWEOF)
 436  423                                  reply.error = NDMP_IO_ERR;
 437  424                          else
 438  425                                  reply.error = NDMP_NO_ERR;
 439  426                          reply.resid_count = tapeop.mt_count;
 440  427                          ndmp_send_reply(connection, (void *)&reply,
 441  428                              "sending tape_mtio reply");
 442  429                          return;
 443  430                  }
 444  431  
 445  432                  if (request->tape_op != NDMP_MTIO_REW &&
 446  433                      request->tape_op != NDMP_MTIO_OFF) {
 447  434                          if (ioctl(session->ns_tape.td_fd, MTIOCGET,
 448  435                              &mtstatus) < 0) {
 449      -                                NDMP_LOG(LOG_ERR,
      436 +                                syslog(LOG_ERR,
 450  437                                      "Failed to send command to tape: %m.");
 451      -                                NDMP_LOG(LOG_DEBUG,
 452      -                                    "ioctl(MTIOCGET) error: %m.");
 453  438                                  reply.error = NDMP_IO_ERR;
 454  439                                  ndmp_send_reply(connection, (void *)&reply,
 455  440                                      "sending tape_mtio reply");
 456  441  
 457  442                                  return;
 458  443                          }
 459  444  
 460  445                          reply.resid_count = labs(mtstatus.mt_resid);
 461  446                  }
 462  447          }
 463  448  
 464      -        NDMP_LOG(LOG_DEBUG, "resid_count: %d",
 465      -            reply.resid_count);
 466  449          ndmp_send_reply(connection, (void *) &reply, "sending tape_mtio reply");
 467  450  }
 468  451  
 469  452  
 470  453  /*
 471  454   * ndmpd_tape_read_v2
 472  455   *
 473  456   * This handler handles tape_read requests.
 474  457   * This interface is a non-buffered interface. Each read request
 475  458   * maps directly to a read to the tape device. It is the responsibility
 476  459   * of the NDMP client to issue read requests with a length that is at
 477  460   * least as large as the record size used write the tape. The tape driver
 478  461   * always reads a full record. Data is discarded if the read request is
 479  462   * smaller than the record size.
 480  463   * It is the responsibility of the NDMP client to ensure that the
 481  464   * length is a multiple of the tape block size if the tape device
 482  465   * is in fixed block mode.
 483  466   *
 484  467   * Parameters:
 485  468   *   connection (input) - connection handle.
 486  469   *   body       (input) - request message body.
 487  470   *
 488  471   * Returns:
 489  472   *   void
 490  473   */
 491  474  void
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
 492  475  ndmpd_tape_read_v2(ndmp_connection_t *connection, void *body)
 493  476  {
 494  477          ndmp_tape_read_request *request = (ndmp_tape_read_request *) body;
 495  478          ndmp_tape_read_reply reply;
 496  479          ndmpd_session_t *session = ndmp_get_client_data(connection);
 497  480          char *buf;
 498  481  
 499  482          reply.data_in.data_in_len = 0;
 500  483  
 501  484          if (session->ns_tape.td_fd == -1) {
 502      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      485 +                syslog(LOG_ERR, "Tape device is not open.");
 503  486                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 504  487                  ndmp_send_reply(connection, (void *)&reply,
 505  488                      "sending tape_read reply");
 506  489                  return;
 507  490          }
 508  491          if (request->count == 0) {
 509  492                  reply.error = NDMP_NO_ERR;
 510  493                  ndmp_send_reply(connection, (void *)&reply,
 511  494                      "sending tape_read reply");
 512  495                  return;
 513  496          }
 514  497          if ((buf = ndmp_malloc(request->count)) == 0) {
 515  498                  reply.error = NDMP_NO_MEM_ERR;
 516  499                  ndmp_send_reply(connection, (void *)&reply,
 517  500                      "sending tape_read reply");
 518  501                  return;
 519  502          }
 520  503  
 521  504          unbuffered_read(session, buf, request->count, &reply);
 522  505  
 523  506          ndmp_send_reply(connection, (void *) &reply, "sending tape_read reply");
 524  507          (void) free(buf);
 525  508  }
 526  509  
 527  510  
 528  511  /*
 529  512   * ndmpd_tape_execute_cdb_v2
 530  513   *
 531  514   * This handler handles tape_execute_cdb requests.
 532  515   *
 533  516   * Parameters:
 534  517   *   connection (input) - connection handle.
 535  518   *   body       (input) - request message body.
 536  519   *
 537  520   * Returns:
 538  521   *   void
 539  522   */
 540  523  void
 541  524  ndmpd_tape_execute_cdb_v2(ndmp_connection_t *connection, void *body)
  
    | 
      ↓ open down ↓ | 
    29 lines elided | 
    
      ↑ open up ↑ | 
  
 542  525  {
 543  526          ndmp_tape_execute_cdb_request *request;
 544  527          ndmp_tape_execute_cdb_reply reply;
 545  528          ndmpd_session_t *session = ndmp_get_client_data(connection);
 546  529  
 547  530          request = (ndmp_tape_execute_cdb_request *) body;
 548  531  
 549  532          if (session->ns_tape.td_fd == -1) {
 550  533                  (void) memset((void *) &reply, 0, sizeof (reply));
 551  534  
 552      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      535 +                syslog(LOG_ERR, "Tape device is not open.");
 553  536                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 554  537                  ndmp_send_reply(connection, (void *) &reply,
 555  538                      "sending tape_execute_cdb reply");
 556  539          } else {
 557  540                  ndmp_execute_cdb(session, session->ns_tape.td_adapter_name,
 558  541                      session->ns_tape.td_sid, session->ns_tape.td_lun,
 559  542                      (ndmp_execute_cdb_request *)request);
 560  543          }
 561  544  }
 562  545  
 563  546  
 564  547  /*
 565  548   * ************************************************************************
 566  549   * NDMP V3 HANDLERS
 567  550   * ************************************************************************
 568  551   */
 569  552  
 570  553  /*
 571  554   * ndmpd_tape_open_v3
 572  555   *
 573  556   * This handler opens the specified tape device.
 574  557   *
 575  558   * Parameters:
 576  559   *   connection (input) - connection handle.
 577  560   *   body       (input) - request message body.
 578  561   *
 579  562   * Returns:
 580  563   *   void
 581  564   */
 582  565  void
 583  566  ndmpd_tape_open_v3(ndmp_connection_t *connection, void *body)
 584  567  {
 585  568          ndmp_tape_open_request_v3 *request = (ndmp_tape_open_request_v3 *)body;
 586  569  
 587  570          common_tape_open(connection, request->device, request->mode);
 588  571  }
 589  572  
 590  573  
 591  574  /*
 592  575   * ndmpd_tape_get_state_v3
 593  576   *
 594  577   * This handler handles the ndmp_tape_get_state_request.
 595  578   * Status information for the currently open tape device is returned.
 596  579   *
 597  580   * Parameters:
 598  581   *   connection (input) - connection handle.
 599  582   *   body       (input) - request message body.
 600  583   *
 601  584   * Returns:
 602  585   *   void
 603  586   */
 604  587  /*ARGSUSED*/
  
    | 
      ↓ open down ↓ | 
    42 lines elided | 
    
      ↑ open up ↑ | 
  
 605  588  void
 606  589  ndmpd_tape_get_state_v3(ndmp_connection_t *connection, void *body)
 607  590  {
 608  591          ndmp_tape_get_state_reply_v3 reply;
 609  592          ndmpd_session_t *session = ndmp_get_client_data(connection);
 610  593          struct mtdrivetype_request dtpr;
 611  594          struct mtdrivetype dtp;
 612  595          struct mtget mtstatus;
 613  596  
 614  597          if (session->ns_tape.td_fd == -1) {
 615      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      598 +                syslog(LOG_ERR, "Tape device is not open.");
 616  599                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 617  600                  ndmp_send_reply(connection, (void *) &reply,
 618  601                      "sending tape_get_state reply");
 619  602                  return;
 620  603          }
 621  604  
 622  605          if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == -1) {
 623      -                NDMP_LOG(LOG_ERR, "Failed to get status from tape: %m.");
 624      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m.");
      606 +                syslog(LOG_ERR, "Failed to get status from tape: %m.");
 625  607  
 626  608                  reply.error = NDMP_IO_ERR;
 627  609                  ndmp_send_reply(connection, (void *)&reply,
 628  610                      "sending tape_get_state reply");
 629  611                  return;
 630  612          }
 631  613  
 632  614          dtpr.size = sizeof (struct mtdrivetype);
 633  615          dtpr.mtdtp = &dtp;
 634  616          if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) {
 635      -                NDMP_LOG(LOG_ERR,
      617 +                syslog(LOG_ERR,
 636  618                      "Failed to get drive type information from tape: %m.");
 637      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m.");
 638  619  
 639  620                  reply.error = NDMP_IO_ERR;
 640  621                  ndmp_send_reply(connection, (void *)&reply,
 641  622                      "sending tape_get_state reply");
 642  623                  return;
 643  624          }
 644  625  
 645  626          reply.flags = 0;
 646  627  
 647  628          reply.file_num = mtstatus.mt_fileno;
 648  629          reply.soft_errors = 0;
 649  630          reply.block_size = dtp.bsize;
 650  631          if (dtp.bsize == 0)
 651  632                  reply.blockno = mtstatus.mt_blkno;
 652  633          else
 653  634                  reply.blockno = mtstatus.mt_blkno *
 654  635                      (session->ns_mover.md_record_size / dtp.bsize);
 655  636          reply.total_space = long_long_to_quad(0); /* not supported */
 656  637          reply.space_remain = long_long_to_quad(0); /* not supported */
 657  638          reply.partition = 0; /* not supported */
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
 658  639  
 659  640          reply.soft_errors = 0;
 660  641          reply.total_space = long_long_to_quad(0LL);
 661  642          reply.space_remain = long_long_to_quad(0LL);
 662  643  
 663  644          reply.invalid = NDMP_TAPE_STATE_SOFT_ERRORS_INVALID |
 664  645              NDMP_TAPE_STATE_TOTAL_SPACE_INVALID |
 665  646              NDMP_TAPE_STATE_SPACE_REMAIN_INVALID |
 666  647              NDMP_TAPE_STATE_PARTITION_INVALID;
 667  648  
 668      -
 669      -        NDMP_LOG(LOG_DEBUG, "f 0x%x, fnum %d, bsize %d, bno: %d",
 670      -            reply.flags, reply.file_num, reply.block_size, reply.blockno);
 671      -
 672  649          reply.error = NDMP_NO_ERR;
 673  650          ndmp_send_reply(connection, (void *) &reply,
 674  651              "sending tape_get_state reply");
 675  652  }
 676  653  
 677  654  /*
 678  655   * tape_is_at_bot
 679  656   *
 680  657   * Returns 1 if tape is at BOT, 0 on error or not at BOT.
 681  658   *
 682  659   */
 683  660  int
 684  661  tape_is_at_bot(ndmpd_session_t *session)
 685  662  {
 686  663          struct mtget mtstatus;
 687  664  
 688  665          if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == 0 &&
 689  666              mtstatus.mt_fileno == 0 && mtstatus.mt_blkno == 0)
 690  667                  return (1);
 691  668  
 692  669          return (0);
 693  670  }
 694  671  
 695  672  /*
 696  673   * If we are at the beginning of a file (block # is zero) and read returns
 697  674   * zero bytes then this has to be end of recorded data on the tape. Repeated
 698  675   * reads at EOT return EIO. In both cases (zero read and EIO read) this
 699  676   * function should be used to test if we are at EOT.
 700  677   *
 701  678   * Returns 1 if tape is at BOF, 0 on error or not at BOF.
 702  679   */
 703  680  int
 704  681  tape_is_at_bof(ndmpd_session_t *session)
 705  682  {
 706  683          struct mtget mtstatus;
 707  684  
 708  685          if ((ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == 0) &&
 709  686              (mtstatus.mt_fileno > 0) && (mtstatus.mt_blkno == 0))
 710  687                  return (1);
 711  688  
 712  689          return (0);
 713  690  }
 714  691  
 715  692  /*
 716  693   * Skips forward over a file mark and then back before the file mark. Why is
 717  694   * this needed? There are two reasons for it:
 718  695   *
 719  696   * 1) Because NDMPv4 spec requires that when EOF is encountered, the tape
 720  697   * position should remain on BOT side of the file mark. When st driver reaches
 721  698   * end of file get-position mtioctl reports position before file mark, however
 722  699   * the file mark has already been read and the real position is thus after the
 723  700   * file mark (real position as reported for example by uscsi commands). Thus we
 724  701   * need to do FSF, which does nothing but only updates file & block counter in
 725  702   * st driver and then BSF, which sets the position before the file mark. Thus
 726  703   * current position as reported by scsi and mtioctl will be in sync.
 727  704   *
 728  705   * 2) st driver returns EIO for repeated reads at EOF while according to NDMP
 729  706   * spec we should continue to return zero bytes until FSF is done. By skipping
 730  707   * forward and backward, st driver will return zero bytes for the next read
 731  708   * again and we don't need to specifically handle this case.
 732  709   */
 733  710  void
 734  711  fm_dance(ndmpd_session_t *session)
 735  712  {
 736  713          (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1);
 737  714          (void) ndmp_mtioctl(session->ns_tape.td_fd, MTBSF, 1);
 738  715  }
 739  716  
 740  717  /*
 741  718   * ndmpd_tape_write_v3
 742  719   *
 743  720   * This handler handles tape_write requests.  This interface is a non-buffered
 744  721   * interface. Each write request maps directly to a write to the tape device.
 745  722   * It is the responsibility of the NDMP client to pad the data to the desired
 746  723   * record size.  It is the responsibility of the NDMP client to ensure that the
 747  724   * length is a multiple of the tape block size if the tape device is in fixed
 748  725   * block mode.
 749  726   *
 750  727   * A logical end of tape will return number of bytes written less than
 751  728   * requested, and one more request to write will give 0 and NDMP_EOM_ERR,
 752  729   * followed by NDMP_NO_ERR until NDMP_IO_ERR when physical end of tape is
 753  730   * reached.
 754  731   *
 755  732   * Parameters:
 756  733   *   connection (input) - connection handle.
  
    | 
      ↓ open down ↓ | 
    75 lines elided | 
    
      ↑ open up ↑ | 
  
 757  734   *   body       (input) - request message body.
 758  735   */
 759  736  void ndmpd_tape_write_v3(ndmp_connection_t *connection, void *body) {
 760  737          ndmp_tape_write_request *request = (ndmp_tape_write_request *)body;
 761  738          ndmp_tape_write_reply reply; ndmpd_session_t *session =
 762  739                  ndmp_get_client_data(connection); ssize_t n;
 763  740  
 764  741          reply.count = 0;
 765  742  
 766  743          if (session->ns_tape.td_fd == -1) {
 767      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      744 +                syslog(LOG_ERR, "Tape device is not open.");
 768  745                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 769  746                  ndmp_send_reply(connection, (void *) &reply,
 770  747                      "sending tape_write reply");
 771  748                  return;
 772  749          }
 773  750          if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
 774      -                NDMP_LOG(LOG_INFO, "Tape device opened in read-only mode");
      751 +                syslog(LOG_INFO, "Tape device opened in read-only mode");
 775  752                  reply.error = NDMP_PERMISSION_ERR;
 776  753                  ndmp_send_reply(connection, (void *) &reply,
 777  754                      "sending tape_write reply");
 778  755                  return;
 779  756          }
 780  757          if (request->data_out.data_out_len == 0) {
 781  758                  reply.error = NDMP_NO_ERR;
 782  759                  ndmp_send_reply(connection, (void *) &reply,
 783  760                      "sending tape_write reply");
 784  761                  return;
 785  762          }
 786  763  
 787  764          /*
 788  765           * V4 suggests that this should not be accepted
 789  766           * when mover is in listen or active state
 790  767           */
 791  768          if (session->ns_protocol_version == NDMPV4 &&
 792  769              (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN ||
 793  770              session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE)) {
 794  771  
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
 795  772                  reply.error = NDMP_DEVICE_BUSY_ERR;
 796  773                  ndmp_send_reply(connection, (void *) &reply,
 797  774                      "sending tape_write reply");
 798  775                  return;
 799  776          }
 800  777  
 801  778          n = write(session->ns_tape.td_fd, request->data_out.data_out_val,
 802  779              request->data_out.data_out_len);
 803  780  
 804  781          if (n < 0) {
 805      -                NDMP_LOG(LOG_ERR, "Tape write error: %m.");
      782 +                syslog(LOG_ERR, "Tape write error: %m.");
 806  783                  reply.error = NDMP_IO_ERR;
 807  784          } else if (n == 0) {
 808      -                NDMP_LOG(LOG_INFO, "EOM detected");
      785 +                syslog(LOG_INFO, "EOM detected");
 809  786                  reply.error = NDMP_EOM_ERR;
 810  787          } else {
 811  788                  NS_ADD(wtape, n);
 812  789                  reply.count = n;
 813  790                  reply.error = NDMP_NO_ERR;
 814  791  
 815  792                  if (n < request->data_out.data_out_len)
 816      -                        NDMP_LOG(LOG_DEBUG,
      793 +                        syslog(LOG_DEBUG,
 817  794                                  "EOM is coming (partial write of %d bytes)", n);
 818  795          }
 819  796  
 820  797          ndmp_send_reply(connection, (void *) &reply,
 821  798              "sending tape_write reply");
 822  799  }
 823  800  
 824  801  /*
 825  802   * ndmpd_tape_read_v3
 826  803   *
 827  804   * This handler handles tape_read requests.  This interface is a non-buffered
 828  805   * interface. Each read request maps directly to a read to the tape device. It
 829  806   * is the responsibility of the NDMP client to issue read requests with a
 830  807   * length that is at least as large as the record size used write the tape. The
 831  808   * tape driver always reads a full record. Data is discarded if the read
 832  809   * request is smaller than the record size.  It is the responsibility of the
 833  810   * NDMP client to ensure that the length is a multiple of the tape block size
 834  811   * if the tape device is in fixed block mode.
 835  812   *
 836  813   * A logical end of tape will return less bytes than requested, and one more
 837  814   * request to read will give 0 and NDMP_EOM_ERR.  All subsequent reads will
 838  815   * return NDMP_EOM_ERR until the tape is repositioned.
 839  816   *
 840  817   * Parameters:
 841  818   *   connection (input) - connection handle.
 842  819   *   body       (input) - request message body.
 843  820   */
 844  821  void
 845  822  ndmpd_tape_read_v3(ndmp_connection_t *connection, void *body)
  
    | 
      ↓ open down ↓ | 
    19 lines elided | 
    
      ↑ open up ↑ | 
  
 846  823  {
 847  824          ndmp_tape_read_request *request = (ndmp_tape_read_request *) body;
 848  825          ndmp_tape_read_reply reply;
 849  826          ndmpd_session_t *session = ndmp_get_client_data(connection);
 850  827          char *buf;
 851  828          int n;
 852  829  
 853  830          reply.data_in.data_in_len = 0;
 854  831  
 855  832          if (session->ns_tape.td_fd == -1) {
 856      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      833 +                syslog(LOG_ERR, "Tape device is not open.");
 857  834                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 858  835                  ndmp_send_reply(connection, (void *) &reply,
 859  836                      "sending tape_read reply");
 860  837                  return;
 861  838          }
 862  839          if (request->count == 0) {
 863  840                  reply.error = NDMP_NO_ERR;
 864  841                  ndmp_send_reply(connection, (void *) &reply,
 865  842                      "sending tape_read reply");
 866  843                  return;
 867  844          }
 868  845  
 869  846          /*
 870  847           * V4 suggests that this should not be accepted
 871  848           * when mover is in listen or active state
 872  849           */
 873  850          if (session->ns_protocol_version == NDMPV4 &&
 874  851              (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN ||
 875  852              session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE)) {
 876  853  
 877  854                  reply.error = NDMP_DEVICE_BUSY_ERR;
 878  855                  ndmp_send_reply(connection, (void *) &reply,
 879  856                      "sending tape_read reply");
 880  857                  return;
 881  858          }
 882  859  
 883  860          if ((buf = ndmp_malloc(request->count)) == NULL) {
 884  861                  reply.error = NDMP_NO_MEM_ERR;
 885  862                  ndmp_send_reply(connection, (void *) &reply,
 886  863                      "sending tape_read reply");
 887  864                  return;
 888  865          }
 889  866  
 890  867          n = read(session->ns_tape.td_fd, buf, request->count);
 891  868          if (n < 0) {
 892  869                  /*
 893  870                   * This fix is for Symantec during importing
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
 894  871                   * of spanned data between the tapes.
 895  872                   */
 896  873                  if (errno == ENOSPC) {
 897  874                          reply.error = NDMP_EOF_ERR;
 898  875                  }
 899  876                  /*
 900  877                   * If at beginning of file and read fails with EIO, then it's
 901  878                   * repeated attempt to read at EOT.
 902  879                   */
 903  880                  else if (errno == EIO && tape_is_at_bof(session)) {
 904      -                        NDMP_LOG(LOG_DEBUG, "Repeated read at EOT");
      881 +                        syslog(LOG_DEBUG, "Repeated read at EOT");
 905  882                          reply.error = NDMP_EOM_ERR;
 906  883                  }
 907  884                  /*
 908  885                   * According to NDMPv4 spec preferred error code when
 909  886                   * trying to read from blank tape is NDMP_EOM_ERR.
 910  887                   */
 911  888                  else if (errno == EIO && tape_is_at_bot(session)) {
 912      -                        NDMP_LOG(LOG_ERR, "Blank tape detected, returning EOM");
      889 +                        syslog(LOG_ERR, "Blank tape detected, returning EOM");
 913  890                          reply.error = NDMP_EOM_ERR;
 914  891                  } else {
 915      -                        NDMP_LOG(LOG_ERR, "Tape read error: %m.");
      892 +                        syslog(LOG_ERR, "Tape read error: %m.");
 916  893                          reply.error = NDMP_IO_ERR;
 917  894                  }
 918  895          } else if (n == 0) {
 919  896                  if (tape_is_at_bof(session)) {
 920      -                        NDMP_LOG(LOG_DEBUG, "EOT detected");
      897 +                        syslog(LOG_DEBUG, "EOT detected");
 921  898                          reply.error = NDMP_EOM_ERR;
 922  899                  } else {
 923  900                          /* reposition the tape to BOT side of FM */
 924  901                          fm_dance(session);
 925      -                        NDMP_LOG(LOG_DEBUG, "EOF detected");
      902 +                        syslog(LOG_DEBUG, "EOF detected");
 926  903                          reply.error = NDMP_EOF_ERR;
 927  904                  }
 928  905          } else {
 929  906                  session->ns_tape.td_pos += n;
 930  907                  reply.data_in.data_in_len = n;
 931  908                  reply.data_in.data_in_val = buf;
 932  909                  reply.error = NDMP_NO_ERR;
 933  910                  NS_ADD(rtape, n);
 934  911          }
 935  912  
 936  913          ndmp_send_reply(connection, (void *) &reply, "sending tape_read reply");
 937  914          free(buf);
 938  915  }
 939  916  
 940  917  
 941  918  /*
 942  919   * ************************************************************************
 943  920   * NDMP V4 HANDLERS
 944  921   * ************************************************************************
 945  922   */
 946  923  
 947  924  /*
 948  925   * ndmpd_tape_get_state_v4
 949  926   *
 950  927   * This handler handles the ndmp_tape_get_state_request.
 951  928   * Status information for the currently open tape device is returned.
 952  929   *
 953  930   * Parameters:
 954  931   *   connection (input) - connection handle.
 955  932   *   body       (input) - request message body.
 956  933   *
 957  934   * Returns:
 958  935   *   void
 959  936   */
 960  937  /*ARGSUSED*/
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
 961  938  void
 962  939  ndmpd_tape_get_state_v4(ndmp_connection_t *connection, void *body)
 963  940  {
 964  941          ndmp_tape_get_state_reply_v4 reply;
 965  942          ndmpd_session_t *session = ndmp_get_client_data(connection);
 966  943          struct mtget mtstatus;
 967  944          struct mtdrivetype_request dtpr;
 968  945          struct mtdrivetype dtp;
 969  946  
 970  947          if (session->ns_tape.td_fd == -1) {
 971      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
      948 +                syslog(LOG_ERR, "Tape device is not open.");
 972  949                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
 973  950                  ndmp_send_reply(connection, (void *) &reply,
 974  951                      "sending tape_get_state reply");
 975  952                  return;
 976  953          }
 977  954  
 978  955          /*
 979  956           * Need code to detect NDMP_TAPE_STATE_NOREWIND
 980  957           */
 981  958  
 982  959          if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == -1) {
 983      -                NDMP_LOG(LOG_ERR,
      960 +                syslog(LOG_ERR,
 984  961                      "Failed to get status information from tape: %m.");
 985      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m.");
 986  962  
 987  963                  reply.error = NDMP_IO_ERR;
 988  964                  ndmp_send_reply(connection, (void *)&reply,
 989  965                      "sending tape_get_state reply");
 990  966                  return;
 991  967          }
 992  968  
 993  969          dtpr.size = sizeof (struct mtdrivetype);
 994  970          dtpr.mtdtp = &dtp;
 995  971          if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) {
 996      -                NDMP_LOG(LOG_ERR,
      972 +                syslog(LOG_ERR,
 997  973                      "Failed to get drive type information from tape: %m.");
 998      -                NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m.");
 999  974  
1000  975                  reply.error = NDMP_IO_ERR;
1001  976                  ndmp_send_reply(connection, (void *)&reply,
1002  977                      "sending tape_get_state reply");
1003  978                  return;
1004  979          }
1005  980  
1006  981          reply.flags = NDMP_TAPE_NOREWIND;
1007  982  
1008  983          reply.file_num = mtstatus.mt_fileno;
1009  984          reply.soft_errors = 0;
1010  985          reply.block_size = dtp.bsize;
1011  986  
1012  987          if (dtp.bsize == 0)
1013  988                  reply.blockno = mtstatus.mt_blkno;
1014  989          else
1015  990                  reply.blockno = mtstatus.mt_blkno /
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
1016  991                      (session->ns_mover.md_record_size / dtp.bsize);
1017  992  
1018  993          reply.total_space = long_long_to_quad(0LL); /* not supported */
1019  994          reply.space_remain = long_long_to_quad(0LL); /* not supported */
1020  995          reply.soft_errors = 0;
1021  996          reply.unsupported = NDMP_TAPE_STATE_SOFT_ERRORS_INVALID |
1022  997              NDMP_TAPE_STATE_TOTAL_SPACE_INVALID |
1023  998              NDMP_TAPE_STATE_SPACE_REMAIN_INVALID |
1024  999              NDMP_TAPE_STATE_PARTITION_INVALID;
1025 1000  
1026      -        NDMP_LOG(LOG_DEBUG, "f 0x%x, fnum %d, bsize %d, bno: %d",
1027      -            reply.flags, reply.file_num, reply.block_size, reply.blockno);
1028      -
1029 1001          reply.error = NDMP_NO_ERR;
1030 1002          ndmp_send_reply(connection, (void *) &reply,
1031 1003              "sending tape_get_state reply");
1032 1004  }
1033 1005  /*
1034 1006   * ndmpd_tape_close_v4
1035 1007   *
1036 1008   * This handler (v4) closes the currently open tape device.
1037 1009   *
1038 1010   * Parameters:
1039 1011   *   connection (input) - connection handle.
1040 1012   *   body       (input) - request message body.
1041 1013   *
1042 1014   * Returns:
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
1043 1015   *   void
1044 1016   */
1045 1017  /*ARGSUSED*/
1046 1018  void
1047 1019  ndmpd_tape_close_v4(ndmp_connection_t *connection, void *body)
1048 1020  {
1049 1021          ndmp_tape_close_reply reply;
1050 1022          ndmpd_session_t *session = ndmp_get_client_data(connection);
1051 1023  
1052 1024          if (session->ns_tape.td_fd == -1) {
1053      -                NDMP_LOG(LOG_ERR, "Tape device is not open.");
     1025 +                syslog(LOG_ERR, "Tape device is not open.");
1054 1026                  reply.error = NDMP_DEV_NOT_OPEN_ERR;
1055 1027                  ndmp_send_reply(connection, (void *) &reply,
1056 1028                      "sending tape_close reply");
1057 1029                  return;
1058 1030          }
1059 1031  
1060 1032          /*
1061 1033           * V4 suggests that this should not be accepted
1062 1034           * when mover is in listen or active state
1063 1035           */
1064 1036          if (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN ||
1065 1037              session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE) {
1066 1038  
1067 1039                  reply.error = NDMP_DEVICE_BUSY_ERR;
1068 1040                  ndmp_send_reply(connection, (void *) &reply,
1069 1041                      "sending tape_close reply");
1070 1042                  return;
1071 1043          }
1072 1044  
1073 1045          common_tape_close(connection);
1074 1046  }
1075 1047  
1076 1048  
1077 1049  /*
1078 1050   * ************************************************************************
1079 1051   * LOCALS
1080 1052   * ************************************************************************
1081 1053   */
1082 1054  /*
1083 1055   * tape_open_send_reply
1084 1056   *
1085 1057   * Send a reply to the tape open message
1086 1058   *
1087 1059   * Parameters:
1088 1060   *   connection (input) - connection handle.
1089 1061   *   err (input) - NDMP error
1090 1062   *
1091 1063   * Returns:
1092 1064   *   void
1093 1065   */
1094 1066  static void
1095 1067  tape_open_send_reply(ndmp_connection_t *connection, int err)
1096 1068  {
1097 1069          ndmp_tape_open_reply reply;
1098 1070  
1099 1071          reply.error = err;
1100 1072          ndmp_send_reply(connection, (void *) &reply, "sending tape_open reply");
1101 1073  }
1102 1074  
1103 1075  /*
1104 1076   * unbuffered_read
1105 1077   *
1106 1078   * Perform tape read without read-ahead
1107 1079   *
1108 1080   * Parameters:
1109 1081   *   session (input) - session handle
1110 1082   *   bp (output) - read buffer
1111 1083   *   wanted (input) - number of bytes wanted
1112 1084   *   reply (output) - tape read reply message
1113 1085   *
1114 1086   * Returns:
1115 1087   *   void
1116 1088   */
1117 1089  static void
1118 1090  unbuffered_read(ndmpd_session_t *session, char *buf, long wanted,
1119 1091      ndmp_tape_read_reply *reply)
1120 1092  {
1121 1093          int n, len;
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
1122 1094  
1123 1095          n = read(session->ns_tape.td_fd, buf, wanted);
1124 1096          if (n < 0) {
1125 1097                  /*
1126 1098                   * This fix is for Symantec during importing
1127 1099                   * of spanned data between the tapes.
1128 1100                   */
1129 1101                  if (errno == ENOSPC) {
1130 1102                          reply->error = NDMP_EOF_ERR;
1131 1103                  } else {
1132      -                        NDMP_LOG(LOG_ERR, "Tape read error: %m.");
     1104 +                        syslog(LOG_ERR, "Tape read error: %m.");
1133 1105                          reply->error = NDMP_IO_ERR;
1134 1106                  }
1135 1107          } else if (n == 0) {
1136      -                NDMP_LOG(LOG_DEBUG, "NDMP_EOF_ERR");
1137      -
1138 1108                  reply->error = NDMP_EOF_ERR;
1139 1109  
1140 1110                  (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1);
1141 1111  
1142 1112                  len = strlen(NDMP_EOM_MAGIC);
1143 1113                  (void) memset(buf, 0, len);
1144 1114                  n = read(session->ns_tape.td_fd, buf, len);
1145 1115                  buf[len] = '\0';
1146 1116  
1147      -                NDMP_LOG(LOG_DEBUG, "Checking EOM: nread %d [%s]", n, buf);
1148      -
1149 1117                  (void) ndmp_mtioctl(session->ns_tape.td_fd, MTBSF, 1);
1150 1118  
1151 1119                  if (strncmp(buf, NDMP_EOM_MAGIC, len) != 0)
1152 1120                          (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1);
1153 1121          } else {
1154 1122                  session->ns_tape.td_pos += n;
1155 1123                  reply->data_in.data_in_len = n;
1156 1124                  reply->data_in.data_in_val = buf;
1157 1125                  reply->error = NDMP_NO_ERR;
1158 1126                  NS_ADD(rtape, n);
1159 1127          }
1160 1128  }
1161 1129  
1162 1130  
1163 1131  /*
1164 1132   * validmode
1165 1133   *
1166 1134   * Check the tape read mode is valid
1167 1135   */
1168 1136  static boolean_t
1169 1137  validmode(int mode)
1170 1138  {
1171 1139          boolean_t rv;
1172 1140  
1173 1141          switch (mode) {
1174 1142          case NDMP_TAPE_READ_MODE:
1175 1143          case NDMP_TAPE_WRITE_MODE:
1176 1144          case NDMP_TAPE_RAW1_MODE:
1177 1145          case NDMP_TAPE_RAW2_MODE:
1178 1146                  rv = TRUE;
1179 1147                  break;
1180 1148          default:
1181 1149                  rv = FALSE;
1182 1150          }
1183 1151  
1184 1152          return (rv);
1185 1153  }
1186 1154  
1187 1155  
1188 1156  /*
1189 1157   * common_tape_open
1190 1158   *
1191 1159   * Generic function for opening the tape for all versions
1192 1160   *
1193 1161   * Parameters:
1194 1162   *   connection (input) - connection handle.
1195 1163   *   devname (input) - tape device name to open.
1196 1164   *   ndmpmode (input) - mode of opening (read, write, raw)
1197 1165   *
1198 1166   * Returns:
1199 1167   *   void
  
    | 
      ↓ open down ↓ | 
    41 lines elided | 
    
      ↑ open up ↑ | 
  
1200 1168   */
1201 1169  static void
1202 1170  common_tape_open(ndmp_connection_t *connection, char *devname, int ndmpmode)
1203 1171  {
1204 1172          ndmpd_session_t *session = ndmp_get_client_data(connection);
1205 1173          char adptnm[SCSI_MAX_NAME];
1206 1174          int err;
1207 1175          int mode;
1208 1176          int sid, lun;
1209 1177          scsi_adapter_t *sa;
1210      -        int devid;
     1178 +        int devid = -1;
1211 1179  
1212 1180          err = NDMP_NO_ERR;
1213 1181  
1214 1182          if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) {
1215      -                NDMP_LOG(LOG_INFO,
     1183 +                syslog(LOG_INFO,
1216 1184                      "Connection already has a tape or scsi device open");
1217 1185                  err = NDMP_DEVICE_OPENED_ERR;
1218 1186          } else if (!validmode(ndmpmode))
1219 1187                  err = NDMP_ILLEGAL_ARGS_ERR;
1220 1188          if ((sa = scsi_get_adapter(0)) != NULL) {
1221      -                NDMP_LOG(LOG_DEBUG, "Adapter device opened: %s", devname);
1222 1189                  (void) strlcpy(adptnm, devname, SCSI_MAX_NAME-2);
1223 1190                  adptnm[SCSI_MAX_NAME-1] = '\0';
1224 1191                  sid = lun = -1;
1225 1192          }
1226 1193          if (sa) {
1227 1194                  scsi_find_sid_lun(sa, devname, &sid, &lun);
1228 1195                  if (ndmp_open_list_find(devname, sid, lun) == 0 &&
1229 1196                      (devid = open(devname, O_RDWR | O_NDELAY)) < 0) {
1230      -                        NDMP_LOG(LOG_ERR,
     1197 +                        syslog(LOG_ERR,
1231 1198                              "Failed to open device %s: %m.", devname);
1232 1199                          err = NDMP_NO_DEVICE_ERR;
1233 1200                  } else {
1234 1201                          (void) close(devid);
1235 1202                  }
1236 1203          } else {
1237      -                NDMP_LOG(LOG_ERR, "%s: No such tape device.", devname);
     1204 +                syslog(LOG_ERR, "%s: No such tape device.", devname);
1238 1205                  err = NDMP_NO_DEVICE_ERR;
1239 1206          }
1240 1207  
1241 1208          if (err != NDMP_NO_ERR) {
1242 1209                  tape_open_send_reply(connection, err);
1243 1210                  return;
1244 1211          }
1245 1212  
1246 1213          /*
1247 1214           * If tape is not opened in raw mode and tape is not loaded
1248 1215           * return error.
1249 1216           */
1250 1217          if (ndmpmode != NDMP_TAPE_RAW1_MODE &&
1251 1218              ndmpmode != NDMP_TAPE_RAW2_MODE &&
1252 1219              !is_tape_unit_ready(adptnm, 0)) {
1253 1220                  tape_open_send_reply(connection, NDMP_NO_TAPE_LOADED_ERR);
1254 1221                  return;
1255 1222          }
1256 1223  
1257 1224          mode = (ndmpmode == NDMP_TAPE_READ_MODE) ? O_RDONLY : O_RDWR;
1258 1225          mode |= O_NDELAY;
1259 1226          session->ns_tape.td_fd = open(devname, mode);
1260 1227          if (session->ns_protocol_version == NDMPV4 &&
1261 1228              session->ns_tape.td_fd < 0 &&
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
1262 1229              ndmpmode == NDMP_TAPE_RAW_MODE && errno == EACCES) {
1263 1230                  /*
1264 1231                   * V4 suggests that if the tape is open in raw mode
1265 1232                   * and could not be opened with write access, it should
1266 1233                   * be opened read only instead.
1267 1234                   */
1268 1235                  ndmpmode = NDMP_TAPE_READ_MODE;
1269 1236                  session->ns_tape.td_fd = open(devname, O_RDONLY);
1270 1237          }
1271 1238          if (session->ns_tape.td_fd < 0) {
1272      -                NDMP_LOG(LOG_ERR, "Failed to open tape device %s: %m.",
     1239 +                syslog(LOG_ERR, "Failed to open tape device %s: %m.",
1273 1240                      devname);
1274 1241                  switch (errno) {
1275 1242                  case EACCES:
1276 1243                          err = NDMP_WRITE_PROTECT_ERR;
1277 1244                          break;
1278 1245                  case ENOENT:
1279 1246                          err = NDMP_NO_DEVICE_ERR;
1280 1247                          break;
1281 1248                  case EBUSY:
1282 1249                          err = NDMP_DEVICE_BUSY_ERR;
1283 1250                          break;
1284 1251                  case EPERM:
1285 1252                          err = NDMP_PERMISSION_ERR;
1286 1253                          break;
1287 1254                  default:
1288 1255                          err = NDMP_IO_ERR;
1289 1256                  }
1290 1257  
1291 1258                  tape_open_send_reply(connection, err);
1292 1259                  return;
1293 1260          }
1294 1261  
1295 1262          switch (ndmp_open_list_add(connection,
1296 1263              adptnm, sid, lun, session->ns_tape.td_fd)) {
1297 1264          case 0:
1298 1265                  err = NDMP_NO_ERR;
1299 1266                  break;
1300 1267          case EBUSY:
1301 1268                  err = NDMP_DEVICE_BUSY_ERR;
1302 1269                  break;
1303 1270          case ENOMEM:
1304 1271                  err = NDMP_NO_MEM_ERR;
1305 1272                  break;
1306 1273          default:
1307 1274                  err = NDMP_IO_ERR;
1308 1275          }
1309 1276          if (err != NDMP_NO_ERR) {
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
1310 1277                  tape_open_send_reply(connection, err);
1311 1278                  return;
1312 1279          }
1313 1280  
1314 1281          session->ns_tape.td_mode = ndmpmode;
1315 1282          session->ns_tape.td_sid = sid;
1316 1283          session->ns_tape.td_lun = lun;
1317 1284          (void) strlcpy(session->ns_tape.td_adapter_name, adptnm, SCSI_MAX_NAME);
1318 1285          session->ns_tape.td_record_count = 0;
1319 1286  
1320      -        NDMP_LOG(LOG_DEBUG, "Tape is opened fd: %d", session->ns_tape.td_fd);
1321      -
1322 1287          tape_open_send_reply(connection, NDMP_NO_ERR);
1323 1288  }
1324 1289  
1325 1290  
1326 1291  /*
1327 1292   * common_tape_close
1328 1293   *
1329 1294   * Generic function for closing the tape
1330 1295   *
1331 1296   * Parameters:
1332 1297   *   connection (input) - connection handle.
1333 1298   *
1334 1299   * Returns:
1335 1300   *   void
1336 1301   */
1337 1302  static void
1338 1303  common_tape_close(ndmp_connection_t *connection)
1339 1304  {
1340 1305          ndmpd_session_t *session = ndmp_get_client_data(connection);
1341 1306          ndmp_tape_close_reply reply;
1342 1307  
1343 1308          (void) ndmp_open_list_del(session->ns_tape.td_adapter_name,
1344 1309              session->ns_tape.td_sid, session->ns_tape.td_lun);
1345 1310          (void) close(session->ns_tape.td_fd);
1346 1311          session->ns_tape.td_fd = -1;
1347 1312          session->ns_tape.td_sid = 0;
1348 1313          session->ns_tape.td_lun = 0;
1349 1314          (void) memset(session->ns_tape.td_adapter_name, 0,
1350 1315              sizeof (session->ns_tape.td_adapter_name));
1351 1316          session->ns_tape.td_record_count = 0;
1352 1317  
1353 1318          reply.error = NDMP_NO_ERR;
1354 1319          ndmp_send_reply(connection, (void *) &reply,
1355 1320              "sending tape_close reply");
1356 1321  }
1357 1322  
1358 1323  /*
1359 1324   * tape_open
1360 1325   *
1361 1326   * Will try to open the tape with the given flags and
1362 1327   * path using the given retries and delay intervals
1363 1328   */
1364 1329  int
1365 1330  tape_open(char *path, int flags)
1366 1331  {
1367 1332          int fd;
1368 1333          int i = 0;
1369 1334  
1370 1335          while ((fd = open(path, flags)) == -1 &&
1371 1336              i++ < ndmp_tape_open_retries) {
1372 1337                  if (errno != EBUSY)
1373 1338                          break;
1374 1339                  (void) usleep(ndmp_tape_open_delay);
1375 1340          }
1376 1341          return (fd);
1377 1342  }
  
    | 
      ↓ open down ↓ | 
    46 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX