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 +1,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * BSD 3 Clause License
  *
@@ -39,10 +39,11 @@
 /* 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,14 +70,10 @@
 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
  * ************************************************************************
  */
@@ -154,11 +151,11 @@
         /*
          * 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);
+                syslog(LOG_ERR, "err: %d", err);
                 reply.error = err;
                 ndmp_send_reply(connection, &reply,
                     "sending data_start_backup reply");
                 ndmpd_data_cleanup(session);
         }
@@ -224,11 +221,11 @@
         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.");
+                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,11 +254,10 @@
 {
         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;
         }
@@ -301,11 +297,10 @@
         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;
         }
@@ -399,21 +394,19 @@
         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.");
+                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) {
-                        NDMP_LOG(LOG_ERR, "Write protected device.");
+                        syslog(LOG_ERR, "Write protected device.");
                         reply.error = NDMP_WRITE_PROTECT_ERR;
                         goto _error;
                 }
         }
 
@@ -428,31 +421,28 @@
                 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.");
+                    "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);
-                NDMP_LOG(LOG_ERR, msg_invalid);
-                NDMP_LOG(LOG_ERR, 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;
         }
 
-        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.
@@ -489,11 +479,11 @@
         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.");
+                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,32 +497,28 @@
                 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.");
+                    "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);
-                NDMP_LOG(LOG_ERR, msg_invalid);
-                NDMP_LOG(LOG_ERR, 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;
         }
 
-        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.
@@ -570,11 +556,10 @@
         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
@@ -595,11 +580,11 @@
                 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",
+                syslog(LOG_ERR, "Unknown data V3 state %d",
                     session->ns_data.dd_state);
         }
 
         ndmp_send_reply(connection, &reply,
             "sending data_abort_v3 reply");
@@ -624,11 +609,10 @@
 {
         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;
         }
@@ -672,15 +656,15 @@
 
         (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,
+                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;
-                NDMP_LOG(LOG_ERR,
+                syslog(LOG_ERR,
                     "Invalid mover state to process listen request.");
         } else {
                 reply.error = NDMP_NO_ERR;
         }
 
@@ -706,16 +690,16 @@
                 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",
+                syslog(LOG_DEBUG, "listen_socket: %d",
                     session->ns_data.dd_listen_sock);
                 break;
 
         default:
-                NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
+                syslog(LOG_ERR, "Invalid address type: %d",
                     request->addr_type);
                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
                 break;
         }
 
@@ -751,15 +735,14 @@
 
         (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",
+                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;
-                NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
         } else {
                 reply.error = NDMP_NO_ERR;
         }
 
         if (reply.error != NDMP_NO_ERR) {
@@ -775,11 +758,11 @@
                  * 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,
+                        syslog(LOG_ERR,
                             "Mover is not in local listen state.");
                 } else {
                         session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                 }
                 break;
@@ -789,11 +772,11 @@
                     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",
+                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,15 +815,14 @@
 
         (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.");
+                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,15 +906,14 @@
 
         (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",
+                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;
-                NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
         } else {
                 reply.error = NDMP_NO_ERR;
         }
 
         if (reply.error != NDMP_NO_ERR) {
@@ -948,11 +929,11 @@
                  * 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,
+                        syslog(LOG_ERR,
                             "Mover is not in local listen state.");
                 } else {
                         session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
                 }
                 break;
@@ -962,11 +943,11 @@
                     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",
+                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,15 +982,15 @@
 
         (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,
+                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;
-                NDMP_LOG(LOG_ERR,
+                syslog(LOG_ERR,
                     "Invalid mover state to process listen request.");
         } else {
                 reply.error = NDMP_NO_ERR;
         }
 
@@ -1049,16 +1030,16 @@
 
                 /* 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",
+                syslog(LOG_DEBUG, "listen_socket: %d",
                     session->ns_data.dd_listen_sock);
                 break;
 
         default:
-                NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
+                syslog(LOG_ERR, "Invalid address type: %d",
                     request->addr_type);
                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
                 break;
         }
 
@@ -1087,11 +1068,11 @@
 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");
+        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,15 +1174,15 @@
         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,
+                        syslog(LOG_ERR,
                             "Error sending notify_data_halted request");
         } else {
                 if (ndmpd_data_error_send(session, reason) < 0)
-                        NDMP_LOG(LOG_DEBUG,
+                        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,22 +1236,22 @@
 
         from_len = sizeof (from);
         session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
             &from_len);
 
-        NDMP_LOG(LOG_DEBUG, "sock fd: %d",
+        syslog(LOG_DEBUG, "sock fd: %d",
             session->ns_data.dd_sock);
-        NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s",
+        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) {
-                NDMP_LOG(LOG_DEBUG, "Accept error: %m");
+                syslog(LOG_ERR, "Accept error: %m");
                 ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                 return;
         }
 
         /*
@@ -1309,11 +1290,11 @@
             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",
+        syslog(LOG_DEBUG, "addr: %s:%d",
             inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
 
         return (0);
 }
 
@@ -1371,10 +1352,11 @@
 {
         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,19 +1422,19 @@
         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);
+                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) {
-                NDMP_LOG(LOG_DEBUG, "Sending data_start_backup_v3 reply");
+                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,18 +1445,21 @@
          * perform the backup
          *
          * Cannot wait for the thread to exit as we are replying to the
          * client request here.
          */
