Print this page
NEX-13374 NDMP should be able to backup unmounted ZFS filesystems
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
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>
NEX-2911 NDMP logging should use syslog and is too chatty
NEX-2110 NDMP leaving zombie restore and backup threads around which hold up resources
NEX-727 Netbackup Catalog verification hangs waiting for NDMP server
        
*** 1,8 ****
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * BSD 3 Clause License
   *
--- 1,8 ----
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * BSD 3 Clause License
   *
*** 39,48 ****
--- 39,49 ----
  /* Copyright (c) 2007, The Storage Networking Industry Association. */
  /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  #include <sys/types.h>
  #include <sys/param.h>
  #include <sys/socket.h>
+ #include <syslog.h>
  #include <netinet/in.h>
  #include <errno.h>
  #include <arpa/inet.h>
  #include <stdlib.h>
  #include <string.h>
*** 69,82 ****
  static ndmp_error ndmpd_tar_start_backup_v3(ndmpd_session_t *, char *,
      ndmp_pval *, ulong_t);
  static ndmp_error ndmpd_tar_start_recover_v3(ndmpd_session_t *,
      ndmp_pval *, ulong_t, ndmp_name_v3 *, ulong_t);
  
- static ndmp_error ndmpd_zfs_start_op(ndmpd_session_t *,
-     ndmp_pval *, ulong_t, ndmp_name_v3 *, ulong_t, enum ndmp_data_operation);
- 
- 
  /*
   * ************************************************************************
   * NDMP V2 HANDLERS
   * ************************************************************************
   */
--- 70,79 ----
*** 154,164 ****
          /*
           * start_backup sends the reply if the backup is successfully started.
           * Otherwise, send the reply containing the error here.
           */
          if (err != NDMP_NO_ERR) {
!                 NDMP_LOG(LOG_DEBUG, "err: %d", err);
                  reply.error = err;
                  ndmp_send_reply(connection, &reply,
                      "sending data_start_backup reply");
                  ndmpd_data_cleanup(session);
          }
--- 151,161 ----
          /*
           * start_backup sends the reply if the backup is successfully started.
           * Otherwise, send the reply containing the error here.
           */
          if (err != NDMP_NO_ERR) {
!                 syslog(LOG_ERR, "err: %d", err);
                  reply.error = err;
                  ndmp_send_reply(connection, &reply,
                      "sending data_start_backup reply");
                  ndmpd_data_cleanup(session);
          }
*** 224,234 ****
          ndmp_data_get_env_reply reply;
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          (void) memset((void*)&reply, 0, sizeof (reply));
          if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
!                 NDMP_LOG(LOG_ERR, "Backup operation not active.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else {
                  reply.error = NDMP_NO_ERR;
                  reply.env.env_len = session->ns_data.dd_env_len;
--- 221,231 ----
          ndmp_data_get_env_reply reply;
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          (void) memset((void*)&reply, 0, sizeof (reply));
          if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
!                 syslog(LOG_ERR, "Backup operation not active.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else {
                  reply.error = NDMP_NO_ERR;
                  reply.env.env_len = session->ns_data.dd_env_len;
*** 257,267 ****
  {
          ndmp_data_stop_reply reply;
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
-                 NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  ndmp_send_reply(connection, &reply,
                      "sending data_stop reply");
                  return;
          }
--- 254,263 ----
*** 301,311 ****
          ndmp_data_abort_reply reply;
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
              session->ns_data.dd_state == NDMP_DATA_STATE_HALTED) {
-                 NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  ndmp_send_reply(connection, &reply,
                      "sending data_abort reply");
                  return;
          }
--- 297,306 ----
*** 399,419 ****
          request = (ndmp_data_start_backup_request_v3 *)body;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
!                 NDMP_LOG(LOG_ERR,
!                     "Can't start new backup in current state.");
!                 NDMP_LOG(LOG_ERR,
!                     "Connection to the mover is not established.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  goto _error;
          }
  
          if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
                  if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
!                         NDMP_LOG(LOG_ERR, "Write protected device.");
                          reply.error = NDMP_WRITE_PROTECT_ERR;
                          goto _error;
                  }
          }
  
--- 394,412 ----
          request = (ndmp_data_start_backup_request_v3 *)body;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
!                 syslog(LOG_ERR,
!                     "Can't start new backup in NOT CONNECTED state.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  goto _error;
          }
  
          if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
                  if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
!                         syslog(LOG_ERR, "Write protected device.");
                          reply.error = NDMP_WRITE_PROTECT_ERR;
                          goto _error;
                  }
          }
  
*** 428,458 ****
                  char msg_types[32];
  
                  (void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
                      request->bu_type);
                  (void) snprintf(msg_types, 32,
!                     "Supported backup types are tar, dump, and zfs.");
  
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_invalid);
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_types);
!                 NDMP_LOG(LOG_ERR, msg_invalid);
!                 NDMP_LOG(LOG_ERR, msg_types);
  
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  goto _error;
          }
  
