12654012fSReza Sabdar /* 28c4f9701SJanice Chang * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 32654012fSReza Sabdar */ 42654012fSReza Sabdar 52654012fSReza Sabdar /* 62654012fSReza Sabdar * BSD 3 Clause License 72654012fSReza Sabdar * 82654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 92654012fSReza Sabdar * 102654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 112654012fSReza Sabdar * modification, are permitted provided that the following conditions 122654012fSReza Sabdar * are met: 132654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 142654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 152654012fSReza Sabdar * 162654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 172654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 182654012fSReza Sabdar * the documentation and/or other materials provided with the 192654012fSReza Sabdar * distribution. 202654012fSReza Sabdar * 212654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 222654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 232654012fSReza Sabdar * products derived from this software without specific prior written 242654012fSReza Sabdar * permission. 252654012fSReza Sabdar * 262654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 272654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 282654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 292654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 302654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 312654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 322654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 332654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 342654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 352654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 362654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 372654012fSReza Sabdar */ 382654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */ 392654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 409ee94b97SJan Kryl /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ 412654012fSReza Sabdar 422654012fSReza Sabdar #include <sys/ioctl.h> 432654012fSReza Sabdar #include <sys/types.h> 442654012fSReza Sabdar #include <sys/socket.h> 452654012fSReza Sabdar #include <sys/socketvar.h> 462654012fSReza Sabdar #include <netinet/in.h> 472654012fSReza Sabdar #include <arpa/inet.h> 482654012fSReza Sabdar #include <net/if.h> 492654012fSReza Sabdar #include <errno.h> 502654012fSReza Sabdar #include <fcntl.h> 512654012fSReza Sabdar #include <netdb.h> 522654012fSReza Sabdar #include <stdlib.h> 532654012fSReza Sabdar #include <unistd.h> 542654012fSReza Sabdar #include <string.h> 552654012fSReza Sabdar #include "ndmpd_common.h" 562654012fSReza Sabdar #include "ndmpd.h" 572654012fSReza Sabdar #include <sys/mtio.h> 582654012fSReza Sabdar 592654012fSReza Sabdar /* 602654012fSReza Sabdar * Maximum mover record size 612654012fSReza Sabdar */ 622654012fSReza Sabdar #define MAX_MOVER_RECSIZE (512*KILOBYTE) 632654012fSReza Sabdar 642654012fSReza Sabdar static int create_listen_socket_v2(ndmpd_session_t *session, ulong_t *addr, 652654012fSReza Sabdar ushort_t *port); 662654012fSReza Sabdar static int tape_read(ndmpd_session_t *session, char *data); 672654012fSReza Sabdar static int change_tape(ndmpd_session_t *session); 682654012fSReza Sabdar static int discard_data(ndmpd_session_t *session, ulong_t length); 692654012fSReza Sabdar static int mover_tape_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf); 702654012fSReza Sabdar static int mover_socket_write_one_buf(ndmpd_session_t *session, 712654012fSReza Sabdar tlm_buffer_t *buf); 722654012fSReza Sabdar static int start_mover_for_restore(ndmpd_session_t *session); 732654012fSReza Sabdar static int mover_socket_read_one_buf(ndmpd_session_t *session, 742654012fSReza Sabdar tlm_buffer_t *buf, long read_size); 752654012fSReza Sabdar static int mover_tape_write_one_buf(ndmpd_session_t *session, 762654012fSReza Sabdar tlm_buffer_t *buf); 772654012fSReza Sabdar static int start_mover_for_backup(ndmpd_session_t *session); 782654012fSReza Sabdar static boolean_t is_writer_running_v3(ndmpd_session_t *session); 792654012fSReza Sabdar static int mover_pause_v3(ndmpd_session_t *session, 802654012fSReza Sabdar ndmp_mover_pause_reason reason); 812654012fSReza Sabdar static int mover_tape_write_v3(ndmpd_session_t *session, char *data, 822654012fSReza Sabdar ssize_t length); 832654012fSReza Sabdar static int mover_tape_flush_v3(ndmpd_session_t *session); 842654012fSReza Sabdar static int mover_tape_read_v3(ndmpd_session_t *session, char *data); 852654012fSReza Sabdar static int create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, 862654012fSReza Sabdar ushort_t *port); 872654012fSReza Sabdar static void mover_data_read_v3(void *cookie, int fd, ulong_t mode); 882654012fSReza Sabdar static void accept_connection(void *cookie, int fd, ulong_t mode); 892654012fSReza Sabdar static void mover_data_write_v3(void *cookie, int fd, ulong_t mode); 902654012fSReza Sabdar static void accept_connection_v3(void *cookie, int fd, ulong_t mode); 9197f7c475SJan Kryl static ndmp_error mover_connect_sock(ndmpd_session_t *session, 922654012fSReza Sabdar ndmp_mover_mode mode, ulong_t addr, ushort_t port); 932654012fSReza Sabdar static boolean_t is_writer_running(ndmpd_session_t *session); 9497f7c475SJan Kryl static int set_socket_nonblock(int sock); 952654012fSReza Sabdar 962654012fSReza Sabdar 972654012fSReza Sabdar int ndmp_max_mover_recsize = MAX_MOVER_RECSIZE; /* patchable */ 982654012fSReza Sabdar 992654012fSReza Sabdar #define TAPE_READ_ERR -1 1002654012fSReza Sabdar #define TAPE_NO_WRITER_ERR -2 1012654012fSReza Sabdar 1022654012fSReza Sabdar /* 10397f7c475SJan Kryl * Set non-blocking mode for socket. 10497f7c475SJan Kryl */ 10597f7c475SJan Kryl static int 10697f7c475SJan Kryl set_socket_nonblock(int sock) 10797f7c475SJan Kryl { 10897f7c475SJan Kryl int flags; 10997f7c475SJan Kryl 11097f7c475SJan Kryl flags = fcntl(sock, F_GETFL, 0); 11197f7c475SJan Kryl if (flags < 0) 11297f7c475SJan Kryl return (0); 11397f7c475SJan Kryl return (fcntl(sock, F_SETFL, flags|O_NONBLOCK) == 0); 11497f7c475SJan Kryl } 11597f7c475SJan Kryl 11697f7c475SJan Kryl /* 1172654012fSReza Sabdar * ************************************************************************ 1182654012fSReza Sabdar * NDMP V2 HANDLERS 1192654012fSReza Sabdar * ************************************************************************ 1202654012fSReza Sabdar */ 1212654012fSReza Sabdar 1222654012fSReza Sabdar /* 1232654012fSReza Sabdar * ndmpd_mover_get_state_v2 1242654012fSReza Sabdar * 1252654012fSReza Sabdar * This handler handles the mover_get_state request. 1262654012fSReza Sabdar * Status information for the mover state machine is returned. 1272654012fSReza Sabdar * 1282654012fSReza Sabdar * Parameters: 1292654012fSReza Sabdar * connection (input) - connection handle. 1302654012fSReza Sabdar * body (input) - request message body. 1312654012fSReza Sabdar * 1322654012fSReza Sabdar * Returns: 1332654012fSReza Sabdar * void 1342654012fSReza Sabdar */ 1352654012fSReza Sabdar /*ARGSUSED*/ 1362654012fSReza Sabdar void 1372654012fSReza Sabdar ndmpd_mover_get_state_v2(ndmp_connection_t *connection, void *body) 1382654012fSReza Sabdar { 1392654012fSReza Sabdar ndmp_mover_get_state_reply_v2 reply; 1402654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 1412654012fSReza Sabdar 1422654012fSReza Sabdar reply.error = NDMP_NO_ERR; 1432654012fSReza Sabdar reply.state = session->ns_mover.md_state; 1442654012fSReza Sabdar reply.pause_reason = session->ns_mover.md_pause_reason; 1452654012fSReza Sabdar reply.halt_reason = session->ns_mover.md_halt_reason; 1462654012fSReza Sabdar reply.record_size = session->ns_mover.md_record_size; 1472654012fSReza Sabdar reply.record_num = session->ns_mover.md_record_num; 1482654012fSReza Sabdar reply.data_written = 1492654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_data_written); 1502654012fSReza Sabdar reply.seek_position = 1512654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_seek_position); 1522654012fSReza Sabdar reply.bytes_left_to_read = 1532654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 1542654012fSReza Sabdar reply.window_offset = 1552654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_offset); 1562654012fSReza Sabdar reply.window_length = 1572654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_length); 1582654012fSReza Sabdar 1592654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 1602654012fSReza Sabdar "sending tape_get_state reply"); 1612654012fSReza Sabdar } 1622654012fSReza Sabdar 1632654012fSReza Sabdar 1642654012fSReza Sabdar /* 1652654012fSReza Sabdar * ndmpd_mover_listen_v2 1662654012fSReza Sabdar * 1672654012fSReza Sabdar * This handler handles mover_listen requests. 1682654012fSReza Sabdar * 1692654012fSReza Sabdar * Parameters: 1702654012fSReza Sabdar * connection (input) - connection handle. 1712654012fSReza Sabdar * body (input) - request message body. 1722654012fSReza Sabdar * 1732654012fSReza Sabdar * Returns: 1742654012fSReza Sabdar * void 1752654012fSReza Sabdar */ 1762654012fSReza Sabdar void 1772654012fSReza Sabdar ndmpd_mover_listen_v2(ndmp_connection_t *connection, void *body) 1782654012fSReza Sabdar { 1792654012fSReza Sabdar ndmp_mover_listen_request_v2 *request; 1802654012fSReza Sabdar ndmp_mover_listen_reply_v2 reply; 1812654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 1822654012fSReza Sabdar ulong_t addr; 1832654012fSReza Sabdar ushort_t port; 1842654012fSReza Sabdar 1852654012fSReza Sabdar request = (ndmp_mover_listen_request_v2 *)body; 1862654012fSReza Sabdar 1872654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE || 1882654012fSReza Sabdar session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 1892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 1902654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 1912654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 1922654012fSReza Sabdar "sending mover_listen reply"); 1932654012fSReza Sabdar return; 1942654012fSReza Sabdar } 1952654012fSReza Sabdar session->ns_mover.md_mode = request->mode; 1962654012fSReza Sabdar 1972654012fSReza Sabdar if (request->addr_type == NDMP_ADDR_LOCAL) { 1982654012fSReza Sabdar reply.mover.addr_type = NDMP_ADDR_LOCAL; 1992654012fSReza Sabdar } else { 2002654012fSReza Sabdar if (create_listen_socket_v2(session, &addr, &port) < 0) { 2012654012fSReza Sabdar reply.error = NDMP_IO_ERR; 2022654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2032654012fSReza Sabdar "sending mover_listen reply"); 2042654012fSReza Sabdar return; 2052654012fSReza Sabdar } 2062654012fSReza Sabdar reply.mover.addr_type = NDMP_ADDR_TCP; 2072654012fSReza Sabdar reply.mover.ndmp_mover_addr_u.addr.ip_addr = htonl(addr); 2082654012fSReza Sabdar reply.mover.ndmp_mover_addr_u.addr.port = htons(port); 2092654012fSReza Sabdar } 2102654012fSReza Sabdar 2112654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 2122654012fSReza Sabdar 2132654012fSReza Sabdar /* 2142654012fSReza Sabdar * ndmp window should always set by client during restore 2152654012fSReza Sabdar */ 2162654012fSReza Sabdar 2172654012fSReza Sabdar /* Set the default window. */ 2182654012fSReza Sabdar session->ns_mover.md_window_offset = 0; 2192654012fSReza Sabdar session->ns_mover.md_window_length = MAX_WINDOW_SIZE; 2202654012fSReza Sabdar session->ns_mover.md_position = 0; 2212654012fSReza Sabdar 2222654012fSReza Sabdar reply.error = NDMP_NO_ERR; 2232654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2242654012fSReza Sabdar "sending mover_listen reply"); 2252654012fSReza Sabdar } 2262654012fSReza Sabdar 2272654012fSReza Sabdar 2282654012fSReza Sabdar /* 2292654012fSReza Sabdar * ndmpd_mover_continue_v2 2302654012fSReza Sabdar * 2312654012fSReza Sabdar * This handler handles mover_continue requests. 2322654012fSReza Sabdar * 2332654012fSReza Sabdar * Parameters: 2342654012fSReza Sabdar * connection (input) - connection handle. 2352654012fSReza Sabdar * body (input) - request message body. 2362654012fSReza Sabdar * 2372654012fSReza Sabdar * Returns: 2382654012fSReza Sabdar * void 2392654012fSReza Sabdar */ 2402654012fSReza Sabdar /*ARGSUSED*/ 2412654012fSReza Sabdar void 2422654012fSReza Sabdar ndmpd_mover_continue_v2(ndmp_connection_t *connection, void *body) 2432654012fSReza Sabdar { 2442654012fSReza Sabdar ndmp_mover_continue_reply reply; 2452654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 2462654012fSReza Sabdar 2472654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 2482654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 2492654012fSReza Sabdar 2502654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 2512654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2522654012fSReza Sabdar "sending mover_continue reply"); 2532654012fSReza Sabdar return; 2542654012fSReza Sabdar } 2552654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 2562654012fSReza Sabdar reply.error = NDMP_NO_ERR; 2572654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2582654012fSReza Sabdar "sending mover_continue reply"); 2592654012fSReza Sabdar } 2602654012fSReza Sabdar 2612654012fSReza Sabdar 2622654012fSReza Sabdar /* 2632654012fSReza Sabdar * ndmpd_mover_abort_v2 2642654012fSReza Sabdar * 2652654012fSReza Sabdar * This handler handles mover_abort requests. 2662654012fSReza Sabdar * 2672654012fSReza Sabdar * Parameters: 2682654012fSReza Sabdar * connection (input) - connection handle. 2692654012fSReza Sabdar * body (input) - request message body. 2702654012fSReza Sabdar * 2712654012fSReza Sabdar * Returns: 2722654012fSReza Sabdar * void 2732654012fSReza Sabdar */ 2742654012fSReza Sabdar /*ARGSUSED*/ 2752654012fSReza Sabdar void 2762654012fSReza Sabdar ndmpd_mover_abort_v2(ndmp_connection_t *connection, void *body) 2772654012fSReza Sabdar { 2782654012fSReza Sabdar ndmp_mover_abort_reply reply; 2792654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 2802654012fSReza Sabdar 2812654012fSReza Sabdar if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 2822654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 2832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 2842654012fSReza Sabdar 2852654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 2862654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2872654012fSReza Sabdar "sending mover_abort reply"); 2882654012fSReza Sabdar return; 2892654012fSReza Sabdar } 2902654012fSReza Sabdar 2912654012fSReza Sabdar reply.error = NDMP_NO_ERR; 2922654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 2932654012fSReza Sabdar "sending mover_abort reply"); 2942654012fSReza Sabdar 2952654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_ABORTED); 2962654012fSReza Sabdar ndmp_stop_buffer_worker(session); 2972654012fSReza Sabdar } 2982654012fSReza Sabdar 2992654012fSReza Sabdar 3002654012fSReza Sabdar /* 3012654012fSReza Sabdar * ndmpd_mover_stop_v2 3022654012fSReza Sabdar * 3032654012fSReza Sabdar * This handler handles mover_stop requests. 3042654012fSReza Sabdar * 3052654012fSReza Sabdar * Parameters: 3062654012fSReza Sabdar * connection (input) - connection handle. 3072654012fSReza Sabdar * body (input) - request message body. 3082654012fSReza Sabdar * 3092654012fSReza Sabdar * Returns: 3102654012fSReza Sabdar * void 3112654012fSReza Sabdar */ 3122654012fSReza Sabdar /*ARGSUSED*/ 3132654012fSReza Sabdar void 3142654012fSReza Sabdar ndmpd_mover_stop_v2(ndmp_connection_t *connection, void *body) 3152654012fSReza Sabdar { 3162654012fSReza Sabdar ndmp_mover_stop_reply reply; 3172654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 3182654012fSReza Sabdar 3192654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_HALTED) { 3202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 3212654012fSReza Sabdar 3222654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 3232654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 3242654012fSReza Sabdar "sending mover_stop reply"); 3252654012fSReza Sabdar return; 3262654012fSReza Sabdar } 3272654012fSReza Sabdar 3282654012fSReza Sabdar ndmp_waitfor_op(session); 3292654012fSReza Sabdar reply.error = NDMP_NO_ERR; 3302654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 3312654012fSReza Sabdar "sending mover_stop reply"); 3322654012fSReza Sabdar 3332654012fSReza Sabdar ndmp_lbr_cleanup(session); 3342654012fSReza Sabdar ndmpd_mover_cleanup(session); 3352654012fSReza Sabdar (void) ndmpd_mover_init(session); 3362654012fSReza Sabdar (void) ndmp_lbr_init(session); 3372654012fSReza Sabdar } 3382654012fSReza Sabdar 3392654012fSReza Sabdar 3402654012fSReza Sabdar /* 3412654012fSReza Sabdar * ndmpd_mover_set_window_v2 3422654012fSReza Sabdar * 3432654012fSReza Sabdar * This handler handles mover_set_window requests. 3442654012fSReza Sabdar * 3452654012fSReza Sabdar * 3462654012fSReza Sabdar * Parameters: 3472654012fSReza Sabdar * connection (input) - connection handle. 3482654012fSReza Sabdar * body (input) - request message body. 3492654012fSReza Sabdar * 3502654012fSReza Sabdar * Returns: 3512654012fSReza Sabdar * void 3522654012fSReza Sabdar */ 3532654012fSReza Sabdar void 3542654012fSReza Sabdar ndmpd_mover_set_window_v2(ndmp_connection_t *connection, void *body) 3552654012fSReza Sabdar { 3562654012fSReza Sabdar ndmp_mover_set_window_request *request; 3572654012fSReza Sabdar ndmp_mover_set_window_reply reply; 3582654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 3592654012fSReza Sabdar 3602654012fSReza Sabdar request = (ndmp_mover_set_window_request *) body; 3612654012fSReza Sabdar 3622654012fSReza Sabdar /* 3632654012fSReza Sabdar * The NDMPv2 specification states that "a window can be set only 3642654012fSReza Sabdar * when in the listen or paused state." 3652654012fSReza Sabdar * 3662654012fSReza Sabdar * See the comment in ndmpd_mover_set_window_v3 regarding the reason for 3672654012fSReza Sabdar * allowing it in the idle state as well. 3682654012fSReza Sabdar */ 3692654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE && 3702654012fSReza Sabdar session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED && 3712654012fSReza Sabdar session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN) { 3722654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 3732654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state %d", 3742654012fSReza Sabdar session->ns_mover.md_state); 3752654012fSReza Sabdar } else { 3762654012fSReza Sabdar if (quad_to_long_long(request->length) == 0) { 3772654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 3782654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid window size %d", 3792654012fSReza Sabdar quad_to_long_long(request->length)); 3802654012fSReza Sabdar } else { 3812654012fSReza Sabdar reply.error = NDMP_NO_ERR; 3822654012fSReza Sabdar session->ns_mover.md_window_offset = 3832654012fSReza Sabdar quad_to_long_long(request->offset); 3842654012fSReza Sabdar session->ns_mover.md_window_length = 3852654012fSReza Sabdar quad_to_long_long(request->length); 3862654012fSReza Sabdar session->ns_mover.md_position = 3872654012fSReza Sabdar session->ns_mover.md_window_offset; 3882654012fSReza Sabdar } 3892654012fSReza Sabdar } 3902654012fSReza Sabdar 3912654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 3922654012fSReza Sabdar "sending mover_set_window reply"); 3932654012fSReza Sabdar } 3942654012fSReza Sabdar 3952654012fSReza Sabdar 3962654012fSReza Sabdar /* 3972654012fSReza Sabdar * ndmpd_mover_read_v2 3982654012fSReza Sabdar * 3992654012fSReza Sabdar * This handler handles mover_read requests. If the requested offset is 4002654012fSReza Sabdar * outside of the current window, the mover is paused and a notify_mover_paused 4012654012fSReza Sabdar * request is sent notifying the client that a seek is required. If the 4022654012fSReza Sabdar * requested offest is within the window but not within the current record, 4032654012fSReza Sabdar * then the tape is positioned to the record containing the requested offest. 4042654012fSReza Sabdar * The requested amount of data is then read from the tape device and written 4052654012fSReza Sabdar * to the data connection. 4062654012fSReza Sabdar * 4072654012fSReza Sabdar * Parameters: 4082654012fSReza Sabdar * connection (input) - connection handle. 4092654012fSReza Sabdar * body (input) - request message body. 4102654012fSReza Sabdar * 4112654012fSReza Sabdar * Returns: 4122654012fSReza Sabdar * void 4132654012fSReza Sabdar */ 4142654012fSReza Sabdar void 4152654012fSReza Sabdar ndmpd_mover_read_v2(ndmp_connection_t *connection, void *body) 4162654012fSReza Sabdar { 4172654012fSReza Sabdar ndmp_mover_read_request *request = (ndmp_mover_read_request *) body; 4182654012fSReza Sabdar ndmp_mover_read_reply reply; 4192654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 4202654012fSReza Sabdar int err; 4212654012fSReza Sabdar 4222654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_ACTIVE || 4232654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read != 0 || 4242654012fSReza Sabdar session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) { 4252654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 4262654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 4272654012fSReza Sabdar ndmp_send_reply(connection, &reply, 4282654012fSReza Sabdar "sending mover_read reply"); 4292654012fSReza Sabdar return; 4302654012fSReza Sabdar } 4312654012fSReza Sabdar if (session->ns_tape.td_fd == -1) { 4322654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Tape device is not open"); 4332654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 4342654012fSReza Sabdar ndmp_send_reply(connection, &reply, 4352654012fSReza Sabdar "sending mover_read reply"); 4362654012fSReza Sabdar return; 4372654012fSReza Sabdar } 4382654012fSReza Sabdar 4392654012fSReza Sabdar reply.error = NDMP_NO_ERR; 4402654012fSReza Sabdar ndmp_send_reply(connection, &reply, "sending mover_read reply"); 4412654012fSReza Sabdar 4422654012fSReza Sabdar err = ndmpd_mover_seek(session, quad_to_long_long(request->offset), 4432654012fSReza Sabdar quad_to_long_long(request->length)); 4442654012fSReza Sabdar if (err < 0) { 4452654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 4462654012fSReza Sabdar return; 4472654012fSReza Sabdar } 4482654012fSReza Sabdar /* 4492654012fSReza Sabdar * Just return if we are waiting for the NDMP client to 4502654012fSReza Sabdar * complete the seek. 4512654012fSReza Sabdar */ 4522654012fSReza Sabdar if (err == 1) 4532654012fSReza Sabdar return; 4542654012fSReza Sabdar 4552654012fSReza Sabdar /* 4562654012fSReza Sabdar * Start the mover for restore in the 3-way backups. 4572654012fSReza Sabdar */ 4582654012fSReza Sabdar if (start_mover_for_restore(session) < 0) 4592654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 4602654012fSReza Sabdar } 4612654012fSReza Sabdar 4622654012fSReza Sabdar 4632654012fSReza Sabdar /* 4642654012fSReza Sabdar * ndmpd_mover_close_v2 4652654012fSReza Sabdar * 4662654012fSReza Sabdar * This handler handles mover_close requests. 4672654012fSReza Sabdar * 4682654012fSReza Sabdar * Parameters: 4692654012fSReza Sabdar * connection (input) - connection handle. 4702654012fSReza Sabdar * body (input) - request message body. 4712654012fSReza Sabdar * 4722654012fSReza Sabdar * Returns: 4732654012fSReza Sabdar * void 4742654012fSReza Sabdar */ 4752654012fSReza Sabdar /*ARGSUSED*/ 4762654012fSReza Sabdar void 4772654012fSReza Sabdar ndmpd_mover_close_v2(ndmp_connection_t *connection, void *body) 4782654012fSReza Sabdar { 4792654012fSReza Sabdar ndmp_mover_close_reply reply; 4802654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 4812654012fSReza Sabdar 4822654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 4832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 4842654012fSReza Sabdar 4852654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 4862654012fSReza Sabdar ndmp_send_reply(connection, &reply, 4872654012fSReza Sabdar "sending mover_close reply"); 4882654012fSReza Sabdar return; 4892654012fSReza Sabdar } 4902654012fSReza Sabdar free(session->ns_mover.md_data_addr_v4.tcp_addr_v4); 4912654012fSReza Sabdar 4922654012fSReza Sabdar reply.error = NDMP_NO_ERR; 4932654012fSReza Sabdar ndmp_send_reply(connection, &reply, "sending mover_close reply"); 4942654012fSReza Sabdar 4952654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 4962654012fSReza Sabdar } 4972654012fSReza Sabdar 4982654012fSReza Sabdar 4992654012fSReza Sabdar /* 5002654012fSReza Sabdar * ndmpd_mover_set_record_size_v2 5012654012fSReza Sabdar * 5022654012fSReza Sabdar * This handler handles mover_set_record_size requests. 5032654012fSReza Sabdar * 5042654012fSReza Sabdar * Parameters: 5052654012fSReza Sabdar * connection (input) - connection handle. 5062654012fSReza Sabdar * body (input) - request message body. 5072654012fSReza Sabdar * 5082654012fSReza Sabdar * Returns: 5092654012fSReza Sabdar * void 5102654012fSReza Sabdar */ 5112654012fSReza Sabdar void 5122654012fSReza Sabdar ndmpd_mover_set_record_size_v2(ndmp_connection_t *connection, void *body) 5132654012fSReza Sabdar { 5142654012fSReza Sabdar ndmp_mover_set_record_size_request *request; 5152654012fSReza Sabdar ndmp_mover_set_record_size_reply reply; 5162654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 5172654012fSReza Sabdar 5182654012fSReza Sabdar request = (ndmp_mover_set_record_size_request *) body; 5192654012fSReza Sabdar 5202654012fSReza Sabdar session->ns_mover.md_record_size = request->len; 5212654012fSReza Sabdar session->ns_mover.md_buf = realloc(session->ns_mover.md_buf, 5222654012fSReza Sabdar request->len); 5232654012fSReza Sabdar 5242654012fSReza Sabdar reply.error = NDMP_NO_ERR; 5252654012fSReza Sabdar ndmp_send_reply(connection, &reply, 5262654012fSReza Sabdar "sending mover_set_record_size reply"); 5272654012fSReza Sabdar } 5282654012fSReza Sabdar 5292654012fSReza Sabdar 5302654012fSReza Sabdar /* 5312654012fSReza Sabdar * ************************************************************************ 5322654012fSReza Sabdar * NDMP V3 HANDLERS 5332654012fSReza Sabdar * ************************************************************************ 5342654012fSReza Sabdar */ 5352654012fSReza Sabdar 5362654012fSReza Sabdar /* 5372654012fSReza Sabdar * ndmpd_mover_get_state_v3 5382654012fSReza Sabdar * 5392654012fSReza Sabdar * This handler handles the ndmp_mover_get_state_request. 5402654012fSReza Sabdar * Status information for the mover state machine is returned. 5412654012fSReza Sabdar * 5422654012fSReza Sabdar * Parameters: 5432654012fSReza Sabdar * connection (input) - connection handle. 5442654012fSReza Sabdar * body (input) - request message body. 5452654012fSReza Sabdar * 5462654012fSReza Sabdar * Returns: 5472654012fSReza Sabdar * void 5482654012fSReza Sabdar */ 5492654012fSReza Sabdar /*ARGSUSED*/ 5502654012fSReza Sabdar void 5512654012fSReza Sabdar ndmpd_mover_get_state_v3(ndmp_connection_t *connection, void *body) 5522654012fSReza Sabdar { 5532654012fSReza Sabdar ndmp_mover_get_state_reply_v3 reply; 5542654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 5552654012fSReza Sabdar 5562654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 5572654012fSReza Sabdar 5582654012fSReza Sabdar reply.error = NDMP_NO_ERR; 5592654012fSReza Sabdar reply.state = session->ns_mover.md_state; 5602654012fSReza Sabdar reply.pause_reason = session->ns_mover.md_pause_reason; 5612654012fSReza Sabdar reply.halt_reason = session->ns_mover.md_halt_reason; 5622654012fSReza Sabdar reply.record_size = session->ns_mover.md_record_size; 5632654012fSReza Sabdar reply.record_num = session->ns_mover.md_record_num; 5642654012fSReza Sabdar reply.data_written = 5652654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_data_written); 5662654012fSReza Sabdar reply.seek_position = 5672654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_seek_position); 5682654012fSReza Sabdar reply.bytes_left_to_read = 5692654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 5702654012fSReza Sabdar reply.window_offset = 5712654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_offset); 5722654012fSReza Sabdar reply.window_length = 5732654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_length); 5742654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) 5752654012fSReza Sabdar ndmp_copy_addr_v3(&reply.data_connection_addr, 5762654012fSReza Sabdar &session->ns_mover.md_data_addr); 5772654012fSReza Sabdar 5782654012fSReza Sabdar ndmp_send_reply(connection, &reply, 5792654012fSReza Sabdar "sending ndmp_mover_get_state reply"); 5802654012fSReza Sabdar } 5812654012fSReza Sabdar 5822654012fSReza Sabdar 5832654012fSReza Sabdar /* 5842654012fSReza Sabdar * ndmpd_mover_listen_v3 5852654012fSReza Sabdar * 5862654012fSReza Sabdar * This handler handles ndmp_mover_listen_requests. 5872654012fSReza Sabdar * A TCP/IP socket is created that is used to listen for 5882654012fSReza Sabdar * and accept data connections initiated by a remote 5892654012fSReza Sabdar * data server. 5902654012fSReza Sabdar * 5912654012fSReza Sabdar * Parameters: 5922654012fSReza Sabdar * connection (input) - connection handle. 5932654012fSReza Sabdar * body (input) - request message body. 5942654012fSReza Sabdar * 5952654012fSReza Sabdar * Returns: 5962654012fSReza Sabdar * void 5972654012fSReza Sabdar */ 5982654012fSReza Sabdar void 5992654012fSReza Sabdar ndmpd_mover_listen_v3(ndmp_connection_t *connection, void *body) 6002654012fSReza Sabdar { 6012654012fSReza Sabdar ndmp_mover_listen_request_v3 *request; 6022654012fSReza Sabdar ndmp_mover_listen_reply_v3 reply; 6032654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 6042654012fSReza Sabdar ulong_t addr; 6052654012fSReza Sabdar ushort_t port; 6062654012fSReza Sabdar 6072654012fSReza Sabdar request = (ndmp_mover_listen_request_v3 *)body; 6082654012fSReza Sabdar 6092654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 6102654012fSReza Sabdar reply.error = NDMP_NO_ERR; 6112654012fSReza Sabdar 6122654012fSReza Sabdar if (request->mode != NDMP_MOVER_MODE_READ && 6132654012fSReza Sabdar request->mode != NDMP_MOVER_MODE_WRITE) { 6142654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 6152654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 6162654012fSReza Sabdar } else if (!ndmp_valid_v3addr_type(request->addr_type)) { 6172654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 6182654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 6192654012fSReza Sabdar request->addr_type); 6202654012fSReza Sabdar } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 6212654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 6222654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6232654012fSReza Sabdar "Invalid mover state to process listen request"); 6242654012fSReza Sabdar } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 6252654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 6262654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6272654012fSReza Sabdar "Invalid data state to process listen request"); 6282654012fSReza Sabdar } else if (session->ns_tape.td_fd == -1) { 6292654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 6302654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No tape device open"); 6312654012fSReza Sabdar } else if (request->mode == NDMP_MOVER_MODE_READ && 6322654012fSReza Sabdar session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 6332654012fSReza Sabdar reply.error = NDMP_PERMISSION_ERR; 6342654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Write protected device."); 6352654012fSReza Sabdar } 6362654012fSReza Sabdar 6372654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) { 6382654012fSReza Sabdar ndmp_send_reply(connection, &reply, 6392654012fSReza Sabdar "error sending ndmp_mover_listen reply"); 6402654012fSReza Sabdar return; 6412654012fSReza Sabdar } 6422654012fSReza Sabdar 6432654012fSReza Sabdar switch (request->addr_type) { 6442654012fSReza Sabdar case NDMP_ADDR_LOCAL: 6452654012fSReza Sabdar reply.data_connection_addr.addr_type = NDMP_ADDR_LOCAL; 6462654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_LOCAL; 6472654012fSReza Sabdar reply.error = NDMP_NO_ERR; 6482654012fSReza Sabdar break; 6492654012fSReza Sabdar case NDMP_ADDR_TCP: 6502654012fSReza Sabdar if (create_listen_socket_v3(session, &addr, &port) < 0) { 6512654012fSReza Sabdar reply.error = NDMP_IO_ERR; 6522654012fSReza Sabdar break; 6532654012fSReza Sabdar } 6542654012fSReza Sabdar reply.error = NDMP_NO_ERR; 6552654012fSReza Sabdar reply.data_connection_addr.addr_type = NDMP_ADDR_TCP; 6562654012fSReza Sabdar reply.data_connection_addr.tcp_ip_v3 = htonl(addr); 6572654012fSReza Sabdar reply.data_connection_addr.tcp_port_v3 = htons(port); 6582654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 6592654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_ip_v3 = addr; 6602654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(port); 6612654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "listen_socket: %d", 6622654012fSReza Sabdar session->ns_mover.md_listen_sock); 6632654012fSReza Sabdar break; 6642654012fSReza Sabdar default: 6652654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 6662654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type: %d", 6672654012fSReza Sabdar request->addr_type); 6682654012fSReza Sabdar } 6692654012fSReza Sabdar 6702654012fSReza Sabdar if (reply.error == NDMP_NO_ERR) { 6712654012fSReza Sabdar session->ns_mover.md_mode = request->mode; 6722654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 6732654012fSReza Sabdar } 6742654012fSReza Sabdar 6752654012fSReza Sabdar ndmp_send_reply(connection, &reply, 6762654012fSReza Sabdar "error sending ndmp_mover_listen reply"); 6772654012fSReza Sabdar } 6782654012fSReza Sabdar 6792654012fSReza Sabdar 6802654012fSReza Sabdar /* 6812654012fSReza Sabdar * ndmpd_mover_continue_v3 6822654012fSReza Sabdar * 6832654012fSReza Sabdar * This handler handles ndmp_mover_continue_requests. 6842654012fSReza Sabdar * 6852654012fSReza Sabdar * Parameters: 6862654012fSReza Sabdar * connection (input) - connection handle. 6872654012fSReza Sabdar * body (input) - request message body. 6882654012fSReza Sabdar * 6892654012fSReza Sabdar * Returns: 6902654012fSReza Sabdar * void 6912654012fSReza Sabdar */ 6922654012fSReza Sabdar /*ARGSUSED*/ 6932654012fSReza Sabdar void 6942654012fSReza Sabdar ndmpd_mover_continue_v3(ndmp_connection_t *connection, void *body) 6952654012fSReza Sabdar { 6962654012fSReza Sabdar ndmp_mover_continue_reply reply; 6972654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 698a23888a3SJan Kryl ndmp_lbr_params_t *nlp = ndmp_get_nlp(session); 6992654012fSReza Sabdar int ret; 7002654012fSReza Sabdar 7012654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 7022654012fSReza Sabdar 7032654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 7042654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 7052654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 7062654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 7072654012fSReza Sabdar "sending mover_continue reply"); 7082654012fSReza Sabdar return; 7092654012fSReza Sabdar } 7102654012fSReza Sabdar 7112654012fSReza Sabdar if (session->ns_protocol_version == NDMPV4 && 7122654012fSReza Sabdar !session->ns_mover.md_pre_cond) { 7132654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Precondition check"); 7142654012fSReza Sabdar reply.error = NDMP_PRECONDITION_ERR; 7152654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 7162654012fSReza Sabdar "sending mover_continue reply"); 7172654012fSReza Sabdar return; 7182654012fSReza Sabdar } 7192654012fSReza Sabdar /* 7202654012fSReza Sabdar * Restore the file handler if the mover is remote to the data 7212654012fSReza Sabdar * server and the handler was removed pending the continuation of a 7222654012fSReza Sabdar * seek request. The handler is removed in mover_data_write(). 7232654012fSReza Sabdar */ 7242654012fSReza Sabdar if (session->ns_mover.md_pause_reason == NDMP_MOVER_PAUSE_SEEK && 7252654012fSReza Sabdar session->ns_mover.md_sock != -1) { 7262654012fSReza Sabdar /* 7272654012fSReza Sabdar * If we are here, it means that we needed DMA interference 7282654012fSReza Sabdar * for seek. We should be on the right window, so we do not 7292654012fSReza Sabdar * need the DMA interference anymore. 7302654012fSReza Sabdar * We do another seek inside the Window to move to the 7312654012fSReza Sabdar * exact position on the tape. 7322654012fSReza Sabdar * If the resore is running without DAR the pause reason should 7332654012fSReza Sabdar * not be seek. 7342654012fSReza Sabdar */ 7352654012fSReza Sabdar ret = ndmpd_mover_seek(session, 7362654012fSReza Sabdar session->ns_mover.md_seek_position, 7372654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read); 7382654012fSReza Sabdar if (ret < 0) { 7392654012fSReza Sabdar ndmpd_mover_error(session, 7402654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 7412654012fSReza Sabdar return; 7422654012fSReza Sabdar } 7432654012fSReza Sabdar 7442654012fSReza Sabdar if (!ret) { 7452654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void*) session, 7462654012fSReza Sabdar session->ns_mover.md_sock, NDMPD_SELECT_MODE_WRITE, 7472654012fSReza Sabdar HC_MOVER, mover_data_write_v3) < 0) 7482654012fSReza Sabdar ndmpd_mover_error(session, 7492654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 7502654012fSReza Sabdar } else { 7512654012fSReza Sabdar /* 7522654012fSReza Sabdar * This should not happen because we should be in the 7532654012fSReza Sabdar * right window. This means that DMA does not follow 7542654012fSReza Sabdar * the V3 spec. 7552654012fSReza Sabdar */ 7562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "DMA Error."); 7572654012fSReza Sabdar ndmpd_mover_error(session, 7582654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 7592654012fSReza Sabdar return; 7602654012fSReza Sabdar } 7612654012fSReza Sabdar } 7622654012fSReza Sabdar 763a23888a3SJan Kryl (void) mutex_lock(&nlp->nlp_mtx); 7642654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 7652654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_NA; 766*f5b1cef2SJan Kryl /* The tape has been likely exchanged, reset tape block counter */ 767*f5b1cef2SJan Kryl session->ns_tape.td_record_count = 0; 768a23888a3SJan Kryl (void) cond_broadcast(&nlp->nlp_cv); 769a23888a3SJan Kryl (void) mutex_unlock(&nlp->nlp_mtx); 7702654012fSReza Sabdar 7712654012fSReza Sabdar reply.error = NDMP_NO_ERR; 7722654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 7732654012fSReza Sabdar "sending mover_continue reply"); 7742654012fSReza Sabdar } 7752654012fSReza Sabdar 7762654012fSReza Sabdar 7772654012fSReza Sabdar /* 7782654012fSReza Sabdar * ndmpd_mover_abort_v3 7792654012fSReza Sabdar * 7802654012fSReza Sabdar * This handler handles mover_abort requests. 7812654012fSReza Sabdar * 7822654012fSReza Sabdar * Parameters: 7832654012fSReza Sabdar * connection (input) - connection handle. 7842654012fSReza Sabdar * body (input) - request message body. 7852654012fSReza Sabdar * 7862654012fSReza Sabdar * Returns: 7872654012fSReza Sabdar * void 7882654012fSReza Sabdar */ 7892654012fSReza Sabdar /*ARGSUSED*/ 7902654012fSReza Sabdar void 7912654012fSReza Sabdar ndmpd_mover_abort_v3(ndmp_connection_t *connection, void *body) 7922654012fSReza Sabdar { 7932654012fSReza Sabdar ndmp_mover_abort_reply reply; 7942654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 7952654012fSReza Sabdar 7962654012fSReza Sabdar if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 7972654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 7982654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 7992654012fSReza Sabdar 8002654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 8012654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 8022654012fSReza Sabdar "sending mover_abort reply"); 8032654012fSReza Sabdar return; 8042654012fSReza Sabdar } 8052654012fSReza Sabdar 8062654012fSReza Sabdar reply.error = NDMP_NO_ERR; 8072654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 8082654012fSReza Sabdar "sending mover_abort reply"); 8092654012fSReza Sabdar 8102654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_ABORTED); 8112654012fSReza Sabdar } 8122654012fSReza Sabdar 8132654012fSReza Sabdar 8142654012fSReza Sabdar /* 8152654012fSReza Sabdar * ndmpd_mover_set_window_v3 8162654012fSReza Sabdar * 8172654012fSReza Sabdar * This handler handles mover_set_window requests. 8182654012fSReza Sabdar * 8192654012fSReza Sabdar * 8202654012fSReza Sabdar * Parameters: 8212654012fSReza Sabdar * connection (input) - connection handle. 8222654012fSReza Sabdar * body (input) - request message body. 8232654012fSReza Sabdar * 8242654012fSReza Sabdar * Returns: 8252654012fSReza Sabdar * void 8262654012fSReza Sabdar */ 8272654012fSReza Sabdar void 8282654012fSReza Sabdar ndmpd_mover_set_window_v3(ndmp_connection_t *connection, void *body) 8292654012fSReza Sabdar { 8302654012fSReza Sabdar ndmp_mover_set_window_request *request; 8312654012fSReza Sabdar ndmp_mover_set_window_reply reply; 8322654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 8332654012fSReza Sabdar 8342654012fSReza Sabdar request = (ndmp_mover_set_window_request *) body; 8352654012fSReza Sabdar 8362654012fSReza Sabdar /* 8372654012fSReza Sabdar * Note: The spec says that the window can be set only in the listen 8382654012fSReza Sabdar * and paused states. We let this happen when mover is in the idle 8392654012fSReza Sabdar * state as well. I can't rememebr which NDMP client (net_backup 4.5 8402654012fSReza Sabdar * or net_worker 6.1.1) forced us to do this! 8412654012fSReza Sabdar */ 8422654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE && 8432654012fSReza Sabdar session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN && 8442654012fSReza Sabdar session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 8452654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 8462654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state %d", 8472654012fSReza Sabdar session->ns_mover.md_state); 8482654012fSReza Sabdar } else if (session->ns_mover.md_record_size == 0) { 8492654012fSReza Sabdar if (session->ns_protocol_version == NDMPV4) 8502654012fSReza Sabdar reply.error = NDMP_PRECONDITION_ERR; 8512654012fSReza Sabdar else 8522654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 8532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 8542654012fSReza Sabdar } else 8552654012fSReza Sabdar reply.error = NDMP_NO_ERR; 8562654012fSReza Sabdar 8572654012fSReza Sabdar if (quad_to_long_long(request->length) == 0) { 8582654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 8592654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid window size %d", 8602654012fSReza Sabdar quad_to_long_long(request->length)); 8612654012fSReza Sabdar } 8622654012fSReza Sabdar 8632654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) { 8642654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 8652654012fSReza Sabdar "sending mover_set_window_v3 reply"); 8662654012fSReza Sabdar return; 8672654012fSReza Sabdar } 8682654012fSReza Sabdar 8692654012fSReza Sabdar session->ns_mover.md_pre_cond = TRUE; 8702654012fSReza Sabdar session->ns_mover.md_window_offset = quad_to_long_long(request->offset); 8712654012fSReza Sabdar session->ns_mover.md_window_length = quad_to_long_long(request->length); 8722654012fSReza Sabdar 8732654012fSReza Sabdar /* 8742654012fSReza Sabdar * We have to update the position for DAR. DAR needs this 8752654012fSReza Sabdar * information to position to the right index on tape, 8762654012fSReza Sabdar * especially when we span the tapes. 8772654012fSReza Sabdar */ 8782654012fSReza Sabdar #ifdef NO_POSITION_CHANGE 8792654012fSReza Sabdar /* 8802654012fSReza Sabdar * Do not change the mover position if we are reading from 8812654012fSReza Sabdar * the tape. In this way, we can use the position+window_length 8822654012fSReza Sabdar * to know how much we can write to a tape before pausing with 8832654012fSReza Sabdar * EOW reason. 8842654012fSReza Sabdar */ 8852654012fSReza Sabdar if (session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) 8862654012fSReza Sabdar #endif /* NO_POSITION_CHANGE */ 8872654012fSReza Sabdar session->ns_mover.md_position = 8882654012fSReza Sabdar session->ns_mover.md_window_offset; 8892654012fSReza Sabdar 8902654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 8912654012fSReza Sabdar "sending mover_set_window_v3 reply"); 8922654012fSReza Sabdar } 8932654012fSReza Sabdar 8942654012fSReza Sabdar 8952654012fSReza Sabdar /* 8962654012fSReza Sabdar * ndmpd_mover_read_v3 8972654012fSReza Sabdar * 8982654012fSReza Sabdar * This handler handles ndmp_mover_read_requests. 8992654012fSReza Sabdar * If the requested offset is outside of the current window, the mover 9002654012fSReza Sabdar * is paused and a notify_mover_paused request is sent notifying the 9012654012fSReza Sabdar * client that a seek is required. If the requested offest is within 9022654012fSReza Sabdar * the window but not within the current record, then the tape is 9032654012fSReza Sabdar * positioned to the record containing the requested offest. The requested 9042654012fSReza Sabdar * amount of data is then read from the tape device and written to the 9052654012fSReza Sabdar * data connection. 9062654012fSReza Sabdar * 9072654012fSReza Sabdar * Parameters: 9082654012fSReza Sabdar * connection (input) - connection handle. 9092654012fSReza Sabdar * body (input) - request message body. 9102654012fSReza Sabdar * 9112654012fSReza Sabdar * Returns: 9122654012fSReza Sabdar * void 9132654012fSReza Sabdar */ 9142654012fSReza Sabdar void 9152654012fSReza Sabdar ndmpd_mover_read_v3(ndmp_connection_t *connection, void *body) 9162654012fSReza Sabdar { 9172654012fSReza Sabdar ndmp_mover_read_request *request = (ndmp_mover_read_request *)body; 9182654012fSReza Sabdar ndmp_mover_read_reply reply; 9192654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 9202654012fSReza Sabdar int err; 9212654012fSReza Sabdar 9222654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 9232654012fSReza Sabdar 9242654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_ACTIVE || 9252654012fSReza Sabdar session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) { 9262654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 9272654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state"); 9282654012fSReza Sabdar } else if (session->ns_mover.md_bytes_left_to_read != 0) { 9292654012fSReza Sabdar reply.error = NDMP_READ_IN_PROGRESS_ERR; 9302654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "In progress"); 9312654012fSReza Sabdar } else if (session->ns_tape.td_fd == -1) { 9322654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 9332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Tape device is not open"); 9342654012fSReza Sabdar } else if (quad_to_long_long(request->length) == 0 || 9352654012fSReza Sabdar (quad_to_long_long(request->length) == MAX_WINDOW_SIZE && 9362654012fSReza Sabdar quad_to_long_long(request->offset) != 0)) { 9372654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 9382654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Illegal args"); 9392654012fSReza Sabdar } else { 9402654012fSReza Sabdar reply.error = NDMP_NO_ERR; 9412654012fSReza Sabdar } 9422654012fSReza Sabdar 9432654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 9442654012fSReza Sabdar "sending ndmp_mover_read_reply"); 9452654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) 9462654012fSReza Sabdar return; 9472654012fSReza Sabdar 9482654012fSReza Sabdar err = ndmpd_mover_seek(session, quad_to_long_long(request->offset), 9492654012fSReza Sabdar quad_to_long_long(request->length)); 9502654012fSReza Sabdar if (err < 0) { 9512654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 9522654012fSReza Sabdar return; 9532654012fSReza Sabdar } 9542654012fSReza Sabdar 9552654012fSReza Sabdar /* 9562654012fSReza Sabdar * Just return if we are waiting for the DMA to complete the seek. 9572654012fSReza Sabdar */ 9582654012fSReza Sabdar if (err == 1) 9592654012fSReza Sabdar return; 9602654012fSReza Sabdar 9612654012fSReza Sabdar /* 9622654012fSReza Sabdar * Setup a handler function that will be called when 9632654012fSReza Sabdar * data can be written to the data connection without blocking. 9642654012fSReza Sabdar */ 9652654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void*)session, 9662654012fSReza Sabdar session->ns_mover.md_sock, NDMPD_SELECT_MODE_WRITE, HC_MOVER, 9672654012fSReza Sabdar mover_data_write_v3) < 0) { 9682654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 9692654012fSReza Sabdar return; 9702654012fSReza Sabdar } 9712654012fSReza Sabdar } 9722654012fSReza Sabdar 9732654012fSReza Sabdar 9742654012fSReza Sabdar /* 9752654012fSReza Sabdar * ndmpd_mover_set_record_size_v3 9762654012fSReza Sabdar * 9772654012fSReza Sabdar * This handler handles mover_set_record_size requests. 9782654012fSReza Sabdar * 9792654012fSReza Sabdar * Parameters: 9802654012fSReza Sabdar * connection (input) - connection handle. 9812654012fSReza Sabdar * body (input) - request message body. 9822654012fSReza Sabdar * 9832654012fSReza Sabdar * Returns: 9842654012fSReza Sabdar * void 9852654012fSReza Sabdar */ 9862654012fSReza Sabdar void 9872654012fSReza Sabdar ndmpd_mover_set_record_size_v3(ndmp_connection_t *connection, void *body) 9882654012fSReza Sabdar { 9892654012fSReza Sabdar ndmp_mover_set_record_size_request *request; 9902654012fSReza Sabdar ndmp_mover_set_record_size_reply reply; 9912654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 9922654012fSReza Sabdar char *cp; 9932654012fSReza Sabdar 9942654012fSReza Sabdar request = (ndmp_mover_set_record_size_request *) body; 9952654012fSReza Sabdar 9962654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 9972654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 9982654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mover state %d", 9992654012fSReza Sabdar session->ns_mover.md_state); 10002654012fSReza Sabdar } else if (request->len > (unsigned int)ndmp_max_mover_recsize) { 10012654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 10022654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 10032654012fSReza Sabdar "Invalid argument %d, should be > 0 and <= %d", 10042654012fSReza Sabdar request->len, ndmp_max_mover_recsize); 10052654012fSReza Sabdar } else if (request->len == session->ns_mover.md_record_size) 10062654012fSReza Sabdar reply.error = NDMP_NO_ERR; 10072654012fSReza Sabdar else if (!(cp = realloc(session->ns_mover.md_buf, request->len))) { 10082654012fSReza Sabdar reply.error = NDMP_NO_MEM_ERR; 10092654012fSReza Sabdar } else { 10102654012fSReza Sabdar reply.error = NDMP_NO_ERR; 10112654012fSReza Sabdar session->ns_mover.md_buf = cp; 10122654012fSReza Sabdar session->ns_mover.md_record_size = request->len; 10132654012fSReza Sabdar session->ns_mover.md_window_offset = 0; 10142654012fSReza Sabdar session->ns_mover.md_window_length = 0; 10152654012fSReza Sabdar } 10162654012fSReza Sabdar 10172654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 10182654012fSReza Sabdar "sending mover_set_record_size reply"); 10192654012fSReza Sabdar } 10202654012fSReza Sabdar 10212654012fSReza Sabdar 10222654012fSReza Sabdar /* 10232654012fSReza Sabdar * ndmpd_mover_connect_v3 10242654012fSReza Sabdar * Request handler. Connects the mover to either a local 10252654012fSReza Sabdar * or remote data server. 10262654012fSReza Sabdar * 10272654012fSReza Sabdar * Parameters: 10282654012fSReza Sabdar * connection (input) - connection handle. 10292654012fSReza Sabdar * body (input) - request message body. 10302654012fSReza Sabdar * 10312654012fSReza Sabdar * Returns: 10322654012fSReza Sabdar * void 10332654012fSReza Sabdar */ 10342654012fSReza Sabdar void 10352654012fSReza Sabdar ndmpd_mover_connect_v3(ndmp_connection_t *connection, void *body) 10362654012fSReza Sabdar { 10372654012fSReza Sabdar ndmp_mover_connect_request_v3 *request; 10382654012fSReza Sabdar ndmp_mover_connect_reply_v3 reply; 10392654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 10402654012fSReza Sabdar 10412654012fSReza Sabdar request = (ndmp_mover_connect_request_v3*)body; 10422654012fSReza Sabdar 10432654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 10442654012fSReza Sabdar 10452654012fSReza Sabdar if (request->mode != NDMP_MOVER_MODE_READ && 10462654012fSReza Sabdar request->mode != NDMP_MOVER_MODE_WRITE) { 10472654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 10482654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 10492654012fSReza Sabdar } else if (!ndmp_valid_v3addr_type(request->addr.addr_type)) { 10502654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 10512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 10522654012fSReza Sabdar request->addr.addr_type); 10532654012fSReza Sabdar } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 10542654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 10552654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state %d: mover is not idle", 10562654012fSReza Sabdar session->ns_mover.md_state); 10572654012fSReza Sabdar } else if (session->ns_tape.td_fd == -1) { 10582654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 10592654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No tape device open"); 10602654012fSReza Sabdar } else if (request->mode == NDMP_MOVER_MODE_READ && 10612654012fSReza Sabdar session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 10622654012fSReza Sabdar reply.error = NDMP_WRITE_PROTECT_ERR; 10632654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Write protected device."); 10642654012fSReza Sabdar } else 10652654012fSReza Sabdar reply.error = NDMP_NO_ERR; 10662654012fSReza Sabdar 10672654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) { 10682654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 10692654012fSReza Sabdar "sending ndmp_mover_connect reply"); 10702654012fSReza Sabdar return; 10712654012fSReza Sabdar } 10722654012fSReza Sabdar 10732654012fSReza Sabdar switch (request->addr.addr_type) { 10742654012fSReza Sabdar case NDMP_ADDR_LOCAL: 10752654012fSReza Sabdar /* 10762654012fSReza Sabdar * Verify that the data server is listening for a 10772654012fSReza Sabdar * local connection. 10782654012fSReza Sabdar */ 10792654012fSReza Sabdar if (session->ns_data.dd_state != NDMP_DATA_STATE_LISTEN || 10802654012fSReza Sabdar session->ns_data.dd_listen_sock != -1) { 10812654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 10822654012fSReza Sabdar "Data server is not in local listen state"); 10832654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 10842654012fSReza Sabdar } else 10852654012fSReza Sabdar session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED; 10862654012fSReza Sabdar break; 10872654012fSReza Sabdar 10882654012fSReza Sabdar case NDMP_ADDR_TCP: 108997f7c475SJan Kryl reply.error = mover_connect_sock(session, request->mode, 10902654012fSReza Sabdar request->addr.tcp_ip_v3, request->addr.tcp_port_v3); 10912654012fSReza Sabdar break; 10922654012fSReza Sabdar 10932654012fSReza Sabdar default: 10942654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 10952654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 10962654012fSReza Sabdar request->addr.addr_type); 10972654012fSReza Sabdar } 10982654012fSReza Sabdar 10992654012fSReza Sabdar if (reply.error == NDMP_NO_ERR) { 11002654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = 11012654012fSReza Sabdar request->addr.addr_type; 11022654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 11032654012fSReza Sabdar session->ns_mover.md_mode = request->mode; 11042654012fSReza Sabdar } 11052654012fSReza Sabdar 11062654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 11072654012fSReza Sabdar "sending ndmp_mover_connect reply"); 11082654012fSReza Sabdar } 11092654012fSReza Sabdar 11102654012fSReza Sabdar 11112654012fSReza Sabdar /* 11122654012fSReza Sabdar * ************************************************************************ 11132654012fSReza Sabdar * NDMP V4 HANDLERS 11142654012fSReza Sabdar * ************************************************************************ 11152654012fSReza Sabdar */ 11162654012fSReza Sabdar 11172654012fSReza Sabdar /* 11182654012fSReza Sabdar * ndmpd_mover_get_state_v4 11192654012fSReza Sabdar * 11202654012fSReza Sabdar * This handler handles the ndmp_mover_get_state_request. 11212654012fSReza Sabdar * Status information for the mover state machine is returned. 11222654012fSReza Sabdar * 11232654012fSReza Sabdar * Parameters: 11242654012fSReza Sabdar * connection (input) - connection handle. 11252654012fSReza Sabdar * body (input) - request message body. 11262654012fSReza Sabdar * 11272654012fSReza Sabdar * Returns: 11282654012fSReza Sabdar * void 11292654012fSReza Sabdar */ 11302654012fSReza Sabdar /*ARGSUSED*/ 11312654012fSReza Sabdar void 11322654012fSReza Sabdar ndmpd_mover_get_state_v4(ndmp_connection_t *connection, void *body) 11332654012fSReza Sabdar { 11342654012fSReza Sabdar ndmp_mover_get_state_reply_v4 reply; 11352654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 11362654012fSReza Sabdar 11372654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 11382654012fSReza Sabdar 11392654012fSReza Sabdar reply.error = NDMP_NO_ERR; 11402654012fSReza Sabdar reply.state = session->ns_mover.md_state; 11412654012fSReza Sabdar reply.mode = session->ns_mover.md_mode; 11422654012fSReza Sabdar reply.pause_reason = session->ns_mover.md_pause_reason; 11432654012fSReza Sabdar reply.halt_reason = session->ns_mover.md_halt_reason; 11442654012fSReza Sabdar reply.record_size = session->ns_mover.md_record_size; 11452654012fSReza Sabdar reply.record_num = session->ns_mover.md_record_num; 11462654012fSReza Sabdar reply.bytes_moved = 11472654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_data_written); 11482654012fSReza Sabdar reply.seek_position = 11492654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_seek_position); 11502654012fSReza Sabdar reply.bytes_left_to_read = 11512654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 11522654012fSReza Sabdar reply.window_offset = 11532654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_offset); 11542654012fSReza Sabdar reply.window_length = 11552654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_window_length); 11562654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) 11572654012fSReza Sabdar ndmp_copy_addr_v4(&reply.data_connection_addr, 11582654012fSReza Sabdar &session->ns_mover.md_data_addr_v4); 11592654012fSReza Sabdar 11602654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 11612654012fSReza Sabdar "sending ndmp_mover_get_state reply"); 11622654012fSReza Sabdar free(reply.data_connection_addr.tcp_addr_v4); 11632654012fSReza Sabdar } 11642654012fSReza Sabdar 11652654012fSReza Sabdar 11662654012fSReza Sabdar /* 11672654012fSReza Sabdar * ndmpd_mover_listen_v4 11682654012fSReza Sabdar * 11692654012fSReza Sabdar * This handler handles ndmp_mover_listen_requests. 11702654012fSReza Sabdar * A TCP/IP socket is created that is used to listen for 11712654012fSReza Sabdar * and accept data connections initiated by a remote 11722654012fSReza Sabdar * data server. 11732654012fSReza Sabdar * 11742654012fSReza Sabdar * Parameters: 11752654012fSReza Sabdar * connection (input) - connection handle. 11762654012fSReza Sabdar * body (input) - request message body. 11772654012fSReza Sabdar * 11782654012fSReza Sabdar * Returns: 11792654012fSReza Sabdar * void 11802654012fSReza Sabdar */ 11812654012fSReza Sabdar void 11822654012fSReza Sabdar ndmpd_mover_listen_v4(ndmp_connection_t *connection, void *body) 11832654012fSReza Sabdar { 11842654012fSReza Sabdar ndmp_mover_listen_request_v4 *request; 11852654012fSReza Sabdar 11862654012fSReza Sabdar ndmp_mover_listen_reply_v4 reply; 11872654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 11882654012fSReza Sabdar ulong_t addr; 11892654012fSReza Sabdar ushort_t port; 11902654012fSReza Sabdar 11912654012fSReza Sabdar request = (ndmp_mover_listen_request_v4 *)body; 11922654012fSReza Sabdar 11932654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 11942654012fSReza Sabdar reply.error = NDMP_NO_ERR; 11952654012fSReza Sabdar 11962654012fSReza Sabdar if (request->mode != NDMP_MOVER_MODE_READ && 11972654012fSReza Sabdar request->mode != NDMP_MOVER_MODE_WRITE) { 11982654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 11992654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 12002654012fSReza Sabdar } else if (!ndmp_valid_v3addr_type(request->addr_type)) { 12012654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 12022654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 12032654012fSReza Sabdar request->addr_type); 12042654012fSReza Sabdar } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 12052654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 12062654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12072654012fSReza Sabdar "Invalid mover state to process listen request"); 12082654012fSReza Sabdar } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 12092654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 12102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12112654012fSReza Sabdar "Invalid data state to process listen request"); 12122654012fSReza Sabdar } else if (session->ns_tape.td_fd == -1) { 12132654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 12142654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No tape device open"); 12152654012fSReza Sabdar } else if (session->ns_mover.md_record_size == 0) { 12162654012fSReza Sabdar reply.error = NDMP_PRECONDITION_ERR; 12172654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 12182654012fSReza Sabdar } else if (request->mode == NDMP_MOVER_MODE_READ && 12192654012fSReza Sabdar session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 12202654012fSReza Sabdar reply.error = NDMP_PERMISSION_ERR; 12212654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Write protected device."); 12222654012fSReza Sabdar } 12232654012fSReza Sabdar 12242654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) { 12252654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 12262654012fSReza Sabdar "error sending ndmp_mover_listen reply"); 12272654012fSReza Sabdar return; 12282654012fSReza Sabdar } 12292654012fSReza Sabdar 12302654012fSReza Sabdar switch (request->addr_type) { 12312654012fSReza Sabdar case NDMP_ADDR_LOCAL: 12322654012fSReza Sabdar reply.connect_addr.addr_type = NDMP_ADDR_LOCAL; 12332654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_LOCAL; 12342654012fSReza Sabdar reply.error = NDMP_NO_ERR; 12352654012fSReza Sabdar break; 12362654012fSReza Sabdar case NDMP_ADDR_TCP: 12372654012fSReza Sabdar if (create_listen_socket_v3(session, &addr, &port) < 0) { 12382654012fSReza Sabdar reply.error = NDMP_IO_ERR; 12392654012fSReza Sabdar break; 12402654012fSReza Sabdar } 12412654012fSReza Sabdar reply.error = NDMP_NO_ERR; 12422654012fSReza Sabdar 12432654012fSReza Sabdar session->ns_mover.md_data_addr_v4.addr_type = NDMP_ADDR_TCP; 12442654012fSReza Sabdar session->ns_mover.md_data_addr_v4.tcp_len_v4 = 1; 12452654012fSReza Sabdar session->ns_mover.md_data_addr_v4.tcp_addr_v4 = 12462654012fSReza Sabdar ndmp_malloc(sizeof (ndmp_tcp_addr_v4)); 12472654012fSReza Sabdar 12482654012fSReza Sabdar session->ns_mover.md_data_addr_v4.tcp_ip_v4(0) = addr; 12492654012fSReza Sabdar session->ns_mover.md_data_addr_v4.tcp_port_v4(0) = ntohs(port); 12502654012fSReza Sabdar 12512654012fSReza Sabdar ndmp_copy_addr_v4(&reply.connect_addr, 12522654012fSReza Sabdar &session->ns_mover.md_data_addr_v4); 12532654012fSReza Sabdar 12542654012fSReza Sabdar /* For compatibility with V3 */ 12552654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 12562654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_ip_v3 = addr; 12572654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(port); 12582654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "listen_socket: %d", 12592654012fSReza Sabdar session->ns_mover.md_listen_sock); 12602654012fSReza Sabdar break; 12612654012fSReza Sabdar default: 12622654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 12632654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type: %d", 12642654012fSReza Sabdar request->addr_type); 12652654012fSReza Sabdar } 12662654012fSReza Sabdar 12672654012fSReza Sabdar if (reply.error == NDMP_NO_ERR) { 12682654012fSReza Sabdar session->ns_mover.md_mode = request->mode; 12692654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 12702654012fSReza Sabdar } 12712654012fSReza Sabdar 12722654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 12732654012fSReza Sabdar "error sending ndmp_mover_listen reply"); 12742654012fSReza Sabdar free(reply.connect_addr.tcp_addr_v4); 12752654012fSReza Sabdar } 12762654012fSReza Sabdar 12772654012fSReza Sabdar /* 12782654012fSReza Sabdar * ndmpd_mover_connect_v4 12792654012fSReza Sabdar * Request handler. Connects the mover to either a local 12802654012fSReza Sabdar * or remote data server. 12812654012fSReza Sabdar * 12822654012fSReza Sabdar * Parameters: 12832654012fSReza Sabdar * connection (input) - connection handle. 12842654012fSReza Sabdar * body (input) - request message body. 12852654012fSReza Sabdar * 12862654012fSReza Sabdar * Returns: 12872654012fSReza Sabdar * void 12882654012fSReza Sabdar */ 12892654012fSReza Sabdar void 12902654012fSReza Sabdar ndmpd_mover_connect_v4(ndmp_connection_t *connection, void *body) 12912654012fSReza Sabdar { 12922654012fSReza Sabdar ndmp_mover_connect_request_v4 *request; 12932654012fSReza Sabdar ndmp_mover_connect_reply_v4 reply; 12942654012fSReza Sabdar ndmpd_session_t *session = ndmp_get_client_data(connection); 12952654012fSReza Sabdar 12962654012fSReza Sabdar request = (ndmp_mover_connect_request_v4 *)body; 12972654012fSReza Sabdar (void) memset((void*)&reply, 0, sizeof (reply)); 12982654012fSReza Sabdar 12992654012fSReza Sabdar if (request->mode != NDMP_MOVER_MODE_READ && 13002654012fSReza Sabdar request->mode != NDMP_MOVER_MODE_WRITE) { 13012654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 13022654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 13032654012fSReza Sabdar } else if (!ndmp_valid_v3addr_type(request->addr.addr_type)) { 13042654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 13052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 13062654012fSReza Sabdar request->addr.addr_type); 13072654012fSReza Sabdar } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 13082654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 13092654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid state %d: mover is not idle", 13102654012fSReza Sabdar session->ns_mover.md_state); 13112654012fSReza Sabdar } else if (session->ns_tape.td_fd == -1) { 13122654012fSReza Sabdar reply.error = NDMP_DEV_NOT_OPEN_ERR; 13132654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No tape device open"); 13142654012fSReza Sabdar } else if (request->mode == NDMP_MOVER_MODE_READ && 13152654012fSReza Sabdar session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 13162654012fSReza Sabdar reply.error = NDMP_PERMISSION_ERR; 13172654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Write protected device."); 13182654012fSReza Sabdar } else if (session->ns_mover.md_record_size == 0) { 13192654012fSReza Sabdar reply.error = NDMP_PRECONDITION_ERR; 13202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 13212654012fSReza Sabdar } else 13222654012fSReza Sabdar reply.error = NDMP_NO_ERR; 13232654012fSReza Sabdar 13242654012fSReza Sabdar if (reply.error != NDMP_NO_ERR) { 13252654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 13262654012fSReza Sabdar "sending ndmp_mover_connect reply"); 13272654012fSReza Sabdar return; 13282654012fSReza Sabdar } 13292654012fSReza Sabdar 13302654012fSReza Sabdar switch (request->addr.addr_type) { 13312654012fSReza Sabdar case NDMP_ADDR_LOCAL: 13322654012fSReza Sabdar /* 13332654012fSReza Sabdar * Verify that the data server is listening for a 13342654012fSReza Sabdar * local connection. 13352654012fSReza Sabdar */ 13362654012fSReza Sabdar if (session->ns_data.dd_state != NDMP_DATA_STATE_LISTEN || 13372654012fSReza Sabdar session->ns_data.dd_listen_sock != -1) { 13382654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13392654012fSReza Sabdar "Data server is not in local listen state"); 13402654012fSReza Sabdar reply.error = NDMP_ILLEGAL_STATE_ERR; 13412654012fSReza Sabdar } else 13422654012fSReza Sabdar session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED; 13432654012fSReza Sabdar break; 13442654012fSReza Sabdar 13452654012fSReza Sabdar case NDMP_ADDR_TCP: 134697f7c475SJan Kryl reply.error = mover_connect_sock(session, request->mode, 13472654012fSReza Sabdar request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0)); 13482654012fSReza Sabdar break; 13492654012fSReza Sabdar 13502654012fSReza Sabdar default: 13512654012fSReza Sabdar reply.error = NDMP_ILLEGAL_ARGS_ERR; 13522654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 13532654012fSReza Sabdar request->addr.addr_type); 13542654012fSReza Sabdar } 13552654012fSReza Sabdar 13562654012fSReza Sabdar if (reply.error == NDMP_NO_ERR) { 13572654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = 13582654012fSReza Sabdar request->addr.addr_type; 13592654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 13602654012fSReza Sabdar session->ns_mover.md_mode = request->mode; 13612654012fSReza Sabdar } 13622654012fSReza Sabdar 13632654012fSReza Sabdar ndmp_send_reply(connection, (void *) &reply, 13642654012fSReza Sabdar "sending ndmp_mover_connect reply"); 13652654012fSReza Sabdar } 13662654012fSReza Sabdar 13672654012fSReza Sabdar 13682654012fSReza Sabdar 13692654012fSReza Sabdar /* 13702654012fSReza Sabdar * ************************************************************************ 13712654012fSReza Sabdar * LOCALS 13722654012fSReza Sabdar * ************************************************************************ 13732654012fSReza Sabdar */ 13742654012fSReza Sabdar 13752654012fSReza Sabdar /* 13762654012fSReza Sabdar * ndmpd_local_write 13772654012fSReza Sabdar * 13782654012fSReza Sabdar * Writes data to the mover. 13792654012fSReza Sabdar * Buffers and write data to the tape device. 13802654012fSReza Sabdar * A full tape record is buffered before being written. 13812654012fSReza Sabdar * 13822654012fSReza Sabdar * Parameters: 13832654012fSReza Sabdar * session (input) - session pointer. 13842654012fSReza Sabdar * data (input) - data to be written. 13852654012fSReza Sabdar * length (input) - data length. 13862654012fSReza Sabdar * 13872654012fSReza Sabdar * Returns: 13882654012fSReza Sabdar * 0 - data successfully written. 13892654012fSReza Sabdar * -1 - error. 13902654012fSReza Sabdar */ 13912654012fSReza Sabdar int 13922654012fSReza Sabdar ndmpd_local_write(ndmpd_session_t *session, char *data, ulong_t length) 13932654012fSReza Sabdar { 13942654012fSReza Sabdar ulong_t count = 0; 13952654012fSReza Sabdar ssize_t n; 13962654012fSReza Sabdar ulong_t len; 13972654012fSReza Sabdar 13982654012fSReza Sabdar /* 13992654012fSReza Sabdar * A length of 0 indicates that any buffered data should be 14002654012fSReza Sabdar * flushed to tape. 14012654012fSReza Sabdar */ 14022654012fSReza Sabdar if (length == 0) { 14032654012fSReza Sabdar if (session->ns_mover.md_w_index == 0) 14042654012fSReza Sabdar return (0); 14052654012fSReza Sabdar 14062654012fSReza Sabdar (void) memset( 14072654012fSReza Sabdar &session->ns_mover.md_buf[session->ns_mover.md_w_index], 14082654012fSReza Sabdar 0, session->ns_mover.md_record_size - 14092654012fSReza Sabdar session->ns_mover.md_w_index); 14102654012fSReza Sabdar 14119ee94b97SJan Kryl n = mover_tape_write_v3(session, session->ns_mover.md_buf, 14122654012fSReza Sabdar session->ns_mover.md_record_size); 14132654012fSReza Sabdar if (n <= 0) { 14142654012fSReza Sabdar ndmpd_mover_error(session, 14152654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14162654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 14172654012fSReza Sabdar return (-1); 14182654012fSReza Sabdar } 14192654012fSReza Sabdar session->ns_mover.md_position += n; 14202654012fSReza Sabdar session->ns_mover.md_data_written += 14212654012fSReza Sabdar session->ns_mover.md_w_index; 14222654012fSReza Sabdar session->ns_mover.md_record_num++; 14232654012fSReza Sabdar session->ns_mover.md_w_index = 0; 14242654012fSReza Sabdar return (0); 14252654012fSReza Sabdar } 14262654012fSReza Sabdar /* Break the data into records. */ 14272654012fSReza Sabdar while (count < length) { 14282654012fSReza Sabdar /* 14292654012fSReza Sabdar * Determine if data needs to be buffered or 14302654012fSReza Sabdar * can be written directly from user supplied location. 14312654012fSReza Sabdar * We can fast path the write if there is no pending 14322654012fSReza Sabdar * buffered data and there is at least a full record's worth 14332654012fSReza Sabdar * of data to be written. 14342654012fSReza Sabdar */ 14352654012fSReza Sabdar if (session->ns_mover.md_w_index == 0 && 14362654012fSReza Sabdar length - count >= session->ns_mover.md_record_size) { 14379ee94b97SJan Kryl n = mover_tape_write_v3(session, &data[count], 14382654012fSReza Sabdar session->ns_mover.md_record_size); 14392654012fSReza Sabdar if (n <= 0) { 14402654012fSReza Sabdar ndmpd_mover_error(session, 14412654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14422654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 14432654012fSReza Sabdar return (-1); 14442654012fSReza Sabdar } 14452654012fSReza Sabdar session->ns_mover.md_position += n; 14462654012fSReza Sabdar session->ns_mover.md_data_written += n; 14472654012fSReza Sabdar session->ns_mover.md_record_num++; 14482654012fSReza Sabdar count += n; 14492654012fSReza Sabdar continue; 14502654012fSReza Sabdar } 14512654012fSReza Sabdar /* Buffer the data */ 14522654012fSReza Sabdar len = length - count; 14532654012fSReza Sabdar if (len > session->ns_mover.md_record_size - 14542654012fSReza Sabdar session->ns_mover.md_w_index) 14552654012fSReza Sabdar len = session->ns_mover.md_record_size - 14562654012fSReza Sabdar session->ns_mover.md_w_index; 14572654012fSReza Sabdar 14582654012fSReza Sabdar (void) memcpy( 14592654012fSReza Sabdar &session->ns_mover.md_buf[session->ns_mover.md_w_index], 14602654012fSReza Sabdar &data[count], len); 14612654012fSReza Sabdar session->ns_mover.md_w_index += len; 14622654012fSReza Sabdar count += len; 14632654012fSReza Sabdar 14642654012fSReza Sabdar /* Write the buffer if its full */ 14652654012fSReza Sabdar if (session->ns_mover.md_w_index == 14662654012fSReza Sabdar session->ns_mover.md_record_size) { 14679ee94b97SJan Kryl n = mover_tape_write_v3(session, 14689ee94b97SJan Kryl session->ns_mover.md_buf, 14692654012fSReza Sabdar session->ns_mover.md_record_size); 14709ee94b97SJan Kryl if (n <= 0) { 14712654012fSReza Sabdar ndmpd_mover_error(session, 14722654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14732654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 14742654012fSReza Sabdar return (-1); 14752654012fSReza Sabdar } 14762654012fSReza Sabdar session->ns_mover.md_position += n; 14772654012fSReza Sabdar session->ns_mover.md_data_written += n; 14782654012fSReza Sabdar session->ns_mover.md_record_num++; 14792654012fSReza Sabdar session->ns_mover.md_w_index = 0; 14802654012fSReza Sabdar } 14812654012fSReza Sabdar } 14822654012fSReza Sabdar 14832654012fSReza Sabdar return (0); 14842654012fSReza Sabdar } 14852654012fSReza Sabdar 14862654012fSReza Sabdar 14872654012fSReza Sabdar /* 14882654012fSReza Sabdar * ndmpd_remote_write 14892654012fSReza Sabdar * 14902654012fSReza Sabdar * Writes data to the remote mover. 14912654012fSReza Sabdar * 14922654012fSReza Sabdar * Parameters: 14932654012fSReza Sabdar * session (input) - session pointer. 14942654012fSReza Sabdar * data (input) - data to be written. 14952654012fSReza Sabdar * length (input) - data length. 14962654012fSReza Sabdar * 14972654012fSReza Sabdar * Returns: 14982654012fSReza Sabdar * 0 - data successfully written. 14992654012fSReza Sabdar * -1 - error. 15002654012fSReza Sabdar */ 15012654012fSReza Sabdar int 15022654012fSReza Sabdar ndmpd_remote_write(ndmpd_session_t *session, char *data, ulong_t length) 15032654012fSReza Sabdar { 15042654012fSReza Sabdar ssize_t n; 15052654012fSReza Sabdar ulong_t count = 0; 15062654012fSReza Sabdar 15072654012fSReza Sabdar while (count < length) { 15082654012fSReza Sabdar if (session->ns_eof == TRUE || 15092654012fSReza Sabdar session->ns_data.dd_abort == TRUE) 15102654012fSReza Sabdar return (-1); 15112654012fSReza Sabdar 15122654012fSReza Sabdar if ((n = write(session->ns_data.dd_sock, &data[count], 15132654012fSReza Sabdar length - count)) < 0) { 15142654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Socket write error: %m."); 15152654012fSReza Sabdar return (-1); 15162654012fSReza Sabdar } 15172654012fSReza Sabdar count += n; 15182654012fSReza Sabdar } 15192654012fSReza Sabdar 15202654012fSReza Sabdar return (0); 15212654012fSReza Sabdar } 15222654012fSReza Sabdar 15232654012fSReza Sabdar /* 15242654012fSReza Sabdar * ndmpd_local_read 15252654012fSReza Sabdar * 15262654012fSReza Sabdar * Reads data from the local tape device. 15272654012fSReza Sabdar * Full tape records are read and buffered. 15282654012fSReza Sabdar * 15292654012fSReza Sabdar * Parameters: 15302654012fSReza Sabdar * session (input) - session pointer. 15312654012fSReza Sabdar * data (input) - location to store data. 15322654012fSReza Sabdar * length (input) - data length. 15332654012fSReza Sabdar * 15342654012fSReza Sabdar * Returns: 15352654012fSReza Sabdar * 0 - data successfully read. 15362654012fSReza Sabdar * -1 - error. 15372654012fSReza Sabdar * 1 - session terminated or operation aborted. 15382654012fSReza Sabdar */ 15392654012fSReza Sabdar int 15402654012fSReza Sabdar ndmpd_local_read(ndmpd_session_t *session, char *data, ulong_t length) 15412654012fSReza Sabdar { 15422654012fSReza Sabdar ulong_t count = 0; 15432654012fSReza Sabdar ssize_t n; 15442654012fSReza Sabdar ulong_t len; 15452654012fSReza Sabdar ndmp_notify_mover_paused_request pause_request; 15462654012fSReza Sabdar 15472654012fSReza Sabdar /* 15482654012fSReza Sabdar * Automatically increase the seek window if necessary. 15492654012fSReza Sabdar * This is needed in the event the module attempts to read 15502654012fSReza Sabdar * past a seek window set via a prior call to ndmpd_seek() or 15512654012fSReza Sabdar * the module has not issued a seek. If no seek was issued then 15522654012fSReza Sabdar * pretend that a seek was issued to read the entire tape. 15532654012fSReza Sabdar */ 15542654012fSReza Sabdar if (length > session->ns_mover.md_bytes_left_to_read) { 15552654012fSReza Sabdar /* ndmpd_seek() never called? */ 15562654012fSReza Sabdar if (session->ns_data.dd_read_length == 0) { 15572654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = ~0LL; 15582654012fSReza Sabdar session->ns_data.dd_read_offset = 0LL; 15592654012fSReza Sabdar session->ns_data.dd_read_length = ~0LL; 15602654012fSReza Sabdar } else { 15612654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = length; 15622654012fSReza Sabdar session->ns_data.dd_read_offset = 15632654012fSReza Sabdar session->ns_mover.md_position; 15642654012fSReza Sabdar session->ns_data.dd_read_length = length; 15652654012fSReza Sabdar } 15662654012fSReza Sabdar } 15672654012fSReza Sabdar /* 15682654012fSReza Sabdar * Read as many records as necessary to satisfy the request. 15692654012fSReza Sabdar */ 15702654012fSReza Sabdar while (count < length) { 15712654012fSReza Sabdar /* 15722654012fSReza Sabdar * If the end of the mover window has been reached, 15732654012fSReza Sabdar * then notify the client that a new data window is needed. 15742654012fSReza Sabdar */ 15752654012fSReza Sabdar if (session->ns_mover.md_position >= 15762654012fSReza Sabdar session->ns_mover.md_window_offset + 15772654012fSReza Sabdar session->ns_mover.md_window_length) { 15782654012fSReza Sabdar 15792654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 15802654012fSReza Sabdar session->ns_mover.md_pause_reason = 15812654012fSReza Sabdar NDMP_MOVER_PAUSE_SEEK; 15822654012fSReza Sabdar pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 15832654012fSReza Sabdar pause_request.seek_position = 15842654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_position); 15852654012fSReza Sabdar 15862654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, 15872654012fSReza Sabdar NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 15882654012fSReza Sabdar (void *) &pause_request, 0) < 0) { 15892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 15902654012fSReza Sabdar "Sending notify_mover_paused request"); 15912654012fSReza Sabdar ndmpd_mover_error(session, 15922654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 15932654012fSReza Sabdar return (-1); 15942654012fSReza Sabdar } 15952654012fSReza Sabdar /* 15968c4f9701SJanice Chang * Wait until the state is changed by 15972654012fSReza Sabdar * an abort or continue request. 15982654012fSReza Sabdar */ 1599a23888a3SJan Kryl if (ndmp_wait_for_mover(session) != 0) 16002654012fSReza Sabdar return (1); 16012654012fSReza Sabdar } 16022654012fSReza Sabdar len = length - count; 16032654012fSReza Sabdar 16042654012fSReza Sabdar /* 16052654012fSReza Sabdar * Prevent reading past the end of the window. 16062654012fSReza Sabdar */ 16072654012fSReza Sabdar if (len > 16082654012fSReza Sabdar session->ns_mover.md_window_offset + 16092654012fSReza Sabdar session->ns_mover.md_window_length - 16102654012fSReza Sabdar session->ns_mover.md_position) 16112654012fSReza Sabdar len = session->ns_mover.md_window_offset + 16122654012fSReza Sabdar session->ns_mover.md_window_length - 16132654012fSReza Sabdar session->ns_mover.md_position; 16142654012fSReza Sabdar 16152654012fSReza Sabdar /* 16162654012fSReza Sabdar * Copy from the data buffer first. 16172654012fSReza Sabdar */ 16182654012fSReza Sabdar if (session->ns_mover.md_w_index - 16192654012fSReza Sabdar session->ns_mover.md_r_index != 0) { 16202654012fSReza Sabdar /* 16212654012fSReza Sabdar * Limit the copy to the amount of data in the buffer. 16222654012fSReza Sabdar */ 16232654012fSReza Sabdar if (len > session->ns_mover.md_w_index - 16242654012fSReza Sabdar session->ns_mover.md_r_index) 16252654012fSReza Sabdar len = session->ns_mover.md_w_index 16262654012fSReza Sabdar - session->ns_mover.md_r_index; 16272654012fSReza Sabdar 16282654012fSReza Sabdar (void) memcpy((void *) &data[count], 16292654012fSReza Sabdar &session->ns_mover.md_buf[session-> 16302654012fSReza Sabdar ns_mover.md_r_index], len); 16312654012fSReza Sabdar count += len; 16322654012fSReza Sabdar session->ns_mover.md_r_index += len; 16332654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= len; 16342654012fSReza Sabdar session->ns_mover.md_position += len; 16352654012fSReza Sabdar continue; 16362654012fSReza Sabdar } 16372654012fSReza Sabdar /* 16382654012fSReza Sabdar * Determine if data needs to be buffered or 16392654012fSReza Sabdar * can be read directly to user supplied location. 16402654012fSReza Sabdar * We can fast path the read if at least a full record 16412654012fSReza Sabdar * needs to be read and there is no seek pending. 16422654012fSReza Sabdar * This is done to eliminate a buffer copy. 16432654012fSReza Sabdar */ 16442654012fSReza Sabdar if (len >= session->ns_mover.md_record_size && 16452654012fSReza Sabdar session->ns_mover.md_position >= 16462654012fSReza Sabdar session->ns_mover.md_seek_position) { 16472654012fSReza Sabdar n = tape_read(session, &data[count]); 16482654012fSReza Sabdar if (n <= 0) { 16492654012fSReza Sabdar if (n == TAPE_NO_WRITER_ERR) 16502654012fSReza Sabdar return (1); 16512654012fSReza Sabdar 16522654012fSReza Sabdar ndmpd_mover_error(session, 16532654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 16542654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 16552654012fSReza Sabdar return (n == 0) ? (1) : (-1); 16562654012fSReza Sabdar } 16572654012fSReza Sabdar count += n; 16582654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= n; 16592654012fSReza Sabdar session->ns_mover.md_position += n; 16602654012fSReza Sabdar continue; 16612654012fSReza Sabdar } 16622654012fSReza Sabdar /* Read the next record into the buffer. */ 16632654012fSReza Sabdar n = tape_read(session, session->ns_mover.md_buf); 16642654012fSReza Sabdar if (n <= 0) { 16652654012fSReza Sabdar if (n == TAPE_NO_WRITER_ERR) 16662654012fSReza Sabdar return (1); 16672654012fSReza Sabdar 16682654012fSReza Sabdar ndmpd_mover_error(session, 16692654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 16702654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 16712654012fSReza Sabdar return (n == 0) ? (1) : (-1); 16722654012fSReza Sabdar } 16732654012fSReza Sabdar session->ns_mover.md_w_index = n; 16742654012fSReza Sabdar session->ns_mover.md_r_index = 0; 16752654012fSReza Sabdar 16762654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d", n); 16772654012fSReza Sabdar 16782654012fSReza Sabdar /* 16792654012fSReza Sabdar * Discard data if the current data stream position is 16802654012fSReza Sabdar * prior to the seek position. This is necessary if a seek 16812654012fSReza Sabdar * request set the seek pointer to a position that is not a 16822654012fSReza Sabdar * record boundary. The seek request handler can only position 16832654012fSReza Sabdar * to the start of a record. 16842654012fSReza Sabdar */ 16852654012fSReza Sabdar if (session->ns_mover.md_position < 16862654012fSReza Sabdar session->ns_mover.md_seek_position) { 16872654012fSReza Sabdar session->ns_mover.md_r_index = 16882654012fSReza Sabdar session->ns_mover.md_seek_position - 16892654012fSReza Sabdar session->ns_mover.md_position; 16902654012fSReza Sabdar session->ns_mover.md_position = 16912654012fSReza Sabdar session->ns_mover.md_seek_position; 16922654012fSReza Sabdar } 16932654012fSReza Sabdar } 16942654012fSReza Sabdar 16952654012fSReza Sabdar return (0); 16962654012fSReza Sabdar } 16972654012fSReza Sabdar 16982654012fSReza Sabdar 16992654012fSReza Sabdar /* 17002654012fSReza Sabdar * ndmpd_remote_read 17012654012fSReza Sabdar * 17022654012fSReza Sabdar * Reads data from the remote mover. 17032654012fSReza Sabdar * 17042654012fSReza Sabdar * Parameters: 17052654012fSReza Sabdar * session (input) - session pointer. 17062654012fSReza Sabdar * data (input) - data to be written. 17072654012fSReza Sabdar * length (input) - data length. 17082654012fSReza Sabdar * 17092654012fSReza Sabdar * Returns: 17102654012fSReza Sabdar * 0 - data successfully read. 17112654012fSReza Sabdar * -1 - error. 17122654012fSReza Sabdar * 1 - session terminated or operation aborted. 17132654012fSReza Sabdar */ 17142654012fSReza Sabdar int 17152654012fSReza Sabdar ndmpd_remote_read(ndmpd_session_t *session, char *data, ulong_t length) 17162654012fSReza Sabdar { 17172654012fSReza Sabdar ulong_t count = 0; 17182654012fSReza Sabdar ssize_t n; 17192654012fSReza Sabdar ulong_t len; 17202654012fSReza Sabdar ndmp_notify_data_read_request request; 17212654012fSReza Sabdar 17222654012fSReza Sabdar while (count < length) { 17232654012fSReza Sabdar len = length - count; 17242654012fSReza Sabdar 17252654012fSReza Sabdar /* 17262654012fSReza Sabdar * If the end of the seek window has been reached then 17272654012fSReza Sabdar * send an ndmp_read request to the client. 17282654012fSReza Sabdar * The NDMP client will then send a mover_data_read request to 17292654012fSReza Sabdar * the remote mover and the mover will send more data. 17302654012fSReza Sabdar * This condition can occur if the module attempts to read past 17312654012fSReza Sabdar * a seek window set via a prior call to ndmpd_seek() or 17322654012fSReza Sabdar * the module has not issued a seek. If no seek was issued then 17332654012fSReza Sabdar * pretend that a seek was issued to read the entire tape. 17342654012fSReza Sabdar */ 17352654012fSReza Sabdar if (session->ns_mover.md_bytes_left_to_read == 0) { 17362654012fSReza Sabdar /* ndmpd_seek() never called? */ 17372654012fSReza Sabdar if (session->ns_data.dd_read_length == 0) { 17382654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = ~0LL; 17392654012fSReza Sabdar session->ns_data.dd_read_offset = 0LL; 17402654012fSReza Sabdar session->ns_data.dd_read_length = ~0LL; 17412654012fSReza Sabdar } else { 17422654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = len; 17432654012fSReza Sabdar session->ns_data.dd_read_offset = 17442654012fSReza Sabdar session->ns_mover.md_position; 17452654012fSReza Sabdar session->ns_data.dd_read_length = len; 17462654012fSReza Sabdar } 17472654012fSReza Sabdar 17482654012fSReza Sabdar request.offset = 17492654012fSReza Sabdar long_long_to_quad(session->ns_data.dd_read_offset); 17502654012fSReza Sabdar request.length = 17512654012fSReza Sabdar long_long_to_quad(session->ns_data.dd_read_length); 17522654012fSReza Sabdar 17537bc22e45SReza Sabdar if (ndmp_send_request_lock(session->ns_connection, 17542654012fSReza Sabdar NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 17552654012fSReza Sabdar (void *) &request, 0) < 0) { 17562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 17572654012fSReza Sabdar "Sending notify_data_read request"); 17582654012fSReza Sabdar return (-1); 17592654012fSReza Sabdar } 17602654012fSReza Sabdar } 17612654012fSReza Sabdar if (session->ns_eof == TRUE || 17622654012fSReza Sabdar session->ns_data.dd_abort == TRUE) 17632654012fSReza Sabdar return (1); 17642654012fSReza Sabdar 17652654012fSReza Sabdar /* 17662654012fSReza Sabdar * If the module called ndmpd_seek() prior to reading all of the 17672654012fSReza Sabdar * data that the remote mover was requested to send, then the 17682654012fSReza Sabdar * excess data from the seek has to be discardd. 17692654012fSReza Sabdar */ 17702654012fSReza Sabdar if (session->ns_mover.md_discard_length != 0) { 17712654012fSReza Sabdar n = discard_data(session, 17722654012fSReza Sabdar (ulong_t)session->ns_mover.md_discard_length); 17732654012fSReza Sabdar if (n < 0) 17742654012fSReza Sabdar return (-1); 17752654012fSReza Sabdar session->ns_mover.md_discard_length -= n; 17762654012fSReza Sabdar continue; 17772654012fSReza Sabdar } 17782654012fSReza Sabdar /* 17792654012fSReza Sabdar * Don't attempt to read more data than the remote is sending. 17802654012fSReza Sabdar */ 17812654012fSReza Sabdar if (len > session->ns_mover.md_bytes_left_to_read) 17822654012fSReza Sabdar len = session->ns_mover.md_bytes_left_to_read; 17832654012fSReza Sabdar 17842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "len: %u", len); 17852654012fSReza Sabdar 17862654012fSReza Sabdar if ((n = read(session->ns_data.dd_sock, &data[count], 17872654012fSReza Sabdar len)) < 0) { 17882654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Socket read error: %m."); 17892654012fSReza Sabdar return (-1); 17902654012fSReza Sabdar } 17912654012fSReza Sabdar /* read returns 0 if the connection was closed */ 17922654012fSReza Sabdar if (n == 0) 17932654012fSReza Sabdar return (-1); 17942654012fSReza Sabdar 17952654012fSReza Sabdar count += n; 17962654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= n; 17972654012fSReza Sabdar session->ns_mover.md_position += n; 17982654012fSReza Sabdar } 17992654012fSReza Sabdar 18002654012fSReza Sabdar return (0); 18012654012fSReza Sabdar } 18022654012fSReza Sabdar 18032654012fSReza Sabdar /* *** ndmpd internal functions ***************************************** */ 18042654012fSReza Sabdar 18052654012fSReza Sabdar /* 18062654012fSReza Sabdar * ndmpd_mover_init 18072654012fSReza Sabdar * 18082654012fSReza Sabdar * Initialize mover specific session variables. 18092654012fSReza Sabdar * Don't initialize variables such as record_size that need to 18102654012fSReza Sabdar * persist across data operations. A client may open a connection and 18112654012fSReza Sabdar * do multiple backups after setting the record_size. 18122654012fSReza Sabdar * 18132654012fSReza Sabdar * Parameters: 18142654012fSReza Sabdar * session (input) - session pointer. 18152654012fSReza Sabdar * 18162654012fSReza Sabdar * Returns: 18172654012fSReza Sabdar * 0 - success. 18182654012fSReza Sabdar * -1 - error. 18192654012fSReza Sabdar */ 18202654012fSReza Sabdar int 18212654012fSReza Sabdar ndmpd_mover_init(ndmpd_session_t *session) 18222654012fSReza Sabdar { 18232654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_IDLE; 18242654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_NA; 18252654012fSReza Sabdar session->ns_mover.md_halt_reason = NDMP_MOVER_HALT_NA; 18262654012fSReza Sabdar session->ns_mover.md_data_written = 0LL; 18272654012fSReza Sabdar session->ns_mover.md_seek_position = 0LL; 18282654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = 0LL; 18292654012fSReza Sabdar session->ns_mover.md_window_offset = 0LL; 18302654012fSReza Sabdar session->ns_mover.md_window_length = MAX_WINDOW_SIZE; 18312654012fSReza Sabdar session->ns_mover.md_position = 0LL; 18322654012fSReza Sabdar session->ns_mover.md_discard_length = 0; 18332654012fSReza Sabdar session->ns_mover.md_record_num = 0; 18342654012fSReza Sabdar session->ns_mover.md_record_size = 0; 18352654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 18362654012fSReza Sabdar session->ns_mover.md_pre_cond = FALSE; 18372654012fSReza Sabdar session->ns_mover.md_sock = -1; 18382654012fSReza Sabdar session->ns_mover.md_r_index = 0; 18392654012fSReza Sabdar session->ns_mover.md_w_index = 0; 18402654012fSReza Sabdar session->ns_mover.md_buf = ndmp_malloc(MAX_RECORD_SIZE); 18412654012fSReza Sabdar if (!session->ns_mover.md_buf) 18422654012fSReza Sabdar return (-1); 18432654012fSReza Sabdar 18442654012fSReza Sabdar if (ndmp_get_version(session->ns_connection) == NDMPV3) { 18452654012fSReza Sabdar session->ns_mover.md_mode = NDMP_MOVER_MODE_READ; 18462654012fSReza Sabdar (void) memset(&session->ns_mover.md_data_addr, 0, 18472654012fSReza Sabdar sizeof (ndmp_addr_v3)); 18482654012fSReza Sabdar } 18492654012fSReza Sabdar return (0); 18502654012fSReza Sabdar } 18512654012fSReza Sabdar 18522654012fSReza Sabdar 18532654012fSReza Sabdar /* 18542654012fSReza Sabdar * ndmpd_mover_shut_down 18552654012fSReza Sabdar * 18562654012fSReza Sabdar * Shutdown the mover. It closes all the sockets. 18572654012fSReza Sabdar * 18582654012fSReza Sabdar * Parameters: 18592654012fSReza Sabdar * session (input) - session pointer. 18602654012fSReza Sabdar * 18612654012fSReza Sabdar * Returns: 18622654012fSReza Sabdar * void 18632654012fSReza Sabdar */ 18642654012fSReza Sabdar void 18652654012fSReza Sabdar ndmpd_mover_shut_down(ndmpd_session_t *session) 18662654012fSReza Sabdar { 1867a23888a3SJan Kryl ndmp_lbr_params_t *nlp; 1868a23888a3SJan Kryl 1869a23888a3SJan Kryl if ((nlp = ndmp_get_nlp(session)) == NULL) 1870a23888a3SJan Kryl return; 1871a23888a3SJan Kryl 1872a23888a3SJan Kryl (void) mutex_lock(&nlp->nlp_mtx); 18732654012fSReza Sabdar if (session->ns_mover.md_listen_sock != -1) { 18742654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "mover.listen_sock: %d", 18752654012fSReza Sabdar session->ns_mover.md_listen_sock); 18762654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, 18772654012fSReza Sabdar session->ns_mover.md_listen_sock); 18782654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 18792654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 18802654012fSReza Sabdar } 18812654012fSReza Sabdar if (session->ns_mover.md_sock != -1) { 18822654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "mover.sock: %d", 18832654012fSReza Sabdar session->ns_mover.md_sock); 18842654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, 18852654012fSReza Sabdar session->ns_mover.md_sock); 18862654012fSReza Sabdar (void) close(session->ns_mover.md_sock); 18872654012fSReza Sabdar session->ns_mover.md_sock = -1; 18882654012fSReza Sabdar } 1889a23888a3SJan Kryl (void) cond_broadcast(&nlp->nlp_cv); 1890a23888a3SJan Kryl (void) mutex_unlock(&nlp->nlp_mtx); 18912654012fSReza Sabdar } 18922654012fSReza Sabdar 18932654012fSReza Sabdar 18942654012fSReza Sabdar /* 18952654012fSReza Sabdar * ndmpd_mover_cleanup 18962654012fSReza Sabdar * 18972654012fSReza Sabdar * Parameters: 18982654012fSReza Sabdar * session (input) - session pointer. 18992654012fSReza Sabdar * 19002654012fSReza Sabdar * Returns: 19012654012fSReza Sabdar * void 19022654012fSReza Sabdar */ 19032654012fSReza Sabdar void 19042654012fSReza Sabdar ndmpd_mover_cleanup(ndmpd_session_t *session) 19052654012fSReza Sabdar { 19062654012fSReza Sabdar NDMP_FREE(session->ns_mover.md_buf); 19072654012fSReza Sabdar } 19082654012fSReza Sabdar 19092654012fSReza Sabdar 19102654012fSReza Sabdar /* 19112654012fSReza Sabdar * ndmpd_mover_connect 19122654012fSReza Sabdar * Create a connection to the specified mover. 19132654012fSReza Sabdar * 19142654012fSReza Sabdar * Parameters: 19152654012fSReza Sabdar * session (input) - session pointer 19162654012fSReza Sabdar * 19172654012fSReza Sabdar * Returns: 19182654012fSReza Sabdar * error code. 19192654012fSReza Sabdar */ 19202654012fSReza Sabdar ndmp_error 19212654012fSReza Sabdar ndmpd_mover_connect(ndmpd_session_t *session, ndmp_mover_mode mover_mode) 19222654012fSReza Sabdar { 19232654012fSReza Sabdar ndmp_mover_addr *mover = &session->ns_data.dd_mover; 19242654012fSReza Sabdar struct sockaddr_in sin; 19252654012fSReza Sabdar int sock = -1; 19262654012fSReza Sabdar 19272654012fSReza Sabdar if (mover->addr_type == NDMP_ADDR_TCP) { 19282654012fSReza Sabdar if (mover->ndmp_mover_addr_u.addr.ip_addr) { 19292654012fSReza Sabdar (void) memset((void *) &sin, 0, sizeof (sin)); 19302654012fSReza Sabdar sin.sin_family = AF_INET; 19312654012fSReza Sabdar sin.sin_addr.s_addr = 19322654012fSReza Sabdar htonl(mover->ndmp_mover_addr_u.addr.ip_addr); 19332654012fSReza Sabdar sin.sin_port = 19342654012fSReza Sabdar htons(mover->ndmp_mover_addr_u.addr.port); 19352654012fSReza Sabdar 19362654012fSReza Sabdar /* 19372654012fSReza Sabdar * If the address type is TCP but both the address and 19382654012fSReza Sabdar * the port number are zero, we have to use a different 19392654012fSReza Sabdar * socket than the mover socket. This can happen when 19402654012fSReza Sabdar * using NDMP disk to disk copy (AKA D2D copy). 19412654012fSReza Sabdar * The NDMPCopy client will send a zero address to 19422654012fSReza Sabdar * direct the server to use the mover socket as the 19432654012fSReza Sabdar * data socket to receive the recovery data. 19442654012fSReza Sabdar */ 19452654012fSReza Sabdar if (sin.sin_addr.s_addr == 0 && sin.sin_port == 0) { 19462654012fSReza Sabdar session->ns_data.dd_sock = 19472654012fSReza Sabdar session->ns_mover.md_sock; 19482654012fSReza Sabdar return (NDMP_NO_ERR); 19492654012fSReza Sabdar } 19502654012fSReza Sabdar 19512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "addr: %u port: %u", 19522654012fSReza Sabdar mover->ndmp_mover_addr_u.addr.ip_addr, 19532654012fSReza Sabdar (ulong_t)sin.sin_port); 19542654012fSReza Sabdar 19552654012fSReza Sabdar if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 19562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Socket error: %m"); 19572654012fSReza Sabdar return (NDMP_IO_ERR); 19582654012fSReza Sabdar } 19592654012fSReza Sabdar if (connect(sock, (struct sockaddr *)&sin, 19602654012fSReza Sabdar sizeof (sin)) < 0) { 19612654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Connect error: %m"); 19622654012fSReza Sabdar (void) close(sock); 19632654012fSReza Sabdar return (NDMP_IO_ERR); 19642654012fSReza Sabdar } 196597f7c475SJan Kryl set_socket_options(sock); 19662654012fSReza Sabdar } else { 19672654012fSReza Sabdar if ((session->ns_mover.md_state != 19682654012fSReza Sabdar NDMP_MOVER_STATE_ACTIVE) || 19692654012fSReza Sabdar (session->ns_mover.md_sock == -1)) { 19702654012fSReza Sabdar 19712654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 19722654012fSReza Sabdar "Not in active state mover" 19732654012fSReza Sabdar " state = %d or Invalid mover sock=%d", 19742654012fSReza Sabdar session->ns_mover.md_state, 19752654012fSReza Sabdar session->ns_mover.md_sock); 19762654012fSReza Sabdar return (NDMP_ILLEGAL_STATE_ERR); 19772654012fSReza Sabdar } 19782654012fSReza Sabdar 19792654012fSReza Sabdar sock = session->ns_mover.md_sock; 19802654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 19812654012fSReza Sabdar "session: 0x%x setting data sock fd: %d to be" 19822654012fSReza Sabdar " same as listen_sock", session, sock); 19832654012fSReza Sabdar } 19842654012fSReza Sabdar 19852654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sock fd: %d", sock); 19862654012fSReza Sabdar 19872654012fSReza Sabdar session->ns_data.dd_sock = sock; 19882654012fSReza Sabdar 19892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "data.mover_sock: %u", sock); 19902654012fSReza Sabdar 19912654012fSReza Sabdar return (NDMP_NO_ERR); 19922654012fSReza Sabdar } 19932654012fSReza Sabdar /* Local mover connection. */ 19942654012fSReza Sabdar 19952654012fSReza Sabdar if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN) { 19962654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Mover is not in listen state"); 19972654012fSReza Sabdar return (NDMP_ILLEGAL_STATE_ERR); 19982654012fSReza Sabdar } 19992654012fSReza Sabdar if (session->ns_tape.td_fd == -1) { 20002654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Tape device not open"); 20012654012fSReza Sabdar return (NDMP_DEV_NOT_OPEN_ERR); 20022654012fSReza Sabdar } 20032654012fSReza Sabdar if (mover_mode == NDMP_MOVER_MODE_READ && 20042654012fSReza Sabdar session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 20052654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Write protected device."); 20062654012fSReza Sabdar return (NDMP_WRITE_PROTECT_ERR); 20072654012fSReza Sabdar } 20082654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 20092654012fSReza Sabdar session->ns_mover.md_mode = mover_mode; 20102654012fSReza Sabdar 20112654012fSReza Sabdar return (NDMP_NO_ERR); 20122654012fSReza Sabdar } 20132654012fSReza Sabdar 20142654012fSReza Sabdar 20152654012fSReza Sabdar 20162654012fSReza Sabdar /* 20172654012fSReza Sabdar * ndmpd_mover_seek 20182654012fSReza Sabdar * 20192654012fSReza Sabdar * Seek to the requested data stream position. 20202654012fSReza Sabdar * If the requested offset is outside of the current window, 20212654012fSReza Sabdar * the mover is paused and a notify_mover_paused request is sent 20222654012fSReza Sabdar * notifying the client that a seek is required. 20232654012fSReza Sabdar * If the requested offest is within the window but not within the 20242654012fSReza Sabdar * current record, then the tape is positioned to the record containing 20252654012fSReza Sabdar * the requested offest. 20262654012fSReza Sabdar * The requested amount of data is then read from the tape device and 20272654012fSReza Sabdar * written to the data connection. 20282654012fSReza Sabdar * 20292654012fSReza Sabdar * Parameters: 20302654012fSReza Sabdar * session (input) - session pointer. 20312654012fSReza Sabdar * offset (input) - data stream position to seek to. 20322654012fSReza Sabdar * length (input) - amount of data that will be read. 20332654012fSReza Sabdar * 20342654012fSReza Sabdar * Returns: 20352654012fSReza Sabdar * 1 - seek pending completion by the NDMP client. 20362654012fSReza Sabdar * 0 - seek successfully completed. 20372654012fSReza Sabdar * -1 - error. 20382654012fSReza Sabdar */ 20392654012fSReza Sabdar int 20402654012fSReza Sabdar ndmpd_mover_seek(ndmpd_session_t *session, u_longlong_t offset, 20412654012fSReza Sabdar u_longlong_t length) 20422654012fSReza Sabdar { 20432654012fSReza Sabdar int ctlcmd; 20442654012fSReza Sabdar int ctlcnt; 20452654012fSReza Sabdar u_longlong_t tape_position; 20462654012fSReza Sabdar u_longlong_t buf_position; 20472654012fSReza Sabdar ndmp_notify_mover_paused_request pause_request; 20482654012fSReza Sabdar 20492654012fSReza Sabdar session->ns_mover.md_seek_position = offset; 20502654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = length; 20512654012fSReza Sabdar 20522654012fSReza Sabdar /* 20532654012fSReza Sabdar * If the requested position is outside of the window, 20542654012fSReza Sabdar * notify the client that a seek is required. 20552654012fSReza Sabdar */ 20562654012fSReza Sabdar if (session->ns_mover.md_seek_position < 20572654012fSReza Sabdar session->ns_mover.md_window_offset || 20582654012fSReza Sabdar session->ns_mover.md_seek_position >= 20592654012fSReza Sabdar session->ns_mover.md_window_offset + 20602654012fSReza Sabdar session->ns_mover.md_window_length) { 20612654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "MOVER_PAUSE_SEEK(%llu)", 20622654012fSReza Sabdar session->ns_mover.md_seek_position); 20632654012fSReza Sabdar 20642654012fSReza Sabdar session->ns_mover.md_w_index = 0; 20652654012fSReza Sabdar session->ns_mover.md_r_index = 0; 20662654012fSReza Sabdar 20672654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 20682654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 20692654012fSReza Sabdar pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 20702654012fSReza Sabdar pause_request.seek_position = long_long_to_quad(offset); 20712654012fSReza Sabdar 20722654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, 20732654012fSReza Sabdar NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 20742654012fSReza Sabdar (void *) &pause_request, 0) < 0) { 20752654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 20762654012fSReza Sabdar "Sending notify_mover_paused request"); 20772654012fSReza Sabdar return (-1); 20782654012fSReza Sabdar } 20792654012fSReza Sabdar return (1); 20802654012fSReza Sabdar } 20812654012fSReza Sabdar /* 20822654012fSReza Sabdar * Determine the data stream position of the first byte in the 20832654012fSReza Sabdar * data buffer. 20842654012fSReza Sabdar */ 20852654012fSReza Sabdar buf_position = session->ns_mover.md_position - 20862654012fSReza Sabdar (session->ns_mover.md_position % session->ns_mover.md_record_size); 20872654012fSReza Sabdar 20882654012fSReza Sabdar /* 20892654012fSReza Sabdar * Determine the data stream position of the next byte that 20902654012fSReza Sabdar * will be read from tape. 20912654012fSReza Sabdar */ 20922654012fSReza Sabdar tape_position = buf_position; 20932654012fSReza Sabdar if (session->ns_mover.md_w_index != 0) 20942654012fSReza Sabdar tape_position += session->ns_mover.md_record_size; 20952654012fSReza Sabdar 20962654012fSReza Sabdar /* 20972654012fSReza Sabdar * Check if requested position is for data that has been read and is 20982654012fSReza Sabdar * in the buffer. 20992654012fSReza Sabdar */ 21002654012fSReza Sabdar if (offset >= buf_position && offset < tape_position) { 21012654012fSReza Sabdar session->ns_mover.md_position = offset; 21022654012fSReza Sabdar session->ns_mover.md_r_index = session->ns_mover.md_position - 21032654012fSReza Sabdar buf_position; 21042654012fSReza Sabdar 21052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "pos %llu r_index %u", 21062654012fSReza Sabdar session->ns_mover.md_position, 21072654012fSReza Sabdar session->ns_mover.md_r_index); 21082654012fSReza Sabdar 21092654012fSReza Sabdar return (0); 21102654012fSReza Sabdar } 21112654012fSReza Sabdar 21122654012fSReza Sabdar ctlcmd = 0; 21132654012fSReza Sabdar if (tape_position > session->ns_mover.md_seek_position) { 21142654012fSReza Sabdar /* Need to seek backward. */ 21152654012fSReza Sabdar ctlcmd = MTBSR; 21162654012fSReza Sabdar ctlcnt = (int)((tape_position - offset - 1) 21172654012fSReza Sabdar / session->ns_mover.md_record_size) + 1; 21182654012fSReza Sabdar tape_position -= ((u_longlong_t)(((tape_position - offset - 1) / 21192654012fSReza Sabdar session->ns_mover.md_record_size) + 1) * 21202654012fSReza Sabdar (u_longlong_t)session->ns_mover.md_record_size); 21212654012fSReza Sabdar 21222654012fSReza Sabdar } else if (offset >= tape_position + session->ns_mover.md_record_size) { 21232654012fSReza Sabdar /* Need to seek forward. */ 21242654012fSReza Sabdar ctlcmd = MTFSR; 21252654012fSReza Sabdar ctlcnt = (int)((offset - tape_position) 21262654012fSReza Sabdar / session->ns_mover.md_record_size); 21272654012fSReza Sabdar tape_position += ((u_longlong_t)(((offset - tape_position) / 21282654012fSReza Sabdar session->ns_mover.md_record_size)) * 21292654012fSReza Sabdar (u_longlong_t)session->ns_mover.md_record_size); 21302654012fSReza Sabdar } 21312654012fSReza Sabdar /* Reposition the tape if necessary. */ 21322654012fSReza Sabdar if (ctlcmd) { 21332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cmd %d count %d", 21342654012fSReza Sabdar ctlcmd, ctlcnt); 21352654012fSReza Sabdar (void) ndmp_mtioctl(session->ns_tape.td_fd, ctlcmd, ctlcnt); 21362654012fSReza Sabdar } 21372654012fSReza Sabdar 21382654012fSReza Sabdar session->ns_mover.md_position = tape_position; 21392654012fSReza Sabdar session->ns_mover.md_r_index = 0; 21402654012fSReza Sabdar session->ns_mover.md_w_index = 0; 21412654012fSReza Sabdar 21422654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "pos %llu", session->ns_mover.md_position); 21432654012fSReza Sabdar 21442654012fSReza Sabdar return (0); 21452654012fSReza Sabdar } 21462654012fSReza Sabdar 21472654012fSReza Sabdar 21482654012fSReza Sabdar /* ** static functions ************************************************** */ 21492654012fSReza Sabdar 21502654012fSReza Sabdar /* 21512654012fSReza Sabdar * create_listen_socket_v2 21522654012fSReza Sabdar * 21532654012fSReza Sabdar * Creates a socket for listening for accepting data connections. 21542654012fSReza Sabdar * 21552654012fSReza Sabdar * Parameters: 21562654012fSReza Sabdar * session (input) - session pointer. 21572654012fSReza Sabdar * addr (output) - location to store address of socket. 21582654012fSReza Sabdar * port (output) - location to store port of socket. 21592654012fSReza Sabdar * 21602654012fSReza Sabdar * Returns: 21612654012fSReza Sabdar * 0 - success. 21622654012fSReza Sabdar * -1 - error. 21632654012fSReza Sabdar */ 21642654012fSReza Sabdar static int 21652654012fSReza Sabdar create_listen_socket_v2(ndmpd_session_t *session, ulong_t *addr, ushort_t *port) 21662654012fSReza Sabdar { 21672654012fSReza Sabdar session->ns_mover.md_listen_sock = ndmp_create_socket(addr, port); 21682654012fSReza Sabdar if (session->ns_mover.md_listen_sock < 0) 21692654012fSReza Sabdar return (-1); 21702654012fSReza Sabdar 21712654012fSReza Sabdar /* 21722654012fSReza Sabdar * Add a file handler for the listen socket. 21732654012fSReza Sabdar * ndmpd_select will call accept_connection when a 21742654012fSReza Sabdar * connection is ready to be accepted. 21752654012fSReza Sabdar */ 21762654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void *) session, 21772654012fSReza Sabdar session->ns_mover.md_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER, 21782654012fSReza Sabdar accept_connection) < 0) { 21792654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 21802654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 21812654012fSReza Sabdar return (-1); 21822654012fSReza Sabdar } 21832654012fSReza Sabdar 21842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "addr: 0x%x, port: %d", *addr, *port); 21852654012fSReza Sabdar return (0); 21862654012fSReza Sabdar } 21872654012fSReza Sabdar 21882654012fSReza Sabdar /* 21892654012fSReza Sabdar * accept_connection 21902654012fSReza Sabdar * 21912654012fSReza Sabdar * Accept a data connection from a data server. 21922654012fSReza Sabdar * Called by ndmpd_select when a connection is pending on 21932654012fSReza Sabdar * the mover listen socket. 21942654012fSReza Sabdar * 21952654012fSReza Sabdar * Parameters: 21962654012fSReza Sabdar * cookie (input) - session pointer. 21972654012fSReza Sabdar * fd (input) - file descriptor. 21982654012fSReza Sabdar * mode (input) - select mode. 21992654012fSReza Sabdar * 22002654012fSReza Sabdar * Returns: 22012654012fSReza Sabdar * void. 22022654012fSReza Sabdar */ 22032654012fSReza Sabdar /*ARGSUSED*/ 22042654012fSReza Sabdar static void 22052654012fSReza Sabdar accept_connection(void *cookie, int fd, ulong_t mode) 22062654012fSReza Sabdar { 22072654012fSReza Sabdar ndmpd_session_t *session = (ndmpd_session_t *)cookie; 22082654012fSReza Sabdar struct sockaddr_in from; 22092654012fSReza Sabdar int from_len; 22102654012fSReza Sabdar 22112654012fSReza Sabdar from_len = sizeof (from); 22122654012fSReza Sabdar session->ns_mover.md_sock = accept(fd, (struct sockaddr *)&from, 22132654012fSReza Sabdar &from_len); 22142654012fSReza Sabdar 22152654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, fd); 22162654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 22172654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 22182654012fSReza Sabdar 22192654012fSReza Sabdar if (session->ns_mover.md_sock < 0) { 22202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Accept error: %m"); 22212654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_ERROR); 22222654012fSReza Sabdar return; 22232654012fSReza Sabdar } 222497f7c475SJan Kryl set_socket_options(session->ns_mover.md_sock); 22252654012fSReza Sabdar 22262654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sock fd: %d", session->ns_mover.md_sock); 22272654012fSReza Sabdar 22282654012fSReza Sabdar if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) { 22292654012fSReza Sabdar if (start_mover_for_backup(session) < 0) { 22302654012fSReza Sabdar ndmpd_mover_error(session, 22312654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 22322654012fSReza Sabdar return; 22332654012fSReza Sabdar } 22342654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Backup connection established by %s:%d", 22352654012fSReza Sabdar inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 22362654012fSReza Sabdar ntohs(from.sin_port)); 22372654012fSReza Sabdar } else { 22382654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Restore connection established by %s:%d", 22392654012fSReza Sabdar inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 22402654012fSReza Sabdar ntohs(from.sin_port)); 22412654012fSReza Sabdar } 22422654012fSReza Sabdar 22432654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Received connection"); 22442654012fSReza Sabdar 22452654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 22462654012fSReza Sabdar } 22472654012fSReza Sabdar 22482654012fSReza Sabdar /* 22492654012fSReza Sabdar * tape_read 22502654012fSReza Sabdar * 22512654012fSReza Sabdar * Reads a data record from tape. Detects and handles EOT conditions. 22522654012fSReza Sabdar * 22532654012fSReza Sabdar * Parameters: 22542654012fSReza Sabdar * session (input) - session pointer. 22552654012fSReza Sabdar * data (input) - location to read data to. 22562654012fSReza Sabdar * 22572654012fSReza Sabdar * Returns: 22582654012fSReza Sabdar * 0 - operation aborted. 22592654012fSReza Sabdar * -1 - tape read error. 22602654012fSReza Sabdar * otherwise - number of bytes read. 22612654012fSReza Sabdar */ 22622654012fSReza Sabdar static int 22632654012fSReza Sabdar tape_read(ndmpd_session_t *session, char *data) 22642654012fSReza Sabdar { 22652654012fSReza Sabdar ssize_t n; 22662654012fSReza Sabdar int err; 22672654012fSReza Sabdar int count = session->ns_mover.md_record_size; 22682654012fSReza Sabdar 22692654012fSReza Sabdar for (; ; ) { 22702654012fSReza Sabdar n = read(session->ns_tape.td_fd, data, count); 22712654012fSReza Sabdar if (n < 0) { 22722654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Tape read error: %m."); 22732654012fSReza Sabdar return (TAPE_READ_ERR); 22742654012fSReza Sabdar } 22752654012fSReza Sabdar NS_ADD(rtape, n); 22762654012fSReza Sabdar 22772654012fSReza Sabdar if (n == 0) { 22782654012fSReza Sabdar if (!is_writer_running(session)) 22792654012fSReza Sabdar return (TAPE_NO_WRITER_ERR); 22802654012fSReza Sabdar 22812654012fSReza Sabdar /* 22822654012fSReza Sabdar * End of media reached. 22832654012fSReza Sabdar * Notify client and wait for the client to 22842654012fSReza Sabdar * either abort the data operation or continue the 22852654012fSReza Sabdar * operation after changing the tape. 22862654012fSReza Sabdar */ 22872654012fSReza Sabdar NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 22882654012fSReza Sabdar ++ndmp_log_msg_id, 22892654012fSReza Sabdar "End of tape reached. Load next tape"); 22902654012fSReza Sabdar 22912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 22922654012fSReza Sabdar "End of tape reached. Load next tape"); 22932654012fSReza Sabdar 22942654012fSReza Sabdar err = change_tape(session); 22952654012fSReza Sabdar 22962654012fSReza Sabdar /* Operation aborted or connection terminated? */ 22972654012fSReza Sabdar if (err < 0) { 22982654012fSReza Sabdar /* 22992654012fSReza Sabdar * K.L. Go back one record if it is read 23002654012fSReza Sabdar * but not used. 23012654012fSReza Sabdar */ 23022654012fSReza Sabdar 23032654012fSReza Sabdar if (count != session->ns_mover.md_record_size) { 23042654012fSReza Sabdar (void) ndmp_mtioctl( 23052654012fSReza Sabdar session->ns_tape.td_fd, MTBSR, 1); 23062654012fSReza Sabdar } 23072654012fSReza Sabdar return (0); 23082654012fSReza Sabdar } 23092654012fSReza Sabdar /* Retry the read from the new tape. */ 23102654012fSReza Sabdar continue; 23112654012fSReza Sabdar } 23122654012fSReza Sabdar 23132654012fSReza Sabdar /* Change to pass Veritas Netbackup prequal test. */ 23142654012fSReza Sabdar data += n; 23152654012fSReza Sabdar count -= n; 23162654012fSReza Sabdar if (count <= 0) { 23172654012fSReza Sabdar session->ns_mover.md_record_num++; 23182654012fSReza Sabdar session->ns_tape.td_record_count++; 23192654012fSReza Sabdar return (n); 23202654012fSReza Sabdar } 23212654012fSReza Sabdar } 23222654012fSReza Sabdar } 23232654012fSReza Sabdar 23242654012fSReza Sabdar /* 23252654012fSReza Sabdar * change_tape 23262654012fSReza Sabdar * 23272654012fSReza Sabdar * Send a notify_pause request (protocol version 1) or 23282654012fSReza Sabdar * notify_mover_pause request (protocol version 2) to the 23292654012fSReza Sabdar * NDMP client to inform 23302654012fSReza Sabdar * the client that a tape volume change is required. 23312654012fSReza Sabdar * Process messages until the data/mover operation is either aborted 23322654012fSReza Sabdar * or continued. 23332654012fSReza Sabdar * 23342654012fSReza Sabdar * Parameters: 23352654012fSReza Sabdar * client_data (input) - session pointer. 23362654012fSReza Sabdar * 23372654012fSReza Sabdar * Returns: 23382654012fSReza Sabdar * 0 - operation has been continued. 23392654012fSReza Sabdar * -1 - operation has been aborted. 23402654012fSReza Sabdar */ 23412654012fSReza Sabdar static int 23422654012fSReza Sabdar change_tape(ndmpd_session_t *session) 23432654012fSReza Sabdar { 23442654012fSReza Sabdar ndmp_notify_mover_paused_request request; 23452654012fSReza Sabdar 23462654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 23472654012fSReza Sabdar 23482654012fSReza Sabdar if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) 23492654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_EOM; 23502654012fSReza Sabdar else 23512654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_EOF; 23522654012fSReza Sabdar 23532654012fSReza Sabdar request.reason = session->ns_mover.md_pause_reason; 23542654012fSReza Sabdar request.seek_position = long_long_to_quad(0LL); 23552654012fSReza Sabdar 23562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "ndmp_send_request: MOVER_PAUSED, reason: %d", 23572654012fSReza Sabdar session->ns_mover.md_pause_reason); 23582654012fSReza Sabdar 23592654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, 23602654012fSReza Sabdar NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 23612654012fSReza Sabdar (void *) &request, 0) < 0) { 23622654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 23632654012fSReza Sabdar "Sending notify_mover_paused request"); 23642654012fSReza Sabdar return (-1); 23652654012fSReza Sabdar } 23662654012fSReza Sabdar /* 23672654012fSReza Sabdar * Wait for until the state is changed by 23682654012fSReza Sabdar * an abort or continue request. 23692654012fSReza Sabdar */ 2370a23888a3SJan Kryl return (ndmp_wait_for_mover(session)); 23712654012fSReza Sabdar } 23722654012fSReza Sabdar 23732654012fSReza Sabdar 23742654012fSReza Sabdar /* 23752654012fSReza Sabdar * discard_data 23762654012fSReza Sabdar * 23772654012fSReza Sabdar * Read and discard data from the data connection. 23782654012fSReza Sabdar * Called when a module has called ndmpd_seek() prior to 23792654012fSReza Sabdar * reading all of the data from the previous seek. 23802654012fSReza Sabdar * 23812654012fSReza Sabdar * Parameters: 23822654012fSReza Sabdar * session (input) - session pointer. 23832654012fSReza Sabdar * 23842654012fSReza Sabdar * Returns: 23852654012fSReza Sabdar * number of bytes read and discarded. 23862654012fSReza Sabdar * -1 - error. 23872654012fSReza Sabdar */ 23882654012fSReza Sabdar static int 23892654012fSReza Sabdar discard_data(ndmpd_session_t *session, ulong_t length) 23902654012fSReza Sabdar { 23912654012fSReza Sabdar int n; 23922654012fSReza Sabdar char *addr; 23932654012fSReza Sabdar 23942654012fSReza Sabdar if ((addr = ndmp_malloc(length)) == NULL) 23952654012fSReza Sabdar return (-1); 23962654012fSReza Sabdar 23972654012fSReza Sabdar /* Read and discard the data. */ 23982654012fSReza Sabdar n = read(session->ns_mover.md_sock, addr, length); 23992654012fSReza Sabdar if (n < 0) { 24002654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Socket read error: %m."); 24012654012fSReza Sabdar free(addr); 24022654012fSReza Sabdar return (-1); 24032654012fSReza Sabdar } 24042654012fSReza Sabdar 24052654012fSReza Sabdar free(addr); 24062654012fSReza Sabdar return (n); 24072654012fSReza Sabdar } 24082654012fSReza Sabdar 24092654012fSReza Sabdar 24102654012fSReza Sabdar /* 24112654012fSReza Sabdar * mover_tape_read_one_buf 24122654012fSReza Sabdar * 24132654012fSReza Sabdar * Read one buffer from the tape. This is used by mover_tape_reader 24142654012fSReza Sabdar * 24152654012fSReza Sabdar * Parameters: 24162654012fSReza Sabdar * session (input) - session pointer. 24172654012fSReza Sabdar * buf (input) - buffer read 24182654012fSReza Sabdar * 24192654012fSReza Sabdar * Returns: 24202654012fSReza Sabdar * 0: on success 24212654012fSReza Sabdar * -1: otherwise 24222654012fSReza Sabdar */ 24232654012fSReza Sabdar static int 24242654012fSReza Sabdar mover_tape_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 24252654012fSReza Sabdar { 24262654012fSReza Sabdar int n; 24272654012fSReza Sabdar 24282654012fSReza Sabdar tlm_buffer_mark_empty(buf); 24292654012fSReza Sabdar 24302654012fSReza Sabdar /* 24312654012fSReza Sabdar * If the end of the mover window has been reached, 24322654012fSReza Sabdar * then notify the client that a seek is needed. 24332654012fSReza Sabdar * Remove the file handler to prevent this function from 24342654012fSReza Sabdar * being called. The handler will be reinstalled in 24352654012fSReza Sabdar * ndmpd_mover_continue. 24362654012fSReza Sabdar */ 24372654012fSReza Sabdar 24382654012fSReza Sabdar if (session->ns_mover.md_position >= 24392654012fSReza Sabdar session->ns_mover.md_window_offset + 24402654012fSReza Sabdar session->ns_mover.md_window_length) { 24412654012fSReza Sabdar ndmp_notify_mover_paused_request pause_request; 24422654012fSReza Sabdar 24432654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "end of mover window"); 24442654012fSReza Sabdar 24452654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 24462654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 24472654012fSReza Sabdar pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 24482654012fSReza Sabdar pause_request.seek_position = 24492654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_position); 24502654012fSReza Sabdar 24512654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, 24522654012fSReza Sabdar NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 24532654012fSReza Sabdar (void *) &pause_request, 0) < 0) { 24542654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 24552654012fSReza Sabdar "Sending notify_mover_paused request"); 24562654012fSReza Sabdar ndmpd_mover_error(session, 24572654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 24582654012fSReza Sabdar } 24592654012fSReza Sabdar buf->tb_errno = EIO; 24602654012fSReza Sabdar return (TAPE_READ_ERR); 24612654012fSReza Sabdar } 24622654012fSReza Sabdar 24632654012fSReza Sabdar n = tape_read(session, buf->tb_buffer_data); 24642654012fSReza Sabdar 24652654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "read %d bytes from tape", n); 24662654012fSReza Sabdar 24672654012fSReza Sabdar if (n <= 0) { 24682654012fSReza Sabdar if (n < 0) 24692654012fSReza Sabdar ndmpd_mover_error(session, 24702654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 24712654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR)); 24722654012fSReza Sabdar return (TAPE_READ_ERR); 24732654012fSReza Sabdar } 24742654012fSReza Sabdar 24752654012fSReza Sabdar buf->tb_full = TRUE; 24762654012fSReza Sabdar buf->tb_buffer_size = session->ns_mover.md_record_size; 24772654012fSReza Sabdar 24782654012fSReza Sabdar /* 24792654012fSReza Sabdar * Discard data if the current data stream position is 24802654012fSReza Sabdar * prior to the seek position. This is necessary if a seek 24812654012fSReza Sabdar * request set the seek pointer to a position that is not a 24822654012fSReza Sabdar * record boundary. The seek request handler can only position 24832654012fSReza Sabdar * to the start of a record. 24842654012fSReza Sabdar */ 24852654012fSReza Sabdar if (session->ns_mover.md_position < session->ns_mover.md_seek_position) 24862654012fSReza Sabdar session->ns_mover.md_position = 24872654012fSReza Sabdar session->ns_mover.md_seek_position; 24882654012fSReza Sabdar 24892654012fSReza Sabdar return (0); 24902654012fSReza Sabdar } 24912654012fSReza Sabdar 24922654012fSReza Sabdar 24932654012fSReza Sabdar /* 24942654012fSReza Sabdar * mover_tape_reader 24952654012fSReza Sabdar * 24962654012fSReza Sabdar * Mover tape reader thread. It is launched when the mover is started 24972654012fSReza Sabdar * for restore. 24982654012fSReza Sabdar * 24992654012fSReza Sabdar * Parameters: 25002654012fSReza Sabdar * session (input) - session pointer. 25012654012fSReza Sabdar * 25022654012fSReza Sabdar * Returns: 25032654012fSReza Sabdar * 0: on success 25042654012fSReza Sabdar * -1: otherwise 25052654012fSReza Sabdar */ 25062654012fSReza Sabdar int 25072654012fSReza Sabdar mover_tape_reader(ndmpd_session_t *session) 25082654012fSReza Sabdar { 25092654012fSReza Sabdar int bidx; /* buffer index */ 25102654012fSReza Sabdar int rv; 25112654012fSReza Sabdar ndmp_lbr_params_t *nlp; 25122654012fSReza Sabdar tlm_buffer_t *buf; 25132654012fSReza Sabdar tlm_buffers_t *bufs; 25142654012fSReza Sabdar tlm_cmd_t *lcmd; /* Local command */ 25152654012fSReza Sabdar tlm_commands_t *cmds; /* Commands structure */ 25162654012fSReza Sabdar 25172654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 25182654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 25192654012fSReza Sabdar return (-1); 25202654012fSReza Sabdar } 25212654012fSReza Sabdar 25222654012fSReza Sabdar cmds = &nlp->nlp_cmds; 25232654012fSReza Sabdar lcmd = cmds->tcs_command; 25242654012fSReza Sabdar bufs = lcmd->tc_buffers; 25252654012fSReza Sabdar 25262654012fSReza Sabdar lcmd->tc_ref++; 25272654012fSReza Sabdar cmds->tcs_reader_count++; 25282654012fSReza Sabdar 25292654012fSReza Sabdar /* 25302654012fSReza Sabdar * Let our parent thread know that we are running. 25312654012fSReza Sabdar */ 25322654012fSReza Sabdar tlm_cmd_signal(cmds->tcs_command, TLM_TAPE_READER); 25332654012fSReza Sabdar 25342654012fSReza Sabdar buf = tlm_buffer_in_buf(bufs, &bidx); 25352654012fSReza Sabdar while (cmds->tcs_reader == TLM_RESTORE_RUN && 25362654012fSReza Sabdar lcmd->tc_reader == TLM_RESTORE_RUN) { 25372654012fSReza Sabdar buf = tlm_buffer_in_buf(bufs, NULL); 25382654012fSReza Sabdar 25392654012fSReza Sabdar if (buf->tb_full) { 25402654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "R%d", bidx); 25412654012fSReza Sabdar /* 25422654012fSReza Sabdar * The buffer is still full, wait for the consumer 25432654012fSReza Sabdar * thread to use it. 25442654012fSReza Sabdar */ 25452654012fSReza Sabdar tlm_buffer_out_buf_timed_wait(bufs, 100); 25462654012fSReza Sabdar 25472654012fSReza Sabdar } else { 25482654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "r%d", bidx); 25492654012fSReza Sabdar 25502654012fSReza Sabdar rv = mover_tape_read_one_buf(session, buf); 25512654012fSReza Sabdar /* 25522654012fSReza Sabdar * If there was an error while reading, such as 25532654012fSReza Sabdar * end of stream. 25542654012fSReza Sabdar */ 25552654012fSReza Sabdar if (rv < 0) { 25562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Exiting, rv: %d", rv); 25572654012fSReza Sabdar break; 25582654012fSReza Sabdar } 25592654012fSReza Sabdar 25602654012fSReza Sabdar /* 25612654012fSReza Sabdar * Can we do more buffering? 25622654012fSReza Sabdar */ 25632654012fSReza Sabdar if (is_buffer_erroneous(buf)) { 25642654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 25652654012fSReza Sabdar "Exiting, errno: %d, eot: %d, eof: %d", 25662654012fSReza Sabdar buf->tb_errno, buf->tb_eot, buf->tb_eof); 25672654012fSReza Sabdar break; 25682654012fSReza Sabdar } 25692654012fSReza Sabdar 25702654012fSReza Sabdar (void) tlm_buffer_advance_in_idx(bufs); 25712654012fSReza Sabdar tlm_buffer_release_in_buf(bufs); 25722654012fSReza Sabdar bidx = bufs->tbs_buffer_in; 25732654012fSReza Sabdar } 25742654012fSReza Sabdar } 25752654012fSReza Sabdar 25762654012fSReza Sabdar /* If the consumer is waiting for us, wake it up. */ 25772654012fSReza Sabdar tlm_buffer_release_in_buf(bufs); 25782654012fSReza Sabdar 25792654012fSReza Sabdar /* 25802654012fSReza Sabdar * Clean up. 25812654012fSReza Sabdar */ 25822654012fSReza Sabdar cmds->tcs_reader_count--; 25832654012fSReza Sabdar lcmd->tc_ref--; 25842654012fSReza Sabdar lcmd->tc_writer = TLM_STOP; 25852654012fSReza Sabdar return (0); 25862654012fSReza Sabdar } 25872654012fSReza Sabdar 25882654012fSReza Sabdar 25892654012fSReza Sabdar /* 25902654012fSReza Sabdar * mover_socket_write_one_buf 25912654012fSReza Sabdar * 25922654012fSReza Sabdar * Write one buffer to the network socket. This is used by mover_socket_writer 25932654012fSReza Sabdar * 25942654012fSReza Sabdar * Parameters: 25952654012fSReza Sabdar * session (input) - session pointer. 25962654012fSReza Sabdar * buf (input) - buffer read 25972654012fSReza Sabdar * 25982654012fSReza Sabdar * Returns: 25992654012fSReza Sabdar * 0: on success 26002654012fSReza Sabdar * -1: otherwise 26012654012fSReza Sabdar */ 26022654012fSReza Sabdar static int 26032654012fSReza Sabdar mover_socket_write_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 26042654012fSReza Sabdar { 26052654012fSReza Sabdar int n; 26062654012fSReza Sabdar 26072654012fSReza Sabdar /* Write the data to the data connection. */ 26082654012fSReza Sabdar errno = 0; 26092654012fSReza Sabdar n = write(session->ns_mover.md_sock, buf->tb_buffer_data, 26102654012fSReza Sabdar buf->tb_buffer_size); 26112654012fSReza Sabdar 26122654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d, len: %d", n, buf->tb_buffer_size); 26132654012fSReza Sabdar 26142654012fSReza Sabdar if (n < 0) { 26152654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d, errno: %m", n); 26162654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 26172654012fSReza Sabdar return (-1); 26182654012fSReza Sabdar } 26192654012fSReza Sabdar 26202654012fSReza Sabdar session->ns_mover.md_position += n; 26212654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= n; 26222654012fSReza Sabdar tlm_buffer_mark_empty(buf); 26232654012fSReza Sabdar 26242654012fSReza Sabdar /* 26252654012fSReza Sabdar * If the read limit has been reached, 26262654012fSReza Sabdar * then remove the file handler to prevent this 26272654012fSReza Sabdar * function from getting called. The next mover_read request 26282654012fSReza Sabdar * will reinstall the handler. 26292654012fSReza Sabdar */ 26302654012fSReza Sabdar if (session->ns_mover.md_bytes_left_to_read == 0) { 26312654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "bytes_left_to_read == 0"); 26322654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, 26332654012fSReza Sabdar session->ns_mover.md_sock); 26342654012fSReza Sabdar return (-1); 26352654012fSReza Sabdar } 26362654012fSReza Sabdar 26372654012fSReza Sabdar return (0); 26382654012fSReza Sabdar } 26392654012fSReza Sabdar 26402654012fSReza Sabdar 26412654012fSReza Sabdar 26422654012fSReza Sabdar /* 26432654012fSReza Sabdar * mover_socket_writer 26442654012fSReza Sabdar * 26452654012fSReza Sabdar * Mover's socket writer thread. This thread sends the read buffer 26462654012fSReza Sabdar * from the tape to the data server through the network socket. 26472654012fSReza Sabdar * 26482654012fSReza Sabdar * Parameters: 26492654012fSReza Sabdar * session (input) - session pointer. 26502654012fSReza Sabdar * 26512654012fSReza Sabdar * Returns: 26522654012fSReza Sabdar * 0: on success 26532654012fSReza Sabdar * -1: otherwise 26542654012fSReza Sabdar */ 26552654012fSReza Sabdar int 26562654012fSReza Sabdar mover_socket_writer(ndmpd_session_t *session) 26572654012fSReza Sabdar { 26582654012fSReza Sabdar int bidx; /* buffer index */ 26592654012fSReza Sabdar ndmp_lbr_params_t *nlp; 26602654012fSReza Sabdar tlm_buffer_t *buf; 26612654012fSReza Sabdar tlm_buffers_t *bufs; 26622654012fSReza Sabdar tlm_cmd_t *lcmd; /* Local command */ 26632654012fSReza Sabdar tlm_commands_t *cmds; /* Commands structure */ 26642654012fSReza Sabdar 26652654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 26662654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 26672654012fSReza Sabdar return (-1); 26682654012fSReza Sabdar } 26692654012fSReza Sabdar 26702654012fSReza Sabdar cmds = &nlp->nlp_cmds; 26712654012fSReza Sabdar lcmd = cmds->tcs_command; 26722654012fSReza Sabdar bufs = lcmd->tc_buffers; 26732654012fSReza Sabdar 26742654012fSReza Sabdar lcmd->tc_ref++; 26752654012fSReza Sabdar cmds->tcs_writer_count++; 26762654012fSReza Sabdar 26772654012fSReza Sabdar /* 26782654012fSReza Sabdar * Let our parent thread know that we are running. 26792654012fSReza Sabdar */ 26802654012fSReza Sabdar tlm_cmd_signal(cmds->tcs_command, TLM_SOCK_WRITER); 26812654012fSReza Sabdar 26822654012fSReza Sabdar bidx = bufs->tbs_buffer_out; 26832654012fSReza Sabdar while (cmds->tcs_writer != (int)TLM_ABORT && 26842654012fSReza Sabdar lcmd->tc_writer != (int)TLM_ABORT) { 26852654012fSReza Sabdar buf = &bufs->tbs_buffer[bidx]; 26862654012fSReza Sabdar 26872654012fSReza Sabdar if (buf->tb_full) { 26882654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "w%d", bidx); 26892654012fSReza Sabdar 26902654012fSReza Sabdar if (mover_socket_write_one_buf(session, buf) < 0) { 26912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 26922654012fSReza Sabdar "mover_socket_write_one_buf() < 0"); 26932654012fSReza Sabdar break; 26942654012fSReza Sabdar } 26952654012fSReza Sabdar 26962654012fSReza Sabdar (void) tlm_buffer_advance_out_idx(bufs); 26972654012fSReza Sabdar tlm_buffer_release_out_buf(bufs); 26982654012fSReza Sabdar bidx = bufs->tbs_buffer_out; 26992654012fSReza Sabdar } else { 27002654012fSReza Sabdar if (lcmd->tc_writer != TLM_RESTORE_RUN) { 27012654012fSReza Sabdar /* No more data is coming, time to exit */ 27022654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Time to exit"); 27032654012fSReza Sabdar break; 27042654012fSReza Sabdar } 27052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "W%d", bidx); 27062654012fSReza Sabdar /* 27072654012fSReza Sabdar * The buffer is not full, wait for the producer 27082654012fSReza Sabdar * thread to fill it. 27092654012fSReza Sabdar */ 271086c48bbfSReza Sabdar tlm_buffer_in_buf_timed_wait(bufs, 100); 27112654012fSReza Sabdar } 27122654012fSReza Sabdar } 27132654012fSReza Sabdar 27142654012fSReza Sabdar if (cmds->tcs_writer == (int)TLM_ABORT) 27152654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cmds->tcs_writer == (int)TLM_ABORT"); 27162654012fSReza Sabdar if (lcmd->tc_writer == (int)TLM_ABORT) 27172654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "lcmd->tc_writer == TLM_ABORT"); 27182654012fSReza Sabdar 27192654012fSReza Sabdar /* If the producer is waiting for us, wake it up. */ 27202654012fSReza Sabdar tlm_buffer_release_out_buf(bufs); 27212654012fSReza Sabdar 27222654012fSReza Sabdar /* 27232654012fSReza Sabdar * Clean up. 27242654012fSReza Sabdar */ 27252654012fSReza Sabdar cmds->tcs_writer_count--; 27262654012fSReza Sabdar lcmd->tc_ref--; 27272654012fSReza Sabdar lcmd->tc_reader = TLM_STOP; 27282654012fSReza Sabdar return (0); 27292654012fSReza Sabdar } 27302654012fSReza Sabdar 27312654012fSReza Sabdar 27322654012fSReza Sabdar /* 27332654012fSReza Sabdar * start_mover_for_restore 27342654012fSReza Sabdar * 27352654012fSReza Sabdar * Creates the mover tape reader and network writer threads for 27362654012fSReza Sabdar * the mover to perform the 3-way restore. 27372654012fSReza Sabdar * 27382654012fSReza Sabdar * Parameters: 27392654012fSReza Sabdar * session (input) - session pointer. 27402654012fSReza Sabdar * 27412654012fSReza Sabdar * Returns: 27422654012fSReza Sabdar * 0: on success 27432654012fSReza Sabdar * -1: otherwise 27442654012fSReza Sabdar */ 27452654012fSReza Sabdar static int 27462654012fSReza Sabdar start_mover_for_restore(ndmpd_session_t *session) 27472654012fSReza Sabdar { 27482654012fSReza Sabdar ndmp_lbr_params_t *nlp; 27492654012fSReza Sabdar tlm_commands_t *cmds; 27502654012fSReza Sabdar long xfer_size; 27512654012fSReza Sabdar int rc; 27522654012fSReza Sabdar 27532654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 27542654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 27552654012fSReza Sabdar return (-1); 27562654012fSReza Sabdar } 27572654012fSReza Sabdar 27582654012fSReza Sabdar cmds = &nlp->nlp_cmds; 27592654012fSReza Sabdar (void) memset(cmds, 0, sizeof (*cmds)); 27602654012fSReza Sabdar cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN; 27612654012fSReza Sabdar xfer_size = ndmp_buffer_get_size(session); 27622654012fSReza Sabdar cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size); 27632654012fSReza Sabdar if (cmds->tcs_command == NULL) 27642654012fSReza Sabdar return (-1); 27652654012fSReza Sabdar 27662654012fSReza Sabdar cmds->tcs_command->tc_reader = TLM_RESTORE_RUN; 27672654012fSReza Sabdar cmds->tcs_command->tc_writer = TLM_RESTORE_RUN; 27682654012fSReza Sabdar 27692654012fSReza Sabdar /* 27702654012fSReza Sabdar * We intentionnally don't wait for the threads to start since the 27712654012fSReza Sabdar * reply of the request (which resulted in calling this function) 27722654012fSReza Sabdar * must be sent to the client before probable errors are sent 27732654012fSReza Sabdar * to the client. 27742654012fSReza Sabdar */ 27752654012fSReza Sabdar rc = pthread_create(NULL, NULL, (funct_t)mover_tape_reader, session); 27762654012fSReza Sabdar if (rc == 0) { 27772654012fSReza Sabdar tlm_cmd_wait(cmds->tcs_command, TLM_TAPE_READER); 27782654012fSReza Sabdar } else { 27792654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Launch mover_tape_reader: %s", 27802654012fSReza Sabdar strerror(rc)); 27812654012fSReza Sabdar return (-1); 27822654012fSReza Sabdar } 27832654012fSReza Sabdar 27842654012fSReza Sabdar rc = pthread_create(NULL, NULL, (funct_t)mover_socket_writer, session); 27852654012fSReza Sabdar if (rc == 0) { 27862654012fSReza Sabdar tlm_cmd_wait(cmds->tcs_command, TLM_SOCK_WRITER); 27872654012fSReza Sabdar } else { 27882654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Launch mover_socket_writer: %s", 27892654012fSReza Sabdar strerror(rc)); 27902654012fSReza Sabdar return (-1); 27912654012fSReza Sabdar } 27922654012fSReza Sabdar 27932654012fSReza Sabdar tlm_release_reader_writer_ipc(cmds->tcs_command); 27942654012fSReza Sabdar return (0); 27952654012fSReza Sabdar } 27962654012fSReza Sabdar 27972654012fSReza Sabdar 27982654012fSReza Sabdar /* 27992654012fSReza Sabdar * mover_socket_read_one_buf 28002654012fSReza Sabdar * 28012654012fSReza Sabdar * Read one buffer from the network socket for the mover. This is used 28022654012fSReza Sabdar * by mover_socket_reader 28032654012fSReza Sabdar * 28042654012fSReza Sabdar * Parameters: 28052654012fSReza Sabdar * session (input) - session pointer. 28062654012fSReza Sabdar * buf (input) - buffer read 28072654012fSReza Sabdar * read_size (input) - size to be read 28082654012fSReza Sabdar * 28092654012fSReza Sabdar * Returns: 28102654012fSReza Sabdar * 0: on success 28112654012fSReza Sabdar * -1: otherwise 28122654012fSReza Sabdar */ 28132654012fSReza Sabdar static int 28142654012fSReza Sabdar mover_socket_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf, 28152654012fSReza Sabdar long read_size) 28162654012fSReza Sabdar { 28172654012fSReza Sabdar int n, index; 28182654012fSReza Sabdar long toread; 28192654012fSReza Sabdar 28202654012fSReza Sabdar tlm_buffer_mark_empty(buf); 28212654012fSReza Sabdar for (index = 0, toread = read_size; toread > 0; ) { 28222654012fSReza Sabdar errno = 0; 28232654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "index: %d, toread: %d", index, toread); 28242654012fSReza Sabdar 28252654012fSReza Sabdar n = read(session->ns_mover.md_sock, &buf->tb_buffer_data[index], 28262654012fSReza Sabdar toread); 28272654012fSReza Sabdar if (n == 0) { 28282654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d", n); 28292654012fSReza Sabdar break; 28302654012fSReza Sabdar } else if (n > 0) { 28312654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d", n); 28322654012fSReza Sabdar index += n; 28332654012fSReza Sabdar toread -= n; 28342654012fSReza Sabdar } else { 28352654012fSReza Sabdar buf->tb_eof = TRUE; 28362654012fSReza Sabdar buf->tb_errno = errno; 28372654012fSReza Sabdar buf->tb_buffer_size = 0; 28382654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d, errno: %m", n); 28392654012fSReza Sabdar return (-1); 28402654012fSReza Sabdar } 28412654012fSReza Sabdar } 28422654012fSReza Sabdar 28432654012fSReza Sabdar if (index > 0) { 28442654012fSReza Sabdar buf->tb_full = TRUE; 28452654012fSReza Sabdar buf->tb_buffer_size = read_size; 28462654012fSReza Sabdar if (read_size > 0) 28472654012fSReza Sabdar (void) memset(&buf->tb_buffer_data[index], 0, 28482654012fSReza Sabdar read_size - index); 28492654012fSReza Sabdar } else { 28502654012fSReza Sabdar buf->tb_eof = TRUE; 28512654012fSReza Sabdar buf->tb_buffer_size = 0; 28522654012fSReza Sabdar } 28532654012fSReza Sabdar 28542654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "full: %d, eot: %d, eof: %d," 28552654012fSReza Sabdar " errno: %d, size: %d, data: 0x%x", 28562654012fSReza Sabdar buf->tb_full, buf->tb_eot, buf->tb_eof, buf->tb_errno, 28572654012fSReza Sabdar buf->tb_buffer_size, buf->tb_buffer_data); 28582654012fSReza Sabdar 28592654012fSReza Sabdar return (0); 28602654012fSReza Sabdar } 28612654012fSReza Sabdar 28622654012fSReza Sabdar 28632654012fSReza Sabdar 28642654012fSReza Sabdar /* 28652654012fSReza Sabdar * mover_socket_reader 28662654012fSReza Sabdar * 28672654012fSReza Sabdar * Mover socket reader thread. This is used when reading data from the 28682654012fSReza Sabdar * network socket for performing remote backups. 28692654012fSReza Sabdar * 28702654012fSReza Sabdar * Parameters: 28712654012fSReza Sabdar * session (input) - session pointer. 28722654012fSReza Sabdar * 28732654012fSReza Sabdar * Returns: 28742654012fSReza Sabdar * 0: on success 28752654012fSReza Sabdar * -1: otherwise 28762654012fSReza Sabdar */ 28772654012fSReza Sabdar int 28782654012fSReza Sabdar mover_socket_reader(ndmpd_session_t *session) 28792654012fSReza Sabdar { 28802654012fSReza Sabdar int bidx; /* buffer index */ 28812654012fSReza Sabdar ndmp_lbr_params_t *nlp; 28822654012fSReza Sabdar tlm_buffer_t *buf; 28832654012fSReza Sabdar tlm_buffers_t *bufs; 28842654012fSReza Sabdar tlm_cmd_t *lcmd; /* Local command */ 28852654012fSReza Sabdar tlm_commands_t *cmds; /* Commands structure */ 28862654012fSReza Sabdar static int nr = 0; 28872654012fSReza Sabdar 28882654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 28892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 28902654012fSReza Sabdar return (-1); 28912654012fSReza Sabdar } 28922654012fSReza Sabdar 28932654012fSReza Sabdar cmds = &nlp->nlp_cmds; 28942654012fSReza Sabdar lcmd = cmds->tcs_command; 28952654012fSReza Sabdar bufs = lcmd->tc_buffers; 28962654012fSReza Sabdar 28972654012fSReza Sabdar lcmd->tc_ref++; 28982654012fSReza Sabdar cmds->tcs_reader_count++; 28992654012fSReza Sabdar 29002654012fSReza Sabdar /* 29012654012fSReza Sabdar * Let our parent thread know that we are running. 29022654012fSReza Sabdar */ 29032654012fSReza Sabdar tlm_cmd_signal(cmds->tcs_command, TLM_SOCK_READER); 29042654012fSReza Sabdar 29052654012fSReza Sabdar bidx = bufs->tbs_buffer_in; 29062654012fSReza Sabdar while (cmds->tcs_reader == TLM_BACKUP_RUN && 29072654012fSReza Sabdar lcmd->tc_reader == TLM_BACKUP_RUN) { 29082654012fSReza Sabdar buf = &bufs->tbs_buffer[bidx]; 29092654012fSReza Sabdar 29102654012fSReza Sabdar if (buf->tb_full) { 29112654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "R%d", bidx); 29122654012fSReza Sabdar /* 29132654012fSReza Sabdar * The buffer is still full, wait for the consumer 29142654012fSReza Sabdar * thread to use it. 29152654012fSReza Sabdar */ 29162654012fSReza Sabdar tlm_buffer_out_buf_timed_wait(bufs, 100); 29172654012fSReza Sabdar } else { 29182654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "r%d, nr: %d", bidx, ++nr); 29192654012fSReza Sabdar 29202654012fSReza Sabdar (void) mover_socket_read_one_buf(session, buf, 29212654012fSReza Sabdar bufs->tbs_data_transfer_size); 29222654012fSReza Sabdar 29232654012fSReza Sabdar /* 29242654012fSReza Sabdar * Can we do more buffering? 29252654012fSReza Sabdar */ 29262654012fSReza Sabdar if (is_buffer_erroneous(buf)) { 29272654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 29282654012fSReza Sabdar "Exiting, errno: %d, eot: %d, eof: %d", 29292654012fSReza Sabdar buf->tb_errno, buf->tb_eot, buf->tb_eof); 29302654012fSReza Sabdar break; 29312654012fSReza Sabdar } 29322654012fSReza Sabdar 29332654012fSReza Sabdar (void) tlm_buffer_advance_in_idx(bufs); 29342654012fSReza Sabdar tlm_buffer_release_in_buf(bufs); 29352654012fSReza Sabdar bidx = bufs->tbs_buffer_in; 29362654012fSReza Sabdar } 29372654012fSReza Sabdar } 29382654012fSReza Sabdar 29392654012fSReza Sabdar if (cmds->tcs_reader != TLM_BACKUP_RUN) 29402654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cmds->tcs_reader != TLM_BACKUP_RUN"); 29412654012fSReza Sabdar if (lcmd->tc_reader != TLM_BACKUP_RUN) 29422654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "lcmd->tc_reader != TLM_BACKUP_RUN"); 29432654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nr: %d", nr); 29442654012fSReza Sabdar 29452654012fSReza Sabdar /* If the consumer is waiting for us, wake it up. */ 29462654012fSReza Sabdar tlm_buffer_release_in_buf(bufs); 29472654012fSReza Sabdar 29482654012fSReza Sabdar /* 29492654012fSReza Sabdar * Clean up. 29502654012fSReza Sabdar */ 29512654012fSReza Sabdar cmds->tcs_reader_count--; 29522654012fSReza Sabdar lcmd->tc_ref--; 29532654012fSReza Sabdar lcmd->tc_writer = TLM_STOP; 29542654012fSReza Sabdar return (0); 29552654012fSReza Sabdar } 29562654012fSReza Sabdar 29572654012fSReza Sabdar 29582654012fSReza Sabdar /* 29592654012fSReza Sabdar * mover_tape_writer_one_buf 29602654012fSReza Sabdar * 29612654012fSReza Sabdar * Write one buffer for the mover to the local tape device. This is 29622654012fSReza Sabdar * used by mover_tape_writer thread. 29632654012fSReza Sabdar * 29642654012fSReza Sabdar * Parameters: 29652654012fSReza Sabdar * session (input) - session pointer. 29662654012fSReza Sabdar * buf (input) - buffer read 29672654012fSReza Sabdar * 29682654012fSReza Sabdar * Returns: 29692654012fSReza Sabdar * 0: on success 29702654012fSReza Sabdar * -1: otherwise 29712654012fSReza Sabdar */ 29722654012fSReza Sabdar static int 29732654012fSReza Sabdar mover_tape_write_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 29742654012fSReza Sabdar { 29752654012fSReza Sabdar int n; 29762654012fSReza Sabdar 29772654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "full: %d, eot: %d, eof: %d," 29782654012fSReza Sabdar " errno: %d, size: %d, data: 0x%x", 29792654012fSReza Sabdar buf->tb_full, buf->tb_eot, buf->tb_eof, buf->tb_errno, 29802654012fSReza Sabdar buf->tb_buffer_size, buf->tb_buffer_data); 29812654012fSReza Sabdar 29829ee94b97SJan Kryl n = mover_tape_write_v3(session, buf->tb_buffer_data, 29839ee94b97SJan Kryl buf->tb_buffer_size); 29842654012fSReza Sabdar 29852654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d", n); 29862654012fSReza Sabdar 29872654012fSReza Sabdar if (n <= 0) { 29882654012fSReza Sabdar ndmpd_mover_error(session, (n == 0 ? NDMP_MOVER_HALT_ABORTED 29892654012fSReza Sabdar : NDMP_MOVER_HALT_INTERNAL_ERROR)); 29902654012fSReza Sabdar return (-1); 29912654012fSReza Sabdar } 29922654012fSReza Sabdar session->ns_mover.md_position += n; 29932654012fSReza Sabdar session->ns_mover.md_data_written += n; 29942654012fSReza Sabdar session->ns_mover.md_record_num++; 29952654012fSReza Sabdar 29962654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Calling tlm_buffer_mark_empty(buf)"); 29972654012fSReza Sabdar tlm_buffer_mark_empty(buf); 29982654012fSReza Sabdar 29992654012fSReza Sabdar return (0); 30002654012fSReza Sabdar } 30012654012fSReza Sabdar 30022654012fSReza Sabdar 30032654012fSReza Sabdar /* 30042654012fSReza Sabdar * mover_tape_writer 30052654012fSReza Sabdar * 30062654012fSReza Sabdar * Mover tape writer thread. This is used for performing remote backups 30072654012fSReza Sabdar * in a 3-way configuration. It writes the data from network socket to 30082654012fSReza Sabdar * the locally attached tape device. 30092654012fSReza Sabdar * 30102654012fSReza Sabdar * Parameters: 30112654012fSReza Sabdar * session (input) - session pointer. 30122654012fSReza Sabdar * 30132654012fSReza Sabdar * Returns: 30142654012fSReza Sabdar * 0: on success 30152654012fSReza Sabdar * -1: otherwise 30162654012fSReza Sabdar */ 30172654012fSReza Sabdar int 30182654012fSReza Sabdar mover_tape_writer(ndmpd_session_t *session) 30192654012fSReza Sabdar { 30202654012fSReza Sabdar int bidx; 30212654012fSReza Sabdar ndmp_lbr_params_t *nlp; 30222654012fSReza Sabdar tlm_buffer_t *buf; 30232654012fSReza Sabdar tlm_buffers_t *bufs; 30242654012fSReza Sabdar tlm_cmd_t *lcmd; 30252654012fSReza Sabdar tlm_commands_t *cmds; 30262654012fSReza Sabdar static int nw = 0; 30272654012fSReza Sabdar 30282654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 30292654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 30302654012fSReza Sabdar return (-1); 30312654012fSReza Sabdar } 30322654012fSReza Sabdar 30332654012fSReza Sabdar cmds = &nlp->nlp_cmds; 30342654012fSReza Sabdar lcmd = cmds->tcs_command; 30352654012fSReza Sabdar bufs = lcmd->tc_buffers; 30362654012fSReza Sabdar 30372654012fSReza Sabdar lcmd->tc_ref++; 30382654012fSReza Sabdar cmds->tcs_writer_count++; 30392654012fSReza Sabdar 30402654012fSReza Sabdar /* 30412654012fSReza Sabdar * Let our parent thread know that we are running. 30422654012fSReza Sabdar */ 30432654012fSReza Sabdar tlm_cmd_signal(cmds->tcs_command, TLM_TAPE_WRITER); 30442654012fSReza Sabdar 30452654012fSReza Sabdar bidx = bufs->tbs_buffer_out; 30462654012fSReza Sabdar buf = &bufs->tbs_buffer[bidx]; 30472654012fSReza Sabdar while (cmds->tcs_writer != (int)TLM_ABORT && 30482654012fSReza Sabdar lcmd->tc_writer != (int)TLM_ABORT) { 30492654012fSReza Sabdar if (buf->tb_full) { 30502654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "w%d, nw: %d", bidx, ++nw); 30512654012fSReza Sabdar 30522654012fSReza Sabdar if (mover_tape_write_one_buf(session, buf) < 0) { 30532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 30542654012fSReza Sabdar "mover_tape_write_one_buf() failed"); 30552654012fSReza Sabdar break; 30562654012fSReza Sabdar } 30572654012fSReza Sabdar 30582654012fSReza Sabdar (void) tlm_buffer_advance_out_idx(bufs); 30592654012fSReza Sabdar tlm_buffer_release_out_buf(bufs); 30602654012fSReza Sabdar bidx = bufs->tbs_buffer_out; 30612654012fSReza Sabdar buf = &bufs->tbs_buffer[bidx]; 30622654012fSReza Sabdar } else { 30632654012fSReza Sabdar if (lcmd->tc_writer != TLM_BACKUP_RUN) { 30642654012fSReza Sabdar /* No more data is coming, time to exit */ 30652654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Time to exit"); 30662654012fSReza Sabdar break; 30672654012fSReza Sabdar } 30682654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "W%d", bidx); 30692654012fSReza Sabdar /* 30702654012fSReza Sabdar * The buffer is not full, wait for the producer 30712654012fSReza Sabdar * thread to fill it. 30722654012fSReza Sabdar */ 30732654012fSReza Sabdar tlm_buffer_in_buf_timed_wait(bufs, 100); 30742654012fSReza Sabdar } 30752654012fSReza Sabdar } 30762654012fSReza Sabdar 30772654012fSReza Sabdar if (cmds->tcs_writer == (int)TLM_ABORT) 30782654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cmds->tcs_writer == TLM_ABORT"); 30792654012fSReza Sabdar if (lcmd->tc_writer == (int)TLM_ABORT) 30802654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "lcmd->tc_writer == TLM_ABORT"); 30812654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nw: %d", nw); 30822654012fSReza Sabdar 30832654012fSReza Sabdar if (buf->tb_errno == 0) { 30842654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 30852654012fSReza Sabdar } else { 30862654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "buf->tb_errno: %d", buf->tb_errno); 30872654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 30882654012fSReza Sabdar } 30892654012fSReza Sabdar 30902654012fSReza Sabdar /* If the producer is waiting for us, wake it up. */ 30912654012fSReza Sabdar tlm_buffer_release_out_buf(bufs); 30922654012fSReza Sabdar 30932654012fSReza Sabdar /* 30942654012fSReza Sabdar * Clean up. 30952654012fSReza Sabdar */ 30962654012fSReza Sabdar cmds->tcs_writer_count--; 30972654012fSReza Sabdar lcmd->tc_ref--; 30982654012fSReza Sabdar lcmd->tc_reader = TLM_STOP; 30992654012fSReza Sabdar return (0); 31002654012fSReza Sabdar } 31012654012fSReza Sabdar 31022654012fSReza Sabdar 31032654012fSReza Sabdar /* 31042654012fSReza Sabdar * start_mover_for_backup 31052654012fSReza Sabdar * 31062654012fSReza Sabdar * Starts a remote backup by running socket reader and tape 31072654012fSReza Sabdar * writer threads. The mover runs a remote backup in a 3-way backup 31082654012fSReza Sabdar * configuration. 31092654012fSReza Sabdar * 31102654012fSReza Sabdar * Parameters: 31112654012fSReza Sabdar * session (input) - session pointer. 31122654012fSReza Sabdar * 31132654012fSReza Sabdar * Returns: 31142654012fSReza Sabdar * 0: on success 31152654012fSReza Sabdar * -1: otherwise 31162654012fSReza Sabdar */ 31172654012fSReza Sabdar static int 31182654012fSReza Sabdar start_mover_for_backup(ndmpd_session_t *session) 31192654012fSReza Sabdar { 31202654012fSReza Sabdar ndmp_lbr_params_t *nlp; 31212654012fSReza Sabdar tlm_commands_t *cmds; 31222654012fSReza Sabdar int rc; 31232654012fSReza Sabdar 31242654012fSReza Sabdar if ((nlp = ndmp_get_nlp(session)) == NULL) { 31252654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 31262654012fSReza Sabdar return (-1); 31272654012fSReza Sabdar } 31282654012fSReza Sabdar 31292654012fSReza Sabdar cmds = &nlp->nlp_cmds; 31302654012fSReza Sabdar (void) memset(cmds, 0, sizeof (*cmds)); 31312654012fSReza Sabdar cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN; 31322654012fSReza Sabdar cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, 31332654012fSReza Sabdar session->ns_mover.md_record_size); 31342654012fSReza Sabdar if (cmds->tcs_command == NULL) 31352654012fSReza Sabdar return (-1); 31362654012fSReza Sabdar 31372654012fSReza Sabdar cmds->tcs_command->tc_reader = TLM_BACKUP_RUN; 31382654012fSReza Sabdar cmds->tcs_command->tc_writer = TLM_BACKUP_RUN; 31392654012fSReza Sabdar 31402654012fSReza Sabdar /* 31412654012fSReza Sabdar * We intentionally don't wait for the threads to start since the 31422654012fSReza Sabdar * reply of the request (which resulted in calling this function) 31432654012fSReza Sabdar * must be sent to the client before probable errors are sent 31442654012fSReza Sabdar * to the client. 31452654012fSReza Sabdar */ 31462654012fSReza Sabdar rc = pthread_create(NULL, NULL, (funct_t)mover_socket_reader, session); 31472654012fSReza Sabdar if (rc == 0) { 31482654012fSReza Sabdar tlm_cmd_wait(cmds->tcs_command, TLM_SOCK_READER); 31492654012fSReza Sabdar } else { 31502654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Launch mover_socket_reader: %s", 31512654012fSReza Sabdar strerror(rc)); 31522654012fSReza Sabdar return (-1); 31532654012fSReza Sabdar } 31542654012fSReza Sabdar 31552654012fSReza Sabdar rc = pthread_create(NULL, NULL, (funct_t)mover_tape_writer, session); 31562654012fSReza Sabdar if (rc == 0) { 31572654012fSReza Sabdar tlm_cmd_wait(cmds->tcs_command, TLM_TAPE_WRITER); 31582654012fSReza Sabdar } else { 31592654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Launch mover_tape_writer: %s", 31602654012fSReza Sabdar strerror(rc)); 31612654012fSReza Sabdar return (-1); 31622654012fSReza Sabdar } 31632654012fSReza Sabdar 31642654012fSReza Sabdar tlm_release_reader_writer_ipc(cmds->tcs_command); 31652654012fSReza Sabdar return (0); 31662654012fSReza Sabdar } 31672654012fSReza Sabdar 31682654012fSReza Sabdar 31692654012fSReza Sabdar /* 31702654012fSReza Sabdar * is_writer_running 31712654012fSReza Sabdar * 31722654012fSReza Sabdar * Find out if the writer thread has started or not. 31732654012fSReza Sabdar * 31742654012fSReza Sabdar * Parameters: 31752654012fSReza Sabdar * session (input) - session pointer. 31762654012fSReza Sabdar * 31772654012fSReza Sabdar * Returns: 31782654012fSReza Sabdar * 0: not started 31792654012fSReza Sabdar * non-zero: started 31808c4f9701SJanice Chang * Note: non-zero is also returned if the backup type is 31818c4f9701SJanice Chang * neither TAR nor DUMP. I.e. the is_writer_running() 31828c4f9701SJanice Chang * check does not apply in this case and things should 31838c4f9701SJanice Chang * appear successful. 31842654012fSReza Sabdar */ 31852654012fSReza Sabdar static boolean_t 31862654012fSReza Sabdar is_writer_running(ndmpd_session_t *session) 31872654012fSReza Sabdar { 31882654012fSReza Sabdar boolean_t rv; 31892654012fSReza Sabdar ndmp_lbr_params_t *nlp; 31902654012fSReza Sabdar 31918c4f9701SJanice Chang if (session && (session->ns_butype > NDMP_BUTYPE_DUMP)) 31928c4f9701SJanice Chang return (1); 31938c4f9701SJanice Chang 31942654012fSReza Sabdar if (session == NULL) 31952654012fSReza Sabdar rv = 0; 31962654012fSReza Sabdar else if ((nlp = ndmp_get_nlp(session)) == NULL) 31972654012fSReza Sabdar rv = 0; 31982654012fSReza Sabdar else 31992654012fSReza Sabdar rv = (nlp->nlp_cmds.tcs_writer_count > 0); 32002654012fSReza Sabdar 32012654012fSReza Sabdar return (rv); 32022654012fSReza Sabdar } 32032654012fSReza Sabdar 32042654012fSReza Sabdar 32052654012fSReza Sabdar /* 32062654012fSReza Sabdar * is_writer_running_v3 32072654012fSReza Sabdar * 32082654012fSReza Sabdar * Find out if the writer thread has started or not. 32092654012fSReza Sabdar * 32102654012fSReza Sabdar * Parameters: 32112654012fSReza Sabdar * session (input) - session pointer. 32122654012fSReza Sabdar * 32132654012fSReza Sabdar * Returns: 32142654012fSReza Sabdar * 0: not started 32152654012fSReza Sabdar * non-zero: started 32168c4f9701SJanice Chang * Note: non-zero is also returned if the backup type is 32178c4f9701SJanice Chang * neither TAR nor DUMP. I.e. the is_writer_running() 32188c4f9701SJanice Chang * check does not apply in this case and things should 32198c4f9701SJanice Chang * appear successful. 32202654012fSReza Sabdar */ 32212654012fSReza Sabdar static boolean_t 32222654012fSReza Sabdar is_writer_running_v3(ndmpd_session_t *session) 32232654012fSReza Sabdar { 32242654012fSReza Sabdar boolean_t rv; 32252654012fSReza Sabdar ndmp_lbr_params_t *nlp; 32262654012fSReza Sabdar 32278c4f9701SJanice Chang if (session && (session->ns_butype > NDMP_BUTYPE_DUMP)) 32288c4f9701SJanice Chang return (1); 32298c4f9701SJanice Chang 32302654012fSReza Sabdar if (session == NULL) 32312654012fSReza Sabdar rv = 0; 32322654012fSReza Sabdar else if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_TCP) 32332654012fSReza Sabdar rv = 1; 32342654012fSReza Sabdar else if ((nlp = ndmp_get_nlp(session)) == NULL) 32352654012fSReza Sabdar rv = 0; 32362654012fSReza Sabdar else 32372654012fSReza Sabdar rv = (nlp->nlp_cmds.tcs_writer_count > 0); 32382654012fSReza Sabdar 32392654012fSReza Sabdar return (rv); 32402654012fSReza Sabdar } 32412654012fSReza Sabdar 32422654012fSReza Sabdar 32432654012fSReza Sabdar /* 32442654012fSReza Sabdar * ndmpd_mover_error_send 32452654012fSReza Sabdar * 32462654012fSReza Sabdar * This function sends the notify message to the client. 32472654012fSReza Sabdar * 32482654012fSReza Sabdar * Parameters: 32492654012fSReza Sabdar * session (input) - session pointer. 32502654012fSReza Sabdar * reason (input) - halt reason. 32512654012fSReza Sabdar * 32522654012fSReza Sabdar * Returns: 32532654012fSReza Sabdar * Error code 32542654012fSReza Sabdar */ 32552654012fSReza Sabdar int 32562654012fSReza Sabdar ndmpd_mover_error_send(ndmpd_session_t *session, ndmp_mover_halt_reason reason) 32572654012fSReza Sabdar { 32582654012fSReza Sabdar ndmp_notify_mover_halted_request req; 32592654012fSReza Sabdar 32602654012fSReza Sabdar req.reason = reason; 32612654012fSReza Sabdar req.text_reason = ""; 32622654012fSReza Sabdar 32632654012fSReza Sabdar return (ndmp_send_request(session->ns_connection, 32642654012fSReza Sabdar NDMP_NOTIFY_MOVER_HALTED, NDMP_NO_ERR, (void *)&req, 0)); 32652654012fSReza Sabdar } 32662654012fSReza Sabdar 32672654012fSReza Sabdar 32682654012fSReza Sabdar /* 32692654012fSReza Sabdar * ndmpd_mover_error_send_v4 32702654012fSReza Sabdar * 32712654012fSReza Sabdar * This function sends the notify message to the client. 32722654012fSReza Sabdar * 32732654012fSReza Sabdar * Parameters: 32742654012fSReza Sabdar * session (input) - session pointer. 32752654012fSReza Sabdar * reason (input) - halt reason. 32762654012fSReza Sabdar * 32772654012fSReza Sabdar * Returns: 32782654012fSReza Sabdar * Error code 32792654012fSReza Sabdar */ 32802654012fSReza Sabdar int 32812654012fSReza Sabdar ndmpd_mover_error_send_v4(ndmpd_session_t *session, 32822654012fSReza Sabdar ndmp_mover_halt_reason reason) 32832654012fSReza Sabdar { 32842654012fSReza Sabdar ndmp_notify_mover_halted_request_v4 req; 32852654012fSReza Sabdar 32862654012fSReza Sabdar req.reason = reason; 32872654012fSReza Sabdar 32882654012fSReza Sabdar return (ndmp_send_request(session->ns_connection, 32892654012fSReza Sabdar NDMP_NOTIFY_MOVER_HALTED, NDMP_NO_ERR, (void *)&req, 0)); 32902654012fSReza Sabdar } 32912654012fSReza Sabdar 32922654012fSReza Sabdar 32932654012fSReza Sabdar /* 32942654012fSReza Sabdar * ndmpd_mover_error 32952654012fSReza Sabdar * 32962654012fSReza Sabdar * This function is called when an unrecoverable mover error 32972654012fSReza Sabdar * has been detected. A notify message is sent to the client and the 32982654012fSReza Sabdar * mover is placed into the halted state. 32992654012fSReza Sabdar * 33002654012fSReza Sabdar * Parameters: 33012654012fSReza Sabdar * session (input) - session pointer. 33022654012fSReza Sabdar * reason (input) - halt reason. 33032654012fSReza Sabdar * 33042654012fSReza Sabdar * Returns: 33052654012fSReza Sabdar * void. 33062654012fSReza Sabdar */ 33072654012fSReza Sabdar void 33082654012fSReza Sabdar ndmpd_mover_error(ndmpd_session_t *session, ndmp_mover_halt_reason reason) 33092654012fSReza Sabdar { 3310a23888a3SJan Kryl ndmp_lbr_params_t *nlp = ndmp_get_nlp(session); 3311a23888a3SJan Kryl 33122654012fSReza Sabdar if (session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED || 33132654012fSReza Sabdar (session->ns_protocol_version > NDMPV2 && 33142654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE)) 33152654012fSReza Sabdar return; 33162654012fSReza Sabdar 33172654012fSReza Sabdar if (session->ns_protocol_version == NDMPV4) { 33182654012fSReza Sabdar if (ndmpd_mover_error_send_v4(session, reason) < 0) 33192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 33202654012fSReza Sabdar "Error sending notify_mover_halted request"); 33212654012fSReza Sabdar } else { 33222654012fSReza Sabdar /* No media error in V3 */ 33232654012fSReza Sabdar if (reason == NDMP_MOVER_HALT_MEDIA_ERROR) 33242654012fSReza Sabdar reason = NDMP_MOVER_HALT_INTERNAL_ERROR; 33252654012fSReza Sabdar if (ndmpd_mover_error_send(session, reason) < 0) 33262654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 33272654012fSReza Sabdar "Error sending notify_mover_halted request"); 33282654012fSReza Sabdar } 33292654012fSReza Sabdar 3330a23888a3SJan Kryl (void) mutex_lock(&nlp->nlp_mtx); 33312654012fSReza Sabdar if (session->ns_mover.md_listen_sock != -1) { 33322654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, 33332654012fSReza Sabdar session->ns_mover.md_listen_sock); 33342654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 33352654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 33362654012fSReza Sabdar } 33372654012fSReza Sabdar if (session->ns_mover.md_sock != -1) { 33382654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, 33392654012fSReza Sabdar session->ns_mover.md_sock); 33402654012fSReza Sabdar (void) close(session->ns_mover.md_sock); 33412654012fSReza Sabdar session->ns_mover.md_sock = -1; 33422654012fSReza Sabdar } 33432654012fSReza Sabdar 33442654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_HALTED; 33452654012fSReza Sabdar session->ns_mover.md_halt_reason = reason; 3346a23888a3SJan Kryl (void) cond_broadcast(&nlp->nlp_cv); 3347a23888a3SJan Kryl (void) mutex_unlock(&nlp->nlp_mtx); 33482654012fSReza Sabdar } 33492654012fSReza Sabdar 33502654012fSReza Sabdar 33512654012fSReza Sabdar /* 33522654012fSReza Sabdar * mover_pause_v3 33532654012fSReza Sabdar * 33542654012fSReza Sabdar * Send an ndmp_notify_mover_paused request to the 33552654012fSReza Sabdar * NDMP client to inform the client that its attention is required. 33562654012fSReza Sabdar * Process messages until the data/mover operation is either aborted 33572654012fSReza Sabdar * or continued. 33582654012fSReza Sabdar * 33592654012fSReza Sabdar * Parameters: 33602654012fSReza Sabdar * client_data (input) - session pointer. 33612654012fSReza Sabdar * reason (input) - pause reason. 33622654012fSReza Sabdar * 33632654012fSReza Sabdar * Returns: 33642654012fSReza Sabdar * 0 - operation has been continued. 33652654012fSReza Sabdar * -1 - operation has been aborted. 33662654012fSReza Sabdar */ 33672654012fSReza Sabdar static int 33682654012fSReza Sabdar mover_pause_v3(ndmpd_session_t *session, ndmp_mover_pause_reason reason) 33692654012fSReza Sabdar { 33702654012fSReza Sabdar int rv; 33712654012fSReza Sabdar ndmp_notify_mover_paused_request request; 33722654012fSReza Sabdar 33732654012fSReza Sabdar rv = 0; 33742654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 33752654012fSReza Sabdar session->ns_mover.md_pause_reason = reason; 33762654012fSReza Sabdar session->ns_mover.md_pre_cond = FALSE; 33772654012fSReza Sabdar 33782654012fSReza Sabdar request.reason = session->ns_mover.md_pause_reason; 33792654012fSReza Sabdar request.seek_position = 33802654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_position); 33812654012fSReza Sabdar 33822654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, NDMP_NOTIFY_MOVER_PAUSED, 33832654012fSReza Sabdar NDMP_NO_ERR, (void *)&request, 0) < 0) { 33842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 33852654012fSReza Sabdar "Error sending notify_mover_paused_request"); 33862654012fSReza Sabdar return (-1); 33872654012fSReza Sabdar } 33882654012fSReza Sabdar 33892654012fSReza Sabdar /* 33902654012fSReza Sabdar * 3-way operations are single-thread. The same thread 33912654012fSReza Sabdar * should process the messages. 33922654012fSReza Sabdar * 33932654012fSReza Sabdar * 2-way operations are multi-thread. The main thread 33942654012fSReza Sabdar * processes the messages. We just need to wait and 33952654012fSReza Sabdar * see if the mover state changes or the operation aborts. 33962654012fSReza Sabdar */ 33972654012fSReza Sabdar if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_TCP) { 33982654012fSReza Sabdar /* 33992654012fSReza Sabdar * Process messages until the state is changed by 34002654012fSReza Sabdar * an abort, continue, or close request . 34012654012fSReza Sabdar */ 34022654012fSReza Sabdar for (; ; ) { 34032654012fSReza Sabdar if (ndmpd_select(session, TRUE, HC_CLIENT) < 0) 34042654012fSReza Sabdar return (-1); 34052654012fSReza Sabdar 34062654012fSReza Sabdar if (session->ns_eof == TRUE) 34072654012fSReza Sabdar return (-1); 34082654012fSReza Sabdar 34092654012fSReza Sabdar switch (session->ns_mover.md_state) { 34102654012fSReza Sabdar case NDMP_MOVER_STATE_ACTIVE: 34112654012fSReza Sabdar session->ns_tape.td_record_count = 0; 34122654012fSReza Sabdar return (0); 34132654012fSReza Sabdar 34142654012fSReza Sabdar case NDMP_MOVER_STATE_PAUSED: 34152654012fSReza Sabdar continue; 34162654012fSReza Sabdar 34172654012fSReza Sabdar default: 34182654012fSReza Sabdar return (-1); 34192654012fSReza Sabdar } 34202654012fSReza Sabdar } 34212654012fSReza Sabdar 34222654012fSReza Sabdar } else { 34232654012fSReza Sabdar if (session->ns_mover.md_data_addr.addr_type == 34242654012fSReza Sabdar NDMP_ADDR_LOCAL) { 3425a23888a3SJan Kryl rv = ndmp_wait_for_mover(session); 34262654012fSReza Sabdar } else { 34272654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 34282654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type); 34292654012fSReza Sabdar rv = -1; 34302654012fSReza Sabdar } 34312654012fSReza Sabdar } 34322654012fSReza Sabdar 34332654012fSReza Sabdar return (rv); 34342654012fSReza Sabdar } 34352654012fSReza Sabdar 34362654012fSReza Sabdar 34372654012fSReza Sabdar /* 34382654012fSReza Sabdar * mover_tape_write_v3 34392654012fSReza Sabdar * 34402654012fSReza Sabdar * Writes a data record to tape. Detects and handles EOT conditions. 34412654012fSReza Sabdar * 34422654012fSReza Sabdar * Parameters: 34432654012fSReza Sabdar * session (input) - session pointer. 34442654012fSReza Sabdar * data (input) - data to be written. 34452654012fSReza Sabdar * length (input) - length of data to be written. 34462654012fSReza Sabdar * 34472654012fSReza Sabdar * Returns: 34482654012fSReza Sabdar * 0 - operation aborted by client. 34492654012fSReza Sabdar * -1 - error. 34502654012fSReza Sabdar * otherwise - number of bytes written. 34512654012fSReza Sabdar */ 34522654012fSReza Sabdar static int 34532654012fSReza Sabdar mover_tape_write_v3(ndmpd_session_t *session, char *data, ssize_t length) 34542654012fSReza Sabdar { 34552654012fSReza Sabdar ssize_t n; 34569ee94b97SJan Kryl ssize_t count = length; 34572654012fSReza Sabdar 34589ee94b97SJan Kryl while (count > 0) { 34592654012fSReza Sabdar /* 34602654012fSReza Sabdar * Enforce mover window on write. 34612654012fSReza Sabdar */ 34622654012fSReza Sabdar if (session->ns_mover.md_position >= 34632654012fSReza Sabdar session->ns_mover.md_window_offset + 34642654012fSReza Sabdar session->ns_mover.md_window_length) { 34652654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "MOVER_PAUSE_EOW"); 34662654012fSReza Sabdar 34679ee94b97SJan Kryl if (mover_pause_v3(session, NDMP_MOVER_PAUSE_EOW) < 0) 34689ee94b97SJan Kryl /* Operation aborted or connection terminated */ 34692654012fSReza Sabdar return (-1); 34702654012fSReza Sabdar 34712654012fSReza Sabdar } 34722654012fSReza Sabdar 34739ee94b97SJan Kryl n = write(session->ns_tape.td_fd, data, count); 34742654012fSReza Sabdar if (n < 0) { 34752654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Tape write error: %m."); 34762654012fSReza Sabdar return (-1); 34779ee94b97SJan Kryl } else if (n > 0) { 34782654012fSReza Sabdar NS_ADD(wtape, n); 34799ee94b97SJan Kryl count -= n; 34809ee94b97SJan Kryl data += n; 34819ee94b97SJan Kryl session->ns_tape.td_record_count++; 34822654012fSReza Sabdar } 34832654012fSReza Sabdar 34849ee94b97SJan Kryl /* EOM handling */ 34859ee94b97SJan Kryl if (count > 0) { 34869ee94b97SJan Kryl struct mtget mtstatus; 34879ee94b97SJan Kryl 34889ee94b97SJan Kryl (void) ioctl(session->ns_tape.td_fd, MTIOCGET, 34899ee94b97SJan Kryl &mtstatus); 34909ee94b97SJan Kryl NDMP_LOG(LOG_DEBUG, "EOM detected (%d written bytes, " 34919ee94b97SJan Kryl "mover record %d, file #%d, block #%d)", n, 34929ee94b97SJan Kryl session->ns_tape.td_record_count, 34939ee94b97SJan Kryl mtstatus.mt_fileno, mtstatus.mt_blkno); 34949ee94b97SJan Kryl 34952654012fSReza Sabdar /* 34969ee94b97SJan Kryl * Notify the client to either abort the operation 34979ee94b97SJan Kryl * or change the tape. 34982654012fSReza Sabdar */ 34992654012fSReza Sabdar NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 35002654012fSReza Sabdar ++ndmp_log_msg_id, 35012654012fSReza Sabdar "End of tape reached. Load next tape"); 35022654012fSReza Sabdar 35039ee94b97SJan Kryl if (mover_pause_v3(session, NDMP_MOVER_PAUSE_EOM) < 0) 35049ee94b97SJan Kryl /* Operation aborted or connection terminated */ 35052654012fSReza Sabdar return (-1); 35069ee94b97SJan Kryl } 35072654012fSReza Sabdar } 35082654012fSReza Sabdar 35099ee94b97SJan Kryl return (length); 35102654012fSReza Sabdar } 35112654012fSReza Sabdar 35122654012fSReza Sabdar 35132654012fSReza Sabdar /* 35142654012fSReza Sabdar * mover_tape_flush_v3 35152654012fSReza Sabdar * 35162654012fSReza Sabdar * Writes all remaining buffered data to tape. A partial record is 35172654012fSReza Sabdar * padded out to a full record with zeros. 35182654012fSReza Sabdar * 35192654012fSReza Sabdar * Parameters: 35202654012fSReza Sabdar * session (input) - session pointer. 35212654012fSReza Sabdar * data (input) - data to be written. 35222654012fSReza Sabdar * length (input) - length of data to be written. 35232654012fSReza Sabdar * 35242654012fSReza Sabdar * Returns: 35252654012fSReza Sabdar * -1 - error. 35262654012fSReza Sabdar * otherwise - number of bytes written. 35272654012fSReza Sabdar */ 35282654012fSReza Sabdar static int 35292654012fSReza Sabdar mover_tape_flush_v3(ndmpd_session_t *session) 35302654012fSReza Sabdar { 35312654012fSReza Sabdar int n; 35322654012fSReza Sabdar 35332654012fSReza Sabdar if (session->ns_mover.md_w_index == 0) 35342654012fSReza Sabdar return (0); 35352654012fSReza Sabdar 35362654012fSReza Sabdar (void) memset((void*)&session->ns_mover.md_buf[session-> 35372654012fSReza Sabdar ns_mover.md_w_index], 0, 35382654012fSReza Sabdar session->ns_mover.md_record_size - session->ns_mover.md_w_index); 35392654012fSReza Sabdar 35402654012fSReza Sabdar n = mover_tape_write_v3(session, session->ns_mover.md_buf, 35412654012fSReza Sabdar session->ns_mover.md_record_size); 35422654012fSReza Sabdar if (n < 0) { 35432654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Tape write error: %m."); 35442654012fSReza Sabdar return (-1); 35452654012fSReza Sabdar } 35462654012fSReza Sabdar 35472654012fSReza Sabdar session->ns_mover.md_w_index = 0; 35482654012fSReza Sabdar session->ns_mover.md_position += n; 35492654012fSReza Sabdar return (n); 35502654012fSReza Sabdar } 35512654012fSReza Sabdar 35522654012fSReza Sabdar 35532654012fSReza Sabdar /* 35542654012fSReza Sabdar * ndmpd_local_write_v3 35552654012fSReza Sabdar * 35562654012fSReza Sabdar * Buffers and writes data to the tape device. 35572654012fSReza Sabdar * A full tape record is buffered before being written. 35582654012fSReza Sabdar * 35592654012fSReza Sabdar * Parameters: 35602654012fSReza Sabdar * session (input) - session pointer. 35612654012fSReza Sabdar * data (input) - data to be written. 35622654012fSReza Sabdar * length (input) - data length. 35632654012fSReza Sabdar * 35642654012fSReza Sabdar * Returns: 35652654012fSReza Sabdar * 0 - data successfully written. 35662654012fSReza Sabdar * -1 - error. 35672654012fSReza Sabdar */ 35682654012fSReza Sabdar int 35692654012fSReza Sabdar ndmpd_local_write_v3(ndmpd_session_t *session, char *data, ulong_t length) 35702654012fSReza Sabdar { 35712654012fSReza Sabdar ulong_t count = 0; 35722654012fSReza Sabdar ssize_t n; 35732654012fSReza Sabdar ulong_t len; 35742654012fSReza Sabdar 35752654012fSReza Sabdar if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 35762654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 35772654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 35782654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mover state to write data"); 35792654012fSReza Sabdar return (-1); 35802654012fSReza Sabdar } 35812654012fSReza Sabdar 35822654012fSReza Sabdar /* 35832654012fSReza Sabdar * A length of 0 indicates that any buffered data should be 35842654012fSReza Sabdar * flushed to tape. 35852654012fSReza Sabdar */ 35862654012fSReza Sabdar if (length == 0) { 35872654012fSReza Sabdar if (session->ns_mover.md_w_index == 0) 35882654012fSReza Sabdar return (0); 35892654012fSReza Sabdar 35902654012fSReza Sabdar (void) memset((void*)&session->ns_mover.md_buf[session-> 35912654012fSReza Sabdar ns_mover.md_w_index], 0, session->ns_mover.md_record_size - 35922654012fSReza Sabdar session->ns_mover.md_w_index); 35932654012fSReza Sabdar 35942654012fSReza Sabdar n = mover_tape_write_v3(session, session->ns_mover.md_buf, 35952654012fSReza Sabdar session->ns_mover.md_record_size); 35962654012fSReza Sabdar if (n <= 0) { 35972654012fSReza Sabdar ndmpd_mover_error(session, 35982654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 35992654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 36002654012fSReza Sabdar return (-1); 36012654012fSReza Sabdar } 36022654012fSReza Sabdar 36032654012fSReza Sabdar session->ns_mover.md_position += n; 36048a5de3ffSReza Sabdar session->ns_mover.md_data_written += 36058a5de3ffSReza Sabdar session->ns_mover.md_w_index; 36062654012fSReza Sabdar session->ns_mover.md_record_num++; 36072654012fSReza Sabdar session->ns_mover.md_w_index = 0; 36082654012fSReza Sabdar return (0); 36092654012fSReza Sabdar } 36102654012fSReza Sabdar 36112654012fSReza Sabdar /* Break the data into records. */ 36122654012fSReza Sabdar while (count < length) { 36132654012fSReza Sabdar /* 36142654012fSReza Sabdar * Determine if data needs to be buffered or 36152654012fSReza Sabdar * can be written directly from user supplied location. 36162654012fSReza Sabdar * We can fast path the write if there is no pending 36172654012fSReza Sabdar * buffered data and there is at least a full records worth 36182654012fSReza Sabdar * of data to be written. 36192654012fSReza Sabdar */ 36202654012fSReza Sabdar if (session->ns_mover.md_w_index == 0 && 36212654012fSReza Sabdar length - count >= session->ns_mover.md_record_size) { 36222654012fSReza Sabdar n = mover_tape_write_v3(session, &data[count], 36232654012fSReza Sabdar session->ns_mover.md_record_size); 36242654012fSReza Sabdar if (n <= 0) { 36252654012fSReza Sabdar ndmpd_mover_error(session, 36262654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 36272654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 36282654012fSReza Sabdar return (-1); 36292654012fSReza Sabdar } 36302654012fSReza Sabdar 36312654012fSReza Sabdar session->ns_mover.md_position += n; 36322654012fSReza Sabdar session->ns_mover.md_data_written += n; 36332654012fSReza Sabdar session->ns_mover.md_record_num++; 36342654012fSReza Sabdar count += n; 36352654012fSReza Sabdar continue; 36362654012fSReza Sabdar } 36372654012fSReza Sabdar 36382654012fSReza Sabdar /* Buffer the data */ 36392654012fSReza Sabdar len = length - count; 36402654012fSReza Sabdar if (len > session->ns_mover.md_record_size - 36412654012fSReza Sabdar session->ns_mover.md_w_index) 36422654012fSReza Sabdar len = session->ns_mover.md_record_size - 36432654012fSReza Sabdar session->ns_mover.md_w_index; 36442654012fSReza Sabdar 36452654012fSReza Sabdar (void) memcpy(&session->ns_mover.md_buf[session-> 36462654012fSReza Sabdar ns_mover.md_w_index], &data[count], len); 36472654012fSReza Sabdar session->ns_mover.md_w_index += len; 36482654012fSReza Sabdar count += len; 36492654012fSReza Sabdar 36502654012fSReza Sabdar /* Write the buffer if its full */ 36512654012fSReza Sabdar if (session->ns_mover.md_w_index == 36522654012fSReza Sabdar session->ns_mover.md_record_size) { 36532654012fSReza Sabdar n = mover_tape_write_v3(session, 36542654012fSReza Sabdar session->ns_mover.md_buf, 36552654012fSReza Sabdar session->ns_mover.md_record_size); 36569ee94b97SJan Kryl if (n <= 0) { 36572654012fSReza Sabdar ndmpd_mover_error(session, 36582654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 36592654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 36602654012fSReza Sabdar return (-1); 36612654012fSReza Sabdar } 36622654012fSReza Sabdar 36632654012fSReza Sabdar session->ns_mover.md_position += n; 36642654012fSReza Sabdar session->ns_mover.md_data_written += n; 36652654012fSReza Sabdar session->ns_mover.md_record_num++; 36662654012fSReza Sabdar session->ns_mover.md_w_index = 0; 36672654012fSReza Sabdar } 36682654012fSReza Sabdar } 36692654012fSReza Sabdar 36702654012fSReza Sabdar return (0); 36712654012fSReza Sabdar } 36722654012fSReza Sabdar 36732654012fSReza Sabdar 36742654012fSReza Sabdar /* 36752654012fSReza Sabdar * mover_data_read_v3 36762654012fSReza Sabdar * 36772654012fSReza Sabdar * Reads backup data from the data connection and writes the 36782654012fSReza Sabdar * received data to the tape device. 36792654012fSReza Sabdar * 36802654012fSReza Sabdar * Parameters: 36812654012fSReza Sabdar * cookie (input) - session pointer. 36822654012fSReza Sabdar * fd (input) - file descriptor. 36832654012fSReza Sabdar * mode (input) - select mode. 36842654012fSReza Sabdar * 36852654012fSReza Sabdar * Returns: 36862654012fSReza Sabdar * void. 36872654012fSReza Sabdar */ 36882654012fSReza Sabdar /*ARGSUSED*/ 36892654012fSReza Sabdar static void 36902654012fSReza Sabdar mover_data_read_v3(void *cookie, int fd, ulong_t mode) 36912654012fSReza Sabdar { 36922654012fSReza Sabdar ndmpd_session_t *session = (ndmpd_session_t *)cookie; 36932654012fSReza Sabdar int n; 36942654012fSReza Sabdar ulong_t index; 36952654012fSReza Sabdar 36962654012fSReza Sabdar n = read(fd, &session->ns_mover.md_buf[session->ns_mover.md_w_index], 36972654012fSReza Sabdar session->ns_mover.md_record_size - session->ns_mover.md_w_index); 36982654012fSReza Sabdar 36992654012fSReza Sabdar /* 37002654012fSReza Sabdar * Since this function is only called when select believes data 37012654012fSReza Sabdar * is available to be read, a return of zero indicates the 37022654012fSReza Sabdar * connection has been closed. 37032654012fSReza Sabdar */ 37042654012fSReza Sabdar if (n <= 0) { 370597f7c475SJan Kryl if (n == 0) { 370697f7c475SJan Kryl NDMP_LOG(LOG_DEBUG, "Data connection closed"); 370797f7c475SJan Kryl ndmpd_mover_error(session, 370897f7c475SJan Kryl NDMP_MOVER_HALT_CONNECT_CLOSED); 370997f7c475SJan Kryl } else { 371097f7c475SJan Kryl /* Socket is non-blocking, perhaps there are no data */ 371197f7c475SJan Kryl if (errno == EAGAIN) { 371297f7c475SJan Kryl NDMP_LOG(LOG_ERR, "No data to read"); 37132654012fSReza Sabdar return; 37142654012fSReza Sabdar } 371597f7c475SJan Kryl 371697f7c475SJan Kryl NDMP_LOG(LOG_ERR, "Failed to read from socket: %m"); 371797f7c475SJan Kryl ndmpd_mover_error(session, 371897f7c475SJan Kryl NDMP_MOVER_HALT_INTERNAL_ERROR); 371997f7c475SJan Kryl } 37202654012fSReza Sabdar 37212654012fSReza Sabdar /* Save the index since mover_tape_flush_v3 resets it. */ 37222654012fSReza Sabdar index = session->ns_mover.md_w_index; 37232654012fSReza Sabdar 37242654012fSReza Sabdar /* Flush any buffered data to tape. */ 37252654012fSReza Sabdar if (mover_tape_flush_v3(session) > 0) { 37262654012fSReza Sabdar session->ns_mover.md_data_written += index; 37272654012fSReza Sabdar session->ns_mover.md_record_num++; 37282654012fSReza Sabdar } 37292654012fSReza Sabdar 37302654012fSReza Sabdar return; 37312654012fSReza Sabdar } 37322654012fSReza Sabdar 37332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n %d", n); 37342654012fSReza Sabdar 37352654012fSReza Sabdar session->ns_mover.md_w_index += n; 37362654012fSReza Sabdar 37372654012fSReza Sabdar if (session->ns_mover.md_w_index == session->ns_mover.md_record_size) { 37382654012fSReza Sabdar n = mover_tape_write_v3(session, session->ns_mover.md_buf, 37392654012fSReza Sabdar session->ns_mover.md_record_size); 37402654012fSReza Sabdar if (n <= 0) { 37412654012fSReza Sabdar ndmpd_mover_error(session, 37422654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 37432654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 37442654012fSReza Sabdar return; 37452654012fSReza Sabdar } 37462654012fSReza Sabdar 37472654012fSReza Sabdar session->ns_mover.md_position += n; 37482654012fSReza Sabdar session->ns_mover.md_w_index = 0; 37492654012fSReza Sabdar session->ns_mover.md_data_written += n; 37502654012fSReza Sabdar session->ns_mover.md_record_num++; 37512654012fSReza Sabdar } 37522654012fSReza Sabdar } 37532654012fSReza Sabdar 37542654012fSReza Sabdar /* 37552654012fSReza Sabdar * mover_tape_read_v3 37562654012fSReza Sabdar * 37572654012fSReza Sabdar * Reads a data record from tape. Detects and handles EOT conditions. 37582654012fSReza Sabdar * 37592654012fSReza Sabdar * Parameters: 37602654012fSReza Sabdar * session (input) - session pointer. 37612654012fSReza Sabdar * data (input) - location to read data to. 37622654012fSReza Sabdar * 37632654012fSReza Sabdar * Returns: 37642654012fSReza Sabdar * 0 - operation aborted. 37652654012fSReza Sabdar * TAPE_READ_ERR - tape read IO error. 37662654012fSReza Sabdar * TAPE_NO_WRITER_ERR - no writer is running during tape read 37672654012fSReza Sabdar * otherwise - number of bytes read. 37682654012fSReza Sabdar */ 37692654012fSReza Sabdar static int 37702654012fSReza Sabdar mover_tape_read_v3(ndmpd_session_t *session, char *data) 37712654012fSReza Sabdar { 37729ee94b97SJan Kryl int pause_reason; 37732654012fSReza Sabdar ssize_t n; 37742654012fSReza Sabdar int err; 37752654012fSReza Sabdar int count; 37762654012fSReza Sabdar 37772654012fSReza Sabdar count = session->ns_mover.md_record_size; 37789ee94b97SJan Kryl while (count > 0) { 37799ee94b97SJan Kryl pause_reason = NDMP_MOVER_PAUSE_NA; 37809ee94b97SJan Kryl 37812654012fSReza Sabdar n = read(session->ns_tape.td_fd, data, count); 37822654012fSReza Sabdar if (n < 0) { 37839ee94b97SJan Kryl /* 37849ee94b97SJan Kryl * If at beginning of file and read fails with EIO, 37859ee94b97SJan Kryl * then it's repeated attempt to read at EOT. 37869ee94b97SJan Kryl */ 37879ee94b97SJan Kryl if (errno == EIO && tape_is_at_bof(session)) { 37889ee94b97SJan Kryl NDMP_LOG(LOG_DEBUG, "Repeated read at EOT"); 37899ee94b97SJan Kryl pause_reason = NDMP_MOVER_PAUSE_EOM; 37909ee94b97SJan Kryl NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 37919ee94b97SJan Kryl ++ndmp_log_msg_id, 37929ee94b97SJan Kryl "End of tape reached. Load next tape"); 37939ee94b97SJan Kryl } 37949ee94b97SJan Kryl /* 37959ee94b97SJan Kryl * According to NDMPv4 spec preferred error code when 37969ee94b97SJan Kryl * trying to read from blank tape is NDMP_EOM_ERR. 37979ee94b97SJan Kryl */ 37989ee94b97SJan Kryl else if (errno == EIO && tape_is_at_bot(session)) { 37999ee94b97SJan Kryl NDMP_LOG(LOG_ERR, 38009ee94b97SJan Kryl "Blank tape detected, returning EOM"); 38019ee94b97SJan Kryl NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 38029ee94b97SJan Kryl ++ndmp_log_msg_id, 38039ee94b97SJan Kryl "Blank tape. Load another tape"); 38049ee94b97SJan Kryl pause_reason = NDMP_MOVER_PAUSE_EOM; 38059ee94b97SJan Kryl } else { 38062654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Tape read error: %m."); 38072654012fSReza Sabdar return (TAPE_READ_ERR); 38082654012fSReza Sabdar } 38099ee94b97SJan Kryl } else if (n > 0) { 38102654012fSReza Sabdar NS_ADD(rtape, n); 38119ee94b97SJan Kryl data += n; 38129ee94b97SJan Kryl count -= n; 38139ee94b97SJan Kryl session->ns_tape.td_record_count++; 38149ee94b97SJan Kryl } else { 38152654012fSReza Sabdar if (!is_writer_running_v3(session)) 38162654012fSReza Sabdar return (TAPE_NO_WRITER_ERR); 38172654012fSReza Sabdar 38182654012fSReza Sabdar /* 38199ee94b97SJan Kryl * End of file or media reached. Notify client and 38209ee94b97SJan Kryl * wait for the client to either abort the data 38219ee94b97SJan Kryl * operation or continue the operation after changing 38229ee94b97SJan Kryl * the tape. 38232654012fSReza Sabdar */ 38249ee94b97SJan Kryl if (tape_is_at_bof(session)) { 38259ee94b97SJan Kryl NDMP_LOG(LOG_DEBUG, "EOT detected"); 38269ee94b97SJan Kryl pause_reason = NDMP_MOVER_PAUSE_EOM; 38272654012fSReza Sabdar NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 38289ee94b97SJan Kryl ++ndmp_log_msg_id, "End of medium reached"); 38299ee94b97SJan Kryl } else { 38309ee94b97SJan Kryl NDMP_LOG(LOG_DEBUG, "EOF detected"); 38319ee94b97SJan Kryl /* reposition the tape to BOT side of FM */ 38329ee94b97SJan Kryl fm_dance(session); 38339ee94b97SJan Kryl pause_reason = NDMP_MOVER_PAUSE_EOF; 38349ee94b97SJan Kryl NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 38359ee94b97SJan Kryl ++ndmp_log_msg_id, "End of file reached."); 38369ee94b97SJan Kryl } 38379ee94b97SJan Kryl } 38382654012fSReza Sabdar 38399ee94b97SJan Kryl if (pause_reason != NDMP_MOVER_PAUSE_NA) { 38409ee94b97SJan Kryl err = mover_pause_v3(session, pause_reason); 38412654012fSReza Sabdar 38422654012fSReza Sabdar /* Operation aborted or connection terminated? */ 38432654012fSReza Sabdar if (err < 0) { 38442654012fSReza Sabdar return (0); 38452654012fSReza Sabdar } 38469ee94b97SJan Kryl /* Retry the read from new location */ 38472654012fSReza Sabdar } 38482654012fSReza Sabdar } 38499ee94b97SJan Kryl return (session->ns_mover.md_record_size); 38502654012fSReza Sabdar } 38512654012fSReza Sabdar 38522654012fSReza Sabdar 38532654012fSReza Sabdar /* 38542654012fSReza Sabdar * mover_data_write_v3 38552654012fSReza Sabdar * 38562654012fSReza Sabdar * Reads backup data from the tape device and writes the 38572654012fSReza Sabdar * data to the data connection. 38582654012fSReza Sabdar * This function is called by ndmpd_select when the data connection 38592654012fSReza Sabdar * is ready for more data to be written. 38602654012fSReza Sabdar * 38612654012fSReza Sabdar * Parameters: 38622654012fSReza Sabdar * cookie (input) - session pointer. 38632654012fSReza Sabdar * fd (input) - file descriptor. 38642654012fSReza Sabdar * mode (input) - select mode. 38652654012fSReza Sabdar * 38662654012fSReza Sabdar * Returns: 38672654012fSReza Sabdar * void. 38682654012fSReza Sabdar */ 38692654012fSReza Sabdar /*ARGSUSED*/ 38702654012fSReza Sabdar static void 38712654012fSReza Sabdar mover_data_write_v3(void *cookie, int fd, ulong_t mode) 38722654012fSReza Sabdar { 38732654012fSReza Sabdar ndmpd_session_t *session = (ndmpd_session_t *)cookie; 38742654012fSReza Sabdar int n; 38752654012fSReza Sabdar ulong_t len; 38762654012fSReza Sabdar u_longlong_t wlen; 38772654012fSReza Sabdar ndmp_notify_mover_paused_request pause_request; 38782654012fSReza Sabdar 38792654012fSReza Sabdar /* 38802654012fSReza Sabdar * If the end of the mover window has been reached, 38812654012fSReza Sabdar * then notify the client that a seek is needed. 38822654012fSReza Sabdar * Remove the file handler to prevent this function from 38832654012fSReza Sabdar * being called. The handler will be reinstalled in 38842654012fSReza Sabdar * ndmpd_mover_continue. 38852654012fSReza Sabdar */ 38862654012fSReza Sabdar if (session->ns_mover.md_position >= session->ns_mover.md_window_offset 38872654012fSReza Sabdar + session->ns_mover.md_window_length) { 38882654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 38892654012fSReza Sabdar "MOVER_PAUSE_SEEK(%llu)", session->ns_mover.md_position); 38902654012fSReza Sabdar 38912654012fSReza Sabdar session->ns_mover.md_w_index = 0; 38922654012fSReza Sabdar session->ns_mover.md_r_index = 0; 38932654012fSReza Sabdar 38942654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 38952654012fSReza Sabdar session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 38962654012fSReza Sabdar pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 38972654012fSReza Sabdar pause_request.seek_position = 38982654012fSReza Sabdar long_long_to_quad(session->ns_mover.md_position); 38992654012fSReza Sabdar session->ns_mover.md_seek_position = 39002654012fSReza Sabdar session->ns_mover.md_position; 39012654012fSReza Sabdar 39022654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, fd); 39032654012fSReza Sabdar 39042654012fSReza Sabdar if (ndmp_send_request(session->ns_connection, 39052654012fSReza Sabdar NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 39062654012fSReza Sabdar (void *)&pause_request, 0) < 0) { 39072654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 39082654012fSReza Sabdar "Sending notify_mover_paused request"); 39092654012fSReza Sabdar ndmpd_mover_error(session, 39102654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 39112654012fSReza Sabdar } 39122654012fSReza Sabdar return; 39132654012fSReza Sabdar } 39142654012fSReza Sabdar 39152654012fSReza Sabdar /* 39162654012fSReza Sabdar * Read more data into the tape buffer if the buffer is empty. 39172654012fSReza Sabdar */ 39182654012fSReza Sabdar if (session->ns_mover.md_w_index == 0) { 39192654012fSReza Sabdar n = mover_tape_read_v3(session, session->ns_mover.md_buf); 39202654012fSReza Sabdar 39212654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 39222654012fSReza Sabdar "read %u bytes from tape", n); 39232654012fSReza Sabdar 39242654012fSReza Sabdar if (n <= 0) { 39252654012fSReza Sabdar ndmpd_mover_error(session, (n == 0 ? 39262654012fSReza Sabdar NDMP_MOVER_HALT_ABORTED 39272654012fSReza Sabdar : NDMP_MOVER_HALT_MEDIA_ERROR)); 39282654012fSReza Sabdar return; 39292654012fSReza Sabdar } 39302654012fSReza Sabdar 39312654012fSReza Sabdar /* 39322654012fSReza Sabdar * Discard data if the current data stream position is 39332654012fSReza Sabdar * prior to the seek position. This is necessary if a seek 39342654012fSReza Sabdar * request set the seek pointer to a position that is not a 39352654012fSReza Sabdar * record boundary. The seek request handler can only position 39362654012fSReza Sabdar * to the start of a record. 39372654012fSReza Sabdar */ 39382654012fSReza Sabdar if (session->ns_mover.md_position < 39392654012fSReza Sabdar session->ns_mover.md_seek_position) { 39402654012fSReza Sabdar session->ns_mover.md_r_index = 39412654012fSReza Sabdar session->ns_mover.md_seek_position - 39422654012fSReza Sabdar session->ns_mover.md_position; 39432654012fSReza Sabdar session->ns_mover.md_position = 39442654012fSReza Sabdar session->ns_mover.md_seek_position; 39452654012fSReza Sabdar } 39462654012fSReza Sabdar 39472654012fSReza Sabdar session->ns_mover.md_w_index = n; 39489ee94b97SJan Kryl session->ns_mover.md_record_num++; 39492654012fSReza Sabdar } 39502654012fSReza Sabdar 39512654012fSReza Sabdar /* 39522654012fSReza Sabdar * The limit on the total amount of data to be sent can be 39532654012fSReza Sabdar * dictated by either the end of the mover window or the end of the 39542654012fSReza Sabdar * seek window. 39552654012fSReza Sabdar * First determine which window applies and then determine if the 39562654012fSReza Sabdar * send length needs to be less than a full record to avoid 39572654012fSReza Sabdar * exceeding the window. 39582654012fSReza Sabdar */ 39592654012fSReza Sabdar if (session->ns_mover.md_position + 39602654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read > 39612654012fSReza Sabdar session->ns_mover.md_window_offset + 39622654012fSReza Sabdar session->ns_mover.md_window_length) 39632654012fSReza Sabdar wlen = session->ns_mover.md_window_offset + 39642654012fSReza Sabdar session->ns_mover.md_window_length - 39652654012fSReza Sabdar session->ns_mover.md_position; 39662654012fSReza Sabdar else 39672654012fSReza Sabdar wlen = session->ns_mover.md_bytes_left_to_read; 39682654012fSReza Sabdar 39692654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "wlen window restrictions: %llu", wlen); 39702654012fSReza Sabdar 39712654012fSReza Sabdar /* 39722654012fSReza Sabdar * Now limit the length to the amount of data in the buffer. 39732654012fSReza Sabdar */ 39742654012fSReza Sabdar if (wlen > session->ns_mover.md_w_index - session->ns_mover.md_r_index) 39752654012fSReza Sabdar wlen = session->ns_mover.md_w_index - 39762654012fSReza Sabdar session->ns_mover.md_r_index; 39772654012fSReza Sabdar 39782654012fSReza Sabdar len = wlen & 0xffffffff; 39792654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 39802654012fSReza Sabdar "buffer restrictions: wlen %llu len %u", wlen, len); 39812654012fSReza Sabdar 39822654012fSReza Sabdar /* 39832654012fSReza Sabdar * Write the data to the data connection. 39842654012fSReza Sabdar */ 39852654012fSReza Sabdar n = write(session->ns_mover.md_sock, 39862654012fSReza Sabdar &session->ns_mover.md_buf[session->ns_mover.md_r_index], len); 39872654012fSReza Sabdar 39882654012fSReza Sabdar if (n < 0) { 398997f7c475SJan Kryl /* Socket is non-blocking, perhaps the write queue is full */ 399097f7c475SJan Kryl if (errno == EAGAIN) { 399197f7c475SJan Kryl NDMP_LOG(LOG_ERR, "Cannot write to socket"); 39922654012fSReza Sabdar return; 39932654012fSReza Sabdar } 399497f7c475SJan Kryl NDMP_LOG(LOG_ERR, "Failed to write to socket: %m"); 39952654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 39962654012fSReza Sabdar return; 39972654012fSReza Sabdar } 39982654012fSReza Sabdar 39992654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 40002654012fSReza Sabdar "wrote %u of %u bytes to data connection position %llu r_index %lu", 40012654012fSReza Sabdar n, len, session->ns_mover.md_position, 40022654012fSReza Sabdar session->ns_mover.md_r_index); 40032654012fSReza Sabdar 40042654012fSReza Sabdar session->ns_mover.md_r_index += n; 40052654012fSReza Sabdar session->ns_mover.md_position += n; 40062654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= n; 40072654012fSReza Sabdar 40082654012fSReza Sabdar /* 40092654012fSReza Sabdar * If all data in the buffer has been written, 40102654012fSReza Sabdar * zero the buffer indices. The next call to this function 40112654012fSReza Sabdar * will read more data from the tape device into the buffer. 40122654012fSReza Sabdar */ 40132654012fSReza Sabdar if (session->ns_mover.md_r_index == session->ns_mover.md_w_index) { 40142654012fSReza Sabdar session->ns_mover.md_r_index = 0; 40152654012fSReza Sabdar session->ns_mover.md_w_index = 0; 40162654012fSReza Sabdar } 40172654012fSReza Sabdar 40182654012fSReza Sabdar /* 40192654012fSReza Sabdar * If the read limit has been reached, 40202654012fSReza Sabdar * then remove the file handler to prevent this 40212654012fSReza Sabdar * function from getting called. The next mover_read request 40222654012fSReza Sabdar * will reinstall the handler. 40232654012fSReza Sabdar */ 40242654012fSReza Sabdar if (session->ns_mover.md_bytes_left_to_read == 0) 40252654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, fd); 40262654012fSReza Sabdar } 40272654012fSReza Sabdar 40282654012fSReza Sabdar 40292654012fSReza Sabdar /* 40302654012fSReza Sabdar * accept_connection_v3 40312654012fSReza Sabdar * 40322654012fSReza Sabdar * Accept a data connection from a data server. 40332654012fSReza Sabdar * Called by ndmpd_select when a connection is pending on 40342654012fSReza Sabdar * the mover listen socket. 40352654012fSReza Sabdar * 40362654012fSReza Sabdar * Parameters: 40372654012fSReza Sabdar * cookie (input) - session pointer. 40382654012fSReza Sabdar * fd (input) - file descriptor. 40392654012fSReza Sabdar * mode (input) - select mode. 40402654012fSReza Sabdar * 40412654012fSReza Sabdar * Returns: 40422654012fSReza Sabdar * void. 40432654012fSReza Sabdar */ 40442654012fSReza Sabdar /*ARGSUSED*/ 40452654012fSReza Sabdar static void 40462654012fSReza Sabdar accept_connection_v3(void *cookie, int fd, ulong_t mode) 40472654012fSReza Sabdar { 40482654012fSReza Sabdar ndmpd_session_t *session = (ndmpd_session_t *)cookie; 40492654012fSReza Sabdar int from_len; 40502654012fSReza Sabdar struct sockaddr_in from; 40512654012fSReza Sabdar 40522654012fSReza Sabdar from_len = sizeof (from); 40532654012fSReza Sabdar session->ns_mover.md_sock = accept(fd, (struct sockaddr *)&from, 40542654012fSReza Sabdar &from_len); 40552654012fSReza Sabdar 40562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s", ntohs(from.sin_port), 40572654012fSReza Sabdar inet_ntoa(IN_ADDR(from.sin_addr.s_addr))); 40582654012fSReza Sabdar 40592654012fSReza Sabdar (void) ndmpd_remove_file_handler(session, fd); 40602654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 40612654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 40622654012fSReza Sabdar 40632654012fSReza Sabdar if (session->ns_mover.md_sock < 0) { 40642654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Accept error: %m"); 40652654012fSReza Sabdar ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_ERROR); 40662654012fSReza Sabdar return; 40672654012fSReza Sabdar } 40682654012fSReza Sabdar 40692654012fSReza Sabdar /* 40702654012fSReza Sabdar * Save the peer address. 40712654012fSReza Sabdar */ 40722654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_ip_v3 = from.sin_addr.s_addr; 40732654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(from.sin_port); 40742654012fSReza Sabdar 407597f7c475SJan Kryl /* Set the parameter of the new socket */ 407697f7c475SJan Kryl set_socket_options(session->ns_mover.md_sock); 40772654012fSReza Sabdar 407897f7c475SJan Kryl /* 407997f7c475SJan Kryl * Backup/restore is handled by a callback called from main event loop, 408097f7c475SJan Kryl * which reads/writes data to md_sock socket. IO on socket must be 408197f7c475SJan Kryl * non-blocking, otherwise ndmpd would be unable to process other 408297f7c475SJan Kryl * incoming requests. 408397f7c475SJan Kryl */ 408497f7c475SJan Kryl if (!set_socket_nonblock(session->ns_mover.md_sock)) { 408597f7c475SJan Kryl NDMP_LOG(LOG_ERR, "Could not set non-blocking mode " 408697f7c475SJan Kryl "on socket: %m"); 408797f7c475SJan Kryl ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 408897f7c475SJan Kryl return; 408997f7c475SJan Kryl } 40902654012fSReza Sabdar 40912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sock fd: %d", session->ns_mover.md_sock); 40922654012fSReza Sabdar 40932654012fSReza Sabdar if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) { 40942654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void*)session, 40952654012fSReza Sabdar session->ns_mover.md_sock, NDMPD_SELECT_MODE_READ, 40962654012fSReza Sabdar HC_MOVER, mover_data_read_v3) < 0) { 40972654012fSReza Sabdar ndmpd_mover_error(session, 40982654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 40992654012fSReza Sabdar return; 41002654012fSReza Sabdar } 41012654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Backup connection established by %s:%d", 41022654012fSReza Sabdar inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 41032654012fSReza Sabdar ntohs(from.sin_port)); 41042654012fSReza Sabdar } else { 41052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Restore connection established by %s:%d", 41062654012fSReza Sabdar inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 41072654012fSReza Sabdar ntohs(from.sin_port)); 41082654012fSReza Sabdar } 41092654012fSReza Sabdar 41102654012fSReza Sabdar session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 41112654012fSReza Sabdar } 41122654012fSReza Sabdar 41132654012fSReza Sabdar 41142654012fSReza Sabdar /* 41152654012fSReza Sabdar * create_listen_socket_v3 41162654012fSReza Sabdar * 41172654012fSReza Sabdar * Creates a socket for listening for accepting data connections. 41182654012fSReza Sabdar * 41192654012fSReza Sabdar * Parameters: 41202654012fSReza Sabdar * session (input) - session pointer. 41212654012fSReza Sabdar * addr (output) - location to store address of socket. 41222654012fSReza Sabdar * port (output) - location to store port of socket. 41232654012fSReza Sabdar * 41242654012fSReza Sabdar * Returns: 41252654012fSReza Sabdar * 0 - success. 41262654012fSReza Sabdar * -1 - error. 41272654012fSReza Sabdar */ 41282654012fSReza Sabdar static int 41292654012fSReza Sabdar create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, ushort_t *port) 41302654012fSReza Sabdar { 41312654012fSReza Sabdar session->ns_mover.md_listen_sock = ndmp_create_socket(addr, port); 41322654012fSReza Sabdar if (session->ns_mover.md_listen_sock < 0) 41332654012fSReza Sabdar return (-1); 41342654012fSReza Sabdar 41352654012fSReza Sabdar /* 41362654012fSReza Sabdar * Add a file handler for the listen socket. 41372654012fSReza Sabdar * ndmpd_select will call accept_connection when a 41382654012fSReza Sabdar * connection is ready to be accepted. 41392654012fSReza Sabdar */ 41402654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void *) session, 41412654012fSReza Sabdar session->ns_mover.md_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER, 41422654012fSReza Sabdar accept_connection_v3) < 0) { 41432654012fSReza Sabdar (void) close(session->ns_mover.md_listen_sock); 41442654012fSReza Sabdar session->ns_mover.md_listen_sock = -1; 41452654012fSReza Sabdar return (-1); 41462654012fSReza Sabdar } 41472654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "IP %s port %d", 41482654012fSReza Sabdar inet_ntoa(*(struct in_addr *)addr), ntohs(*port)); 41492654012fSReza Sabdar return (0); 41502654012fSReza Sabdar } 41512654012fSReza Sabdar 41522654012fSReza Sabdar 41532654012fSReza Sabdar /* 415497f7c475SJan Kryl * mover_connect_sock 41552654012fSReza Sabdar * 41562654012fSReza Sabdar * Connect the mover to the specified address 41572654012fSReza Sabdar * 41582654012fSReza Sabdar * Parameters: 41592654012fSReza Sabdar * session (input) - session pointer. 41602654012fSReza Sabdar * mode (input) - mover mode. 41612654012fSReza Sabdar * addr (output) - location to store address of socket. 41622654012fSReza Sabdar * port (output) - location to store port of socket. 41632654012fSReza Sabdar * 41642654012fSReza Sabdar * Returns: 41652654012fSReza Sabdar * error code. 41662654012fSReza Sabdar */ 41672654012fSReza Sabdar static ndmp_error 416897f7c475SJan Kryl mover_connect_sock(ndmpd_session_t *session, ndmp_mover_mode mode, 41692654012fSReza Sabdar ulong_t addr, ushort_t port) 41702654012fSReza Sabdar { 41712654012fSReza Sabdar int sock; 41722654012fSReza Sabdar 41732654012fSReza Sabdar sock = ndmp_connect_sock_v3(addr, port); 41742654012fSReza Sabdar if (sock < 0) 41752654012fSReza Sabdar return (NDMP_CONNECT_ERR); 41762654012fSReza Sabdar 417797f7c475SJan Kryl /* 417897f7c475SJan Kryl * Backup/restore is handled by a callback called from main event loop, 417997f7c475SJan Kryl * which reads/writes data to md_sock socket. IO on socket must be 418097f7c475SJan Kryl * non-blocking, otherwise ndmpd would be unable to process other 418197f7c475SJan Kryl * incoming requests. 418297f7c475SJan Kryl */ 418397f7c475SJan Kryl if (!set_socket_nonblock(sock)) { 418497f7c475SJan Kryl NDMP_LOG(LOG_ERR, "Could not set non-blocking mode " 418597f7c475SJan Kryl "on socket: %m"); 418697f7c475SJan Kryl (void) close(sock); 418797f7c475SJan Kryl return (NDMP_CONNECT_ERR); 418897f7c475SJan Kryl } 418997f7c475SJan Kryl 41902654012fSReza Sabdar if (mode == NDMP_MOVER_MODE_READ) { 41912654012fSReza Sabdar if (ndmpd_add_file_handler(session, (void*)session, sock, 41922654012fSReza Sabdar NDMPD_SELECT_MODE_READ, HC_MOVER, mover_data_read_v3) < 0) { 41932654012fSReza Sabdar (void) close(sock); 41942654012fSReza Sabdar return (NDMP_CONNECT_ERR); 41952654012fSReza Sabdar } 41962654012fSReza Sabdar } 41972654012fSReza Sabdar session->ns_mover.md_sock = sock; 41982654012fSReza Sabdar session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 41992654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_ip_v3 = ntohl(addr); 42002654012fSReza Sabdar session->ns_mover.md_data_addr.tcp_port_v3 = port; 42012654012fSReza Sabdar return (NDMP_NO_ERR); 42022654012fSReza Sabdar } 42032654012fSReza Sabdar 42042654012fSReza Sabdar 42052654012fSReza Sabdar /* 42062654012fSReza Sabdar * ndmpd_local_read_v3 42072654012fSReza Sabdar * 42082654012fSReza Sabdar * Reads data from the local tape device. 42092654012fSReza Sabdar * Full tape records are read and buffered. 42102654012fSReza Sabdar * 42112654012fSReza Sabdar * Parameters: 42122654012fSReza Sabdar * session (input) - session pointer. 42132654012fSReza Sabdar * data (input) - location to store data. 42142654012fSReza Sabdar * length (input) - data length. 42152654012fSReza Sabdar * 42162654012fSReza Sabdar * Returns: 42172654012fSReza Sabdar * 1 - no read error but no writer running 42182654012fSReza Sabdar * 0 - data successfully read. 42192654012fSReza Sabdar * -1 - error. 42202654012fSReza Sabdar */ 42212654012fSReza Sabdar int 42222654012fSReza Sabdar ndmpd_local_read_v3(ndmpd_session_t *session, char *data, ulong_t length) 42232654012fSReza Sabdar { 42242654012fSReza Sabdar ulong_t count; 42252654012fSReza Sabdar ulong_t len; 42262654012fSReza Sabdar ssize_t n; 42272654012fSReza Sabdar 42282654012fSReza Sabdar count = 0; 42292654012fSReza Sabdar if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 42302654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 42312654012fSReza Sabdar session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 42322654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid mover state to read data"); 42332654012fSReza Sabdar return (-1); 42342654012fSReza Sabdar } 42352654012fSReza Sabdar 42362654012fSReza Sabdar /* 42372654012fSReza Sabdar * Automatically increase the seek window if necessary. 42382654012fSReza Sabdar * This is needed in the event the module attempts to read 42392654012fSReza Sabdar * past a seek window set via a prior call to ndmpd_seek() or 42402654012fSReza Sabdar * the module has not issued a seek. If no seek was issued then 42412654012fSReza Sabdar * pretend that a seek was issued to read the entire tape. 42422654012fSReza Sabdar */ 42432654012fSReza Sabdar if (length > session->ns_mover.md_bytes_left_to_read) { 42442654012fSReza Sabdar /* ndmpd_seek() never called? */ 42452654012fSReza Sabdar if (session->ns_data.dd_read_length == 0) { 42462654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = ~0LL; 42472654012fSReza Sabdar session->ns_data.dd_read_offset = 0LL; 42482654012fSReza Sabdar session->ns_data.dd_read_length = ~0LL; 42492654012fSReza Sabdar } else { 42502654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read = length; 42512654012fSReza Sabdar session->ns_data.dd_read_offset = 42522654012fSReza Sabdar session->ns_mover.md_position; 42532654012fSReza Sabdar session->ns_data.dd_read_length = length; 42542654012fSReza Sabdar } 42552654012fSReza Sabdar } 42562654012fSReza Sabdar 42572654012fSReza Sabdar /* 42582654012fSReza Sabdar * Read as many records as necessary to satisfy the request. 42592654012fSReza Sabdar */ 42602654012fSReza Sabdar while (count < length) { 42612654012fSReza Sabdar /* 42622654012fSReza Sabdar * If the end of the mover window has been reached, 42632654012fSReza Sabdar * then notify the client that a new data window is needed. 42642654012fSReza Sabdar */ 42652654012fSReza Sabdar if (session->ns_mover.md_position >= 42662654012fSReza Sabdar session->ns_mover.md_window_offset + 42672654012fSReza Sabdar session->ns_mover.md_window_length) { 42682654012fSReza Sabdar if (mover_pause_v3(session, 42692654012fSReza Sabdar NDMP_MOVER_PAUSE_SEEK) < 0) { 42702654012fSReza Sabdar ndmpd_mover_error(session, 42712654012fSReza Sabdar NDMP_MOVER_HALT_INTERNAL_ERROR); 42722654012fSReza Sabdar return (-1); 42732654012fSReza Sabdar } 42742654012fSReza Sabdar continue; 42752654012fSReza Sabdar } 42762654012fSReza Sabdar 42772654012fSReza Sabdar len = length - count; 42782654012fSReza Sabdar 42792654012fSReza Sabdar /* 42802654012fSReza Sabdar * Prevent reading past the end of the window. 42812654012fSReza Sabdar */ 42822654012fSReza Sabdar if (len > session->ns_mover.md_window_offset + 42832654012fSReza Sabdar session->ns_mover.md_window_length - 42842654012fSReza Sabdar session->ns_mover.md_position) 42852654012fSReza Sabdar len = session->ns_mover.md_window_offset + 42862654012fSReza Sabdar session->ns_mover.md_window_length - 42872654012fSReza Sabdar session->ns_mover.md_position; 42882654012fSReza Sabdar 42892654012fSReza Sabdar /* 42902654012fSReza Sabdar * Copy from the data buffer first. 42912654012fSReza Sabdar */ 42922654012fSReza Sabdar if (session->ns_mover.md_w_index - 42932654012fSReza Sabdar session->ns_mover.md_r_index != 0) { 42942654012fSReza Sabdar /* 42952654012fSReza Sabdar * Limit the copy to the amount of data in the buffer. 42962654012fSReza Sabdar */ 42972654012fSReza Sabdar if (len > session->ns_mover.md_w_index - 42982654012fSReza Sabdar session->ns_mover.md_r_index) 42992654012fSReza Sabdar len = session->ns_mover.md_w_index - 43002654012fSReza Sabdar session->ns_mover.md_r_index; 43012654012fSReza Sabdar (void) memcpy((void*)&data[count], 43022654012fSReza Sabdar &session->ns_mover.md_buf[session-> 43032654012fSReza Sabdar ns_mover.md_r_index], len); 43042654012fSReza Sabdar count += len; 43052654012fSReza Sabdar session->ns_mover.md_r_index += len; 43062654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= len; 43072654012fSReza Sabdar session->ns_mover.md_position += len; 43082654012fSReza Sabdar continue; 43092654012fSReza Sabdar } 43102654012fSReza Sabdar 43112654012fSReza Sabdar /* 43122654012fSReza Sabdar * Determine if data needs to be buffered or 43132654012fSReza Sabdar * can be read directly to user supplied location. 43142654012fSReza Sabdar * We can fast path the read if at least a full record 43152654012fSReza Sabdar * needs to be read and there is no seek pending. 43162654012fSReza Sabdar * This is done to eliminate a buffer copy. 43172654012fSReza Sabdar */ 43182654012fSReza Sabdar if (len >= session->ns_mover.md_record_size && 43192654012fSReza Sabdar session->ns_mover.md_position >= 43202654012fSReza Sabdar session->ns_mover.md_seek_position) { 43212654012fSReza Sabdar n = mover_tape_read_v3(session, &data[count]); 43222654012fSReza Sabdar if (n <= 0) { 43232654012fSReza Sabdar if (n == TAPE_NO_WRITER_ERR) 43242654012fSReza Sabdar return (1); 43252654012fSReza Sabdar 43262654012fSReza Sabdar ndmpd_mover_error(session, 43272654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 43282654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 43292654012fSReza Sabdar return ((n == 0) ? 1 : -1); 43302654012fSReza Sabdar } 43312654012fSReza Sabdar 43322654012fSReza Sabdar count += n; 43332654012fSReza Sabdar session->ns_mover.md_bytes_left_to_read -= n; 43342654012fSReza Sabdar session->ns_mover.md_position += n; 43359ee94b97SJan Kryl session->ns_mover.md_record_num++; 43362654012fSReza Sabdar continue; 43372654012fSReza Sabdar } 43382654012fSReza Sabdar 43392654012fSReza Sabdar /* Read the next record into the buffer. */ 43402654012fSReza Sabdar n = mover_tape_read_v3(session, session->ns_mover.md_buf); 43412654012fSReza Sabdar if (n <= 0) { 43422654012fSReza Sabdar if (n == TAPE_NO_WRITER_ERR) 43432654012fSReza Sabdar return (1); 43442654012fSReza Sabdar 43452654012fSReza Sabdar ndmpd_mover_error(session, 43462654012fSReza Sabdar (n == 0 ? NDMP_MOVER_HALT_ABORTED : 43472654012fSReza Sabdar NDMP_MOVER_HALT_MEDIA_ERROR)); 43482654012fSReza Sabdar return ((n == 0) ? 1 : -1); 43492654012fSReza Sabdar } 43502654012fSReza Sabdar 43512654012fSReza Sabdar session->ns_mover.md_w_index = n; 43522654012fSReza Sabdar session->ns_mover.md_r_index = 0; 43539ee94b97SJan Kryl session->ns_mover.md_record_num++; 43542654012fSReza Sabdar 43552654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n: %d", n); 43562654012fSReza Sabdar 43572654012fSReza Sabdar /* 43582654012fSReza Sabdar * Discard data if the current data stream position is 43592654012fSReza Sabdar * prior to the seek position. This is necessary if a seek 43602654012fSReza Sabdar * request set the seek pointer to a position that is not a 43612654012fSReza Sabdar * record boundary. The seek request handler can only position 43622654012fSReza Sabdar * to the start of a record. 43632654012fSReza Sabdar */ 43642654012fSReza Sabdar if (session->ns_mover.md_position < 43652654012fSReza Sabdar session->ns_mover.md_seek_position) { 43662654012fSReza Sabdar session->ns_mover.md_r_index = 43672654012fSReza Sabdar session->ns_mover.md_seek_position - 43682654012fSReza Sabdar session->ns_mover.md_position; 43692654012fSReza Sabdar session->ns_mover.md_position = 43702654012fSReza Sabdar session->ns_mover.md_seek_position; 43712654012fSReza Sabdar } 43722654012fSReza Sabdar } 43732654012fSReza Sabdar 43742654012fSReza Sabdar return (0); 43752654012fSReza Sabdar } 4376