-        err = pthread_create(NULL, NULL,
+        err = pthread_create(&tid, NULL,
             (funct_t)session->ns_data.dd_module.dm_start_func,
             params);
+
         if (err != 0) {
-                NDMP_LOG(LOG_ERR, "Can't start backup session.");
+                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,10 +1484,11 @@
     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,11 +1561,11 @@
         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,
+                syslog(LOG_ERR,
                     "Error sending ndmp_data_start_recover_reply");
                 ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
                 return (NDMP_NO_ERR);
         }
 
@@ -1592,128 +1578,21 @@
          * perform the restore
          *
          * Cannot wait for the thread to exit as we are replying to the
          * client request here.
          */
-        err = pthread_create(NULL, NULL,
+        err = pthread_create(&tid, NULL,
             (funct_t)session->ns_data.dd_module.dm_start_func,
             params);
 
         if (err != 0) {
-                NDMP_LOG(LOG_ERR, "Can't start recover session.");
+                syslog(LOG_ERR, "Can't start V3 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
@@ -1739,11 +1618,11 @@
             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.");
+                syslog(LOG_ERR, "Socket read error: %m.");
                 n = -1;
         }
 
         return (n);
 }
@@ -1771,17 +1650,10 @@
         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;
 
                 /*
@@ -1808,13 +1680,10 @@
                                  * 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)
@@ -1829,18 +1698,18 @@
                         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]",
+                        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) {
-                                NDMP_LOG(LOG_DEBUG,
+                                syslog(LOG_ERR,
                                     "Sending notify_data_read request");
                                 return (-1);
                         }
                 }
 
@@ -1865,17 +1734,17 @@
                 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.");
+                        syslog(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",
+                        syslog(LOG_ERR, "n 0 errno %d",
                             errno);
                         return (-1);
                 }
 
                 count += n;
@@ -1900,20 +1769,18 @@
 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 *********************************** */
 
@@ -1973,19 +1840,19 @@
  */
 void
 ndmpd_data_cleanup(ndmpd_session_t *session)
 {
         if (session->ns_data.dd_listen_sock != -1) {
-                NDMP_LOG(LOG_DEBUG, "data.listen_sock: %d",
+                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) {
-                NDMP_LOG(LOG_DEBUG, "data.sock: %d",
+                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,11 +1900,11 @@
                     (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.",
+                syslog(LOG_ERR, "Invalid protocol version %d.",
                     session->ns_protocol_version);
         }
 
         return (rv);
 }
@@ -2065,20 +1932,21 @@
     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) {
-                NDMP_LOG(LOG_ERR, "Can't start new backup in current state.");
+                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) {
-                NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
-                NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
+                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,18 +2003,18 @@
         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);
+                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) {
-                NDMP_LOG(LOG_DEBUG,
+                syslog(LOG_ERR,
                     "mover connect err: %d", err);
                 NDMP_FREE(nlp->nlp_params);
                 return (err);
         }
 
@@ -2153,16 +2021,16 @@
         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");
+        syslog(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");
+                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,14 +2050,21 @@
          * perform the backup
          *
          * Cannot wait for the thread to exit as we are replying to the
          * client request here.
          */
-        (void) pthread_create(NULL, NULL,
+        (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,21 +2089,22 @@
     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) {
-                NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
+                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) {
-                NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
-                NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
+                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,11 +2169,11 @@
         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");
+                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,14 +2195,21 @@
          * perform the restore
          *
          * Cannot wait for the thread to exit as we are replying to the
          * client request here.
          */
-        (void) pthread_create(NULL, NULL,
+        (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