-         if (session->ns_butype == NDMP_BUTYPE_ZFS) {
-                 reply.error = ndmpd_zfs_start_op(session, request->env.env_val,
-                     request->env.env_len, NULL, 0, NDMP_DATA_OP_BACKUP);
-         } else {
                  reply.error = ndmpd_tar_start_backup_v3(session,
                      request->bu_type, request->env.env_val,
                      request->env.env_len);
-         }
  
          /*
           * *_start_backup* sends the reply if the backup is
           * successfully started.  Otherwise, send the reply
           * containing the error here.
--- 421,448 ----
                  char msg_types[32];
  
                  (void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
                      request->bu_type);
                  (void) snprintf(msg_types, 32,
!                     "Supported backup types are tar, dump.");
  
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_invalid);
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_types);
!                 syslog(LOG_ERR, "Invalid backup type: %s.",
!                     request->bu_type);
!                 syslog(LOG_ERR,
!                     "Supported backup types are tar, dump.");
  
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  goto _error;
          }
  
          reply.error = ndmpd_tar_start_backup_v3(session,
              request->bu_type, request->env.env_val,
              request->env.env_len);
  
          /*
           * *_start_backup* sends the reply if the backup is
           * successfully started.  Otherwise, send the reply
           * containing the error here.
*** 489,499 ****
          request = (ndmp_data_start_recover_request_v3 *)body;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
!                 NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  goto _error;
          }
  
          if (strcasecmp(request->bu_type, NDMP_TAR_TYPE) == 0) {
--- 479,489 ----
          request = (ndmp_data_start_recover_request_v3 *)body;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
!                 syslog(LOG_ERR, "Can't start new recover in current state.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  goto _error;
          }
  
          if (strcasecmp(request->bu_type, NDMP_TAR_TYPE) == 0) {
*** 507,538 ****
                  char msg_types[32];
  
                  (void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
                      request->bu_type);
                  (void) snprintf(msg_types, 32,
!                     "Supported backup types are tar, dump, and zfs.");
  
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_invalid);
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_types);
!                 NDMP_LOG(LOG_ERR, msg_invalid);
!                 NDMP_LOG(LOG_ERR, msg_types);
  
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  goto _error;
          }
  
-         if (session->ns_butype == NDMP_BUTYPE_ZFS) {
-                 reply.error = ndmpd_zfs_start_op(session, request->env.env_val,
-                     request->env.env_len, request->nlist.nlist_val,
-                     request->nlist.nlist_len, NDMP_DATA_OP_RECOVER);
-         } else {
                  reply.error = ndmpd_tar_start_recover_v3(session,
                      request->env.env_val, request->env.env_len,
                      request->nlist.nlist_val, request->nlist.nlist_len);
-         }
  
          /*
           * *_start_recover* sends the reply if the recover is
           * successfully started.  Otherwise, send the reply
           * containing the error here.
--- 497,524 ----
                  char msg_types[32];
  
                  (void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
                      request->bu_type);
                  (void) snprintf(msg_types, 32,
!                     "Supported backup types are tar, dump.");
  
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_invalid);
                  NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
                      msg_types);
!                 syslog(LOG_ERR, "Invalid backup type: %s.",
!                     request->bu_type);
!                 syslog(LOG_ERR,
!                     "Supported backup types are tar, dump.");
  
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  goto _error;
          }
  
          reply.error = ndmpd_tar_start_recover_v3(session,
              request->env.env_val, request->env.env_len,
              request->nlist.nlist_val, request->nlist.nlist_len);
  
          /*
           * *_start_recover* sends the reply if the recover is
           * successfully started.  Otherwise, send the reply
           * containing the error here.
*** 570,580 ****
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          switch (session->ns_data.dd_state) {
          case NDMP_DATA_STATE_IDLE:
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
-                 NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
                  break;
  
          case NDMP_DATA_STATE_ACTIVE:
                  /*
                   * Don't go to HALTED state yet.  Need to wait for data
--- 556,565 ----
*** 595,605 ****
                  session->ns_data.dd_abort = TRUE;
                  ndmpd_data_error(session, NDMP_DATA_HALT_ABORTED);
                  break;
          default:
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 NDMP_LOG(LOG_DEBUG, "Unknown data V3 state %d",
                      session->ns_data.dd_state);
          }
  
          ndmp_send_reply(connection, &reply,
              "sending data_abort_v3 reply");
--- 580,590 ----
                  session->ns_data.dd_abort = TRUE;
                  ndmpd_data_error(session, NDMP_DATA_HALT_ABORTED);
                  break;
          default:
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 syslog(LOG_ERR, "Unknown data V3 state %d",
                      session->ns_data.dd_state);
          }
  
          ndmp_send_reply(connection, &reply,
              "sending data_abort_v3 reply");
*** 624,634 ****
  {
          ndmp_data_stop_reply reply;
          ndmpd_session_t *session = ndmp_get_client_data(connection);
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
-                 NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  ndmp_send_reply(connection, &reply,
                      "sending data_stop_v3 reply");
                  return;
          }
--- 609,618 ----
*** 672,686 ****
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 NDMP_LOG(LOG_ERR,
                      "Invalid internal data state to process listen request.");
          } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 NDMP_LOG(LOG_ERR,
                      "Invalid mover state to process listen request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
--- 656,670 ----
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 syslog(LOG_ERR,
                      "Invalid internal data state to process listen request.");
          } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 syslog(LOG_ERR,
                      "Invalid mover state to process listen request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
*** 706,721 ****
                  reply.data_connection_addr.tcp_ip_v3 = htonl(addr);
                  reply.data_connection_addr.tcp_port_v3 = htons(port);
                  session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
                  session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
                  session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
!                 NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
                      session->ns_data.dd_listen_sock);
                  break;
  
          default:
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
                      request->addr_type);
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  break;
          }
  
--- 690,705 ----
                  reply.data_connection_addr.tcp_ip_v3 = htonl(addr);
                  reply.data_connection_addr.tcp_port_v3 = htons(port);
                  session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
                  session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
                  session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
!                 syslog(LOG_DEBUG, "listen_socket: %d",
                      session->ns_data.dd_listen_sock);
                  break;
  
          default:
!                 syslog(LOG_ERR, "Invalid address type: %d",
                      request->addr_type);
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  break;
          }
  
*** 751,765 ****
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
                      request->addr.addr_type);
          } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
-                 NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
          if (reply.error != NDMP_NO_ERR) {
--- 735,748 ----
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 syslog(LOG_ERR, "Invalid address type %d",
                      request->addr.addr_type);
          } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
          if (reply.error != NDMP_NO_ERR) {
*** 775,785 ****
                   * local connection
                   */
                  if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
                      session->ns_mover.md_listen_sock != -1) {
                          reply.error = NDMP_ILLEGAL_STATE_ERR;
!                         NDMP_LOG(LOG_ERR,
                              "Mover is not in local listen state.");
                  } else {
                          session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                  }
                  break;
--- 758,768 ----
                   * local connection
                   */
                  if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
                      session->ns_mover.md_listen_sock != -1) {
                          reply.error = NDMP_ILLEGAL_STATE_ERR;
!                         syslog(LOG_ERR,
                              "Mover is not in local listen state.");
                  } else {
                          session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                  }
                  break;
*** 789,799 ****
                      request->addr.tcp_ip_v3, request->addr.tcp_port_v3);
                  break;
  
          default:
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
                      request->addr.addr_type);
          }
  
          if (reply.error == NDMP_NO_ERR)
                  session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
--- 772,782 ----
                      request->addr.tcp_ip_v3, request->addr.tcp_port_v3);
                  break;
  
          default:
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 syslog(LOG_ERR, "Invalid address type %d",
                      request->addr.addr_type);
          }
  
          if (reply.error == NDMP_NO_ERR)
                  session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
*** 832,846 ****
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_ACTIVE &&
              session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
-                 NDMP_LOG(LOG_ERR, "Invalid state for the data server.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
!                 NDMP_LOG(LOG_ERR, "Backup operation not active.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else {
                  reply.error = NDMP_NO_ERR;
                  reply.env.env_len = session->ns_data.dd_env_len;
--- 815,828 ----
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_ACTIVE &&
              session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
!                 syslog(LOG_ERR, "Backup operation not active.");
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
                  reply.env.env_len = 0;
          } else {
                  reply.error = NDMP_NO_ERR;
                  reply.env.env_len = session->ns_data.dd_env_len;
*** 924,938 ****
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
                      request->addr.addr_type);
          } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
-                 NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
          if (reply.error != NDMP_NO_ERR) {
--- 906,919 ----
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 syslog(LOG_ERR, "Invalid address type %d",
                      request->addr.addr_type);
          } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
          if (reply.error != NDMP_NO_ERR) {
*** 948,958 ****
                   * local connection
                   */
                  if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
                      session->ns_mover.md_listen_sock != -1) {
                          reply.error = NDMP_ILLEGAL_STATE_ERR;
!                         NDMP_LOG(LOG_ERR,
                              "Mover is not in local listen state.");
                  } else {
                          session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                  }
                  break;
--- 929,939 ----
                   * local connection
                   */
                  if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
                      session->ns_mover.md_listen_sock != -1) {
                          reply.error = NDMP_ILLEGAL_STATE_ERR;
!                         syslog(LOG_ERR,
                              "Mover is not in local listen state.");
                  } else {
                          session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                  }
                  break;
*** 962,972 ****
                      request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0));
                  break;
  
          default:
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
                      request->addr.addr_type);
          }
  
          if (reply.error == NDMP_NO_ERR)
                  session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
--- 943,953 ----
                      request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0));
                  break;
  
          default:
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
!                 syslog(LOG_ERR, "Invalid address type %d",
                      request->addr.addr_type);
          }
  
          if (reply.error == NDMP_NO_ERR)
                  session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
*** 1001,1015 ****
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 NDMP_LOG(LOG_ERR,
                      "Invalid internal data state to process listen request.");
          } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 NDMP_LOG(LOG_ERR,
                      "Invalid mover state to process listen request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
--- 982,996 ----
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 syslog(LOG_ERR,
                      "Invalid internal data state to process listen request.");
          } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
                  reply.error = NDMP_ILLEGAL_STATE_ERR;
!                 syslog(LOG_ERR,
                      "Invalid mover state to process listen request.");
          } else {
                  reply.error = NDMP_NO_ERR;
          }
  
*** 1049,1064 ****
  
                  /* Copy that to data_addr for compatibility */
                  session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
                  session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
                  session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
!                 NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
                      session->ns_data.dd_listen_sock);
                  break;
  
          default:
!                 NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
                      request->addr_type);
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  break;
          }
  
--- 1030,1045 ----
  
                  /* Copy that to data_addr for compatibility */
                  session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
                  session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
                  session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
!                 syslog(LOG_DEBUG, "listen_socket: %d",
                      session->ns_data.dd_listen_sock);
                  break;
  
          default:
!                 syslog(LOG_ERR, "Invalid address type: %d",
                      request->addr_type);
                  reply.error = NDMP_ILLEGAL_ARGS_ERR;
                  break;
          }
  
*** 1087,1097 ****
  void
  ndmpd_data_start_recover_filehist_v4(ndmp_connection_t *connection, void *body)
  {
          ndmp_data_start_recover_filehist_reply_v4 reply;
  
!         NDMP_LOG(LOG_DEBUG, "Request not supported");
          reply.error = NDMP_NOT_SUPPORTED_ERR;
  
          ndmp_send_reply(connection, &reply,
              "sending ndmp_data_start_recover_filehist_reply_v4 reply");
  }
--- 1068,1078 ----
  void
  ndmpd_data_start_recover_filehist_v4(ndmp_connection_t *connection, void *body)
  {
          ndmp_data_start_recover_filehist_reply_v4 reply;
  
!         syslog(LOG_DEBUG, "Request not supported");
          reply.error = NDMP_NOT_SUPPORTED_ERR;
  
          ndmp_send_reply(connection, &reply,
              "sending ndmp_data_start_recover_filehist_reply_v4 reply");
  }
*** 1193,1207 ****
          session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
          session->ns_data.dd_halt_reason = reason;
  
          if (session->ns_protocol_version == NDMPV4) {
                  if (ndmpd_data_error_send_v4(session, reason) < 0)
!                         NDMP_LOG(LOG_DEBUG,
                              "Error sending notify_data_halted request");
          } else {
                  if (ndmpd_data_error_send(session, reason) < 0)
!                         NDMP_LOG(LOG_DEBUG,
                              "Error sending notify_data_halted request");
          }
  
          if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP) {
                  if (session->ns_data.dd_sock != -1) {
--- 1174,1188 ----
          session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
          session->ns_data.dd_halt_reason = reason;
  
          if (session->ns_protocol_version == NDMPV4) {
                  if (ndmpd_data_error_send_v4(session, reason) < 0)
!                         syslog(LOG_ERR,
                              "Error sending notify_data_halted request");
          } else {
                  if (ndmpd_data_error_send(session, reason) < 0)
!                         syslog(LOG_ERR,
                              "Error sending notify_data_halted request");
          }
  
          if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP) {
                  if (session->ns_data.dd_sock != -1) {
*** 1255,1276 ****
  
          from_len = sizeof (from);
          session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
              &from_len);
  
!         NDMP_LOG(LOG_DEBUG, "sock fd: %d",
              session->ns_data.dd_sock);
!         NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s",
              ntohs(from.sin_port),
              inet_ntoa(IN_ADDR(from.sin_addr.s_addr)));
  
          (void) ndmpd_remove_file_handler(session, fd);
          (void) close(session->ns_data.dd_listen_sock);
          session->ns_data.dd_listen_sock = -1;
  
          if (session->ns_data.dd_sock < 0) {
!                 NDMP_LOG(LOG_DEBUG, "Accept error: %m");
                  ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                  return;
          }
  
          /*
--- 1236,1257 ----
  
          from_len = sizeof (from);
          session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
              &from_len);
  
!         syslog(LOG_DEBUG, "sock fd: %d",
              session->ns_data.dd_sock);
!         syslog(LOG_DEBUG, "sin: port %d addr %s",
              ntohs(from.sin_port),
              inet_ntoa(IN_ADDR(from.sin_addr.s_addr)));
  
          (void) ndmpd_remove_file_handler(session, fd);
          (void) close(session->ns_data.dd_listen_sock);
          session->ns_data.dd_listen_sock = -1;
  
          if (session->ns_data.dd_sock < 0) {
!                 syslog(LOG_ERR, "Accept error: %m");
                  ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                  return;
          }
  
          /*
*** 1309,1319 ****
              data_accept_connection_v3) < 0) {
                  (void) close(session->ns_data.dd_listen_sock);
                  session->ns_data.dd_listen_sock = -1;
                  return (-1);
          }
!         NDMP_LOG(LOG_DEBUG, "addr: %s:%d",
              inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
  
          return (0);
  }
  
--- 1290,1300 ----
              data_accept_connection_v3) < 0) {
                  (void) close(session->ns_data.dd_listen_sock);
                  session->ns_data.dd_listen_sock = -1;
                  return (-1);
          }
!         syslog(LOG_DEBUG, "addr: %s:%d",
              inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
  
          return (0);
  }
  
*** 1371,1380 ****
--- 1352,1362 ----
  {
          int err;
          ndmp_lbr_params_t *nlp;
          ndmpd_module_params_t *params;
          ndmp_data_start_backup_reply_v3 reply;
+         pthread_t tid;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          err = ndmpd_save_env(session, env_val, env_len);
          if (err != NDMP_NO_ERR)
*** 1440,1458 ****
          session->ns_data.dd_read_offset = 0;
          session->ns_data.dd_read_length = 0;
  
          reply.error = ndmp_backup_get_params_v3(session, params);
          if (reply.error != NDMP_NO_ERR) {
!                 NDMP_LOG(LOG_DEBUG, "err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (reply.error);
          }
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 NDMP_LOG(LOG_DEBUG, "Sending data_start_backup_v3 reply");
                  return (NDMP_NO_ERR);
          }
  
          NS_INC(nbk);
          session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
--- 1422,1440 ----
          session->ns_data.dd_read_offset = 0;
          session->ns_data.dd_read_length = 0;
  
          reply.error = ndmp_backup_get_params_v3(session, params);
          if (reply.error != NDMP_NO_ERR) {
!                 syslog(LOG_ERR, "err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (reply.error);
          }
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 syslog(LOG_DEBUG, "Sending data_start_backup_v3 reply");
                  return (NDMP_NO_ERR);
          }
  
          NS_INC(nbk);
          session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
*** 1463,1480 ****
           * perform the backup
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         err = pthread_create(NULL, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
          if (err != 0) {
!                 NDMP_LOG(LOG_ERR, "Can't start backup session.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
  
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_tar_start_recover_v3
--- 1445,1465 ----
           * perform the backup
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         err = pthread_create(&tid, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
+ 
          if (err != 0) {
!                 syslog(LOG_ERR, "Can't start V3 backup session.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
  
+         (void) pthread_detach(tid);
+ 
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_tar_start_recover_v3
*** 1499,1508 ****
--- 1484,1494 ----
      ulong_t nlist_len)
  {
          ndmp_data_start_recover_reply_v3 reply;
          ndmpd_module_params_t *params;
          ndmp_lbr_params_t *nlp;
+         pthread_t tid;
          int err;
  
          (void) memset((void*)&reply, 0, sizeof (reply));
  
          nlp = ndmp_get_nlp(session);
*** 1575,1585 ****
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
                  NDMP_FREE(nlp->nlp_params);
                  ndmpd_free_nlist_v3(session);
!                 NDMP_LOG(LOG_DEBUG,
                      "Error sending ndmp_data_start_recover_reply");
                  ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                  return (NDMP_NO_ERR);
          }
  
--- 1561,1571 ----
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
                  NDMP_FREE(nlp->nlp_params);
                  ndmpd_free_nlist_v3(session);
!                 syslog(LOG_ERR,
                      "Error sending ndmp_data_start_recover_reply");
                  ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                  return (NDMP_NO_ERR);
          }
  
*** 1592,1719 ****
           * perform the restore
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         err = pthread_create(NULL, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
          if (err != 0) {
!                 NDMP_LOG(LOG_ERR, "Can't start recover session.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
-         return (NDMP_NO_ERR);
- }
  
- static ndmp_error
- ndmpd_zfs_start_op(ndmpd_session_t *session, ndmp_pval *env_val,
-     ulong_t env_len, ndmp_name_v3 *nlist_val, ulong_t nlist_len,
-     enum ndmp_data_operation op)
- {
-         ndmpd_zfs_args_t *ndmpd_zfs_args = &session->ns_ndmpd_zfs_args;
-         ndmp_data_start_backup_reply_v3 backup_reply;
-         ndmp_data_start_recover_reply_v3 recover_reply;
-         pthread_t tid;
-         void *reply;
-         char str[8];
-         int err;
- 
-         if (ndmpd_zfs_init(session) != 0)
-                 return (NDMP_UNDEFINED_ERR);
- 
-         err = ndmpd_save_env(session, env_val, env_len);
-         if (err != NDMP_NO_ERR) {
-                 ndmpd_zfs_fini(ndmpd_zfs_args);
-                 return (err);
-         }
- 
-         switch (op) {
-         case NDMP_DATA_OP_BACKUP:
-                 if (!ndmpd_zfs_backup_parms_valid(ndmpd_zfs_args)) {
-                         ndmpd_zfs_fini(ndmpd_zfs_args);
-                         return (NDMP_ILLEGAL_ARGS_ERR);
-                 }
- 
-                 if (ndmpd_zfs_pre_backup(ndmpd_zfs_args)) {
-                         NDMP_LOG(LOG_ERR, "pre_backup error");
-                         return (NDMP_ILLEGAL_ARGS_ERR);
-                 }
- 
-                 session->ns_data.dd_module.dm_start_func =
-                     ndmpd_zfs_backup_starter;
-                 (void) strlcpy(str, "backup", 8);
-                 break;
-         case NDMP_DATA_OP_RECOVER:
-                 err = ndmpd_save_nlist_v3(session, nlist_val, nlist_len);
-                 if (err != NDMP_NO_ERR) {
-                         ndmpd_zfs_fini(ndmpd_zfs_args);
-                         return (NDMP_NO_MEM_ERR);
-                 }
- 
-                 if (!ndmpd_zfs_restore_parms_valid(ndmpd_zfs_args)) {
-                         ndmpd_zfs_fini(ndmpd_zfs_args);
-                         return (NDMP_ILLEGAL_ARGS_ERR);
-                 }
- 
-                 if (ndmpd_zfs_pre_restore(ndmpd_zfs_args)) {
-                         NDMP_LOG(LOG_ERR, "pre_restore error");
-                         (void) ndmpd_zfs_post_restore(ndmpd_zfs_args);
-                         return (NDMP_ILLEGAL_ARGS_ERR);
-                 }
-                 session->ns_data.dd_module.dm_start_func =
-                     ndmpd_zfs_restore_starter;
-                 (void) strlcpy(str, "recover", 8);
-                 break;
-         }
- 
-         ndmpd_zfs_params->mp_operation = op;
-         session->ns_data.dd_operation = op;
-         session->ns_data.dd_module.dm_abort_func = ndmpd_zfs_abort;
-         session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
-         session->ns_data.dd_abort = FALSE;
- 
-         if (op == NDMP_DATA_OP_BACKUP) {
-                 (void) memset((void*)&backup_reply, 0, sizeof (backup_reply));
-                 backup_reply.error = NDMP_NO_ERR;
-                 reply = &backup_reply;
-         } else {
-                 (void) memset((void*)&recover_reply, 0, sizeof (recover_reply));
-                 recover_reply.error = NDMP_NO_ERR;
-                 reply = &recover_reply;
-         }
- 
-         if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
-             reply) < 0) {
-                 NDMP_LOG(LOG_DEBUG, "Sending data_start_%s_v3 reply", str);
-                 if (op == NDMP_DATA_OP_RECOVER)
-                         ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
-                 ndmpd_zfs_fini(ndmpd_zfs_args);
-                 return (NDMP_NO_ERR);
-         }
- 
-         err = pthread_create(&tid, NULL,
-             (funct_t)session->ns_data.dd_module.dm_start_func, ndmpd_zfs_args);
- 
-         if (err) {
-                 NDMP_LOG(LOG_ERR, "Can't start %s session (errno %d)",
-                     str, err);
-                 ndmpd_zfs_fini(ndmpd_zfs_args);
-                 MOD_DONE(ndmpd_zfs_params, -1);
-                 return (NDMP_NO_ERR);
-         }
- 
          (void) pthread_detach(tid);
  
-         if (op == NDMP_DATA_OP_BACKUP)
-                 NS_INC(nbk);
-         else
-                 NS_INC(nrs);
- 
-         ndmpd_zfs_dma_log(ndmpd_zfs_args, NDMP_LOG_NORMAL,
-             "'zfs' %s starting\n", str);
- 
          return (NDMP_NO_ERR);
  }
  
  /*
   * discard_data_v3
--- 1578,1598 ----
           * perform the restore
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         err = pthread_create(&tid, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
          if (err != 0) {
!                 syslog(LOG_ERR, "Can't start V3 recover session.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
  
          (void) pthread_detach(tid);
  
          return (NDMP_NO_ERR);
  }
  
  /*
   * discard_data_v3
*** 1739,1749 ****
              MAX_RECORD_SIZE;
  
          /* Read and discard the data. */
          n = read(session->ns_data.dd_sock, buf, toread);
          if (n < 0) {
!                 NDMP_LOG(LOG_ERR, "Socket read error: %m.");
                  n = -1;
          }
  
          return (n);
  }
--- 1618,1628 ----
              MAX_RECORD_SIZE;
  
          /* Read and discard the data. */
          n = read(session->ns_data.dd_sock, buf, toread);
          if (n < 0) {
!                 syslog(LOG_ERR, "Socket read error: %m.");
                  n = -1;
          }
  
          return (n);
  }
*** 1771,1787 ****
          ssize_t n;
          ndmp_notify_data_read_request request;
          tlm_job_stats_t *jstat;
          longlong_t fsize;
  
-         NDMP_LOG(LOG_DEBUG, "ns_data.dd_xx: [%llu, %llu, %llu, %llu, %llu]",
-             session->ns_data.dd_bytes_left_to_read,
-             session->ns_data.dd_read_offset,
-             session->ns_data.dd_read_length,
-             session->ns_data.dd_position,
-             session->ns_data.dd_discard_length);
- 
          count = 0;
          while (count < length) {
                  len = length - count;
  
                  /*
--- 1650,1659 ----
*** 1808,1820 ****
                                   * when asking for data from the tape.
                                   */
                                  jstat = session->ns_ndmp_lbr_params->nlp_jstat;
                                  fsize = jstat->js_bytes_in_file;
  
-                                 NDMP_LOG(LOG_DEBUG, "bytes_left [%llu / %u]",
-                                     fsize, len);
- 
                                  /*
                                   * Fall back to the old way if fsize if too
                                   * small.
                                   */
                                  if (fsize < len)
--- 1680,1689 ----
*** 1829,1846 ****
                          request.offset =
                              long_long_to_quad(session->ns_data.dd_read_offset);
                          request.length =
                              long_long_to_quad(session->ns_data.dd_read_length);
  
!                         NDMP_LOG(LOG_DEBUG, "to NOTIFY_DATA_READ [%llu, %llu]",
                              session->ns_data.dd_read_offset,
                              session->ns_data.dd_read_length);
  
                          if (ndmp_send_request_lock(session->ns_connection,
                              NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
                              &request, 0) < 0) {
!                                 NDMP_LOG(LOG_DEBUG,
                                      "Sending notify_data_read request");
                                  return (-1);
                          }
                  }
  
--- 1698,1715 ----
                          request.offset =
                              long_long_to_quad(session->ns_data.dd_read_offset);
                          request.length =
                              long_long_to_quad(session->ns_data.dd_read_length);
  
!                         syslog(LOG_DEBUG, "to NOTIFY_DATA_READ [%lu, %lu]",
                              session->ns_data.dd_read_offset,
                              session->ns_data.dd_read_length);
  
                          if (ndmp_send_request_lock(session->ns_connection,
                              NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
                              &request, 0) < 0) {
!                                 syslog(LOG_ERR,
                                      "Sending notify_data_read request");
                                  return (-1);
                          }
                  }
  
*** 1865,1881 ****
                  if (len > session->ns_data.dd_bytes_left_to_read)
                          len = session->ns_data.dd_bytes_left_to_read;
  
                  if ((n = read(session->ns_data.dd_sock, &data[count],
                      len)) < 0) {
!                         NDMP_LOG(LOG_ERR, "Socket read error: %m.");
                          return (-1);
                  }
  
                  /* read returns 0 if the connection was closed */
                  if (n == 0) {
!                         NDMP_LOG(LOG_DEBUG, "n 0 errno %d",
                              errno);
                          return (-1);
                  }
  
                  count += n;
--- 1734,1750 ----
                  if (len > session->ns_data.dd_bytes_left_to_read)
                          len = session->ns_data.dd_bytes_left_to_read;
  
                  if ((n = read(session->ns_data.dd_sock, &data[count],
                      len)) < 0) {
!                         syslog(LOG_ERR, "Socket read error: %m.");
                          return (-1);
                  }
  
                  /* read returns 0 if the connection was closed */
                  if (n == 0) {
!                         syslog(LOG_ERR, "n 0 errno %d",
                              errno);
                          return (-1);
                  }
  
                  count += n;
*** 1900,1919 ****
  nlp_release_job_stat(ndmpd_session_t *session)
  {
          ndmp_lbr_params_t *nlp;
  
          if ((nlp = ndmp_get_nlp(session)) == NULL) {
-                 NDMP_LOG(LOG_DEBUG, "nlp == NULL");
                  return;
          }
          if (nlp->nlp_jstat != NULL) {
                  nlp->nlp_bytes_total =
                      (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
                  tlm_un_ref_job_stats(nlp->nlp_jstat->js_job_name);
                  nlp->nlp_jstat = NULL;
!         } else
!                 NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
  }
  
  
  /* *** ndmpd global internal functions *********************************** */
  
--- 1769,1786 ----
  nlp_release_job_stat(ndmpd_session_t *session)
  {
          ndmp_lbr_params_t *nlp;
  
          if ((nlp = ndmp_get_nlp(session)) == NULL) {
                  return;
          }
          if (nlp->nlp_jstat != NULL) {
                  nlp->nlp_bytes_total =
                      (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
                  tlm_un_ref_job_stats(nlp->nlp_jstat->js_job_name);
                  nlp->nlp_jstat = NULL;
!         }
  }
  
  
  /* *** ndmpd global internal functions *********************************** */
  
*** 1973,1991 ****
   */
  void
  ndmpd_data_cleanup(ndmpd_session_t *session)
  {
          if (session->ns_data.dd_listen_sock != -1) {
!                 NDMP_LOG(LOG_DEBUG, "data.listen_sock: %d",
                      session->ns_data.dd_listen_sock);
                  (void) ndmpd_remove_file_handler(session,
                      session->ns_data.dd_listen_sock);
                  (void) close(session->ns_data.dd_listen_sock);
                  session->ns_data.dd_listen_sock = -1;
          }
          if (session->ns_data.dd_sock != -1) {
!                 NDMP_LOG(LOG_DEBUG, "data.sock: %d",
                      session->ns_data.dd_sock);
  
                  /*
                   * ndmpcopy: we use the same socket for the mover,
                   * so expect to close when mover is done!
--- 1840,1858 ----
   */
  void
  ndmpd_data_cleanup(ndmpd_session_t *session)
  {
          if (session->ns_data.dd_listen_sock != -1) {
!                 syslog(LOG_DEBUG, "data.listen_sock: %d",
                      session->ns_data.dd_listen_sock);
                  (void) ndmpd_remove_file_handler(session,
                      session->ns_data.dd_listen_sock);
                  (void) close(session->ns_data.dd_listen_sock);
                  session->ns_data.dd_listen_sock = -1;
          }
          if (session->ns_data.dd_sock != -1) {
!                 syslog(LOG_ERR, "data.sock: %d",
                      session->ns_data.dd_sock);
  
                  /*
                   * ndmpcopy: we use the same socket for the mover,
                   * so expect to close when mover is done!
*** 2033,2043 ****
                      (session->ns_data.dd_data_addr_v4.addr_type ==
                      NDMP_ADDR_TCP)) ? "remote" : "local");
                  break;
          default:
                  rv = "Unknown";
!                 NDMP_LOG(LOG_ERR, "Invalid protocol version %d.",
                      session->ns_protocol_version);
          }
  
          return (rv);
  }
--- 1900,1910 ----
                      (session->ns_data.dd_data_addr_v4.addr_type ==
                      NDMP_ADDR_TCP)) ? "remote" : "local");
                  break;
          default:
                  rv = "Unknown";
!                 syslog(LOG_ERR, "Invalid protocol version %d.",
                      session->ns_protocol_version);
          }
  
          return (rv);
  }
*** 2065,2084 ****
      ndmp_pval *env_val, ulong_t env_len)
  {
          ndmp_data_start_backup_reply reply;
          ndmpd_module_params_t *params;
          ndmp_lbr_params_t *nlp;
          int err;
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
!                 NDMP_LOG(LOG_ERR, "Can't start new backup in current state.");
                  return (NDMP_ILLEGAL_STATE_ERR);
          }
          if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
              strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
!                 NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
!                 NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
          if ((err = ndmpd_save_env(session, env_val, env_len)) != NDMP_NO_ERR)
                  return (err);
  
--- 1932,1952 ----
      ndmp_pval *env_val, ulong_t env_len)
  {
          ndmp_data_start_backup_reply reply;
          ndmpd_module_params_t *params;
          ndmp_lbr_params_t *nlp;
+         pthread_t tid;
          int err;
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
!                 syslog(LOG_ERR, "Can't start new backup in current state.");
                  return (NDMP_ILLEGAL_STATE_ERR);
          }
          if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
              strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
!                 syslog(LOG_ERR, "Invalid backup type: %s.", bu_type);
!                 syslog(LOG_ERR, "Supported backup types are tar and dump.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
          if ((err = ndmpd_save_env(session, env_val, env_len)) != NDMP_NO_ERR)
                  return (err);
  
*** 2135,2152 ****
          session->ns_data.dd_read_offset = 0;
          session->ns_data.dd_read_length = 0;
  
          if ((err = ndmp_backup_extract_params(session,
              params)) != NDMP_NO_ERR) {
!                 NDMP_LOG(LOG_DEBUG, "err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (err);
          }
  
          err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_READ);
          if (err != NDMP_NO_ERR) {
!                 NDMP_LOG(LOG_DEBUG,
                      "mover connect err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (err);
          }
  
--- 2003,2020 ----
          session->ns_data.dd_read_offset = 0;
          session->ns_data.dd_read_length = 0;
  
          if ((err = ndmp_backup_extract_params(session,
              params)) != NDMP_NO_ERR) {
!                 syslog(LOG_ERR, "err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (err);
          }
  
          err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_READ);
          if (err != NDMP_NO_ERR) {
!                 syslog(LOG_ERR,
                      "mover connect err: %d", err);
                  NDMP_FREE(nlp->nlp_params);
                  return (err);
          }
  
*** 2153,2168 ****
          session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
  
          session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
          session->ns_data.dd_abort = FALSE;
  
!         NDMP_LOG(LOG_DEBUG, "starting backup");
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 NDMP_LOG(LOG_DEBUG, "Sending data_start_backup reply");
                  NDMP_FREE(nlp->nlp_params);
                  if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
                          /*
                           * ndmpcopy: we use the same socket for the mover,
                           * so expect to close when mover is done!
--- 2021,2036 ----
          session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
  
          session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
          session->ns_data.dd_abort = FALSE;
  
!         syslog(LOG_DEBUG, "starting backup");
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 syslog(LOG_DEBUG, "Sending data_start_backup reply");
                  NDMP_FREE(nlp->nlp_params);
                  if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
                          /*
                           * ndmpcopy: we use the same socket for the mover,
                           * so expect to close when mover is done!
*** 2182,2195 ****
           * perform the backup
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         (void) pthread_create(NULL, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_tar_start_recover_v2
--- 2050,2070 ----
           * perform the backup
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         (void) pthread_create(&tid, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
+         if (err) {
+                 syslog(LOG_ERR, "Can't start V2 backup session.");
+                 return (NDMP_ILLEGAL_ARGS_ERR);
+         }
+ 
+         (void) pthread_detach(tid);
+ 
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_tar_start_recover_v2
*** 2214,2234 ****
      ulong_t nlist_len)
  {
          ndmp_data_start_recover_reply_v2 reply;
          ndmpd_module_params_t *params;
          ndmp_lbr_params_t *nlp;
          int err;
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
!                 NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
                  return (NDMP_ILLEGAL_STATE_ERR);
          }
  
          if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
              strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
!                 NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
!                 NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
  
          reply.error = ndmpd_save_env(session, env_val, env_len);
          if (reply.error != NDMP_NO_ERR)
--- 2089,2110 ----
      ulong_t nlist_len)
  {
          ndmp_data_start_recover_reply_v2 reply;
          ndmpd_module_params_t *params;
          ndmp_lbr_params_t *nlp;
+         pthread_t tid;
          int err;
  
          if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
!                 syslog(LOG_ERR, "Can't start new recover in current state.");
                  return (NDMP_ILLEGAL_STATE_ERR);
          }
  
          if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
              strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
!                 syslog(LOG_ERR, "Invalid backup type: %s.", bu_type);
!                 syslog(LOG_ERR, "Supported backup types are tar and dump.");
                  return (NDMP_ILLEGAL_ARGS_ERR);
          }
  
          reply.error = ndmpd_save_env(session, env_val, env_len);
          if (reply.error != NDMP_NO_ERR)
*** 2293,2303 ****
          session->ns_data.dd_abort = FALSE;
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 NDMP_LOG(LOG_DEBUG, "Sending data_start_recover reply");
                  NDMP_FREE(nlp->nlp_params);
                  if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
                          /*
                           * ndmpcopy: we use the same socket for the mover,
                           * so expect to close when mover is done!
--- 2169,2179 ----
          session->ns_data.dd_abort = FALSE;
  
          reply.error = NDMP_NO_ERR;
          if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
              &reply) < 0) {
!                 syslog(LOG_DEBUG, "Sending data_start_recover reply");
                  NDMP_FREE(nlp->nlp_params);
                  if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
                          /*
                           * ndmpcopy: we use the same socket for the mover,
                           * so expect to close when mover is done!
*** 2319,2332 ****
           * perform the restore
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         (void) pthread_create(NULL, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_data_get_info
--- 2195,2215 ----
           * perform the restore
           *
           * Cannot wait for the thread to exit as we are replying to the
           * client request here.
           */
!         (void) pthread_create(&tid, NULL,
              (funct_t)session->ns_data.dd_module.dm_start_func,
              params);
  
+         if (err != 0) {
+                 syslog(LOG_ERR, "Can't start V2 recover session.");
+                 return (NDMP_ILLEGAL_ARGS_ERR);
+         }
+ 
+         (void) pthread_detach(tid);
+ 
          return (NDMP_NO_ERR);
  }
  
  /*
   * ndmpd_data_get_info