17917SReza.Sabdar@Sun.COM /* 2*8800SReza.Sabdar@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37917SReza.Sabdar@Sun.COM * Use is subject to license terms. 47917SReza.Sabdar@Sun.COM */ 57917SReza.Sabdar@Sun.COM 67917SReza.Sabdar@Sun.COM /* 77917SReza.Sabdar@Sun.COM * BSD 3 Clause License 87917SReza.Sabdar@Sun.COM * 97917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association. 107917SReza.Sabdar@Sun.COM * 117917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without 127917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions 137917SReza.Sabdar@Sun.COM * are met: 147917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright 157917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer. 167917SReza.Sabdar@Sun.COM * 177917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright 187917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in 197917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the 207917SReza.Sabdar@Sun.COM * distribution. 217917SReza.Sabdar@Sun.COM * 227917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA) 237917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote 247917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written 257917SReza.Sabdar@Sun.COM * permission. 267917SReza.Sabdar@Sun.COM * 277917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 287917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 297917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 307917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 317917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 327917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 337917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 347917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 357917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 367917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 377917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 387917SReza.Sabdar@Sun.COM */ 397917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */ 407917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 417917SReza.Sabdar@Sun.COM 427917SReza.Sabdar@Sun.COM #include <sys/ioctl.h> 437917SReza.Sabdar@Sun.COM #include <sys/types.h> 447917SReza.Sabdar@Sun.COM #include <sys/socket.h> 457917SReza.Sabdar@Sun.COM #include <sys/socketvar.h> 467917SReza.Sabdar@Sun.COM #include <netinet/in.h> 477917SReza.Sabdar@Sun.COM #include <arpa/inet.h> 487917SReza.Sabdar@Sun.COM #include <net/if.h> 497917SReza.Sabdar@Sun.COM #include <errno.h> 507917SReza.Sabdar@Sun.COM #include <fcntl.h> 517917SReza.Sabdar@Sun.COM #include <netdb.h> 527917SReza.Sabdar@Sun.COM #include <stdlib.h> 537917SReza.Sabdar@Sun.COM #include <unistd.h> 547917SReza.Sabdar@Sun.COM #include <string.h> 557917SReza.Sabdar@Sun.COM #include "ndmpd_common.h" 567917SReza.Sabdar@Sun.COM #include "ndmpd.h" 577917SReza.Sabdar@Sun.COM #include <sys/mtio.h> 587917SReza.Sabdar@Sun.COM 597917SReza.Sabdar@Sun.COM /* 607917SReza.Sabdar@Sun.COM * Maximum mover record size 617917SReza.Sabdar@Sun.COM */ 627917SReza.Sabdar@Sun.COM #define MAX_MOVER_RECSIZE (512*KILOBYTE) 637917SReza.Sabdar@Sun.COM 647917SReza.Sabdar@Sun.COM static int create_listen_socket_v2(ndmpd_session_t *session, ulong_t *addr, 657917SReza.Sabdar@Sun.COM ushort_t *port); 667917SReza.Sabdar@Sun.COM static int tape_write(ndmpd_session_t *session, char *data, ssize_t length); 677917SReza.Sabdar@Sun.COM static int tape_read(ndmpd_session_t *session, char *data); 687917SReza.Sabdar@Sun.COM static int change_tape(ndmpd_session_t *session); 697917SReza.Sabdar@Sun.COM static int discard_data(ndmpd_session_t *session, ulong_t length); 707917SReza.Sabdar@Sun.COM static int mover_tape_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf); 717917SReza.Sabdar@Sun.COM static int mover_socket_write_one_buf(ndmpd_session_t *session, 727917SReza.Sabdar@Sun.COM tlm_buffer_t *buf); 737917SReza.Sabdar@Sun.COM static int start_mover_for_restore(ndmpd_session_t *session); 747917SReza.Sabdar@Sun.COM static int mover_socket_read_one_buf(ndmpd_session_t *session, 757917SReza.Sabdar@Sun.COM tlm_buffer_t *buf, long read_size); 767917SReza.Sabdar@Sun.COM static int mover_tape_write_one_buf(ndmpd_session_t *session, 777917SReza.Sabdar@Sun.COM tlm_buffer_t *buf); 787917SReza.Sabdar@Sun.COM static int start_mover_for_backup(ndmpd_session_t *session); 797917SReza.Sabdar@Sun.COM static boolean_t is_writer_running_v3(ndmpd_session_t *session); 807917SReza.Sabdar@Sun.COM static int mover_pause_v3(ndmpd_session_t *session, 817917SReza.Sabdar@Sun.COM ndmp_mover_pause_reason reason); 827917SReza.Sabdar@Sun.COM static int mover_tape_write_v3(ndmpd_session_t *session, char *data, 837917SReza.Sabdar@Sun.COM ssize_t length); 847917SReza.Sabdar@Sun.COM static int mover_tape_flush_v3(ndmpd_session_t *session); 857917SReza.Sabdar@Sun.COM static int mover_tape_read_v3(ndmpd_session_t *session, char *data); 867917SReza.Sabdar@Sun.COM static int create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, 877917SReza.Sabdar@Sun.COM ushort_t *port); 887917SReza.Sabdar@Sun.COM static void mover_data_read_v3(void *cookie, int fd, ulong_t mode); 897917SReza.Sabdar@Sun.COM static void accept_connection(void *cookie, int fd, ulong_t mode); 907917SReza.Sabdar@Sun.COM static void mover_data_write_v3(void *cookie, int fd, ulong_t mode); 917917SReza.Sabdar@Sun.COM static void accept_connection_v3(void *cookie, int fd, ulong_t mode); 927917SReza.Sabdar@Sun.COM static ndmp_error mover_connect_sock_v3(ndmpd_session_t *session, 937917SReza.Sabdar@Sun.COM ndmp_mover_mode mode, ulong_t addr, ushort_t port); 947917SReza.Sabdar@Sun.COM static boolean_t is_writer_running(ndmpd_session_t *session); 957917SReza.Sabdar@Sun.COM 967917SReza.Sabdar@Sun.COM 977917SReza.Sabdar@Sun.COM int ndmp_max_mover_recsize = MAX_MOVER_RECSIZE; /* patchable */ 987917SReza.Sabdar@Sun.COM 997917SReza.Sabdar@Sun.COM #define TAPE_READ_ERR -1 1007917SReza.Sabdar@Sun.COM #define TAPE_NO_WRITER_ERR -2 1017917SReza.Sabdar@Sun.COM 1027917SReza.Sabdar@Sun.COM #define NDMP_APILOG(s, t, m, ...) \ 1037917SReza.Sabdar@Sun.COM { \ 1047917SReza.Sabdar@Sun.COM if (((ndmpd_session_t *)(s))->ns_protocol_version == NDMPV4) \ 1057917SReza.Sabdar@Sun.COM (void) ndmpd_api_log_v4(s, t, m, __VA_ARGS__); \ 1067917SReza.Sabdar@Sun.COM else if (((ndmpd_session_t *)(s))->ns_protocol_version == NDMPV3) \ 1077917SReza.Sabdar@Sun.COM (void) ndmpd_api_log_v3(s, t, m, __VA_ARGS__); \ 1087917SReza.Sabdar@Sun.COM else \ 1097917SReza.Sabdar@Sun.COM (void) ndmpd_api_log_v2(s, __VA_ARGS__); \ 1107917SReza.Sabdar@Sun.COM } 1117917SReza.Sabdar@Sun.COM 1127917SReza.Sabdar@Sun.COM /* 1137917SReza.Sabdar@Sun.COM * ************************************************************************ 1147917SReza.Sabdar@Sun.COM * NDMP V2 HANDLERS 1157917SReza.Sabdar@Sun.COM * ************************************************************************ 1167917SReza.Sabdar@Sun.COM */ 1177917SReza.Sabdar@Sun.COM 1187917SReza.Sabdar@Sun.COM /* 1197917SReza.Sabdar@Sun.COM * ndmpd_mover_get_state_v2 1207917SReza.Sabdar@Sun.COM * 1217917SReza.Sabdar@Sun.COM * This handler handles the mover_get_state request. 1227917SReza.Sabdar@Sun.COM * Status information for the mover state machine is returned. 1237917SReza.Sabdar@Sun.COM * 1247917SReza.Sabdar@Sun.COM * Parameters: 1257917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 1267917SReza.Sabdar@Sun.COM * body (input) - request message body. 1277917SReza.Sabdar@Sun.COM * 1287917SReza.Sabdar@Sun.COM * Returns: 1297917SReza.Sabdar@Sun.COM * void 1307917SReza.Sabdar@Sun.COM */ 1317917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 1327917SReza.Sabdar@Sun.COM void 1337917SReza.Sabdar@Sun.COM ndmpd_mover_get_state_v2(ndmp_connection_t *connection, void *body) 1347917SReza.Sabdar@Sun.COM { 1357917SReza.Sabdar@Sun.COM ndmp_mover_get_state_reply_v2 reply; 1367917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 1377917SReza.Sabdar@Sun.COM 1387917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 1397917SReza.Sabdar@Sun.COM reply.state = session->ns_mover.md_state; 1407917SReza.Sabdar@Sun.COM reply.pause_reason = session->ns_mover.md_pause_reason; 1417917SReza.Sabdar@Sun.COM reply.halt_reason = session->ns_mover.md_halt_reason; 1427917SReza.Sabdar@Sun.COM reply.record_size = session->ns_mover.md_record_size; 1437917SReza.Sabdar@Sun.COM reply.record_num = session->ns_mover.md_record_num; 1447917SReza.Sabdar@Sun.COM reply.data_written = 1457917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_data_written); 1467917SReza.Sabdar@Sun.COM reply.seek_position = 1477917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_seek_position); 1487917SReza.Sabdar@Sun.COM reply.bytes_left_to_read = 1497917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 1507917SReza.Sabdar@Sun.COM reply.window_offset = 1517917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_offset); 1527917SReza.Sabdar@Sun.COM reply.window_length = 1537917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_length); 1547917SReza.Sabdar@Sun.COM 1557917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 1567917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 1577917SReza.Sabdar@Sun.COM } 1587917SReza.Sabdar@Sun.COM 1597917SReza.Sabdar@Sun.COM 1607917SReza.Sabdar@Sun.COM /* 1617917SReza.Sabdar@Sun.COM * ndmpd_mover_listen_v2 1627917SReza.Sabdar@Sun.COM * 1637917SReza.Sabdar@Sun.COM * This handler handles mover_listen requests. 1647917SReza.Sabdar@Sun.COM * 1657917SReza.Sabdar@Sun.COM * Parameters: 1667917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 1677917SReza.Sabdar@Sun.COM * body (input) - request message body. 1687917SReza.Sabdar@Sun.COM * 1697917SReza.Sabdar@Sun.COM * Returns: 1707917SReza.Sabdar@Sun.COM * void 1717917SReza.Sabdar@Sun.COM */ 1727917SReza.Sabdar@Sun.COM void 1737917SReza.Sabdar@Sun.COM ndmpd_mover_listen_v2(ndmp_connection_t *connection, void *body) 1747917SReza.Sabdar@Sun.COM { 1757917SReza.Sabdar@Sun.COM ndmp_mover_listen_request_v2 *request; 1767917SReza.Sabdar@Sun.COM ndmp_mover_listen_reply_v2 reply; 1777917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 1787917SReza.Sabdar@Sun.COM ulong_t addr; 1797917SReza.Sabdar@Sun.COM ushort_t port; 1807917SReza.Sabdar@Sun.COM 1817917SReza.Sabdar@Sun.COM request = (ndmp_mover_listen_request_v2 *)body; 1827917SReza.Sabdar@Sun.COM 1837917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE || 1847917SReza.Sabdar@Sun.COM session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 1857917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 1867917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 1877917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 1887917SReza.Sabdar@Sun.COM "sending mover_listen reply"); 1897917SReza.Sabdar@Sun.COM return; 1907917SReza.Sabdar@Sun.COM } 1917917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = request->mode; 1927917SReza.Sabdar@Sun.COM 1937917SReza.Sabdar@Sun.COM if (request->addr_type == NDMP_ADDR_LOCAL) { 1947917SReza.Sabdar@Sun.COM reply.mover.addr_type = NDMP_ADDR_LOCAL; 1957917SReza.Sabdar@Sun.COM } else { 1967917SReza.Sabdar@Sun.COM if (create_listen_socket_v2(session, &addr, &port) < 0) { 1977917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 1987917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 1997917SReza.Sabdar@Sun.COM "sending mover_listen reply"); 2007917SReza.Sabdar@Sun.COM return; 2017917SReza.Sabdar@Sun.COM } 2027917SReza.Sabdar@Sun.COM reply.mover.addr_type = NDMP_ADDR_TCP; 2037917SReza.Sabdar@Sun.COM reply.mover.ndmp_mover_addr_u.addr.ip_addr = htonl(addr); 2047917SReza.Sabdar@Sun.COM reply.mover.ndmp_mover_addr_u.addr.port = htons(port); 2057917SReza.Sabdar@Sun.COM } 2067917SReza.Sabdar@Sun.COM 2077917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 2087917SReza.Sabdar@Sun.COM 2097917SReza.Sabdar@Sun.COM /* 2107917SReza.Sabdar@Sun.COM * ndmp window should always set by client during restore 2117917SReza.Sabdar@Sun.COM */ 2127917SReza.Sabdar@Sun.COM 2137917SReza.Sabdar@Sun.COM /* Set the default window. */ 2147917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset = 0; 2157917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length = MAX_WINDOW_SIZE; 2167917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 0; 2177917SReza.Sabdar@Sun.COM 2187917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 2197917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2207917SReza.Sabdar@Sun.COM "sending mover_listen reply"); 2217917SReza.Sabdar@Sun.COM } 2227917SReza.Sabdar@Sun.COM 2237917SReza.Sabdar@Sun.COM 2247917SReza.Sabdar@Sun.COM /* 2257917SReza.Sabdar@Sun.COM * ndmpd_mover_continue_v2 2267917SReza.Sabdar@Sun.COM * 2277917SReza.Sabdar@Sun.COM * This handler handles mover_continue requests. 2287917SReza.Sabdar@Sun.COM * 2297917SReza.Sabdar@Sun.COM * Parameters: 2307917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 2317917SReza.Sabdar@Sun.COM * body (input) - request message body. 2327917SReza.Sabdar@Sun.COM * 2337917SReza.Sabdar@Sun.COM * Returns: 2347917SReza.Sabdar@Sun.COM * void 2357917SReza.Sabdar@Sun.COM */ 2367917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 2377917SReza.Sabdar@Sun.COM void 2387917SReza.Sabdar@Sun.COM ndmpd_mover_continue_v2(ndmp_connection_t *connection, void *body) 2397917SReza.Sabdar@Sun.COM { 2407917SReza.Sabdar@Sun.COM ndmp_mover_continue_reply reply; 2417917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 2427917SReza.Sabdar@Sun.COM 2437917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 2447917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 2457917SReza.Sabdar@Sun.COM 2467917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 2477917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2487917SReza.Sabdar@Sun.COM "sending mover_continue reply"); 2497917SReza.Sabdar@Sun.COM return; 2507917SReza.Sabdar@Sun.COM } 2517917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 2527917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 2537917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2547917SReza.Sabdar@Sun.COM "sending mover_continue reply"); 2557917SReza.Sabdar@Sun.COM } 2567917SReza.Sabdar@Sun.COM 2577917SReza.Sabdar@Sun.COM 2587917SReza.Sabdar@Sun.COM /* 2597917SReza.Sabdar@Sun.COM * ndmpd_mover_abort_v2 2607917SReza.Sabdar@Sun.COM * 2617917SReza.Sabdar@Sun.COM * This handler handles mover_abort requests. 2627917SReza.Sabdar@Sun.COM * 2637917SReza.Sabdar@Sun.COM * Parameters: 2647917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 2657917SReza.Sabdar@Sun.COM * body (input) - request message body. 2667917SReza.Sabdar@Sun.COM * 2677917SReza.Sabdar@Sun.COM * Returns: 2687917SReza.Sabdar@Sun.COM * void 2697917SReza.Sabdar@Sun.COM */ 2707917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 2717917SReza.Sabdar@Sun.COM void 2727917SReza.Sabdar@Sun.COM ndmpd_mover_abort_v2(ndmp_connection_t *connection, void *body) 2737917SReza.Sabdar@Sun.COM { 2747917SReza.Sabdar@Sun.COM ndmp_mover_abort_reply reply; 2757917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 2767917SReza.Sabdar@Sun.COM 2777917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 2787917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 2797917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 2807917SReza.Sabdar@Sun.COM 2817917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 2827917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2837917SReza.Sabdar@Sun.COM "sending mover_abort reply"); 2847917SReza.Sabdar@Sun.COM return; 2857917SReza.Sabdar@Sun.COM } 2867917SReza.Sabdar@Sun.COM 2877917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 2887917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2897917SReza.Sabdar@Sun.COM "sending mover_abort reply"); 2907917SReza.Sabdar@Sun.COM 2917917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_ABORTED); 2927917SReza.Sabdar@Sun.COM 2937917SReza.Sabdar@Sun.COM nlp_event_nw(session); 2947917SReza.Sabdar@Sun.COM ndmp_stop_buffer_worker(session); 2957917SReza.Sabdar@Sun.COM } 2967917SReza.Sabdar@Sun.COM 2977917SReza.Sabdar@Sun.COM 2987917SReza.Sabdar@Sun.COM /* 2997917SReza.Sabdar@Sun.COM * ndmpd_mover_stop_v2 3007917SReza.Sabdar@Sun.COM * 3017917SReza.Sabdar@Sun.COM * This handler handles mover_stop requests. 3027917SReza.Sabdar@Sun.COM * 3037917SReza.Sabdar@Sun.COM * Parameters: 3047917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 3057917SReza.Sabdar@Sun.COM * body (input) - request message body. 3067917SReza.Sabdar@Sun.COM * 3077917SReza.Sabdar@Sun.COM * Returns: 3087917SReza.Sabdar@Sun.COM * void 3097917SReza.Sabdar@Sun.COM */ 3107917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 3117917SReza.Sabdar@Sun.COM void 3127917SReza.Sabdar@Sun.COM ndmpd_mover_stop_v2(ndmp_connection_t *connection, void *body) 3137917SReza.Sabdar@Sun.COM { 3147917SReza.Sabdar@Sun.COM ndmp_mover_stop_reply reply; 3157917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 3167917SReza.Sabdar@Sun.COM 3177917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_HALTED) { 3187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 3197917SReza.Sabdar@Sun.COM 3207917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 3217917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 3227917SReza.Sabdar@Sun.COM "sending mover_stop reply"); 3237917SReza.Sabdar@Sun.COM return; 3247917SReza.Sabdar@Sun.COM } 3257917SReza.Sabdar@Sun.COM 3267917SReza.Sabdar@Sun.COM ndmp_waitfor_op(session); 3277917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 3287917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 3297917SReza.Sabdar@Sun.COM "sending mover_stop reply"); 3307917SReza.Sabdar@Sun.COM 3317917SReza.Sabdar@Sun.COM ndmp_lbr_cleanup(session); 3327917SReza.Sabdar@Sun.COM ndmpd_mover_cleanup(session); 3337917SReza.Sabdar@Sun.COM (void) ndmpd_mover_init(session); 3347917SReza.Sabdar@Sun.COM (void) ndmp_lbr_init(session); 3357917SReza.Sabdar@Sun.COM } 3367917SReza.Sabdar@Sun.COM 3377917SReza.Sabdar@Sun.COM 3387917SReza.Sabdar@Sun.COM /* 3397917SReza.Sabdar@Sun.COM * ndmpd_mover_set_window_v2 3407917SReza.Sabdar@Sun.COM * 3417917SReza.Sabdar@Sun.COM * This handler handles mover_set_window requests. 3427917SReza.Sabdar@Sun.COM * 3437917SReza.Sabdar@Sun.COM * 3447917SReza.Sabdar@Sun.COM * Parameters: 3457917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 3467917SReza.Sabdar@Sun.COM * body (input) - request message body. 3477917SReza.Sabdar@Sun.COM * 3487917SReza.Sabdar@Sun.COM * Returns: 3497917SReza.Sabdar@Sun.COM * void 3507917SReza.Sabdar@Sun.COM */ 3517917SReza.Sabdar@Sun.COM void 3527917SReza.Sabdar@Sun.COM ndmpd_mover_set_window_v2(ndmp_connection_t *connection, void *body) 3537917SReza.Sabdar@Sun.COM { 3547917SReza.Sabdar@Sun.COM ndmp_mover_set_window_request *request; 3557917SReza.Sabdar@Sun.COM ndmp_mover_set_window_reply reply; 3567917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 3577917SReza.Sabdar@Sun.COM 3587917SReza.Sabdar@Sun.COM request = (ndmp_mover_set_window_request *) body; 3597917SReza.Sabdar@Sun.COM 3607917SReza.Sabdar@Sun.COM /* 3617917SReza.Sabdar@Sun.COM * The NDMPv2 specification states that "a window can be set only 3627917SReza.Sabdar@Sun.COM * when in the listen or paused state." 3637917SReza.Sabdar@Sun.COM * 3647917SReza.Sabdar@Sun.COM * See the comment in ndmpd_mover_set_window_v3 regarding the reason for 3657917SReza.Sabdar@Sun.COM * allowing it in the idle state as well. 3667917SReza.Sabdar@Sun.COM */ 3677917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE && 3687917SReza.Sabdar@Sun.COM session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED && 3697917SReza.Sabdar@Sun.COM session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN) { 3707917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 3717917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state %d", 3727917SReza.Sabdar@Sun.COM session->ns_mover.md_state); 3737917SReza.Sabdar@Sun.COM } else { 3747917SReza.Sabdar@Sun.COM if (quad_to_long_long(request->length) == 0) { 3757917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 3767917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid window size %d", 3777917SReza.Sabdar@Sun.COM quad_to_long_long(request->length)); 3787917SReza.Sabdar@Sun.COM } else { 3797917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 3807917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset = 3817917SReza.Sabdar@Sun.COM quad_to_long_long(request->offset); 3827917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length = 3837917SReza.Sabdar@Sun.COM quad_to_long_long(request->length); 3847917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 3857917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset; 3867917SReza.Sabdar@Sun.COM } 3877917SReza.Sabdar@Sun.COM } 3887917SReza.Sabdar@Sun.COM 3897917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 3907917SReza.Sabdar@Sun.COM "sending mover_set_window reply"); 3917917SReza.Sabdar@Sun.COM } 3927917SReza.Sabdar@Sun.COM 3937917SReza.Sabdar@Sun.COM 3947917SReza.Sabdar@Sun.COM /* 3957917SReza.Sabdar@Sun.COM * ndmpd_mover_read_v2 3967917SReza.Sabdar@Sun.COM * 3977917SReza.Sabdar@Sun.COM * This handler handles mover_read requests. If the requested offset is 3987917SReza.Sabdar@Sun.COM * outside of the current window, the mover is paused and a notify_mover_paused 3997917SReza.Sabdar@Sun.COM * request is sent notifying the client that a seek is required. If the 4007917SReza.Sabdar@Sun.COM * requested offest is within the window but not within the current record, 4017917SReza.Sabdar@Sun.COM * then the tape is positioned to the record containing the requested offest. 4027917SReza.Sabdar@Sun.COM * The requested amount of data is then read from the tape device and written 4037917SReza.Sabdar@Sun.COM * to the data connection. 4047917SReza.Sabdar@Sun.COM * 4057917SReza.Sabdar@Sun.COM * Parameters: 4067917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 4077917SReza.Sabdar@Sun.COM * body (input) - request message body. 4087917SReza.Sabdar@Sun.COM * 4097917SReza.Sabdar@Sun.COM * Returns: 4107917SReza.Sabdar@Sun.COM * void 4117917SReza.Sabdar@Sun.COM */ 4127917SReza.Sabdar@Sun.COM void 4137917SReza.Sabdar@Sun.COM ndmpd_mover_read_v2(ndmp_connection_t *connection, void *body) 4147917SReza.Sabdar@Sun.COM { 4157917SReza.Sabdar@Sun.COM ndmp_mover_read_request *request = (ndmp_mover_read_request *) body; 4167917SReza.Sabdar@Sun.COM ndmp_mover_read_reply reply; 4177917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 4187917SReza.Sabdar@Sun.COM int err; 4197917SReza.Sabdar@Sun.COM 4207917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_ACTIVE || 4217917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read != 0 || 4227917SReza.Sabdar@Sun.COM session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) { 4237917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 4247917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 4257917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 4267917SReza.Sabdar@Sun.COM "sending mover_read reply"); 4277917SReza.Sabdar@Sun.COM return; 4287917SReza.Sabdar@Sun.COM } 4297917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 4307917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Tape device is not open"); 4317917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 4327917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 4337917SReza.Sabdar@Sun.COM "sending mover_read reply"); 4347917SReza.Sabdar@Sun.COM return; 4357917SReza.Sabdar@Sun.COM } 4367917SReza.Sabdar@Sun.COM 4377917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 4387917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, "sending mover_read reply"); 4397917SReza.Sabdar@Sun.COM 4407917SReza.Sabdar@Sun.COM err = ndmpd_mover_seek(session, quad_to_long_long(request->offset), 4417917SReza.Sabdar@Sun.COM quad_to_long_long(request->length)); 4427917SReza.Sabdar@Sun.COM if (err < 0) { 4437917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 4447917SReza.Sabdar@Sun.COM return; 4457917SReza.Sabdar@Sun.COM } 4467917SReza.Sabdar@Sun.COM /* 4477917SReza.Sabdar@Sun.COM * Just return if we are waiting for the NDMP client to 4487917SReza.Sabdar@Sun.COM * complete the seek. 4497917SReza.Sabdar@Sun.COM */ 4507917SReza.Sabdar@Sun.COM if (err == 1) 4517917SReza.Sabdar@Sun.COM return; 4527917SReza.Sabdar@Sun.COM 4537917SReza.Sabdar@Sun.COM /* 4547917SReza.Sabdar@Sun.COM * Start the mover for restore in the 3-way backups. 4557917SReza.Sabdar@Sun.COM */ 4567917SReza.Sabdar@Sun.COM if (start_mover_for_restore(session) < 0) 4577917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 4587917SReza.Sabdar@Sun.COM } 4597917SReza.Sabdar@Sun.COM 4607917SReza.Sabdar@Sun.COM 4617917SReza.Sabdar@Sun.COM /* 4627917SReza.Sabdar@Sun.COM * ndmpd_mover_close_v2 4637917SReza.Sabdar@Sun.COM * 4647917SReza.Sabdar@Sun.COM * This handler handles mover_close requests. 4657917SReza.Sabdar@Sun.COM * 4667917SReza.Sabdar@Sun.COM * Parameters: 4677917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 4687917SReza.Sabdar@Sun.COM * body (input) - request message body. 4697917SReza.Sabdar@Sun.COM * 4707917SReza.Sabdar@Sun.COM * Returns: 4717917SReza.Sabdar@Sun.COM * void 4727917SReza.Sabdar@Sun.COM */ 4737917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 4747917SReza.Sabdar@Sun.COM void 4757917SReza.Sabdar@Sun.COM ndmpd_mover_close_v2(ndmp_connection_t *connection, void *body) 4767917SReza.Sabdar@Sun.COM { 4777917SReza.Sabdar@Sun.COM ndmp_mover_close_reply reply; 4787917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 4797917SReza.Sabdar@Sun.COM 4807917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 4817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 4827917SReza.Sabdar@Sun.COM 4837917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 4847917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 4857917SReza.Sabdar@Sun.COM "sending mover_close reply"); 4867917SReza.Sabdar@Sun.COM return; 4877917SReza.Sabdar@Sun.COM } 4887917SReza.Sabdar@Sun.COM free(session->ns_mover.md_data_addr_v4.tcp_addr_v4); 4897917SReza.Sabdar@Sun.COM 4907917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 4917917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, "sending mover_close reply"); 4927917SReza.Sabdar@Sun.COM 4937917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 4947917SReza.Sabdar@Sun.COM } 4957917SReza.Sabdar@Sun.COM 4967917SReza.Sabdar@Sun.COM 4977917SReza.Sabdar@Sun.COM /* 4987917SReza.Sabdar@Sun.COM * ndmpd_mover_set_record_size_v2 4997917SReza.Sabdar@Sun.COM * 5007917SReza.Sabdar@Sun.COM * This handler handles mover_set_record_size requests. 5017917SReza.Sabdar@Sun.COM * 5027917SReza.Sabdar@Sun.COM * Parameters: 5037917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 5047917SReza.Sabdar@Sun.COM * body (input) - request message body. 5057917SReza.Sabdar@Sun.COM * 5067917SReza.Sabdar@Sun.COM * Returns: 5077917SReza.Sabdar@Sun.COM * void 5087917SReza.Sabdar@Sun.COM */ 5097917SReza.Sabdar@Sun.COM void 5107917SReza.Sabdar@Sun.COM ndmpd_mover_set_record_size_v2(ndmp_connection_t *connection, void *body) 5117917SReza.Sabdar@Sun.COM { 5127917SReza.Sabdar@Sun.COM ndmp_mover_set_record_size_request *request; 5137917SReza.Sabdar@Sun.COM ndmp_mover_set_record_size_reply reply; 5147917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 5157917SReza.Sabdar@Sun.COM 5167917SReza.Sabdar@Sun.COM request = (ndmp_mover_set_record_size_request *) body; 5177917SReza.Sabdar@Sun.COM 5187917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size = request->len; 5197917SReza.Sabdar@Sun.COM session->ns_mover.md_buf = realloc(session->ns_mover.md_buf, 5207917SReza.Sabdar@Sun.COM request->len); 5217917SReza.Sabdar@Sun.COM 5227917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 5237917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 5247917SReza.Sabdar@Sun.COM "sending mover_set_record_size reply"); 5257917SReza.Sabdar@Sun.COM } 5267917SReza.Sabdar@Sun.COM 5277917SReza.Sabdar@Sun.COM 5287917SReza.Sabdar@Sun.COM /* 5297917SReza.Sabdar@Sun.COM * ************************************************************************ 5307917SReza.Sabdar@Sun.COM * NDMP V3 HANDLERS 5317917SReza.Sabdar@Sun.COM * ************************************************************************ 5327917SReza.Sabdar@Sun.COM */ 5337917SReza.Sabdar@Sun.COM 5347917SReza.Sabdar@Sun.COM /* 5357917SReza.Sabdar@Sun.COM * ndmpd_mover_get_state_v3 5367917SReza.Sabdar@Sun.COM * 5377917SReza.Sabdar@Sun.COM * This handler handles the ndmp_mover_get_state_request. 5387917SReza.Sabdar@Sun.COM * Status information for the mover state machine is returned. 5397917SReza.Sabdar@Sun.COM * 5407917SReza.Sabdar@Sun.COM * Parameters: 5417917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 5427917SReza.Sabdar@Sun.COM * body (input) - request message body. 5437917SReza.Sabdar@Sun.COM * 5447917SReza.Sabdar@Sun.COM * Returns: 5457917SReza.Sabdar@Sun.COM * void 5467917SReza.Sabdar@Sun.COM */ 5477917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 5487917SReza.Sabdar@Sun.COM void 5497917SReza.Sabdar@Sun.COM ndmpd_mover_get_state_v3(ndmp_connection_t *connection, void *body) 5507917SReza.Sabdar@Sun.COM { 5517917SReza.Sabdar@Sun.COM ndmp_mover_get_state_reply_v3 reply; 5527917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 5537917SReza.Sabdar@Sun.COM 5547917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 5557917SReza.Sabdar@Sun.COM 5567917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 5577917SReza.Sabdar@Sun.COM reply.state = session->ns_mover.md_state; 5587917SReza.Sabdar@Sun.COM reply.pause_reason = session->ns_mover.md_pause_reason; 5597917SReza.Sabdar@Sun.COM reply.halt_reason = session->ns_mover.md_halt_reason; 5607917SReza.Sabdar@Sun.COM reply.record_size = session->ns_mover.md_record_size; 5617917SReza.Sabdar@Sun.COM reply.record_num = session->ns_mover.md_record_num; 5627917SReza.Sabdar@Sun.COM reply.data_written = 5637917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_data_written); 5647917SReza.Sabdar@Sun.COM reply.seek_position = 5657917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_seek_position); 5667917SReza.Sabdar@Sun.COM reply.bytes_left_to_read = 5677917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 5687917SReza.Sabdar@Sun.COM reply.window_offset = 5697917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_offset); 5707917SReza.Sabdar@Sun.COM reply.window_length = 5717917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_length); 5727917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) 5737917SReza.Sabdar@Sun.COM ndmp_copy_addr_v3(&reply.data_connection_addr, 5747917SReza.Sabdar@Sun.COM &session->ns_mover.md_data_addr); 5757917SReza.Sabdar@Sun.COM 5767917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 5777917SReza.Sabdar@Sun.COM "sending ndmp_mover_get_state reply"); 5787917SReza.Sabdar@Sun.COM } 5797917SReza.Sabdar@Sun.COM 5807917SReza.Sabdar@Sun.COM 5817917SReza.Sabdar@Sun.COM /* 5827917SReza.Sabdar@Sun.COM * ndmpd_mover_listen_v3 5837917SReza.Sabdar@Sun.COM * 5847917SReza.Sabdar@Sun.COM * This handler handles ndmp_mover_listen_requests. 5857917SReza.Sabdar@Sun.COM * A TCP/IP socket is created that is used to listen for 5867917SReza.Sabdar@Sun.COM * and accept data connections initiated by a remote 5877917SReza.Sabdar@Sun.COM * data server. 5887917SReza.Sabdar@Sun.COM * 5897917SReza.Sabdar@Sun.COM * Parameters: 5907917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 5917917SReza.Sabdar@Sun.COM * body (input) - request message body. 5927917SReza.Sabdar@Sun.COM * 5937917SReza.Sabdar@Sun.COM * Returns: 5947917SReza.Sabdar@Sun.COM * void 5957917SReza.Sabdar@Sun.COM */ 5967917SReza.Sabdar@Sun.COM void 5977917SReza.Sabdar@Sun.COM ndmpd_mover_listen_v3(ndmp_connection_t *connection, void *body) 5987917SReza.Sabdar@Sun.COM { 5997917SReza.Sabdar@Sun.COM ndmp_mover_listen_request_v3 *request; 6007917SReza.Sabdar@Sun.COM ndmp_mover_listen_reply_v3 reply; 6017917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 6027917SReza.Sabdar@Sun.COM ulong_t addr; 6037917SReza.Sabdar@Sun.COM ushort_t port; 6047917SReza.Sabdar@Sun.COM 6057917SReza.Sabdar@Sun.COM request = (ndmp_mover_listen_request_v3 *)body; 6067917SReza.Sabdar@Sun.COM 6077917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 6087917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 6097917SReza.Sabdar@Sun.COM 6107917SReza.Sabdar@Sun.COM if (request->mode != NDMP_MOVER_MODE_READ && 6117917SReza.Sabdar@Sun.COM request->mode != NDMP_MOVER_MODE_WRITE) { 6127917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 6137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 6147917SReza.Sabdar@Sun.COM } else if (!ndmp_valid_v3addr_type(request->addr_type)) { 6157917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 6167917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 6177917SReza.Sabdar@Sun.COM request->addr_type); 6187917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 6197917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 6207917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 6217917SReza.Sabdar@Sun.COM "Invalid mover state to process listen request"); 6227917SReza.Sabdar@Sun.COM } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 6237917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 6247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 6257917SReza.Sabdar@Sun.COM "Invalid data state to process listen request"); 6267917SReza.Sabdar@Sun.COM } else if (session->ns_tape.td_fd == -1) { 6277917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 6287917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "No tape device open"); 6297917SReza.Sabdar@Sun.COM } else if (request->mode == NDMP_MOVER_MODE_READ && 6307917SReza.Sabdar@Sun.COM session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 6317917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 6327917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Write protected device."); 6337917SReza.Sabdar@Sun.COM } 6347917SReza.Sabdar@Sun.COM 6357917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) { 6367917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 6377917SReza.Sabdar@Sun.COM "error sending ndmp_mover_listen reply"); 6387917SReza.Sabdar@Sun.COM return; 6397917SReza.Sabdar@Sun.COM } 6407917SReza.Sabdar@Sun.COM 6417917SReza.Sabdar@Sun.COM switch (request->addr_type) { 6427917SReza.Sabdar@Sun.COM case NDMP_ADDR_LOCAL: 6437917SReza.Sabdar@Sun.COM reply.data_connection_addr.addr_type = NDMP_ADDR_LOCAL; 6447917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_LOCAL; 6457917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 6467917SReza.Sabdar@Sun.COM break; 6477917SReza.Sabdar@Sun.COM case NDMP_ADDR_TCP: 6487917SReza.Sabdar@Sun.COM if (create_listen_socket_v3(session, &addr, &port) < 0) { 6497917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 6507917SReza.Sabdar@Sun.COM break; 6517917SReza.Sabdar@Sun.COM } 6527917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 6537917SReza.Sabdar@Sun.COM reply.data_connection_addr.addr_type = NDMP_ADDR_TCP; 6547917SReza.Sabdar@Sun.COM reply.data_connection_addr.tcp_ip_v3 = htonl(addr); 6557917SReza.Sabdar@Sun.COM reply.data_connection_addr.tcp_port_v3 = htons(port); 6567917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 6577917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_ip_v3 = addr; 6587917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(port); 6597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "listen_socket: %d", 6607917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock); 6617917SReza.Sabdar@Sun.COM break; 6627917SReza.Sabdar@Sun.COM default: 6637917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 6647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type: %d", 6657917SReza.Sabdar@Sun.COM request->addr_type); 6667917SReza.Sabdar@Sun.COM } 6677917SReza.Sabdar@Sun.COM 6687917SReza.Sabdar@Sun.COM if (reply.error == NDMP_NO_ERR) { 6697917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = request->mode; 6707917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 6717917SReza.Sabdar@Sun.COM } 6727917SReza.Sabdar@Sun.COM 6737917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 6747917SReza.Sabdar@Sun.COM "error sending ndmp_mover_listen reply"); 6757917SReza.Sabdar@Sun.COM } 6767917SReza.Sabdar@Sun.COM 6777917SReza.Sabdar@Sun.COM 6787917SReza.Sabdar@Sun.COM /* 6797917SReza.Sabdar@Sun.COM * ndmpd_mover_continue_v3 6807917SReza.Sabdar@Sun.COM * 6817917SReza.Sabdar@Sun.COM * This handler handles ndmp_mover_continue_requests. 6827917SReza.Sabdar@Sun.COM * 6837917SReza.Sabdar@Sun.COM * Parameters: 6847917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 6857917SReza.Sabdar@Sun.COM * body (input) - request message body. 6867917SReza.Sabdar@Sun.COM * 6877917SReza.Sabdar@Sun.COM * Returns: 6887917SReza.Sabdar@Sun.COM * void 6897917SReza.Sabdar@Sun.COM */ 6907917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 6917917SReza.Sabdar@Sun.COM void 6927917SReza.Sabdar@Sun.COM ndmpd_mover_continue_v3(ndmp_connection_t *connection, void *body) 6937917SReza.Sabdar@Sun.COM { 6947917SReza.Sabdar@Sun.COM ndmp_mover_continue_reply reply; 6957917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 6967917SReza.Sabdar@Sun.COM int ret; 6977917SReza.Sabdar@Sun.COM 6987917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 6997917SReza.Sabdar@Sun.COM 7007917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 7017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 7027917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 7037917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7047917SReza.Sabdar@Sun.COM "sending mover_continue reply"); 7057917SReza.Sabdar@Sun.COM return; 7067917SReza.Sabdar@Sun.COM } 7077917SReza.Sabdar@Sun.COM 7087917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4 && 7097917SReza.Sabdar@Sun.COM !session->ns_mover.md_pre_cond) { 7107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Precondition check"); 7117917SReza.Sabdar@Sun.COM reply.error = NDMP_PRECONDITION_ERR; 7127917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7137917SReza.Sabdar@Sun.COM "sending mover_continue reply"); 7147917SReza.Sabdar@Sun.COM return; 7157917SReza.Sabdar@Sun.COM } 7167917SReza.Sabdar@Sun.COM /* 7177917SReza.Sabdar@Sun.COM * Restore the file handler if the mover is remote to the data 7187917SReza.Sabdar@Sun.COM * server and the handler was removed pending the continuation of a 7197917SReza.Sabdar@Sun.COM * seek request. The handler is removed in mover_data_write(). 7207917SReza.Sabdar@Sun.COM */ 7217917SReza.Sabdar@Sun.COM if (session->ns_mover.md_pause_reason == NDMP_MOVER_PAUSE_SEEK && 7227917SReza.Sabdar@Sun.COM session->ns_mover.md_sock != -1) { 7237917SReza.Sabdar@Sun.COM /* 7247917SReza.Sabdar@Sun.COM * If we are here, it means that we needed DMA interference 7257917SReza.Sabdar@Sun.COM * for seek. We should be on the right window, so we do not 7267917SReza.Sabdar@Sun.COM * need the DMA interference anymore. 7277917SReza.Sabdar@Sun.COM * We do another seek inside the Window to move to the 7287917SReza.Sabdar@Sun.COM * exact position on the tape. 7297917SReza.Sabdar@Sun.COM * If the resore is running without DAR the pause reason should 7307917SReza.Sabdar@Sun.COM * not be seek. 7317917SReza.Sabdar@Sun.COM */ 7327917SReza.Sabdar@Sun.COM ret = ndmpd_mover_seek(session, 7337917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position, 7347917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read); 7357917SReza.Sabdar@Sun.COM if (ret < 0) { 7367917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 7377917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 7387917SReza.Sabdar@Sun.COM return; 7397917SReza.Sabdar@Sun.COM } 7407917SReza.Sabdar@Sun.COM 7417917SReza.Sabdar@Sun.COM if (!ret) { 7427917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void*) session, 7437917SReza.Sabdar@Sun.COM session->ns_mover.md_sock, NDMPD_SELECT_MODE_WRITE, 7447917SReza.Sabdar@Sun.COM HC_MOVER, mover_data_write_v3) < 0) 7457917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 7467917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 7477917SReza.Sabdar@Sun.COM } else { 7487917SReza.Sabdar@Sun.COM /* 7497917SReza.Sabdar@Sun.COM * This should not happen because we should be in the 7507917SReza.Sabdar@Sun.COM * right window. This means that DMA does not follow 7517917SReza.Sabdar@Sun.COM * the V3 spec. 7527917SReza.Sabdar@Sun.COM */ 7537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "DMA Error."); 7547917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 7557917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 7567917SReza.Sabdar@Sun.COM return; 7577917SReza.Sabdar@Sun.COM } 7587917SReza.Sabdar@Sun.COM } 7597917SReza.Sabdar@Sun.COM 7607917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 7617917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_NA; 7627917SReza.Sabdar@Sun.COM 7637917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 7647917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7657917SReza.Sabdar@Sun.COM "sending mover_continue reply"); 7667917SReza.Sabdar@Sun.COM } 7677917SReza.Sabdar@Sun.COM 7687917SReza.Sabdar@Sun.COM 7697917SReza.Sabdar@Sun.COM /* 7707917SReza.Sabdar@Sun.COM * ndmpd_mover_abort_v3 7717917SReza.Sabdar@Sun.COM * 7727917SReza.Sabdar@Sun.COM * This handler handles mover_abort requests. 7737917SReza.Sabdar@Sun.COM * 7747917SReza.Sabdar@Sun.COM * Parameters: 7757917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 7767917SReza.Sabdar@Sun.COM * body (input) - request message body. 7777917SReza.Sabdar@Sun.COM * 7787917SReza.Sabdar@Sun.COM * Returns: 7797917SReza.Sabdar@Sun.COM * void 7807917SReza.Sabdar@Sun.COM */ 7817917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 7827917SReza.Sabdar@Sun.COM void 7837917SReza.Sabdar@Sun.COM ndmpd_mover_abort_v3(ndmp_connection_t *connection, void *body) 7847917SReza.Sabdar@Sun.COM { 7857917SReza.Sabdar@Sun.COM ndmp_mover_abort_reply reply; 7867917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 7877917SReza.Sabdar@Sun.COM 7887917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 7897917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 7907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 7917917SReza.Sabdar@Sun.COM 7927917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 7937917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7947917SReza.Sabdar@Sun.COM "sending mover_abort reply"); 7957917SReza.Sabdar@Sun.COM return; 7967917SReza.Sabdar@Sun.COM } 7977917SReza.Sabdar@Sun.COM 7987917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 7997917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8007917SReza.Sabdar@Sun.COM "sending mover_abort reply"); 8017917SReza.Sabdar@Sun.COM 8027917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_ABORTED); 8037917SReza.Sabdar@Sun.COM } 8047917SReza.Sabdar@Sun.COM 8057917SReza.Sabdar@Sun.COM 8067917SReza.Sabdar@Sun.COM /* 8077917SReza.Sabdar@Sun.COM * ndmpd_mover_set_window_v3 8087917SReza.Sabdar@Sun.COM * 8097917SReza.Sabdar@Sun.COM * This handler handles mover_set_window requests. 8107917SReza.Sabdar@Sun.COM * 8117917SReza.Sabdar@Sun.COM * 8127917SReza.Sabdar@Sun.COM * Parameters: 8137917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 8147917SReza.Sabdar@Sun.COM * body (input) - request message body. 8157917SReza.Sabdar@Sun.COM * 8167917SReza.Sabdar@Sun.COM * Returns: 8177917SReza.Sabdar@Sun.COM * void 8187917SReza.Sabdar@Sun.COM */ 8197917SReza.Sabdar@Sun.COM void 8207917SReza.Sabdar@Sun.COM ndmpd_mover_set_window_v3(ndmp_connection_t *connection, void *body) 8217917SReza.Sabdar@Sun.COM { 8227917SReza.Sabdar@Sun.COM ndmp_mover_set_window_request *request; 8237917SReza.Sabdar@Sun.COM ndmp_mover_set_window_reply reply; 8247917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 8257917SReza.Sabdar@Sun.COM 8267917SReza.Sabdar@Sun.COM request = (ndmp_mover_set_window_request *) body; 8277917SReza.Sabdar@Sun.COM 8287917SReza.Sabdar@Sun.COM /* 8297917SReza.Sabdar@Sun.COM * Note: The spec says that the window can be set only in the listen 8307917SReza.Sabdar@Sun.COM * and paused states. We let this happen when mover is in the idle 8317917SReza.Sabdar@Sun.COM * state as well. I can't rememebr which NDMP client (net_backup 4.5 8327917SReza.Sabdar@Sun.COM * or net_worker 6.1.1) forced us to do this! 8337917SReza.Sabdar@Sun.COM */ 8347917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE && 8357917SReza.Sabdar@Sun.COM session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN && 8367917SReza.Sabdar@Sun.COM session->ns_mover.md_state != NDMP_MOVER_STATE_PAUSED) { 8377917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 8387917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state %d", 8397917SReza.Sabdar@Sun.COM session->ns_mover.md_state); 8407917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_record_size == 0) { 8417917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4) 8427917SReza.Sabdar@Sun.COM reply.error = NDMP_PRECONDITION_ERR; 8437917SReza.Sabdar@Sun.COM else 8447917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 8457917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 8467917SReza.Sabdar@Sun.COM } else 8477917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 8487917SReza.Sabdar@Sun.COM 8497917SReza.Sabdar@Sun.COM if (quad_to_long_long(request->length) == 0) { 8507917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 8517917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid window size %d", 8527917SReza.Sabdar@Sun.COM quad_to_long_long(request->length)); 8537917SReza.Sabdar@Sun.COM } 8547917SReza.Sabdar@Sun.COM 8557917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) { 8567917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8577917SReza.Sabdar@Sun.COM "sending mover_set_window_v3 reply"); 8587917SReza.Sabdar@Sun.COM return; 8597917SReza.Sabdar@Sun.COM } 8607917SReza.Sabdar@Sun.COM 8617917SReza.Sabdar@Sun.COM session->ns_mover.md_pre_cond = TRUE; 8627917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset = quad_to_long_long(request->offset); 8637917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length = quad_to_long_long(request->length); 8647917SReza.Sabdar@Sun.COM 8657917SReza.Sabdar@Sun.COM /* 8667917SReza.Sabdar@Sun.COM * We have to update the position for DAR. DAR needs this 8677917SReza.Sabdar@Sun.COM * information to position to the right index on tape, 8687917SReza.Sabdar@Sun.COM * especially when we span the tapes. 8697917SReza.Sabdar@Sun.COM */ 8707917SReza.Sabdar@Sun.COM #ifdef NO_POSITION_CHANGE 8717917SReza.Sabdar@Sun.COM /* 8727917SReza.Sabdar@Sun.COM * Do not change the mover position if we are reading from 8737917SReza.Sabdar@Sun.COM * the tape. In this way, we can use the position+window_length 8747917SReza.Sabdar@Sun.COM * to know how much we can write to a tape before pausing with 8757917SReza.Sabdar@Sun.COM * EOW reason. 8767917SReza.Sabdar@Sun.COM */ 8777917SReza.Sabdar@Sun.COM if (session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) 8787917SReza.Sabdar@Sun.COM #endif /* NO_POSITION_CHANGE */ 8797917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 8807917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset; 8817917SReza.Sabdar@Sun.COM 8827917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8837917SReza.Sabdar@Sun.COM "sending mover_set_window_v3 reply"); 8847917SReza.Sabdar@Sun.COM } 8857917SReza.Sabdar@Sun.COM 8867917SReza.Sabdar@Sun.COM 8877917SReza.Sabdar@Sun.COM /* 8887917SReza.Sabdar@Sun.COM * ndmpd_mover_read_v3 8897917SReza.Sabdar@Sun.COM * 8907917SReza.Sabdar@Sun.COM * This handler handles ndmp_mover_read_requests. 8917917SReza.Sabdar@Sun.COM * If the requested offset is outside of the current window, the mover 8927917SReza.Sabdar@Sun.COM * is paused and a notify_mover_paused request is sent notifying the 8937917SReza.Sabdar@Sun.COM * client that a seek is required. If the requested offest is within 8947917SReza.Sabdar@Sun.COM * the window but not within the current record, then the tape is 8957917SReza.Sabdar@Sun.COM * positioned to the record containing the requested offest. The requested 8967917SReza.Sabdar@Sun.COM * amount of data is then read from the tape device and written to the 8977917SReza.Sabdar@Sun.COM * data connection. 8987917SReza.Sabdar@Sun.COM * 8997917SReza.Sabdar@Sun.COM * Parameters: 9007917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 9017917SReza.Sabdar@Sun.COM * body (input) - request message body. 9027917SReza.Sabdar@Sun.COM * 9037917SReza.Sabdar@Sun.COM * Returns: 9047917SReza.Sabdar@Sun.COM * void 9057917SReza.Sabdar@Sun.COM */ 9067917SReza.Sabdar@Sun.COM void 9077917SReza.Sabdar@Sun.COM ndmpd_mover_read_v3(ndmp_connection_t *connection, void *body) 9087917SReza.Sabdar@Sun.COM { 9097917SReza.Sabdar@Sun.COM ndmp_mover_read_request *request = (ndmp_mover_read_request *)body; 9107917SReza.Sabdar@Sun.COM ndmp_mover_read_reply reply; 9117917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 9127917SReza.Sabdar@Sun.COM int err; 9137917SReza.Sabdar@Sun.COM 9147917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 9157917SReza.Sabdar@Sun.COM 9167917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_ACTIVE || 9177917SReza.Sabdar@Sun.COM session->ns_mover.md_mode != NDMP_MOVER_MODE_WRITE) { 9187917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 9197917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state"); 9207917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_bytes_left_to_read != 0) { 9217917SReza.Sabdar@Sun.COM reply.error = NDMP_READ_IN_PROGRESS_ERR; 9227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "In progress"); 9237917SReza.Sabdar@Sun.COM } else if (session->ns_tape.td_fd == -1) { 9247917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 9257917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Tape device is not open"); 9267917SReza.Sabdar@Sun.COM } else if (quad_to_long_long(request->length) == 0 || 9277917SReza.Sabdar@Sun.COM (quad_to_long_long(request->length) == MAX_WINDOW_SIZE && 9287917SReza.Sabdar@Sun.COM quad_to_long_long(request->offset) != 0)) { 9297917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 9307917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Illegal args"); 9317917SReza.Sabdar@Sun.COM } else { 9327917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 9337917SReza.Sabdar@Sun.COM } 9347917SReza.Sabdar@Sun.COM 9357917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 9367917SReza.Sabdar@Sun.COM "sending ndmp_mover_read_reply"); 9377917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) 9387917SReza.Sabdar@Sun.COM return; 9397917SReza.Sabdar@Sun.COM 9407917SReza.Sabdar@Sun.COM err = ndmpd_mover_seek(session, quad_to_long_long(request->offset), 9417917SReza.Sabdar@Sun.COM quad_to_long_long(request->length)); 9427917SReza.Sabdar@Sun.COM if (err < 0) { 9437917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 9447917SReza.Sabdar@Sun.COM return; 9457917SReza.Sabdar@Sun.COM } 9467917SReza.Sabdar@Sun.COM 9477917SReza.Sabdar@Sun.COM /* 9487917SReza.Sabdar@Sun.COM * Just return if we are waiting for the DMA to complete the seek. 9497917SReza.Sabdar@Sun.COM */ 9507917SReza.Sabdar@Sun.COM if (err == 1) 9517917SReza.Sabdar@Sun.COM return; 9527917SReza.Sabdar@Sun.COM 9537917SReza.Sabdar@Sun.COM /* 9547917SReza.Sabdar@Sun.COM * Setup a handler function that will be called when 9557917SReza.Sabdar@Sun.COM * data can be written to the data connection without blocking. 9567917SReza.Sabdar@Sun.COM */ 9577917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void*)session, 9587917SReza.Sabdar@Sun.COM session->ns_mover.md_sock, NDMPD_SELECT_MODE_WRITE, HC_MOVER, 9597917SReza.Sabdar@Sun.COM mover_data_write_v3) < 0) { 9607917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 9617917SReza.Sabdar@Sun.COM return; 9627917SReza.Sabdar@Sun.COM } 9637917SReza.Sabdar@Sun.COM } 9647917SReza.Sabdar@Sun.COM 9657917SReza.Sabdar@Sun.COM 9667917SReza.Sabdar@Sun.COM /* 9677917SReza.Sabdar@Sun.COM * ndmpd_mover_set_record_size_v3 9687917SReza.Sabdar@Sun.COM * 9697917SReza.Sabdar@Sun.COM * This handler handles mover_set_record_size requests. 9707917SReza.Sabdar@Sun.COM * 9717917SReza.Sabdar@Sun.COM * Parameters: 9727917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 9737917SReza.Sabdar@Sun.COM * body (input) - request message body. 9747917SReza.Sabdar@Sun.COM * 9757917SReza.Sabdar@Sun.COM * Returns: 9767917SReza.Sabdar@Sun.COM * void 9777917SReza.Sabdar@Sun.COM */ 9787917SReza.Sabdar@Sun.COM void 9797917SReza.Sabdar@Sun.COM ndmpd_mover_set_record_size_v3(ndmp_connection_t *connection, void *body) 9807917SReza.Sabdar@Sun.COM { 9817917SReza.Sabdar@Sun.COM ndmp_mover_set_record_size_request *request; 9827917SReza.Sabdar@Sun.COM ndmp_mover_set_record_size_reply reply; 9837917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 9847917SReza.Sabdar@Sun.COM char *cp; 9857917SReza.Sabdar@Sun.COM 9867917SReza.Sabdar@Sun.COM request = (ndmp_mover_set_record_size_request *) body; 9877917SReza.Sabdar@Sun.COM 9887917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 9897917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 9907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mover state %d", 9917917SReza.Sabdar@Sun.COM session->ns_mover.md_state); 9927917SReza.Sabdar@Sun.COM } else if (request->len > (unsigned int)ndmp_max_mover_recsize) { 9937917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 9947917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 9957917SReza.Sabdar@Sun.COM "Invalid argument %d, should be > 0 and <= %d", 9967917SReza.Sabdar@Sun.COM request->len, ndmp_max_mover_recsize); 9977917SReza.Sabdar@Sun.COM } else if (request->len == session->ns_mover.md_record_size) 9987917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 9997917SReza.Sabdar@Sun.COM else if (!(cp = realloc(session->ns_mover.md_buf, request->len))) { 10007917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_MEM_ERR; 10017917SReza.Sabdar@Sun.COM } else { 10027917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 10037917SReza.Sabdar@Sun.COM session->ns_mover.md_buf = cp; 10047917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size = request->len; 10057917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset = 0; 10067917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length = 0; 10077917SReza.Sabdar@Sun.COM } 10087917SReza.Sabdar@Sun.COM 10097917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 10107917SReza.Sabdar@Sun.COM "sending mover_set_record_size reply"); 10117917SReza.Sabdar@Sun.COM } 10127917SReza.Sabdar@Sun.COM 10137917SReza.Sabdar@Sun.COM 10147917SReza.Sabdar@Sun.COM /* 10157917SReza.Sabdar@Sun.COM * ndmpd_mover_connect_v3 10167917SReza.Sabdar@Sun.COM * Request handler. Connects the mover to either a local 10177917SReza.Sabdar@Sun.COM * or remote data server. 10187917SReza.Sabdar@Sun.COM * 10197917SReza.Sabdar@Sun.COM * Parameters: 10207917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 10217917SReza.Sabdar@Sun.COM * body (input) - request message body. 10227917SReza.Sabdar@Sun.COM * 10237917SReza.Sabdar@Sun.COM * Returns: 10247917SReza.Sabdar@Sun.COM * void 10257917SReza.Sabdar@Sun.COM */ 10267917SReza.Sabdar@Sun.COM void 10277917SReza.Sabdar@Sun.COM ndmpd_mover_connect_v3(ndmp_connection_t *connection, void *body) 10287917SReza.Sabdar@Sun.COM { 10297917SReza.Sabdar@Sun.COM ndmp_mover_connect_request_v3 *request; 10307917SReza.Sabdar@Sun.COM ndmp_mover_connect_reply_v3 reply; 10317917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 10327917SReza.Sabdar@Sun.COM 10337917SReza.Sabdar@Sun.COM request = (ndmp_mover_connect_request_v3*)body; 10347917SReza.Sabdar@Sun.COM 10357917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 10367917SReza.Sabdar@Sun.COM 10377917SReza.Sabdar@Sun.COM if (request->mode != NDMP_MOVER_MODE_READ && 10387917SReza.Sabdar@Sun.COM request->mode != NDMP_MOVER_MODE_WRITE) { 10397917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 10407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 10417917SReza.Sabdar@Sun.COM } else if (!ndmp_valid_v3addr_type(request->addr.addr_type)) { 10427917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 10437917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 10447917SReza.Sabdar@Sun.COM request->addr.addr_type); 10457917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 10467917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 10477917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state %d: mover is not idle", 10487917SReza.Sabdar@Sun.COM session->ns_mover.md_state); 10497917SReza.Sabdar@Sun.COM } else if (session->ns_tape.td_fd == -1) { 10507917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 10517917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "No tape device open"); 10527917SReza.Sabdar@Sun.COM } else if (request->mode == NDMP_MOVER_MODE_READ && 10537917SReza.Sabdar@Sun.COM session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 10547917SReza.Sabdar@Sun.COM reply.error = NDMP_WRITE_PROTECT_ERR; 10557917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Write protected device."); 10567917SReza.Sabdar@Sun.COM } else 10577917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 10587917SReza.Sabdar@Sun.COM 10597917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) { 10607917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 10617917SReza.Sabdar@Sun.COM "sending ndmp_mover_connect reply"); 10627917SReza.Sabdar@Sun.COM return; 10637917SReza.Sabdar@Sun.COM } 10647917SReza.Sabdar@Sun.COM 10657917SReza.Sabdar@Sun.COM switch (request->addr.addr_type) { 10667917SReza.Sabdar@Sun.COM case NDMP_ADDR_LOCAL: 10677917SReza.Sabdar@Sun.COM /* 10687917SReza.Sabdar@Sun.COM * Verify that the data server is listening for a 10697917SReza.Sabdar@Sun.COM * local connection. 10707917SReza.Sabdar@Sun.COM */ 10717917SReza.Sabdar@Sun.COM if (session->ns_data.dd_state != NDMP_DATA_STATE_LISTEN || 10727917SReza.Sabdar@Sun.COM session->ns_data.dd_listen_sock != -1) { 10737917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10747917SReza.Sabdar@Sun.COM "Data server is not in local listen state"); 10757917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 10767917SReza.Sabdar@Sun.COM } else 10777917SReza.Sabdar@Sun.COM session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED; 10787917SReza.Sabdar@Sun.COM break; 10797917SReza.Sabdar@Sun.COM 10807917SReza.Sabdar@Sun.COM case NDMP_ADDR_TCP: 10817917SReza.Sabdar@Sun.COM reply.error = mover_connect_sock_v3(session, request->mode, 10827917SReza.Sabdar@Sun.COM request->addr.tcp_ip_v3, request->addr.tcp_port_v3); 10837917SReza.Sabdar@Sun.COM break; 10847917SReza.Sabdar@Sun.COM 10857917SReza.Sabdar@Sun.COM default: 10867917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 10877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 10887917SReza.Sabdar@Sun.COM request->addr.addr_type); 10897917SReza.Sabdar@Sun.COM } 10907917SReza.Sabdar@Sun.COM 10917917SReza.Sabdar@Sun.COM if (reply.error == NDMP_NO_ERR) { 10927917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = 10937917SReza.Sabdar@Sun.COM request->addr.addr_type; 10947917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 10957917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = request->mode; 10967917SReza.Sabdar@Sun.COM } 10977917SReza.Sabdar@Sun.COM 10987917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 10997917SReza.Sabdar@Sun.COM "sending ndmp_mover_connect reply"); 11007917SReza.Sabdar@Sun.COM } 11017917SReza.Sabdar@Sun.COM 11027917SReza.Sabdar@Sun.COM 11037917SReza.Sabdar@Sun.COM /* 11047917SReza.Sabdar@Sun.COM * ************************************************************************ 11057917SReza.Sabdar@Sun.COM * NDMP V4 HANDLERS 11067917SReza.Sabdar@Sun.COM * ************************************************************************ 11077917SReza.Sabdar@Sun.COM */ 11087917SReza.Sabdar@Sun.COM 11097917SReza.Sabdar@Sun.COM /* 11107917SReza.Sabdar@Sun.COM * ndmpd_mover_get_state_v4 11117917SReza.Sabdar@Sun.COM * 11127917SReza.Sabdar@Sun.COM * This handler handles the ndmp_mover_get_state_request. 11137917SReza.Sabdar@Sun.COM * Status information for the mover state machine is returned. 11147917SReza.Sabdar@Sun.COM * 11157917SReza.Sabdar@Sun.COM * Parameters: 11167917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 11177917SReza.Sabdar@Sun.COM * body (input) - request message body. 11187917SReza.Sabdar@Sun.COM * 11197917SReza.Sabdar@Sun.COM * Returns: 11207917SReza.Sabdar@Sun.COM * void 11217917SReza.Sabdar@Sun.COM */ 11227917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 11237917SReza.Sabdar@Sun.COM void 11247917SReza.Sabdar@Sun.COM ndmpd_mover_get_state_v4(ndmp_connection_t *connection, void *body) 11257917SReza.Sabdar@Sun.COM { 11267917SReza.Sabdar@Sun.COM ndmp_mover_get_state_reply_v4 reply; 11277917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 11287917SReza.Sabdar@Sun.COM 11297917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 11307917SReza.Sabdar@Sun.COM 11317917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 11327917SReza.Sabdar@Sun.COM reply.state = session->ns_mover.md_state; 11337917SReza.Sabdar@Sun.COM reply.mode = session->ns_mover.md_mode; 11347917SReza.Sabdar@Sun.COM reply.pause_reason = session->ns_mover.md_pause_reason; 11357917SReza.Sabdar@Sun.COM reply.halt_reason = session->ns_mover.md_halt_reason; 11367917SReza.Sabdar@Sun.COM reply.record_size = session->ns_mover.md_record_size; 11377917SReza.Sabdar@Sun.COM reply.record_num = session->ns_mover.md_record_num; 11387917SReza.Sabdar@Sun.COM reply.bytes_moved = 11397917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_data_written); 11407917SReza.Sabdar@Sun.COM reply.seek_position = 11417917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_seek_position); 11427917SReza.Sabdar@Sun.COM reply.bytes_left_to_read = 11437917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_bytes_left_to_read); 11447917SReza.Sabdar@Sun.COM reply.window_offset = 11457917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_offset); 11467917SReza.Sabdar@Sun.COM reply.window_length = 11477917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_window_length); 11487917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) 11497917SReza.Sabdar@Sun.COM ndmp_copy_addr_v4(&reply.data_connection_addr, 11507917SReza.Sabdar@Sun.COM &session->ns_mover.md_data_addr_v4); 11517917SReza.Sabdar@Sun.COM 11527917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 11537917SReza.Sabdar@Sun.COM "sending ndmp_mover_get_state reply"); 11547917SReza.Sabdar@Sun.COM free(reply.data_connection_addr.tcp_addr_v4); 11557917SReza.Sabdar@Sun.COM } 11567917SReza.Sabdar@Sun.COM 11577917SReza.Sabdar@Sun.COM 11587917SReza.Sabdar@Sun.COM /* 11597917SReza.Sabdar@Sun.COM * ndmpd_mover_listen_v4 11607917SReza.Sabdar@Sun.COM * 11617917SReza.Sabdar@Sun.COM * This handler handles ndmp_mover_listen_requests. 11627917SReza.Sabdar@Sun.COM * A TCP/IP socket is created that is used to listen for 11637917SReza.Sabdar@Sun.COM * and accept data connections initiated by a remote 11647917SReza.Sabdar@Sun.COM * data server. 11657917SReza.Sabdar@Sun.COM * 11667917SReza.Sabdar@Sun.COM * Parameters: 11677917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 11687917SReza.Sabdar@Sun.COM * body (input) - request message body. 11697917SReza.Sabdar@Sun.COM * 11707917SReza.Sabdar@Sun.COM * Returns: 11717917SReza.Sabdar@Sun.COM * void 11727917SReza.Sabdar@Sun.COM */ 11737917SReza.Sabdar@Sun.COM void 11747917SReza.Sabdar@Sun.COM ndmpd_mover_listen_v4(ndmp_connection_t *connection, void *body) 11757917SReza.Sabdar@Sun.COM { 11767917SReza.Sabdar@Sun.COM ndmp_mover_listen_request_v4 *request; 11777917SReza.Sabdar@Sun.COM 11787917SReza.Sabdar@Sun.COM ndmp_mover_listen_reply_v4 reply; 11797917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 11807917SReza.Sabdar@Sun.COM ulong_t addr; 11817917SReza.Sabdar@Sun.COM ushort_t port; 11827917SReza.Sabdar@Sun.COM 11837917SReza.Sabdar@Sun.COM request = (ndmp_mover_listen_request_v4 *)body; 11847917SReza.Sabdar@Sun.COM 11857917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 11867917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 11877917SReza.Sabdar@Sun.COM 11887917SReza.Sabdar@Sun.COM if (request->mode != NDMP_MOVER_MODE_READ && 11897917SReza.Sabdar@Sun.COM request->mode != NDMP_MOVER_MODE_WRITE) { 11907917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 11917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 11927917SReza.Sabdar@Sun.COM } else if (!ndmp_valid_v3addr_type(request->addr_type)) { 11937917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 11947917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 11957917SReza.Sabdar@Sun.COM request->addr_type); 11967917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 11977917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 11987917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 11997917SReza.Sabdar@Sun.COM "Invalid mover state to process listen request"); 12007917SReza.Sabdar@Sun.COM } else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) { 12017917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 12027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 12037917SReza.Sabdar@Sun.COM "Invalid data state to process listen request"); 12047917SReza.Sabdar@Sun.COM } else if (session->ns_tape.td_fd == -1) { 12057917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 12067917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "No tape device open"); 12077917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_record_size == 0) { 12087917SReza.Sabdar@Sun.COM reply.error = NDMP_PRECONDITION_ERR; 12097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 12107917SReza.Sabdar@Sun.COM } else if (request->mode == NDMP_MOVER_MODE_READ && 12117917SReza.Sabdar@Sun.COM session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 12127917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 12137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Write protected device."); 12147917SReza.Sabdar@Sun.COM } 12157917SReza.Sabdar@Sun.COM 12167917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) { 12177917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 12187917SReza.Sabdar@Sun.COM "error sending ndmp_mover_listen reply"); 12197917SReza.Sabdar@Sun.COM return; 12207917SReza.Sabdar@Sun.COM } 12217917SReza.Sabdar@Sun.COM 12227917SReza.Sabdar@Sun.COM switch (request->addr_type) { 12237917SReza.Sabdar@Sun.COM case NDMP_ADDR_LOCAL: 12247917SReza.Sabdar@Sun.COM reply.connect_addr.addr_type = NDMP_ADDR_LOCAL; 12257917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_LOCAL; 12267917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 12277917SReza.Sabdar@Sun.COM break; 12287917SReza.Sabdar@Sun.COM case NDMP_ADDR_TCP: 12297917SReza.Sabdar@Sun.COM if (create_listen_socket_v3(session, &addr, &port) < 0) { 12307917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 12317917SReza.Sabdar@Sun.COM break; 12327917SReza.Sabdar@Sun.COM } 12337917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 12347917SReza.Sabdar@Sun.COM 12357917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr_v4.addr_type = NDMP_ADDR_TCP; 12367917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr_v4.tcp_len_v4 = 1; 12377917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr_v4.tcp_addr_v4 = 12387917SReza.Sabdar@Sun.COM ndmp_malloc(sizeof (ndmp_tcp_addr_v4)); 12397917SReza.Sabdar@Sun.COM 12407917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr_v4.tcp_ip_v4(0) = addr; 12417917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr_v4.tcp_port_v4(0) = ntohs(port); 12427917SReza.Sabdar@Sun.COM 12437917SReza.Sabdar@Sun.COM ndmp_copy_addr_v4(&reply.connect_addr, 12447917SReza.Sabdar@Sun.COM &session->ns_mover.md_data_addr_v4); 12457917SReza.Sabdar@Sun.COM 12467917SReza.Sabdar@Sun.COM /* For compatibility with V3 */ 12477917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 12487917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_ip_v3 = addr; 12497917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(port); 12507917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "listen_socket: %d", 12517917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock); 12527917SReza.Sabdar@Sun.COM break; 12537917SReza.Sabdar@Sun.COM default: 12547917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 12557917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type: %d", 12567917SReza.Sabdar@Sun.COM request->addr_type); 12577917SReza.Sabdar@Sun.COM } 12587917SReza.Sabdar@Sun.COM 12597917SReza.Sabdar@Sun.COM if (reply.error == NDMP_NO_ERR) { 12607917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = request->mode; 12617917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_LISTEN; 12627917SReza.Sabdar@Sun.COM } 12637917SReza.Sabdar@Sun.COM 12647917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 12657917SReza.Sabdar@Sun.COM "error sending ndmp_mover_listen reply"); 12667917SReza.Sabdar@Sun.COM free(reply.connect_addr.tcp_addr_v4); 12677917SReza.Sabdar@Sun.COM } 12687917SReza.Sabdar@Sun.COM 12697917SReza.Sabdar@Sun.COM /* 12707917SReza.Sabdar@Sun.COM * ndmpd_mover_connect_v4 12717917SReza.Sabdar@Sun.COM * Request handler. Connects the mover to either a local 12727917SReza.Sabdar@Sun.COM * or remote data server. 12737917SReza.Sabdar@Sun.COM * 12747917SReza.Sabdar@Sun.COM * Parameters: 12757917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 12767917SReza.Sabdar@Sun.COM * body (input) - request message body. 12777917SReza.Sabdar@Sun.COM * 12787917SReza.Sabdar@Sun.COM * Returns: 12797917SReza.Sabdar@Sun.COM * void 12807917SReza.Sabdar@Sun.COM */ 12817917SReza.Sabdar@Sun.COM void 12827917SReza.Sabdar@Sun.COM ndmpd_mover_connect_v4(ndmp_connection_t *connection, void *body) 12837917SReza.Sabdar@Sun.COM { 12847917SReza.Sabdar@Sun.COM ndmp_mover_connect_request_v4 *request; 12857917SReza.Sabdar@Sun.COM ndmp_mover_connect_reply_v4 reply; 12867917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 12877917SReza.Sabdar@Sun.COM 12887917SReza.Sabdar@Sun.COM request = (ndmp_mover_connect_request_v4 *)body; 12897917SReza.Sabdar@Sun.COM (void) memset((void*)&reply, 0, sizeof (reply)); 12907917SReza.Sabdar@Sun.COM 12917917SReza.Sabdar@Sun.COM if (request->mode != NDMP_MOVER_MODE_READ && 12927917SReza.Sabdar@Sun.COM request->mode != NDMP_MOVER_MODE_WRITE) { 12937917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 12947917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mode %d", request->mode); 12957917SReza.Sabdar@Sun.COM } else if (!ndmp_valid_v3addr_type(request->addr.addr_type)) { 12967917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 12977917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 12987917SReza.Sabdar@Sun.COM request->addr.addr_type); 12997917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) { 13007917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 13017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid state %d: mover is not idle", 13027917SReza.Sabdar@Sun.COM session->ns_mover.md_state); 13037917SReza.Sabdar@Sun.COM } else if (session->ns_tape.td_fd == -1) { 13047917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 13057917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "No tape device open"); 13067917SReza.Sabdar@Sun.COM } else if (request->mode == NDMP_MOVER_MODE_READ && 13077917SReza.Sabdar@Sun.COM session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 13087917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 13097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Write protected device."); 13107917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_record_size == 0) { 13117917SReza.Sabdar@Sun.COM reply.error = NDMP_PRECONDITION_ERR; 13127917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid record size 0"); 13137917SReza.Sabdar@Sun.COM } else 13147917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 13157917SReza.Sabdar@Sun.COM 13167917SReza.Sabdar@Sun.COM if (reply.error != NDMP_NO_ERR) { 13177917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 13187917SReza.Sabdar@Sun.COM "sending ndmp_mover_connect reply"); 13197917SReza.Sabdar@Sun.COM return; 13207917SReza.Sabdar@Sun.COM } 13217917SReza.Sabdar@Sun.COM 13227917SReza.Sabdar@Sun.COM switch (request->addr.addr_type) { 13237917SReza.Sabdar@Sun.COM case NDMP_ADDR_LOCAL: 13247917SReza.Sabdar@Sun.COM /* 13257917SReza.Sabdar@Sun.COM * Verify that the data server is listening for a 13267917SReza.Sabdar@Sun.COM * local connection. 13277917SReza.Sabdar@Sun.COM */ 13287917SReza.Sabdar@Sun.COM if (session->ns_data.dd_state != NDMP_DATA_STATE_LISTEN || 13297917SReza.Sabdar@Sun.COM session->ns_data.dd_listen_sock != -1) { 13307917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 13317917SReza.Sabdar@Sun.COM "Data server is not in local listen state"); 13327917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_STATE_ERR; 13337917SReza.Sabdar@Sun.COM } else 13347917SReza.Sabdar@Sun.COM session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED; 13357917SReza.Sabdar@Sun.COM break; 13367917SReza.Sabdar@Sun.COM 13377917SReza.Sabdar@Sun.COM case NDMP_ADDR_TCP: 13387917SReza.Sabdar@Sun.COM reply.error = mover_connect_sock_v3(session, request->mode, 13397917SReza.Sabdar@Sun.COM request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0)); 13407917SReza.Sabdar@Sun.COM break; 13417917SReza.Sabdar@Sun.COM 13427917SReza.Sabdar@Sun.COM default: 13437917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 13447917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 13457917SReza.Sabdar@Sun.COM request->addr.addr_type); 13467917SReza.Sabdar@Sun.COM } 13477917SReza.Sabdar@Sun.COM 13487917SReza.Sabdar@Sun.COM if (reply.error == NDMP_NO_ERR) { 13497917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = 13507917SReza.Sabdar@Sun.COM request->addr.addr_type; 13517917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 13527917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = request->mode; 13537917SReza.Sabdar@Sun.COM } 13547917SReza.Sabdar@Sun.COM 13557917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 13567917SReza.Sabdar@Sun.COM "sending ndmp_mover_connect reply"); 13577917SReza.Sabdar@Sun.COM } 13587917SReza.Sabdar@Sun.COM 13597917SReza.Sabdar@Sun.COM 13607917SReza.Sabdar@Sun.COM 13617917SReza.Sabdar@Sun.COM /* 13627917SReza.Sabdar@Sun.COM * ************************************************************************ 13637917SReza.Sabdar@Sun.COM * LOCALS 13647917SReza.Sabdar@Sun.COM * ************************************************************************ 13657917SReza.Sabdar@Sun.COM */ 13667917SReza.Sabdar@Sun.COM 13677917SReza.Sabdar@Sun.COM /* 13687917SReza.Sabdar@Sun.COM * ndmpd_write_eom 13697917SReza.Sabdar@Sun.COM * 13707917SReza.Sabdar@Sun.COM * Write end-of-media magic string. This is called after hitting the LEOT. 13717917SReza.Sabdar@Sun.COM */ 13727917SReza.Sabdar@Sun.COM void 13737917SReza.Sabdar@Sun.COM ndmpd_write_eom(int fd) 13747917SReza.Sabdar@Sun.COM { 13757917SReza.Sabdar@Sun.COM int n; 13767917SReza.Sabdar@Sun.COM 13777917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(fd, MTWEOF, 1); 13787917SReza.Sabdar@Sun.COM n = write(fd, NDMP_EOM_MAGIC, strlen(NDMP_EOM_MAGIC)); 13797917SReza.Sabdar@Sun.COM 13807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "%d EOM bytes wrote", n); 13817917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(fd, MTWEOF, 1); 13827917SReza.Sabdar@Sun.COM 13837917SReza.Sabdar@Sun.COM /* 13847917SReza.Sabdar@Sun.COM * Rewind to the previous file since the last two files are used 13857917SReza.Sabdar@Sun.COM * as the indicator for logical EOM. 13867917SReza.Sabdar@Sun.COM */ 13877917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(fd, MTBSF, 2); 13887917SReza.Sabdar@Sun.COM } 13897917SReza.Sabdar@Sun.COM 13907917SReza.Sabdar@Sun.COM 13917917SReza.Sabdar@Sun.COM /* 13927917SReza.Sabdar@Sun.COM * ndmpd_local_write 13937917SReza.Sabdar@Sun.COM * 13947917SReza.Sabdar@Sun.COM * Writes data to the mover. 13957917SReza.Sabdar@Sun.COM * Buffers and write data to the tape device. 13967917SReza.Sabdar@Sun.COM * A full tape record is buffered before being written. 13977917SReza.Sabdar@Sun.COM * 13987917SReza.Sabdar@Sun.COM * Parameters: 13997917SReza.Sabdar@Sun.COM * session (input) - session pointer. 14007917SReza.Sabdar@Sun.COM * data (input) - data to be written. 14017917SReza.Sabdar@Sun.COM * length (input) - data length. 14027917SReza.Sabdar@Sun.COM * 14037917SReza.Sabdar@Sun.COM * Returns: 14047917SReza.Sabdar@Sun.COM * 0 - data successfully written. 14057917SReza.Sabdar@Sun.COM * -1 - error. 14067917SReza.Sabdar@Sun.COM */ 14077917SReza.Sabdar@Sun.COM int 14087917SReza.Sabdar@Sun.COM ndmpd_local_write(ndmpd_session_t *session, char *data, ulong_t length) 14097917SReza.Sabdar@Sun.COM { 14107917SReza.Sabdar@Sun.COM ulong_t count = 0; 14117917SReza.Sabdar@Sun.COM ssize_t n; 14127917SReza.Sabdar@Sun.COM ulong_t len; 14137917SReza.Sabdar@Sun.COM 14147917SReza.Sabdar@Sun.COM /* 14157917SReza.Sabdar@Sun.COM * A length of 0 indicates that any buffered data should be 14167917SReza.Sabdar@Sun.COM * flushed to tape. 14177917SReza.Sabdar@Sun.COM */ 14187917SReza.Sabdar@Sun.COM if (length == 0) { 14197917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0) 14207917SReza.Sabdar@Sun.COM return (0); 14217917SReza.Sabdar@Sun.COM 14227917SReza.Sabdar@Sun.COM (void) memset( 14237917SReza.Sabdar@Sun.COM &session->ns_mover.md_buf[session->ns_mover.md_w_index], 14247917SReza.Sabdar@Sun.COM 0, session->ns_mover.md_record_size - 14257917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index); 14267917SReza.Sabdar@Sun.COM 14277917SReza.Sabdar@Sun.COM n = tape_write(session, session->ns_mover.md_buf, 14287917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 14297917SReza.Sabdar@Sun.COM if (n <= 0) { 14307917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 14317917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14327917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 14337917SReza.Sabdar@Sun.COM return (-1); 14347917SReza.Sabdar@Sun.COM } 14357917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 14367917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += 14377917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index; 14387917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 14397917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 14407917SReza.Sabdar@Sun.COM return (0); 14417917SReza.Sabdar@Sun.COM } 14427917SReza.Sabdar@Sun.COM /* Break the data into records. */ 14437917SReza.Sabdar@Sun.COM while (count < length) { 14447917SReza.Sabdar@Sun.COM /* 14457917SReza.Sabdar@Sun.COM * Determine if data needs to be buffered or 14467917SReza.Sabdar@Sun.COM * can be written directly from user supplied location. 14477917SReza.Sabdar@Sun.COM * We can fast path the write if there is no pending 14487917SReza.Sabdar@Sun.COM * buffered data and there is at least a full record's worth 14497917SReza.Sabdar@Sun.COM * of data to be written. 14507917SReza.Sabdar@Sun.COM */ 14517917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0 && 14527917SReza.Sabdar@Sun.COM length - count >= session->ns_mover.md_record_size) { 14537917SReza.Sabdar@Sun.COM n = tape_write(session, &data[count], 14547917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 14557917SReza.Sabdar@Sun.COM if (n <= 0) { 14567917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 14577917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14587917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 14597917SReza.Sabdar@Sun.COM return (-1); 14607917SReza.Sabdar@Sun.COM } 14617917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 14627917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 14637917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 14647917SReza.Sabdar@Sun.COM count += n; 14657917SReza.Sabdar@Sun.COM continue; 14667917SReza.Sabdar@Sun.COM } 14677917SReza.Sabdar@Sun.COM /* Buffer the data */ 14687917SReza.Sabdar@Sun.COM len = length - count; 14697917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_record_size - 14707917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index) 14717917SReza.Sabdar@Sun.COM len = session->ns_mover.md_record_size - 14727917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index; 14737917SReza.Sabdar@Sun.COM 14747917SReza.Sabdar@Sun.COM (void) memcpy( 14757917SReza.Sabdar@Sun.COM &session->ns_mover.md_buf[session->ns_mover.md_w_index], 14767917SReza.Sabdar@Sun.COM &data[count], len); 14777917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index += len; 14787917SReza.Sabdar@Sun.COM count += len; 14797917SReza.Sabdar@Sun.COM 14807917SReza.Sabdar@Sun.COM /* Write the buffer if its full */ 14817917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 14827917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size) { 14837917SReza.Sabdar@Sun.COM n = tape_write(session, session->ns_mover.md_buf, 14847917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 14857917SReza.Sabdar@Sun.COM if (n < 0) { 14867917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 14877917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 14887917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 14897917SReza.Sabdar@Sun.COM return (-1); 14907917SReza.Sabdar@Sun.COM } 14917917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 14927917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 14937917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 14947917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 14957917SReza.Sabdar@Sun.COM } 14967917SReza.Sabdar@Sun.COM } 14977917SReza.Sabdar@Sun.COM 14987917SReza.Sabdar@Sun.COM return (0); 14997917SReza.Sabdar@Sun.COM } 15007917SReza.Sabdar@Sun.COM 15017917SReza.Sabdar@Sun.COM 15027917SReza.Sabdar@Sun.COM /* 15037917SReza.Sabdar@Sun.COM * ndmpd_remote_write 15047917SReza.Sabdar@Sun.COM * 15057917SReza.Sabdar@Sun.COM * Writes data to the remote mover. 15067917SReza.Sabdar@Sun.COM * 15077917SReza.Sabdar@Sun.COM * Parameters: 15087917SReza.Sabdar@Sun.COM * session (input) - session pointer. 15097917SReza.Sabdar@Sun.COM * data (input) - data to be written. 15107917SReza.Sabdar@Sun.COM * length (input) - data length. 15117917SReza.Sabdar@Sun.COM * 15127917SReza.Sabdar@Sun.COM * Returns: 15137917SReza.Sabdar@Sun.COM * 0 - data successfully written. 15147917SReza.Sabdar@Sun.COM * -1 - error. 15157917SReza.Sabdar@Sun.COM */ 15167917SReza.Sabdar@Sun.COM int 15177917SReza.Sabdar@Sun.COM ndmpd_remote_write(ndmpd_session_t *session, char *data, ulong_t length) 15187917SReza.Sabdar@Sun.COM { 15197917SReza.Sabdar@Sun.COM ssize_t n; 15207917SReza.Sabdar@Sun.COM ulong_t count = 0; 15217917SReza.Sabdar@Sun.COM 15227917SReza.Sabdar@Sun.COM while (count < length) { 15237917SReza.Sabdar@Sun.COM if (session->ns_eof == TRUE || 15247917SReza.Sabdar@Sun.COM session->ns_data.dd_abort == TRUE) 15257917SReza.Sabdar@Sun.COM return (-1); 15267917SReza.Sabdar@Sun.COM 15277917SReza.Sabdar@Sun.COM if ((n = write(session->ns_data.dd_sock, &data[count], 15287917SReza.Sabdar@Sun.COM length - count)) < 0) { 15297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Socket write error: %m."); 15307917SReza.Sabdar@Sun.COM return (-1); 15317917SReza.Sabdar@Sun.COM } 15327917SReza.Sabdar@Sun.COM count += n; 15337917SReza.Sabdar@Sun.COM } 15347917SReza.Sabdar@Sun.COM 15357917SReza.Sabdar@Sun.COM return (0); 15367917SReza.Sabdar@Sun.COM } 15377917SReza.Sabdar@Sun.COM 15387917SReza.Sabdar@Sun.COM /* 15397917SReza.Sabdar@Sun.COM * ndmpd_local_read 15407917SReza.Sabdar@Sun.COM * 15417917SReza.Sabdar@Sun.COM * Reads data from the local tape device. 15427917SReza.Sabdar@Sun.COM * Full tape records are read and buffered. 15437917SReza.Sabdar@Sun.COM * 15447917SReza.Sabdar@Sun.COM * Parameters: 15457917SReza.Sabdar@Sun.COM * session (input) - session pointer. 15467917SReza.Sabdar@Sun.COM * data (input) - location to store data. 15477917SReza.Sabdar@Sun.COM * length (input) - data length. 15487917SReza.Sabdar@Sun.COM * 15497917SReza.Sabdar@Sun.COM * Returns: 15507917SReza.Sabdar@Sun.COM * 0 - data successfully read. 15517917SReza.Sabdar@Sun.COM * -1 - error. 15527917SReza.Sabdar@Sun.COM * 1 - session terminated or operation aborted. 15537917SReza.Sabdar@Sun.COM */ 15547917SReza.Sabdar@Sun.COM int 15557917SReza.Sabdar@Sun.COM ndmpd_local_read(ndmpd_session_t *session, char *data, ulong_t length) 15567917SReza.Sabdar@Sun.COM { 15577917SReza.Sabdar@Sun.COM ulong_t count = 0; 15587917SReza.Sabdar@Sun.COM ssize_t n; 15597917SReza.Sabdar@Sun.COM ulong_t len; 15607917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request pause_request; 15617917SReza.Sabdar@Sun.COM 15627917SReza.Sabdar@Sun.COM /* 15637917SReza.Sabdar@Sun.COM * Automatically increase the seek window if necessary. 15647917SReza.Sabdar@Sun.COM * This is needed in the event the module attempts to read 15657917SReza.Sabdar@Sun.COM * past a seek window set via a prior call to ndmpd_seek() or 15667917SReza.Sabdar@Sun.COM * the module has not issued a seek. If no seek was issued then 15677917SReza.Sabdar@Sun.COM * pretend that a seek was issued to read the entire tape. 15687917SReza.Sabdar@Sun.COM */ 15697917SReza.Sabdar@Sun.COM if (length > session->ns_mover.md_bytes_left_to_read) { 15707917SReza.Sabdar@Sun.COM /* ndmpd_seek() never called? */ 15717917SReza.Sabdar@Sun.COM if (session->ns_data.dd_read_length == 0) { 15727917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = ~0LL; 15737917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 0LL; 15747917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = ~0LL; 15757917SReza.Sabdar@Sun.COM } else { 15767917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = length; 15777917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 15787917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 15797917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = length; 15807917SReza.Sabdar@Sun.COM } 15817917SReza.Sabdar@Sun.COM } 15827917SReza.Sabdar@Sun.COM /* 15837917SReza.Sabdar@Sun.COM * Read as many records as necessary to satisfy the request. 15847917SReza.Sabdar@Sun.COM */ 15857917SReza.Sabdar@Sun.COM while (count < length) { 15867917SReza.Sabdar@Sun.COM /* 15877917SReza.Sabdar@Sun.COM * If the end of the mover window has been reached, 15887917SReza.Sabdar@Sun.COM * then notify the client that a new data window is needed. 15897917SReza.Sabdar@Sun.COM */ 15907917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position >= 15917917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 15927917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) { 15937917SReza.Sabdar@Sun.COM 15947917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 15957917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = 15967917SReza.Sabdar@Sun.COM NDMP_MOVER_PAUSE_SEEK; 15977917SReza.Sabdar@Sun.COM pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 15987917SReza.Sabdar@Sun.COM pause_request.seek_position = 15997917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_position); 16007917SReza.Sabdar@Sun.COM 16017917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, 16027917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 16037917SReza.Sabdar@Sun.COM (void *) &pause_request, 0) < 0) { 16047917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 16057917SReza.Sabdar@Sun.COM "Sending notify_mover_paused request"); 16067917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 16077917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 16087917SReza.Sabdar@Sun.COM return (-1); 16097917SReza.Sabdar@Sun.COM } 16107917SReza.Sabdar@Sun.COM /* 16117917SReza.Sabdar@Sun.COM * Wait for until the state is changed by 16127917SReza.Sabdar@Sun.COM * an abort or continue request. 16137917SReza.Sabdar@Sun.COM */ 16147917SReza.Sabdar@Sun.COM nlp_ref_nw(session); 16157917SReza.Sabdar@Sun.COM for (; ; ) { 16167917SReza.Sabdar@Sun.COM nlp_wait_nw(session); 16177917SReza.Sabdar@Sun.COM 16187917SReza.Sabdar@Sun.COM if (session->ns_eof == TRUE) { 16197917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 16207917SReza.Sabdar@Sun.COM return (1); 16217917SReza.Sabdar@Sun.COM } 16227917SReza.Sabdar@Sun.COM 16237917SReza.Sabdar@Sun.COM switch (session->ns_mover.md_state) { 16247917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_ACTIVE: 16257917SReza.Sabdar@Sun.COM break; 16267917SReza.Sabdar@Sun.COM 16277917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_PAUSED: 16287917SReza.Sabdar@Sun.COM continue; 16297917SReza.Sabdar@Sun.COM 16307917SReza.Sabdar@Sun.COM default: 16317917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 16327917SReza.Sabdar@Sun.COM return (-1); 16337917SReza.Sabdar@Sun.COM } 16347917SReza.Sabdar@Sun.COM } 16357917SReza.Sabdar@Sun.COM } 16367917SReza.Sabdar@Sun.COM len = length - count; 16377917SReza.Sabdar@Sun.COM 16387917SReza.Sabdar@Sun.COM /* 16397917SReza.Sabdar@Sun.COM * Prevent reading past the end of the window. 16407917SReza.Sabdar@Sun.COM */ 16417917SReza.Sabdar@Sun.COM if (len > 16427917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 16437917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length - 16447917SReza.Sabdar@Sun.COM session->ns_mover.md_position) 16457917SReza.Sabdar@Sun.COM len = session->ns_mover.md_window_offset + 16467917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length - 16477917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 16487917SReza.Sabdar@Sun.COM 16497917SReza.Sabdar@Sun.COM /* 16507917SReza.Sabdar@Sun.COM * Copy from the data buffer first. 16517917SReza.Sabdar@Sun.COM */ 16527917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index - 16537917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index != 0) { 16547917SReza.Sabdar@Sun.COM /* 16557917SReza.Sabdar@Sun.COM * Limit the copy to the amount of data in the buffer. 16567917SReza.Sabdar@Sun.COM */ 16577917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_w_index - 16587917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index) 16597917SReza.Sabdar@Sun.COM len = session->ns_mover.md_w_index 16607917SReza.Sabdar@Sun.COM - session->ns_mover.md_r_index; 16617917SReza.Sabdar@Sun.COM 16627917SReza.Sabdar@Sun.COM (void) memcpy((void *) &data[count], 16637917SReza.Sabdar@Sun.COM &session->ns_mover.md_buf[session-> 16647917SReza.Sabdar@Sun.COM ns_mover.md_r_index], len); 16657917SReza.Sabdar@Sun.COM count += len; 16667917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index += len; 16677917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= len; 16687917SReza.Sabdar@Sun.COM session->ns_mover.md_position += len; 16697917SReza.Sabdar@Sun.COM continue; 16707917SReza.Sabdar@Sun.COM } 16717917SReza.Sabdar@Sun.COM /* 16727917SReza.Sabdar@Sun.COM * Determine if data needs to be buffered or 16737917SReza.Sabdar@Sun.COM * can be read directly to user supplied location. 16747917SReza.Sabdar@Sun.COM * We can fast path the read if at least a full record 16757917SReza.Sabdar@Sun.COM * needs to be read and there is no seek pending. 16767917SReza.Sabdar@Sun.COM * This is done to eliminate a buffer copy. 16777917SReza.Sabdar@Sun.COM */ 16787917SReza.Sabdar@Sun.COM if (len >= session->ns_mover.md_record_size && 16797917SReza.Sabdar@Sun.COM session->ns_mover.md_position >= 16807917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position) { 16817917SReza.Sabdar@Sun.COM n = tape_read(session, &data[count]); 16827917SReza.Sabdar@Sun.COM if (n <= 0) { 16837917SReza.Sabdar@Sun.COM if (n == TAPE_NO_WRITER_ERR) 16847917SReza.Sabdar@Sun.COM return (1); 16857917SReza.Sabdar@Sun.COM 16867917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 16877917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 16887917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 16897917SReza.Sabdar@Sun.COM return (n == 0) ? (1) : (-1); 16907917SReza.Sabdar@Sun.COM } 16917917SReza.Sabdar@Sun.COM count += n; 16927917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= n; 16937917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 16947917SReza.Sabdar@Sun.COM continue; 16957917SReza.Sabdar@Sun.COM } 16967917SReza.Sabdar@Sun.COM /* Read the next record into the buffer. */ 16977917SReza.Sabdar@Sun.COM n = tape_read(session, session->ns_mover.md_buf); 16987917SReza.Sabdar@Sun.COM if (n <= 0) { 16997917SReza.Sabdar@Sun.COM if (n == TAPE_NO_WRITER_ERR) 17007917SReza.Sabdar@Sun.COM return (1); 17017917SReza.Sabdar@Sun.COM 17027917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 17037917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 17047917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 17057917SReza.Sabdar@Sun.COM return (n == 0) ? (1) : (-1); 17067917SReza.Sabdar@Sun.COM } 17077917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = n; 17087917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 17097917SReza.Sabdar@Sun.COM 17107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d", n); 17117917SReza.Sabdar@Sun.COM 17127917SReza.Sabdar@Sun.COM /* 17137917SReza.Sabdar@Sun.COM * Discard data if the current data stream position is 17147917SReza.Sabdar@Sun.COM * prior to the seek position. This is necessary if a seek 17157917SReza.Sabdar@Sun.COM * request set the seek pointer to a position that is not a 17167917SReza.Sabdar@Sun.COM * record boundary. The seek request handler can only position 17177917SReza.Sabdar@Sun.COM * to the start of a record. 17187917SReza.Sabdar@Sun.COM */ 17197917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position < 17207917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position) { 17217917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 17227917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position - 17237917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 17247917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 17257917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position; 17267917SReza.Sabdar@Sun.COM } 17277917SReza.Sabdar@Sun.COM } 17287917SReza.Sabdar@Sun.COM 17297917SReza.Sabdar@Sun.COM return (0); 17307917SReza.Sabdar@Sun.COM } 17317917SReza.Sabdar@Sun.COM 17327917SReza.Sabdar@Sun.COM 17337917SReza.Sabdar@Sun.COM /* 17347917SReza.Sabdar@Sun.COM * ndmpd_remote_read 17357917SReza.Sabdar@Sun.COM * 17367917SReza.Sabdar@Sun.COM * Reads data from the remote mover. 17377917SReza.Sabdar@Sun.COM * 17387917SReza.Sabdar@Sun.COM * Parameters: 17397917SReza.Sabdar@Sun.COM * session (input) - session pointer. 17407917SReza.Sabdar@Sun.COM * data (input) - data to be written. 17417917SReza.Sabdar@Sun.COM * length (input) - data length. 17427917SReza.Sabdar@Sun.COM * 17437917SReza.Sabdar@Sun.COM * Returns: 17447917SReza.Sabdar@Sun.COM * 0 - data successfully read. 17457917SReza.Sabdar@Sun.COM * -1 - error. 17467917SReza.Sabdar@Sun.COM * 1 - session terminated or operation aborted. 17477917SReza.Sabdar@Sun.COM */ 17487917SReza.Sabdar@Sun.COM int 17497917SReza.Sabdar@Sun.COM ndmpd_remote_read(ndmpd_session_t *session, char *data, ulong_t length) 17507917SReza.Sabdar@Sun.COM { 17517917SReza.Sabdar@Sun.COM ulong_t count = 0; 17527917SReza.Sabdar@Sun.COM ssize_t n; 17537917SReza.Sabdar@Sun.COM ulong_t len; 17547917SReza.Sabdar@Sun.COM ndmp_notify_data_read_request request; 17557917SReza.Sabdar@Sun.COM 17567917SReza.Sabdar@Sun.COM while (count < length) { 17577917SReza.Sabdar@Sun.COM len = length - count; 17587917SReza.Sabdar@Sun.COM 17597917SReza.Sabdar@Sun.COM /* 17607917SReza.Sabdar@Sun.COM * If the end of the seek window has been reached then 17617917SReza.Sabdar@Sun.COM * send an ndmp_read request to the client. 17627917SReza.Sabdar@Sun.COM * The NDMP client will then send a mover_data_read request to 17637917SReza.Sabdar@Sun.COM * the remote mover and the mover will send more data. 17647917SReza.Sabdar@Sun.COM * This condition can occur if the module attempts to read past 17657917SReza.Sabdar@Sun.COM * a seek window set via a prior call to ndmpd_seek() or 17667917SReza.Sabdar@Sun.COM * the module has not issued a seek. If no seek was issued then 17677917SReza.Sabdar@Sun.COM * pretend that a seek was issued to read the entire tape. 17687917SReza.Sabdar@Sun.COM */ 17697917SReza.Sabdar@Sun.COM if (session->ns_mover.md_bytes_left_to_read == 0) { 17707917SReza.Sabdar@Sun.COM /* ndmpd_seek() never called? */ 17717917SReza.Sabdar@Sun.COM if (session->ns_data.dd_read_length == 0) { 17727917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = ~0LL; 17737917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 0LL; 17747917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = ~0LL; 17757917SReza.Sabdar@Sun.COM } else { 17767917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = len; 17777917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 17787917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 17797917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = len; 17807917SReza.Sabdar@Sun.COM } 17817917SReza.Sabdar@Sun.COM 17827917SReza.Sabdar@Sun.COM request.offset = 17837917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_data.dd_read_offset); 17847917SReza.Sabdar@Sun.COM request.length = 17857917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_data.dd_read_length); 17867917SReza.Sabdar@Sun.COM 17878193SReza.Sabdar@Sun.COM if (ndmp_send_request_lock(session->ns_connection, 17887917SReza.Sabdar@Sun.COM NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR, 17897917SReza.Sabdar@Sun.COM (void *) &request, 0) < 0) { 17907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 17917917SReza.Sabdar@Sun.COM "Sending notify_data_read request"); 17927917SReza.Sabdar@Sun.COM return (-1); 17937917SReza.Sabdar@Sun.COM } 17947917SReza.Sabdar@Sun.COM } 17957917SReza.Sabdar@Sun.COM if (session->ns_eof == TRUE || 17967917SReza.Sabdar@Sun.COM session->ns_data.dd_abort == TRUE) 17977917SReza.Sabdar@Sun.COM return (1); 17987917SReza.Sabdar@Sun.COM 17997917SReza.Sabdar@Sun.COM /* 18007917SReza.Sabdar@Sun.COM * If the module called ndmpd_seek() prior to reading all of the 18017917SReza.Sabdar@Sun.COM * data that the remote mover was requested to send, then the 18027917SReza.Sabdar@Sun.COM * excess data from the seek has to be discardd. 18037917SReza.Sabdar@Sun.COM */ 18047917SReza.Sabdar@Sun.COM if (session->ns_mover.md_discard_length != 0) { 18057917SReza.Sabdar@Sun.COM n = discard_data(session, 18067917SReza.Sabdar@Sun.COM (ulong_t)session->ns_mover.md_discard_length); 18077917SReza.Sabdar@Sun.COM if (n < 0) 18087917SReza.Sabdar@Sun.COM return (-1); 18097917SReza.Sabdar@Sun.COM session->ns_mover.md_discard_length -= n; 18107917SReza.Sabdar@Sun.COM continue; 18117917SReza.Sabdar@Sun.COM } 18127917SReza.Sabdar@Sun.COM /* 18137917SReza.Sabdar@Sun.COM * Don't attempt to read more data than the remote is sending. 18147917SReza.Sabdar@Sun.COM */ 18157917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_bytes_left_to_read) 18167917SReza.Sabdar@Sun.COM len = session->ns_mover.md_bytes_left_to_read; 18177917SReza.Sabdar@Sun.COM 18187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "len: %u", len); 18197917SReza.Sabdar@Sun.COM 18207917SReza.Sabdar@Sun.COM if ((n = read(session->ns_data.dd_sock, &data[count], 18217917SReza.Sabdar@Sun.COM len)) < 0) { 18227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Socket read error: %m."); 18237917SReza.Sabdar@Sun.COM return (-1); 18247917SReza.Sabdar@Sun.COM } 18257917SReza.Sabdar@Sun.COM /* read returns 0 if the connection was closed */ 18267917SReza.Sabdar@Sun.COM if (n == 0) 18277917SReza.Sabdar@Sun.COM return (-1); 18287917SReza.Sabdar@Sun.COM 18297917SReza.Sabdar@Sun.COM count += n; 18307917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= n; 18317917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 18327917SReza.Sabdar@Sun.COM } 18337917SReza.Sabdar@Sun.COM 18347917SReza.Sabdar@Sun.COM return (0); 18357917SReza.Sabdar@Sun.COM } 18367917SReza.Sabdar@Sun.COM 18377917SReza.Sabdar@Sun.COM /* *** ndmpd internal functions ***************************************** */ 18387917SReza.Sabdar@Sun.COM 18397917SReza.Sabdar@Sun.COM /* 18407917SReza.Sabdar@Sun.COM * ndmpd_mover_init 18417917SReza.Sabdar@Sun.COM * 18427917SReza.Sabdar@Sun.COM * Initialize mover specific session variables. 18437917SReza.Sabdar@Sun.COM * Don't initialize variables such as record_size that need to 18447917SReza.Sabdar@Sun.COM * persist across data operations. A client may open a connection and 18457917SReza.Sabdar@Sun.COM * do multiple backups after setting the record_size. 18467917SReza.Sabdar@Sun.COM * 18477917SReza.Sabdar@Sun.COM * Parameters: 18487917SReza.Sabdar@Sun.COM * session (input) - session pointer. 18497917SReza.Sabdar@Sun.COM * 18507917SReza.Sabdar@Sun.COM * Returns: 18517917SReza.Sabdar@Sun.COM * 0 - success. 18527917SReza.Sabdar@Sun.COM * -1 - error. 18537917SReza.Sabdar@Sun.COM */ 18547917SReza.Sabdar@Sun.COM int 18557917SReza.Sabdar@Sun.COM ndmpd_mover_init(ndmpd_session_t *session) 18567917SReza.Sabdar@Sun.COM { 18577917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_IDLE; 18587917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_NA; 18597917SReza.Sabdar@Sun.COM session->ns_mover.md_halt_reason = NDMP_MOVER_HALT_NA; 18607917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written = 0LL; 18617917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position = 0LL; 18627917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = 0LL; 18637917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset = 0LL; 18647917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length = MAX_WINDOW_SIZE; 18657917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 0LL; 18667917SReza.Sabdar@Sun.COM session->ns_mover.md_discard_length = 0; 18677917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num = 0; 18687917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size = 0; 18697917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 18707917SReza.Sabdar@Sun.COM session->ns_mover.md_pre_cond = FALSE; 18717917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = -1; 18727917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 18737917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 18747917SReza.Sabdar@Sun.COM session->ns_mover.md_buf = ndmp_malloc(MAX_RECORD_SIZE); 18757917SReza.Sabdar@Sun.COM if (!session->ns_mover.md_buf) 18767917SReza.Sabdar@Sun.COM return (-1); 18777917SReza.Sabdar@Sun.COM 18787917SReza.Sabdar@Sun.COM if (ndmp_get_version(session->ns_connection) == NDMPV3) { 18797917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = NDMP_MOVER_MODE_READ; 18807917SReza.Sabdar@Sun.COM (void) memset(&session->ns_mover.md_data_addr, 0, 18817917SReza.Sabdar@Sun.COM sizeof (ndmp_addr_v3)); 18827917SReza.Sabdar@Sun.COM } 18837917SReza.Sabdar@Sun.COM return (0); 18847917SReza.Sabdar@Sun.COM } 18857917SReza.Sabdar@Sun.COM 18867917SReza.Sabdar@Sun.COM 18877917SReza.Sabdar@Sun.COM /* 18887917SReza.Sabdar@Sun.COM * ndmpd_mover_shut_down 18897917SReza.Sabdar@Sun.COM * 18907917SReza.Sabdar@Sun.COM * Shutdown the mover. It closes all the sockets. 18917917SReza.Sabdar@Sun.COM * 18927917SReza.Sabdar@Sun.COM * Parameters: 18937917SReza.Sabdar@Sun.COM * session (input) - session pointer. 18947917SReza.Sabdar@Sun.COM * 18957917SReza.Sabdar@Sun.COM * Returns: 18967917SReza.Sabdar@Sun.COM * void 18977917SReza.Sabdar@Sun.COM */ 18987917SReza.Sabdar@Sun.COM void 18997917SReza.Sabdar@Sun.COM ndmpd_mover_shut_down(ndmpd_session_t *session) 19007917SReza.Sabdar@Sun.COM { 19017917SReza.Sabdar@Sun.COM if (session->ns_mover.md_listen_sock != -1) { 19027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "mover.listen_sock: %d", 19037917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock); 19047917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, 19057917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock); 19067917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 19077917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 19087917SReza.Sabdar@Sun.COM } 19097917SReza.Sabdar@Sun.COM if (session->ns_mover.md_sock != -1) { 19107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "mover.sock: %d", 19117917SReza.Sabdar@Sun.COM session->ns_mover.md_sock); 19127917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, 19137917SReza.Sabdar@Sun.COM session->ns_mover.md_sock); 19147917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_sock); 19157917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = -1; 19167917SReza.Sabdar@Sun.COM } 19177917SReza.Sabdar@Sun.COM } 19187917SReza.Sabdar@Sun.COM 19197917SReza.Sabdar@Sun.COM 19207917SReza.Sabdar@Sun.COM /* 19217917SReza.Sabdar@Sun.COM * ndmpd_mover_cleanup 19227917SReza.Sabdar@Sun.COM * 19237917SReza.Sabdar@Sun.COM * Parameters: 19247917SReza.Sabdar@Sun.COM * session (input) - session pointer. 19257917SReza.Sabdar@Sun.COM * 19267917SReza.Sabdar@Sun.COM * Returns: 19277917SReza.Sabdar@Sun.COM * void 19287917SReza.Sabdar@Sun.COM */ 19297917SReza.Sabdar@Sun.COM void 19307917SReza.Sabdar@Sun.COM ndmpd_mover_cleanup(ndmpd_session_t *session) 19317917SReza.Sabdar@Sun.COM { 19327917SReza.Sabdar@Sun.COM NDMP_FREE(session->ns_mover.md_buf); 19337917SReza.Sabdar@Sun.COM } 19347917SReza.Sabdar@Sun.COM 19357917SReza.Sabdar@Sun.COM 19367917SReza.Sabdar@Sun.COM /* 19377917SReza.Sabdar@Sun.COM * ndmpd_mover_connect 19387917SReza.Sabdar@Sun.COM * Create a connection to the specified mover. 19397917SReza.Sabdar@Sun.COM * 19407917SReza.Sabdar@Sun.COM * Parameters: 19417917SReza.Sabdar@Sun.COM * session (input) - session pointer 19427917SReza.Sabdar@Sun.COM * 19437917SReza.Sabdar@Sun.COM * Returns: 19447917SReza.Sabdar@Sun.COM * error code. 19457917SReza.Sabdar@Sun.COM */ 19467917SReza.Sabdar@Sun.COM ndmp_error 19477917SReza.Sabdar@Sun.COM ndmpd_mover_connect(ndmpd_session_t *session, ndmp_mover_mode mover_mode) 19487917SReza.Sabdar@Sun.COM { 19497917SReza.Sabdar@Sun.COM ndmp_mover_addr *mover = &session->ns_data.dd_mover; 19507917SReza.Sabdar@Sun.COM struct sockaddr_in sin; 19517917SReza.Sabdar@Sun.COM int sock = -1; 19527917SReza.Sabdar@Sun.COM int flag = 1; 19537917SReza.Sabdar@Sun.COM 19547917SReza.Sabdar@Sun.COM if (mover->addr_type == NDMP_ADDR_TCP) { 19557917SReza.Sabdar@Sun.COM if (mover->ndmp_mover_addr_u.addr.ip_addr) { 19567917SReza.Sabdar@Sun.COM (void) memset((void *) &sin, 0, sizeof (sin)); 19577917SReza.Sabdar@Sun.COM sin.sin_family = AF_INET; 19587917SReza.Sabdar@Sun.COM sin.sin_addr.s_addr = 19597917SReza.Sabdar@Sun.COM htonl(mover->ndmp_mover_addr_u.addr.ip_addr); 19607917SReza.Sabdar@Sun.COM sin.sin_port = 19617917SReza.Sabdar@Sun.COM htons(mover->ndmp_mover_addr_u.addr.port); 19627917SReza.Sabdar@Sun.COM 19637917SReza.Sabdar@Sun.COM /* 19647917SReza.Sabdar@Sun.COM * If the address type is TCP but both the address and 19657917SReza.Sabdar@Sun.COM * the port number are zero, we have to use a different 19667917SReza.Sabdar@Sun.COM * socket than the mover socket. This can happen when 19677917SReza.Sabdar@Sun.COM * using NDMP disk to disk copy (AKA D2D copy). 19687917SReza.Sabdar@Sun.COM * The NDMPCopy client will send a zero address to 19697917SReza.Sabdar@Sun.COM * direct the server to use the mover socket as the 19707917SReza.Sabdar@Sun.COM * data socket to receive the recovery data. 19717917SReza.Sabdar@Sun.COM */ 19727917SReza.Sabdar@Sun.COM if (sin.sin_addr.s_addr == 0 && sin.sin_port == 0) { 19737917SReza.Sabdar@Sun.COM session->ns_data.dd_sock = 19747917SReza.Sabdar@Sun.COM session->ns_mover.md_sock; 19757917SReza.Sabdar@Sun.COM return (NDMP_NO_ERR); 19767917SReza.Sabdar@Sun.COM } 19777917SReza.Sabdar@Sun.COM 19787917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "addr: %u port: %u", 19797917SReza.Sabdar@Sun.COM mover->ndmp_mover_addr_u.addr.ip_addr, 19807917SReza.Sabdar@Sun.COM (ulong_t)sin.sin_port); 19817917SReza.Sabdar@Sun.COM 19827917SReza.Sabdar@Sun.COM if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 19837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Socket error: %m"); 19847917SReza.Sabdar@Sun.COM return (NDMP_IO_ERR); 19857917SReza.Sabdar@Sun.COM } 19867917SReza.Sabdar@Sun.COM if (connect(sock, (struct sockaddr *)&sin, 19877917SReza.Sabdar@Sun.COM sizeof (sin)) < 0) { 19887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Connect error: %m"); 19897917SReza.Sabdar@Sun.COM (void) close(sock); 19907917SReza.Sabdar@Sun.COM return (NDMP_IO_ERR); 19917917SReza.Sabdar@Sun.COM } 19927917SReza.Sabdar@Sun.COM 19937917SReza.Sabdar@Sun.COM if (ndmp_sbs > 0) 19947917SReza.Sabdar@Sun.COM ndmp_set_socket_snd_buf(sock, 19957917SReza.Sabdar@Sun.COM ndmp_sbs * KILOBYTE); 19967917SReza.Sabdar@Sun.COM if (ndmp_rbs > 0) 19977917SReza.Sabdar@Sun.COM ndmp_set_socket_rcv_buf(sock, 19987917SReza.Sabdar@Sun.COM ndmp_rbs * KILOBYTE); 19997917SReza.Sabdar@Sun.COM 20007917SReza.Sabdar@Sun.COM ndmp_set_socket_nodelay(sock); 20017917SReza.Sabdar@Sun.COM (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &flag, 20027917SReza.Sabdar@Sun.COM sizeof (flag)); 20037917SReza.Sabdar@Sun.COM } else { 20047917SReza.Sabdar@Sun.COM if ((session->ns_mover.md_state != 20057917SReza.Sabdar@Sun.COM NDMP_MOVER_STATE_ACTIVE) || 20067917SReza.Sabdar@Sun.COM (session->ns_mover.md_sock == -1)) { 20077917SReza.Sabdar@Sun.COM 20087917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 20097917SReza.Sabdar@Sun.COM "Not in active state mover" 20107917SReza.Sabdar@Sun.COM " state = %d or Invalid mover sock=%d", 20117917SReza.Sabdar@Sun.COM session->ns_mover.md_state, 20127917SReza.Sabdar@Sun.COM session->ns_mover.md_sock); 20137917SReza.Sabdar@Sun.COM return (NDMP_ILLEGAL_STATE_ERR); 20147917SReza.Sabdar@Sun.COM } 20157917SReza.Sabdar@Sun.COM 20167917SReza.Sabdar@Sun.COM sock = session->ns_mover.md_sock; 20177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 20187917SReza.Sabdar@Sun.COM "session: 0x%x setting data sock fd: %d to be" 20197917SReza.Sabdar@Sun.COM " same as listen_sock", session, sock); 20207917SReza.Sabdar@Sun.COM } 20217917SReza.Sabdar@Sun.COM 20227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "sock fd: %d", sock); 20237917SReza.Sabdar@Sun.COM 20247917SReza.Sabdar@Sun.COM session->ns_data.dd_sock = sock; 20257917SReza.Sabdar@Sun.COM 20267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "data.mover_sock: %u", sock); 20277917SReza.Sabdar@Sun.COM 20287917SReza.Sabdar@Sun.COM return (NDMP_NO_ERR); 20297917SReza.Sabdar@Sun.COM } 20307917SReza.Sabdar@Sun.COM /* Local mover connection. */ 20317917SReza.Sabdar@Sun.COM 20327917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN) { 20337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Mover is not in listen state"); 20347917SReza.Sabdar@Sun.COM return (NDMP_ILLEGAL_STATE_ERR); 20357917SReza.Sabdar@Sun.COM } 20367917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 20377917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Tape device not open"); 20387917SReza.Sabdar@Sun.COM return (NDMP_DEV_NOT_OPEN_ERR); 20397917SReza.Sabdar@Sun.COM } 20407917SReza.Sabdar@Sun.COM if (mover_mode == NDMP_MOVER_MODE_READ && 20417917SReza.Sabdar@Sun.COM session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 20427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Write protected device."); 20437917SReza.Sabdar@Sun.COM return (NDMP_WRITE_PROTECT_ERR); 20447917SReza.Sabdar@Sun.COM } 20457917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 20467917SReza.Sabdar@Sun.COM session->ns_mover.md_mode = mover_mode; 20477917SReza.Sabdar@Sun.COM 20487917SReza.Sabdar@Sun.COM return (NDMP_NO_ERR); 20497917SReza.Sabdar@Sun.COM } 20507917SReza.Sabdar@Sun.COM 20517917SReza.Sabdar@Sun.COM 20527917SReza.Sabdar@Sun.COM 20537917SReza.Sabdar@Sun.COM /* 20547917SReza.Sabdar@Sun.COM * ndmpd_mover_seek 20557917SReza.Sabdar@Sun.COM * 20567917SReza.Sabdar@Sun.COM * Seek to the requested data stream position. 20577917SReza.Sabdar@Sun.COM * If the requested offset is outside of the current window, 20587917SReza.Sabdar@Sun.COM * the mover is paused and a notify_mover_paused request is sent 20597917SReza.Sabdar@Sun.COM * notifying the client that a seek is required. 20607917SReza.Sabdar@Sun.COM * If the requested offest is within the window but not within the 20617917SReza.Sabdar@Sun.COM * current record, then the tape is positioned to the record containing 20627917SReza.Sabdar@Sun.COM * the requested offest. 20637917SReza.Sabdar@Sun.COM * The requested amount of data is then read from the tape device and 20647917SReza.Sabdar@Sun.COM * written to the data connection. 20657917SReza.Sabdar@Sun.COM * 20667917SReza.Sabdar@Sun.COM * Parameters: 20677917SReza.Sabdar@Sun.COM * session (input) - session pointer. 20687917SReza.Sabdar@Sun.COM * offset (input) - data stream position to seek to. 20697917SReza.Sabdar@Sun.COM * length (input) - amount of data that will be read. 20707917SReza.Sabdar@Sun.COM * 20717917SReza.Sabdar@Sun.COM * Returns: 20727917SReza.Sabdar@Sun.COM * 1 - seek pending completion by the NDMP client. 20737917SReza.Sabdar@Sun.COM * 0 - seek successfully completed. 20747917SReza.Sabdar@Sun.COM * -1 - error. 20757917SReza.Sabdar@Sun.COM */ 20767917SReza.Sabdar@Sun.COM int 20777917SReza.Sabdar@Sun.COM ndmpd_mover_seek(ndmpd_session_t *session, u_longlong_t offset, 20787917SReza.Sabdar@Sun.COM u_longlong_t length) 20797917SReza.Sabdar@Sun.COM { 20807917SReza.Sabdar@Sun.COM int ctlcmd; 20817917SReza.Sabdar@Sun.COM int ctlcnt; 20827917SReza.Sabdar@Sun.COM u_longlong_t tape_position; 20837917SReza.Sabdar@Sun.COM u_longlong_t buf_position; 20847917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request pause_request; 20857917SReza.Sabdar@Sun.COM 20867917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position = offset; 20877917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = length; 20887917SReza.Sabdar@Sun.COM 20897917SReza.Sabdar@Sun.COM /* 20907917SReza.Sabdar@Sun.COM * If the requested position is outside of the window, 20917917SReza.Sabdar@Sun.COM * notify the client that a seek is required. 20927917SReza.Sabdar@Sun.COM */ 20937917SReza.Sabdar@Sun.COM if (session->ns_mover.md_seek_position < 20947917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset || 20957917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position >= 20967917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 20977917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) { 20987917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "MOVER_PAUSE_SEEK(%llu)", 20997917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position); 21007917SReza.Sabdar@Sun.COM 21017917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 21027917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 21037917SReza.Sabdar@Sun.COM 21047917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 21057917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 21067917SReza.Sabdar@Sun.COM pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 21077917SReza.Sabdar@Sun.COM pause_request.seek_position = long_long_to_quad(offset); 21087917SReza.Sabdar@Sun.COM 21097917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, 21107917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 21117917SReza.Sabdar@Sun.COM (void *) &pause_request, 0) < 0) { 21127917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 21137917SReza.Sabdar@Sun.COM "Sending notify_mover_paused request"); 21147917SReza.Sabdar@Sun.COM return (-1); 21157917SReza.Sabdar@Sun.COM } 21167917SReza.Sabdar@Sun.COM return (1); 21177917SReza.Sabdar@Sun.COM } 21187917SReza.Sabdar@Sun.COM /* 21197917SReza.Sabdar@Sun.COM * Determine the data stream position of the first byte in the 21207917SReza.Sabdar@Sun.COM * data buffer. 21217917SReza.Sabdar@Sun.COM */ 21227917SReza.Sabdar@Sun.COM buf_position = session->ns_mover.md_position - 21237917SReza.Sabdar@Sun.COM (session->ns_mover.md_position % session->ns_mover.md_record_size); 21247917SReza.Sabdar@Sun.COM 21257917SReza.Sabdar@Sun.COM /* 21267917SReza.Sabdar@Sun.COM * Determine the data stream position of the next byte that 21277917SReza.Sabdar@Sun.COM * will be read from tape. 21287917SReza.Sabdar@Sun.COM */ 21297917SReza.Sabdar@Sun.COM tape_position = buf_position; 21307917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index != 0) 21317917SReza.Sabdar@Sun.COM tape_position += session->ns_mover.md_record_size; 21327917SReza.Sabdar@Sun.COM 21337917SReza.Sabdar@Sun.COM /* 21347917SReza.Sabdar@Sun.COM * Check if requested position is for data that has been read and is 21357917SReza.Sabdar@Sun.COM * in the buffer. 21367917SReza.Sabdar@Sun.COM */ 21377917SReza.Sabdar@Sun.COM if (offset >= buf_position && offset < tape_position) { 21387917SReza.Sabdar@Sun.COM session->ns_mover.md_position = offset; 21397917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = session->ns_mover.md_position - 21407917SReza.Sabdar@Sun.COM buf_position; 21417917SReza.Sabdar@Sun.COM 21427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos %llu r_index %u", 21437917SReza.Sabdar@Sun.COM session->ns_mover.md_position, 21447917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index); 21457917SReza.Sabdar@Sun.COM 21467917SReza.Sabdar@Sun.COM return (0); 21477917SReza.Sabdar@Sun.COM } 21487917SReza.Sabdar@Sun.COM 21497917SReza.Sabdar@Sun.COM ctlcmd = 0; 21507917SReza.Sabdar@Sun.COM if (tape_position > session->ns_mover.md_seek_position) { 21517917SReza.Sabdar@Sun.COM /* Need to seek backward. */ 21527917SReza.Sabdar@Sun.COM ctlcmd = MTBSR; 21537917SReza.Sabdar@Sun.COM ctlcnt = (int)((tape_position - offset - 1) 21547917SReza.Sabdar@Sun.COM / session->ns_mover.md_record_size) + 1; 21557917SReza.Sabdar@Sun.COM tape_position -= ((u_longlong_t)(((tape_position - offset - 1) / 21567917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size) + 1) * 21577917SReza.Sabdar@Sun.COM (u_longlong_t)session->ns_mover.md_record_size); 21587917SReza.Sabdar@Sun.COM 21597917SReza.Sabdar@Sun.COM } else if (offset >= tape_position + session->ns_mover.md_record_size) { 21607917SReza.Sabdar@Sun.COM /* Need to seek forward. */ 21617917SReza.Sabdar@Sun.COM ctlcmd = MTFSR; 21627917SReza.Sabdar@Sun.COM ctlcnt = (int)((offset - tape_position) 21637917SReza.Sabdar@Sun.COM / session->ns_mover.md_record_size); 21647917SReza.Sabdar@Sun.COM tape_position += ((u_longlong_t)(((offset - tape_position) / 21657917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size)) * 21667917SReza.Sabdar@Sun.COM (u_longlong_t)session->ns_mover.md_record_size); 21677917SReza.Sabdar@Sun.COM } 21687917SReza.Sabdar@Sun.COM /* Reposition the tape if necessary. */ 21697917SReza.Sabdar@Sun.COM if (ctlcmd) { 21707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "cmd %d count %d", 21717917SReza.Sabdar@Sun.COM ctlcmd, ctlcnt); 21727917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, ctlcmd, ctlcnt); 21737917SReza.Sabdar@Sun.COM } 21747917SReza.Sabdar@Sun.COM 21757917SReza.Sabdar@Sun.COM session->ns_mover.md_position = tape_position; 21767917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 21777917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 21787917SReza.Sabdar@Sun.COM 21797917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos %llu", session->ns_mover.md_position); 21807917SReza.Sabdar@Sun.COM 21817917SReza.Sabdar@Sun.COM return (0); 21827917SReza.Sabdar@Sun.COM } 21837917SReza.Sabdar@Sun.COM 21847917SReza.Sabdar@Sun.COM 21857917SReza.Sabdar@Sun.COM /* ** static functions ************************************************** */ 21867917SReza.Sabdar@Sun.COM 21877917SReza.Sabdar@Sun.COM /* 21887917SReza.Sabdar@Sun.COM * create_listen_socket_v2 21897917SReza.Sabdar@Sun.COM * 21907917SReza.Sabdar@Sun.COM * Creates a socket for listening for accepting data connections. 21917917SReza.Sabdar@Sun.COM * 21927917SReza.Sabdar@Sun.COM * Parameters: 21937917SReza.Sabdar@Sun.COM * session (input) - session pointer. 21947917SReza.Sabdar@Sun.COM * addr (output) - location to store address of socket. 21957917SReza.Sabdar@Sun.COM * port (output) - location to store port of socket. 21967917SReza.Sabdar@Sun.COM * 21977917SReza.Sabdar@Sun.COM * Returns: 21987917SReza.Sabdar@Sun.COM * 0 - success. 21997917SReza.Sabdar@Sun.COM * -1 - error. 22007917SReza.Sabdar@Sun.COM */ 22017917SReza.Sabdar@Sun.COM static int 22027917SReza.Sabdar@Sun.COM create_listen_socket_v2(ndmpd_session_t *session, ulong_t *addr, ushort_t *port) 22037917SReza.Sabdar@Sun.COM { 22047917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = ndmp_create_socket(addr, port); 22057917SReza.Sabdar@Sun.COM if (session->ns_mover.md_listen_sock < 0) 22067917SReza.Sabdar@Sun.COM return (-1); 22077917SReza.Sabdar@Sun.COM 22087917SReza.Sabdar@Sun.COM /* 22097917SReza.Sabdar@Sun.COM * Add a file handler for the listen socket. 22107917SReza.Sabdar@Sun.COM * ndmpd_select will call accept_connection when a 22117917SReza.Sabdar@Sun.COM * connection is ready to be accepted. 22127917SReza.Sabdar@Sun.COM */ 22137917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void *) session, 22147917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER, 22157917SReza.Sabdar@Sun.COM accept_connection) < 0) { 22167917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 22177917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 22187917SReza.Sabdar@Sun.COM return (-1); 22197917SReza.Sabdar@Sun.COM } 22207917SReza.Sabdar@Sun.COM 22217917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "addr: 0x%x, port: %d", *addr, *port); 22227917SReza.Sabdar@Sun.COM return (0); 22237917SReza.Sabdar@Sun.COM } 22247917SReza.Sabdar@Sun.COM 22257917SReza.Sabdar@Sun.COM 22267917SReza.Sabdar@Sun.COM /* 22277917SReza.Sabdar@Sun.COM * accept_connection 22287917SReza.Sabdar@Sun.COM * 22297917SReza.Sabdar@Sun.COM * Accept a data connection from a data server. 22307917SReza.Sabdar@Sun.COM * Called by ndmpd_select when a connection is pending on 22317917SReza.Sabdar@Sun.COM * the mover listen socket. 22327917SReza.Sabdar@Sun.COM * 22337917SReza.Sabdar@Sun.COM * Parameters: 22347917SReza.Sabdar@Sun.COM * cookie (input) - session pointer. 22357917SReza.Sabdar@Sun.COM * fd (input) - file descriptor. 22367917SReza.Sabdar@Sun.COM * mode (input) - select mode. 22377917SReza.Sabdar@Sun.COM * 22387917SReza.Sabdar@Sun.COM * Returns: 22397917SReza.Sabdar@Sun.COM * void. 22407917SReza.Sabdar@Sun.COM */ 22417917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 22427917SReza.Sabdar@Sun.COM static void 22437917SReza.Sabdar@Sun.COM accept_connection(void *cookie, int fd, ulong_t mode) 22447917SReza.Sabdar@Sun.COM { 22457917SReza.Sabdar@Sun.COM ndmpd_session_t *session = (ndmpd_session_t *)cookie; 22467917SReza.Sabdar@Sun.COM struct sockaddr_in from; 22477917SReza.Sabdar@Sun.COM int from_len; 22487917SReza.Sabdar@Sun.COM int flag = 1; 22497917SReza.Sabdar@Sun.COM 22507917SReza.Sabdar@Sun.COM from_len = sizeof (from); 22517917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = accept(fd, (struct sockaddr *)&from, 22527917SReza.Sabdar@Sun.COM &from_len); 22537917SReza.Sabdar@Sun.COM 22547917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, fd); 22557917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 22567917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 22577917SReza.Sabdar@Sun.COM 22587917SReza.Sabdar@Sun.COM if (session->ns_mover.md_sock < 0) { 22597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Accept error: %m"); 22607917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_ERROR); 22617917SReza.Sabdar@Sun.COM return; 22627917SReza.Sabdar@Sun.COM } 22637917SReza.Sabdar@Sun.COM 22647917SReza.Sabdar@Sun.COM (void) setsockopt(session->ns_mover.md_sock, SOL_SOCKET, SO_KEEPALIVE, 22657917SReza.Sabdar@Sun.COM &flag, sizeof (flag)); 22667917SReza.Sabdar@Sun.COM ndmp_set_socket_nodelay(session->ns_mover.md_sock); 22677917SReza.Sabdar@Sun.COM ndmp_set_socket_rcv_buf(session->ns_mover.md_sock, 60 * KILOBYTE); 22687917SReza.Sabdar@Sun.COM ndmp_set_socket_snd_buf(session->ns_mover.md_sock, 60 * KILOBYTE); 22697917SReza.Sabdar@Sun.COM 22707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "sock fd: %d", session->ns_mover.md_sock); 22717917SReza.Sabdar@Sun.COM 22727917SReza.Sabdar@Sun.COM if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) { 22737917SReza.Sabdar@Sun.COM if (start_mover_for_backup(session) < 0) { 22747917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 22757917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 22767917SReza.Sabdar@Sun.COM return; 22777917SReza.Sabdar@Sun.COM } 22787917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Backup connection established by %s:%d", 22797917SReza.Sabdar@Sun.COM inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 22807917SReza.Sabdar@Sun.COM ntohs(from.sin_port)); 22817917SReza.Sabdar@Sun.COM } else { 22827917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Restore connection established by %s:%d", 22837917SReza.Sabdar@Sun.COM inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 22847917SReza.Sabdar@Sun.COM ntohs(from.sin_port)); 22857917SReza.Sabdar@Sun.COM } 22867917SReza.Sabdar@Sun.COM 22877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Received connection"); 22887917SReza.Sabdar@Sun.COM 22897917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 22907917SReza.Sabdar@Sun.COM } 22917917SReza.Sabdar@Sun.COM 22927917SReza.Sabdar@Sun.COM /* 22937917SReza.Sabdar@Sun.COM * tape_write 22947917SReza.Sabdar@Sun.COM * 22957917SReza.Sabdar@Sun.COM * Writes a data record to tape. Detects and handles EOT conditions. 22967917SReza.Sabdar@Sun.COM * 22977917SReza.Sabdar@Sun.COM * Parameters: 22987917SReza.Sabdar@Sun.COM * session (input) - session pointer. 22997917SReza.Sabdar@Sun.COM * data (input) - data to be written. 23007917SReza.Sabdar@Sun.COM * length (input) - length of data to be written. 23017917SReza.Sabdar@Sun.COM * 23027917SReza.Sabdar@Sun.COM * Returns: 23037917SReza.Sabdar@Sun.COM * 0 - operation aborted by client. 23047917SReza.Sabdar@Sun.COM * -1 - error. 23057917SReza.Sabdar@Sun.COM * otherwise - number of bytes written. 23067917SReza.Sabdar@Sun.COM */ 23077917SReza.Sabdar@Sun.COM static int 23087917SReza.Sabdar@Sun.COM tape_write(ndmpd_session_t *session, char *data, ssize_t length) 23097917SReza.Sabdar@Sun.COM { 23107917SReza.Sabdar@Sun.COM ssize_t n; 23117917SReza.Sabdar@Sun.COM int err; 23127917SReza.Sabdar@Sun.COM 23137917SReza.Sabdar@Sun.COM for (; ; ) { 23147917SReza.Sabdar@Sun.COM /* 23157917SReza.Sabdar@Sun.COM * Refer to the comment at the top of ndmpd_tape.c file for 23167917SReza.Sabdar@Sun.COM * Mammoth2 tape drives. 23177917SReza.Sabdar@Sun.COM */ 23187917SReza.Sabdar@Sun.COM if (session->ns_tape.td_eom_seen) { 23197917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "eom_seen"); 23207917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 23217917SReza.Sabdar@Sun.COM /* 23227917SReza.Sabdar@Sun.COM * End of media reached. 23237917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 23247917SReza.Sabdar@Sun.COM * either abort the operation or continue the 23257917SReza.Sabdar@Sun.COM * operation after changing the tape. 23267917SReza.Sabdar@Sun.COM */ 23277917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 23287917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 23297917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape.\n"); 23307917SReza.Sabdar@Sun.COM 23317917SReza.Sabdar@Sun.COM err = change_tape(session); 23327917SReza.Sabdar@Sun.COM 23337917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 23347917SReza.Sabdar@Sun.COM if (err < 0) 23357917SReza.Sabdar@Sun.COM return (-1); 23367917SReza.Sabdar@Sun.COM 23377917SReza.Sabdar@Sun.COM continue; 23387917SReza.Sabdar@Sun.COM } 23397917SReza.Sabdar@Sun.COM 23407917SReza.Sabdar@Sun.COM n = write(session->ns_tape.td_fd, data, length); 23417917SReza.Sabdar@Sun.COM if (n < 0) { 23427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape write error: %m."); 23437917SReza.Sabdar@Sun.COM return (-1); 23447917SReza.Sabdar@Sun.COM } 23457917SReza.Sabdar@Sun.COM NS_ADD(wtape, n); 23467917SReza.Sabdar@Sun.COM 23477917SReza.Sabdar@Sun.COM if (n == 0 || n != length) { 23487917SReza.Sabdar@Sun.COM if (n != 0) { 23497917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "LEOT n: %d", n); 23507917SReza.Sabdar@Sun.COM 23517917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Backup one record"); 23527917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, 23537917SReza.Sabdar@Sun.COM MTBSR, 1); 23547917SReza.Sabdar@Sun.COM 23557917SReza.Sabdar@Sun.COM /* setting logical EOM */ 23567917SReza.Sabdar@Sun.COM ndmpd_write_eom(session->ns_tape.td_fd); 23577917SReza.Sabdar@Sun.COM } 23587917SReza.Sabdar@Sun.COM 23597917SReza.Sabdar@Sun.COM /* 23607917SReza.Sabdar@Sun.COM * End of media reached. 23617917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 23627917SReza.Sabdar@Sun.COM * either abort the operation or continue the 23637917SReza.Sabdar@Sun.COM * operation after changing the tape. 23647917SReza.Sabdar@Sun.COM */ 23657917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 23667917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 23677917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape.\n"); 23687917SReza.Sabdar@Sun.COM 23697917SReza.Sabdar@Sun.COM err = change_tape(session); 23707917SReza.Sabdar@Sun.COM 23717917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 23727917SReza.Sabdar@Sun.COM if (err < 0) 23737917SReza.Sabdar@Sun.COM return (-1); 23747917SReza.Sabdar@Sun.COM 23757917SReza.Sabdar@Sun.COM /* Retry the write to the new tape. */ 23767917SReza.Sabdar@Sun.COM continue; 23777917SReza.Sabdar@Sun.COM } 23787917SReza.Sabdar@Sun.COM 23797917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count++; 23807917SReza.Sabdar@Sun.COM return (n); 23817917SReza.Sabdar@Sun.COM } 23827917SReza.Sabdar@Sun.COM } 23837917SReza.Sabdar@Sun.COM 23847917SReza.Sabdar@Sun.COM 23857917SReza.Sabdar@Sun.COM /* 23867917SReza.Sabdar@Sun.COM * tape_read 23877917SReza.Sabdar@Sun.COM * 23887917SReza.Sabdar@Sun.COM * Reads a data record from tape. Detects and handles EOT conditions. 23897917SReza.Sabdar@Sun.COM * 23907917SReza.Sabdar@Sun.COM * Parameters: 23917917SReza.Sabdar@Sun.COM * session (input) - session pointer. 23927917SReza.Sabdar@Sun.COM * data (input) - location to read data to. 23937917SReza.Sabdar@Sun.COM * 23947917SReza.Sabdar@Sun.COM * Returns: 23957917SReza.Sabdar@Sun.COM * 0 - operation aborted. 23967917SReza.Sabdar@Sun.COM * -1 - tape read error. 23977917SReza.Sabdar@Sun.COM * otherwise - number of bytes read. 23987917SReza.Sabdar@Sun.COM */ 23997917SReza.Sabdar@Sun.COM static int 24007917SReza.Sabdar@Sun.COM tape_read(ndmpd_session_t *session, char *data) 24017917SReza.Sabdar@Sun.COM { 24027917SReza.Sabdar@Sun.COM ssize_t n; 24037917SReza.Sabdar@Sun.COM int err; 24047917SReza.Sabdar@Sun.COM int count = session->ns_mover.md_record_size; 24057917SReza.Sabdar@Sun.COM 24067917SReza.Sabdar@Sun.COM for (; ; ) { 24077917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, data, count); 24087917SReza.Sabdar@Sun.COM if (n < 0) { 24097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape read error: %m."); 24107917SReza.Sabdar@Sun.COM return (TAPE_READ_ERR); 24117917SReza.Sabdar@Sun.COM } 24127917SReza.Sabdar@Sun.COM NS_ADD(rtape, n); 24137917SReza.Sabdar@Sun.COM 24147917SReza.Sabdar@Sun.COM if (n == 0) { 24157917SReza.Sabdar@Sun.COM if (!is_writer_running(session)) 24167917SReza.Sabdar@Sun.COM return (TAPE_NO_WRITER_ERR); 24177917SReza.Sabdar@Sun.COM 24187917SReza.Sabdar@Sun.COM /* 24197917SReza.Sabdar@Sun.COM * End of media reached. 24207917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 24217917SReza.Sabdar@Sun.COM * either abort the data operation or continue the 24227917SReza.Sabdar@Sun.COM * operation after changing the tape. 24237917SReza.Sabdar@Sun.COM */ 24247917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 24257917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 24267917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape"); 24277917SReza.Sabdar@Sun.COM 24287917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 24297917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape"); 24307917SReza.Sabdar@Sun.COM 24317917SReza.Sabdar@Sun.COM err = change_tape(session); 24327917SReza.Sabdar@Sun.COM 24337917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 24347917SReza.Sabdar@Sun.COM if (err < 0) { 24357917SReza.Sabdar@Sun.COM /* 24367917SReza.Sabdar@Sun.COM * K.L. Go back one record if it is read 24377917SReza.Sabdar@Sun.COM * but not used. 24387917SReza.Sabdar@Sun.COM */ 24397917SReza.Sabdar@Sun.COM 24407917SReza.Sabdar@Sun.COM if (count != session->ns_mover.md_record_size) { 24417917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl( 24427917SReza.Sabdar@Sun.COM session->ns_tape.td_fd, MTBSR, 1); 24437917SReza.Sabdar@Sun.COM } 24447917SReza.Sabdar@Sun.COM return (0); 24457917SReza.Sabdar@Sun.COM } 24467917SReza.Sabdar@Sun.COM /* Retry the read from the new tape. */ 24477917SReza.Sabdar@Sun.COM continue; 24487917SReza.Sabdar@Sun.COM } 24497917SReza.Sabdar@Sun.COM 24507917SReza.Sabdar@Sun.COM /* Change to pass Veritas Netbackup prequal test. */ 24517917SReza.Sabdar@Sun.COM data += n; 24527917SReza.Sabdar@Sun.COM count -= n; 24537917SReza.Sabdar@Sun.COM if (count <= 0) { 24547917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 24557917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count++; 24567917SReza.Sabdar@Sun.COM return (n); 24577917SReza.Sabdar@Sun.COM } 24587917SReza.Sabdar@Sun.COM } 24597917SReza.Sabdar@Sun.COM } 24607917SReza.Sabdar@Sun.COM 24617917SReza.Sabdar@Sun.COM /* 24627917SReza.Sabdar@Sun.COM * change_tape 24637917SReza.Sabdar@Sun.COM * 24647917SReza.Sabdar@Sun.COM * Send a notify_pause request (protocol version 1) or 24657917SReza.Sabdar@Sun.COM * notify_mover_pause request (protocol version 2) to the 24667917SReza.Sabdar@Sun.COM * NDMP client to inform 24677917SReza.Sabdar@Sun.COM * the client that a tape volume change is required. 24687917SReza.Sabdar@Sun.COM * Process messages until the data/mover operation is either aborted 24697917SReza.Sabdar@Sun.COM * or continued. 24707917SReza.Sabdar@Sun.COM * 24717917SReza.Sabdar@Sun.COM * Parameters: 24727917SReza.Sabdar@Sun.COM * client_data (input) - session pointer. 24737917SReza.Sabdar@Sun.COM * 24747917SReza.Sabdar@Sun.COM * Returns: 24757917SReza.Sabdar@Sun.COM * 0 - operation has been continued. 24767917SReza.Sabdar@Sun.COM * -1 - operation has been aborted. 24777917SReza.Sabdar@Sun.COM */ 24787917SReza.Sabdar@Sun.COM static int 24797917SReza.Sabdar@Sun.COM change_tape(ndmpd_session_t *session) 24807917SReza.Sabdar@Sun.COM { 24817917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request request; 24827917SReza.Sabdar@Sun.COM 24837917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 24847917SReza.Sabdar@Sun.COM 24857917SReza.Sabdar@Sun.COM if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) 24867917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_EOM; 24877917SReza.Sabdar@Sun.COM else 24887917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_EOF; 24897917SReza.Sabdar@Sun.COM 24907917SReza.Sabdar@Sun.COM request.reason = session->ns_mover.md_pause_reason; 24917917SReza.Sabdar@Sun.COM request.seek_position = long_long_to_quad(0LL); 24927917SReza.Sabdar@Sun.COM 24937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ndmp_send_request: MOVER_PAUSED, reason: %d", 24947917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason); 24957917SReza.Sabdar@Sun.COM 24967917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, 24977917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 24987917SReza.Sabdar@Sun.COM (void *) &request, 0) < 0) { 24997917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 25007917SReza.Sabdar@Sun.COM "Sending notify_mover_paused request"); 25017917SReza.Sabdar@Sun.COM return (-1); 25027917SReza.Sabdar@Sun.COM } 25037917SReza.Sabdar@Sun.COM /* 25047917SReza.Sabdar@Sun.COM * Wait for until the state is changed by 25057917SReza.Sabdar@Sun.COM * an abort or continue request. 25067917SReza.Sabdar@Sun.COM */ 25077917SReza.Sabdar@Sun.COM nlp_ref_nw(session); 25087917SReza.Sabdar@Sun.COM for (; ; ) { 25097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "calling nlp_wait_nw()"); 25107917SReza.Sabdar@Sun.COM 25117917SReza.Sabdar@Sun.COM nlp_wait_nw(session); 25127917SReza.Sabdar@Sun.COM 25137917SReza.Sabdar@Sun.COM if (nlp_event_rv_get(session) < 0) { 25147917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 25157917SReza.Sabdar@Sun.COM return (-1); 25167917SReza.Sabdar@Sun.COM } 25177917SReza.Sabdar@Sun.COM 25187917SReza.Sabdar@Sun.COM if (session->ns_eof == TRUE) { 25197917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "session->ns_eof == TRUE"); 25207917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 25217917SReza.Sabdar@Sun.COM return (-1); 25227917SReza.Sabdar@Sun.COM } 25237917SReza.Sabdar@Sun.COM 25247917SReza.Sabdar@Sun.COM switch (session->ns_mover.md_state) { 25257917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_ACTIVE: 25267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 25277917SReza.Sabdar@Sun.COM "mover.state: NDMP_MOVER_STATE_ACTIVE"); 25287917SReza.Sabdar@Sun.COM 25297917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 25307917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 25317917SReza.Sabdar@Sun.COM return (0); 25327917SReza.Sabdar@Sun.COM 25337917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_PAUSED: 25347917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 25357917SReza.Sabdar@Sun.COM "mover.state: NDMP_MOVER_STATE_PAUSED"); 25367917SReza.Sabdar@Sun.COM continue; 25377917SReza.Sabdar@Sun.COM 25387917SReza.Sabdar@Sun.COM default: 25397917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "default"); 25407917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 25417917SReza.Sabdar@Sun.COM return (-1); 25427917SReza.Sabdar@Sun.COM } 25437917SReza.Sabdar@Sun.COM } 25447917SReza.Sabdar@Sun.COM 25457917SReza.Sabdar@Sun.COM /* nlp_unref_nw(session); - statement never reached */ 25467917SReza.Sabdar@Sun.COM } 25477917SReza.Sabdar@Sun.COM 25487917SReza.Sabdar@Sun.COM 25497917SReza.Sabdar@Sun.COM /* 25507917SReza.Sabdar@Sun.COM * discard_data 25517917SReza.Sabdar@Sun.COM * 25527917SReza.Sabdar@Sun.COM * Read and discard data from the data connection. 25537917SReza.Sabdar@Sun.COM * Called when a module has called ndmpd_seek() prior to 25547917SReza.Sabdar@Sun.COM * reading all of the data from the previous seek. 25557917SReza.Sabdar@Sun.COM * 25567917SReza.Sabdar@Sun.COM * Parameters: 25577917SReza.Sabdar@Sun.COM * session (input) - session pointer. 25587917SReza.Sabdar@Sun.COM * 25597917SReza.Sabdar@Sun.COM * Returns: 25607917SReza.Sabdar@Sun.COM * number of bytes read and discarded. 25617917SReza.Sabdar@Sun.COM * -1 - error. 25627917SReza.Sabdar@Sun.COM */ 25637917SReza.Sabdar@Sun.COM static int 25647917SReza.Sabdar@Sun.COM discard_data(ndmpd_session_t *session, ulong_t length) 25657917SReza.Sabdar@Sun.COM { 25667917SReza.Sabdar@Sun.COM int n; 25677917SReza.Sabdar@Sun.COM char *addr; 25687917SReza.Sabdar@Sun.COM 25697917SReza.Sabdar@Sun.COM if ((addr = ndmp_malloc(length)) == NULL) 25707917SReza.Sabdar@Sun.COM return (-1); 25717917SReza.Sabdar@Sun.COM 25727917SReza.Sabdar@Sun.COM /* Read and discard the data. */ 25737917SReza.Sabdar@Sun.COM n = read(session->ns_mover.md_sock, addr, length); 25747917SReza.Sabdar@Sun.COM if (n < 0) { 25757917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Socket read error: %m."); 25767917SReza.Sabdar@Sun.COM free(addr); 25777917SReza.Sabdar@Sun.COM return (-1); 25787917SReza.Sabdar@Sun.COM } 25797917SReza.Sabdar@Sun.COM 25807917SReza.Sabdar@Sun.COM free(addr); 25817917SReza.Sabdar@Sun.COM return (n); 25827917SReza.Sabdar@Sun.COM } 25837917SReza.Sabdar@Sun.COM 25847917SReza.Sabdar@Sun.COM 25857917SReza.Sabdar@Sun.COM /* 25867917SReza.Sabdar@Sun.COM * mover_tape_read_one_buf 25877917SReza.Sabdar@Sun.COM * 25887917SReza.Sabdar@Sun.COM * Read one buffer from the tape. This is used by mover_tape_reader 25897917SReza.Sabdar@Sun.COM * 25907917SReza.Sabdar@Sun.COM * Parameters: 25917917SReza.Sabdar@Sun.COM * session (input) - session pointer. 25927917SReza.Sabdar@Sun.COM * buf (input) - buffer read 25937917SReza.Sabdar@Sun.COM * 25947917SReza.Sabdar@Sun.COM * Returns: 25957917SReza.Sabdar@Sun.COM * 0: on success 25967917SReza.Sabdar@Sun.COM * -1: otherwise 25977917SReza.Sabdar@Sun.COM */ 25987917SReza.Sabdar@Sun.COM static int 25997917SReza.Sabdar@Sun.COM mover_tape_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 26007917SReza.Sabdar@Sun.COM { 26017917SReza.Sabdar@Sun.COM int n; 26027917SReza.Sabdar@Sun.COM 26037917SReza.Sabdar@Sun.COM tlm_buffer_mark_empty(buf); 26047917SReza.Sabdar@Sun.COM 26057917SReza.Sabdar@Sun.COM /* 26067917SReza.Sabdar@Sun.COM * If the end of the mover window has been reached, 26077917SReza.Sabdar@Sun.COM * then notify the client that a seek is needed. 26087917SReza.Sabdar@Sun.COM * Remove the file handler to prevent this function from 26097917SReza.Sabdar@Sun.COM * being called. The handler will be reinstalled in 26107917SReza.Sabdar@Sun.COM * ndmpd_mover_continue. 26117917SReza.Sabdar@Sun.COM */ 26127917SReza.Sabdar@Sun.COM 26137917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position >= 26147917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 26157917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) { 26167917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request pause_request; 26177917SReza.Sabdar@Sun.COM 26187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "end of mover window"); 26197917SReza.Sabdar@Sun.COM 26207917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 26217917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 26227917SReza.Sabdar@Sun.COM pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 26237917SReza.Sabdar@Sun.COM pause_request.seek_position = 26247917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_position); 26257917SReza.Sabdar@Sun.COM 26267917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, 26277917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 26287917SReza.Sabdar@Sun.COM (void *) &pause_request, 0) < 0) { 26297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 26307917SReza.Sabdar@Sun.COM "Sending notify_mover_paused request"); 26317917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 26327917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 26337917SReza.Sabdar@Sun.COM } 26347917SReza.Sabdar@Sun.COM buf->tb_errno = EIO; 26357917SReza.Sabdar@Sun.COM return (TAPE_READ_ERR); 26367917SReza.Sabdar@Sun.COM } 26377917SReza.Sabdar@Sun.COM 26387917SReza.Sabdar@Sun.COM n = tape_read(session, buf->tb_buffer_data); 26397917SReza.Sabdar@Sun.COM 26407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "read %d bytes from tape", n); 26417917SReza.Sabdar@Sun.COM 26427917SReza.Sabdar@Sun.COM if (n <= 0) { 26437917SReza.Sabdar@Sun.COM if (n < 0) 26447917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 26457917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 26467917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR)); 26477917SReza.Sabdar@Sun.COM return (TAPE_READ_ERR); 26487917SReza.Sabdar@Sun.COM } 26497917SReza.Sabdar@Sun.COM 26507917SReza.Sabdar@Sun.COM buf->tb_full = TRUE; 26517917SReza.Sabdar@Sun.COM buf->tb_buffer_size = session->ns_mover.md_record_size; 26527917SReza.Sabdar@Sun.COM 26537917SReza.Sabdar@Sun.COM /* 26547917SReza.Sabdar@Sun.COM * Discard data if the current data stream position is 26557917SReza.Sabdar@Sun.COM * prior to the seek position. This is necessary if a seek 26567917SReza.Sabdar@Sun.COM * request set the seek pointer to a position that is not a 26577917SReza.Sabdar@Sun.COM * record boundary. The seek request handler can only position 26587917SReza.Sabdar@Sun.COM * to the start of a record. 26597917SReza.Sabdar@Sun.COM */ 26607917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position < session->ns_mover.md_seek_position) 26617917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 26627917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position; 26637917SReza.Sabdar@Sun.COM 26647917SReza.Sabdar@Sun.COM return (0); 26657917SReza.Sabdar@Sun.COM } 26667917SReza.Sabdar@Sun.COM 26677917SReza.Sabdar@Sun.COM 26687917SReza.Sabdar@Sun.COM /* 26697917SReza.Sabdar@Sun.COM * mover_tape_reader 26707917SReza.Sabdar@Sun.COM * 26717917SReza.Sabdar@Sun.COM * Mover tape reader thread. It is launched when the mover is started 26727917SReza.Sabdar@Sun.COM * for restore. 26737917SReza.Sabdar@Sun.COM * 26747917SReza.Sabdar@Sun.COM * Parameters: 26757917SReza.Sabdar@Sun.COM * session (input) - session pointer. 26767917SReza.Sabdar@Sun.COM * 26777917SReza.Sabdar@Sun.COM * Returns: 26787917SReza.Sabdar@Sun.COM * 0: on success 26797917SReza.Sabdar@Sun.COM * -1: otherwise 26807917SReza.Sabdar@Sun.COM */ 26817917SReza.Sabdar@Sun.COM int 26827917SReza.Sabdar@Sun.COM mover_tape_reader(ndmpd_session_t *session) 26837917SReza.Sabdar@Sun.COM { 26847917SReza.Sabdar@Sun.COM int bidx; /* buffer index */ 26857917SReza.Sabdar@Sun.COM int rv; 26867917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 26877917SReza.Sabdar@Sun.COM tlm_buffer_t *buf; 26887917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 26897917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; /* Local command */ 26907917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; /* Commands structure */ 26917917SReza.Sabdar@Sun.COM 26927917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 26937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 26947917SReza.Sabdar@Sun.COM return (-1); 26957917SReza.Sabdar@Sun.COM } 26967917SReza.Sabdar@Sun.COM 26977917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 26987917SReza.Sabdar@Sun.COM lcmd = cmds->tcs_command; 26997917SReza.Sabdar@Sun.COM bufs = lcmd->tc_buffers; 27007917SReza.Sabdar@Sun.COM 27017917SReza.Sabdar@Sun.COM lcmd->tc_ref++; 27027917SReza.Sabdar@Sun.COM cmds->tcs_reader_count++; 27037917SReza.Sabdar@Sun.COM 27047917SReza.Sabdar@Sun.COM /* 27057917SReza.Sabdar@Sun.COM * Let our parent thread know that we are running. 27067917SReza.Sabdar@Sun.COM */ 27077917SReza.Sabdar@Sun.COM tlm_cmd_signal(cmds->tcs_command, TLM_TAPE_READER); 27087917SReza.Sabdar@Sun.COM 27097917SReza.Sabdar@Sun.COM buf = tlm_buffer_in_buf(bufs, &bidx); 27107917SReza.Sabdar@Sun.COM while (cmds->tcs_reader == TLM_RESTORE_RUN && 27117917SReza.Sabdar@Sun.COM lcmd->tc_reader == TLM_RESTORE_RUN) { 27127917SReza.Sabdar@Sun.COM buf = tlm_buffer_in_buf(bufs, NULL); 27137917SReza.Sabdar@Sun.COM 27147917SReza.Sabdar@Sun.COM if (buf->tb_full) { 27157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "R%d", bidx); 27167917SReza.Sabdar@Sun.COM /* 27177917SReza.Sabdar@Sun.COM * The buffer is still full, wait for the consumer 27187917SReza.Sabdar@Sun.COM * thread to use it. 27197917SReza.Sabdar@Sun.COM */ 27207917SReza.Sabdar@Sun.COM tlm_buffer_out_buf_timed_wait(bufs, 100); 27217917SReza.Sabdar@Sun.COM 27227917SReza.Sabdar@Sun.COM } else { 27237917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "r%d", bidx); 27247917SReza.Sabdar@Sun.COM 27257917SReza.Sabdar@Sun.COM rv = mover_tape_read_one_buf(session, buf); 27267917SReza.Sabdar@Sun.COM /* 27277917SReza.Sabdar@Sun.COM * If there was an error while reading, such as 27287917SReza.Sabdar@Sun.COM * end of stream. 27297917SReza.Sabdar@Sun.COM */ 27307917SReza.Sabdar@Sun.COM if (rv < 0) { 27317917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Exiting, rv: %d", rv); 27327917SReza.Sabdar@Sun.COM break; 27337917SReza.Sabdar@Sun.COM } 27347917SReza.Sabdar@Sun.COM 27357917SReza.Sabdar@Sun.COM /* 27367917SReza.Sabdar@Sun.COM * Can we do more buffering? 27377917SReza.Sabdar@Sun.COM */ 27387917SReza.Sabdar@Sun.COM if (is_buffer_erroneous(buf)) { 27397917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 27407917SReza.Sabdar@Sun.COM "Exiting, errno: %d, eot: %d, eof: %d", 27417917SReza.Sabdar@Sun.COM buf->tb_errno, buf->tb_eot, buf->tb_eof); 27427917SReza.Sabdar@Sun.COM break; 27437917SReza.Sabdar@Sun.COM } 27447917SReza.Sabdar@Sun.COM 27457917SReza.Sabdar@Sun.COM (void) tlm_buffer_advance_in_idx(bufs); 27467917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 27477917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_in; 27487917SReza.Sabdar@Sun.COM } 27497917SReza.Sabdar@Sun.COM } 27507917SReza.Sabdar@Sun.COM 27517917SReza.Sabdar@Sun.COM /* If the consumer is waiting for us, wake it up. */ 27527917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 27537917SReza.Sabdar@Sun.COM 27547917SReza.Sabdar@Sun.COM /* 27557917SReza.Sabdar@Sun.COM * Clean up. 27567917SReza.Sabdar@Sun.COM */ 27577917SReza.Sabdar@Sun.COM cmds->tcs_reader_count--; 27587917SReza.Sabdar@Sun.COM lcmd->tc_ref--; 27597917SReza.Sabdar@Sun.COM lcmd->tc_writer = TLM_STOP; 27607917SReza.Sabdar@Sun.COM return (0); 27617917SReza.Sabdar@Sun.COM } 27627917SReza.Sabdar@Sun.COM 27637917SReza.Sabdar@Sun.COM 27647917SReza.Sabdar@Sun.COM /* 27657917SReza.Sabdar@Sun.COM * mover_socket_write_one_buf 27667917SReza.Sabdar@Sun.COM * 27677917SReza.Sabdar@Sun.COM * Write one buffer to the network socket. This is used by mover_socket_writer 27687917SReza.Sabdar@Sun.COM * 27697917SReza.Sabdar@Sun.COM * Parameters: 27707917SReza.Sabdar@Sun.COM * session (input) - session pointer. 27717917SReza.Sabdar@Sun.COM * buf (input) - buffer read 27727917SReza.Sabdar@Sun.COM * 27737917SReza.Sabdar@Sun.COM * Returns: 27747917SReza.Sabdar@Sun.COM * 0: on success 27757917SReza.Sabdar@Sun.COM * -1: otherwise 27767917SReza.Sabdar@Sun.COM */ 27777917SReza.Sabdar@Sun.COM static int 27787917SReza.Sabdar@Sun.COM mover_socket_write_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 27797917SReza.Sabdar@Sun.COM { 27807917SReza.Sabdar@Sun.COM int n; 27817917SReza.Sabdar@Sun.COM 27827917SReza.Sabdar@Sun.COM /* Write the data to the data connection. */ 27837917SReza.Sabdar@Sun.COM errno = 0; 27847917SReza.Sabdar@Sun.COM n = write(session->ns_mover.md_sock, buf->tb_buffer_data, 27857917SReza.Sabdar@Sun.COM buf->tb_buffer_size); 27867917SReza.Sabdar@Sun.COM 27877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d, len: %d", n, buf->tb_buffer_size); 27887917SReza.Sabdar@Sun.COM 27897917SReza.Sabdar@Sun.COM if (n < 0) { 27907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d, errno: %m", n); 27917917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 27927917SReza.Sabdar@Sun.COM return (-1); 27937917SReza.Sabdar@Sun.COM } 27947917SReza.Sabdar@Sun.COM 27957917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 27967917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= n; 27977917SReza.Sabdar@Sun.COM tlm_buffer_mark_empty(buf); 27987917SReza.Sabdar@Sun.COM 27997917SReza.Sabdar@Sun.COM /* 28007917SReza.Sabdar@Sun.COM * If the read limit has been reached, 28017917SReza.Sabdar@Sun.COM * then remove the file handler to prevent this 28027917SReza.Sabdar@Sun.COM * function from getting called. The next mover_read request 28037917SReza.Sabdar@Sun.COM * will reinstall the handler. 28047917SReza.Sabdar@Sun.COM */ 28057917SReza.Sabdar@Sun.COM if (session->ns_mover.md_bytes_left_to_read == 0) { 28067917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "bytes_left_to_read == 0"); 28077917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, 28087917SReza.Sabdar@Sun.COM session->ns_mover.md_sock); 28097917SReza.Sabdar@Sun.COM return (-1); 28107917SReza.Sabdar@Sun.COM } 28117917SReza.Sabdar@Sun.COM 28127917SReza.Sabdar@Sun.COM return (0); 28137917SReza.Sabdar@Sun.COM } 28147917SReza.Sabdar@Sun.COM 28157917SReza.Sabdar@Sun.COM 28167917SReza.Sabdar@Sun.COM 28177917SReza.Sabdar@Sun.COM /* 28187917SReza.Sabdar@Sun.COM * mover_socket_writer 28197917SReza.Sabdar@Sun.COM * 28207917SReza.Sabdar@Sun.COM * Mover's socket writer thread. This thread sends the read buffer 28217917SReza.Sabdar@Sun.COM * from the tape to the data server through the network socket. 28227917SReza.Sabdar@Sun.COM * 28237917SReza.Sabdar@Sun.COM * Parameters: 28247917SReza.Sabdar@Sun.COM * session (input) - session pointer. 28257917SReza.Sabdar@Sun.COM * 28267917SReza.Sabdar@Sun.COM * Returns: 28277917SReza.Sabdar@Sun.COM * 0: on success 28287917SReza.Sabdar@Sun.COM * -1: otherwise 28297917SReza.Sabdar@Sun.COM */ 28307917SReza.Sabdar@Sun.COM int 28317917SReza.Sabdar@Sun.COM mover_socket_writer(ndmpd_session_t *session) 28327917SReza.Sabdar@Sun.COM { 28337917SReza.Sabdar@Sun.COM int bidx; /* buffer index */ 28347917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 28357917SReza.Sabdar@Sun.COM tlm_buffer_t *buf; 28367917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 28377917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; /* Local command */ 28387917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; /* Commands structure */ 28397917SReza.Sabdar@Sun.COM 28407917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 28417917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 28427917SReza.Sabdar@Sun.COM return (-1); 28437917SReza.Sabdar@Sun.COM } 28447917SReza.Sabdar@Sun.COM 28457917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 28467917SReza.Sabdar@Sun.COM lcmd = cmds->tcs_command; 28477917SReza.Sabdar@Sun.COM bufs = lcmd->tc_buffers; 28487917SReza.Sabdar@Sun.COM 28497917SReza.Sabdar@Sun.COM lcmd->tc_ref++; 28507917SReza.Sabdar@Sun.COM cmds->tcs_writer_count++; 28517917SReza.Sabdar@Sun.COM 28527917SReza.Sabdar@Sun.COM /* 28537917SReza.Sabdar@Sun.COM * Let our parent thread know that we are running. 28547917SReza.Sabdar@Sun.COM */ 28557917SReza.Sabdar@Sun.COM tlm_cmd_signal(cmds->tcs_command, TLM_SOCK_WRITER); 28567917SReza.Sabdar@Sun.COM 28577917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_out; 28587917SReza.Sabdar@Sun.COM while (cmds->tcs_writer != (int)TLM_ABORT && 28597917SReza.Sabdar@Sun.COM lcmd->tc_writer != (int)TLM_ABORT) { 28607917SReza.Sabdar@Sun.COM buf = &bufs->tbs_buffer[bidx]; 28617917SReza.Sabdar@Sun.COM 28627917SReza.Sabdar@Sun.COM if (buf->tb_full) { 28637917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "w%d", bidx); 28647917SReza.Sabdar@Sun.COM 28657917SReza.Sabdar@Sun.COM if (mover_socket_write_one_buf(session, buf) < 0) { 28667917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 28677917SReza.Sabdar@Sun.COM "mover_socket_write_one_buf() < 0"); 28687917SReza.Sabdar@Sun.COM break; 28697917SReza.Sabdar@Sun.COM } 28707917SReza.Sabdar@Sun.COM 28717917SReza.Sabdar@Sun.COM (void) tlm_buffer_advance_out_idx(bufs); 28727917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(bufs); 28737917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_out; 28747917SReza.Sabdar@Sun.COM } else { 28757917SReza.Sabdar@Sun.COM if (lcmd->tc_writer != TLM_RESTORE_RUN) { 28767917SReza.Sabdar@Sun.COM /* No more data is coming, time to exit */ 28777917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Time to exit"); 28787917SReza.Sabdar@Sun.COM break; 28797917SReza.Sabdar@Sun.COM } 28807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "W%d", bidx); 28817917SReza.Sabdar@Sun.COM /* 28827917SReza.Sabdar@Sun.COM * The buffer is not full, wait for the producer 28837917SReza.Sabdar@Sun.COM * thread to fill it. 28847917SReza.Sabdar@Sun.COM */ 2885*8800SReza.Sabdar@Sun.COM tlm_buffer_in_buf_timed_wait(bufs, 100); 28867917SReza.Sabdar@Sun.COM } 28877917SReza.Sabdar@Sun.COM } 28887917SReza.Sabdar@Sun.COM 28897917SReza.Sabdar@Sun.COM if (cmds->tcs_writer == (int)TLM_ABORT) 28907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "cmds->tcs_writer == (int)TLM_ABORT"); 28917917SReza.Sabdar@Sun.COM if (lcmd->tc_writer == (int)TLM_ABORT) 28927917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "lcmd->tc_writer == TLM_ABORT"); 28937917SReza.Sabdar@Sun.COM 28947917SReza.Sabdar@Sun.COM /* If the producer is waiting for us, wake it up. */ 28957917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(bufs); 28967917SReza.Sabdar@Sun.COM 28977917SReza.Sabdar@Sun.COM /* 28987917SReza.Sabdar@Sun.COM * Clean up. 28997917SReza.Sabdar@Sun.COM */ 29007917SReza.Sabdar@Sun.COM cmds->tcs_writer_count--; 29017917SReza.Sabdar@Sun.COM lcmd->tc_ref--; 29027917SReza.Sabdar@Sun.COM lcmd->tc_reader = TLM_STOP; 29037917SReza.Sabdar@Sun.COM return (0); 29047917SReza.Sabdar@Sun.COM } 29057917SReza.Sabdar@Sun.COM 29067917SReza.Sabdar@Sun.COM 29077917SReza.Sabdar@Sun.COM /* 29087917SReza.Sabdar@Sun.COM * start_mover_for_restore 29097917SReza.Sabdar@Sun.COM * 29107917SReza.Sabdar@Sun.COM * Creates the mover tape reader and network writer threads for 29117917SReza.Sabdar@Sun.COM * the mover to perform the 3-way restore. 29127917SReza.Sabdar@Sun.COM * 29137917SReza.Sabdar@Sun.COM * Parameters: 29147917SReza.Sabdar@Sun.COM * session (input) - session pointer. 29157917SReza.Sabdar@Sun.COM * 29167917SReza.Sabdar@Sun.COM * Returns: 29177917SReza.Sabdar@Sun.COM * 0: on success 29187917SReza.Sabdar@Sun.COM * -1: otherwise 29197917SReza.Sabdar@Sun.COM */ 29207917SReza.Sabdar@Sun.COM static int 29217917SReza.Sabdar@Sun.COM start_mover_for_restore(ndmpd_session_t *session) 29227917SReza.Sabdar@Sun.COM { 29237917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 29247917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 29257917SReza.Sabdar@Sun.COM long xfer_size; 29267917SReza.Sabdar@Sun.COM int rc; 29277917SReza.Sabdar@Sun.COM 29287917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 29297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 29307917SReza.Sabdar@Sun.COM return (-1); 29317917SReza.Sabdar@Sun.COM } 29327917SReza.Sabdar@Sun.COM 29337917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 29347917SReza.Sabdar@Sun.COM (void) memset(cmds, 0, sizeof (*cmds)); 29357917SReza.Sabdar@Sun.COM cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN; 29367917SReza.Sabdar@Sun.COM xfer_size = ndmp_buffer_get_size(session); 29377917SReza.Sabdar@Sun.COM cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size); 29387917SReza.Sabdar@Sun.COM if (cmds->tcs_command == NULL) 29397917SReza.Sabdar@Sun.COM return (-1); 29407917SReza.Sabdar@Sun.COM 29417917SReza.Sabdar@Sun.COM cmds->tcs_command->tc_reader = TLM_RESTORE_RUN; 29427917SReza.Sabdar@Sun.COM cmds->tcs_command->tc_writer = TLM_RESTORE_RUN; 29437917SReza.Sabdar@Sun.COM 29447917SReza.Sabdar@Sun.COM /* 29457917SReza.Sabdar@Sun.COM * We intentionnally don't wait for the threads to start since the 29467917SReza.Sabdar@Sun.COM * reply of the request (which resulted in calling this function) 29477917SReza.Sabdar@Sun.COM * must be sent to the client before probable errors are sent 29487917SReza.Sabdar@Sun.COM * to the client. 29497917SReza.Sabdar@Sun.COM */ 29507917SReza.Sabdar@Sun.COM rc = pthread_create(NULL, NULL, (funct_t)mover_tape_reader, session); 29517917SReza.Sabdar@Sun.COM if (rc == 0) { 29527917SReza.Sabdar@Sun.COM tlm_cmd_wait(cmds->tcs_command, TLM_TAPE_READER); 29537917SReza.Sabdar@Sun.COM } else { 29547917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Launch mover_tape_reader: %s", 29557917SReza.Sabdar@Sun.COM strerror(rc)); 29567917SReza.Sabdar@Sun.COM return (-1); 29577917SReza.Sabdar@Sun.COM } 29587917SReza.Sabdar@Sun.COM 29597917SReza.Sabdar@Sun.COM rc = pthread_create(NULL, NULL, (funct_t)mover_socket_writer, session); 29607917SReza.Sabdar@Sun.COM if (rc == 0) { 29617917SReza.Sabdar@Sun.COM tlm_cmd_wait(cmds->tcs_command, TLM_SOCK_WRITER); 29627917SReza.Sabdar@Sun.COM } else { 29637917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Launch mover_socket_writer: %s", 29647917SReza.Sabdar@Sun.COM strerror(rc)); 29657917SReza.Sabdar@Sun.COM return (-1); 29667917SReza.Sabdar@Sun.COM } 29677917SReza.Sabdar@Sun.COM 29687917SReza.Sabdar@Sun.COM tlm_release_reader_writer_ipc(cmds->tcs_command); 29697917SReza.Sabdar@Sun.COM return (0); 29707917SReza.Sabdar@Sun.COM } 29717917SReza.Sabdar@Sun.COM 29727917SReza.Sabdar@Sun.COM 29737917SReza.Sabdar@Sun.COM /* 29747917SReza.Sabdar@Sun.COM * mover_socket_read_one_buf 29757917SReza.Sabdar@Sun.COM * 29767917SReza.Sabdar@Sun.COM * Read one buffer from the network socket for the mover. This is used 29777917SReza.Sabdar@Sun.COM * by mover_socket_reader 29787917SReza.Sabdar@Sun.COM * 29797917SReza.Sabdar@Sun.COM * Parameters: 29807917SReza.Sabdar@Sun.COM * session (input) - session pointer. 29817917SReza.Sabdar@Sun.COM * buf (input) - buffer read 29827917SReza.Sabdar@Sun.COM * read_size (input) - size to be read 29837917SReza.Sabdar@Sun.COM * 29847917SReza.Sabdar@Sun.COM * Returns: 29857917SReza.Sabdar@Sun.COM * 0: on success 29867917SReza.Sabdar@Sun.COM * -1: otherwise 29877917SReza.Sabdar@Sun.COM */ 29887917SReza.Sabdar@Sun.COM static int 29897917SReza.Sabdar@Sun.COM mover_socket_read_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf, 29907917SReza.Sabdar@Sun.COM long read_size) 29917917SReza.Sabdar@Sun.COM { 29927917SReza.Sabdar@Sun.COM int n, index; 29937917SReza.Sabdar@Sun.COM long toread; 29947917SReza.Sabdar@Sun.COM 29957917SReza.Sabdar@Sun.COM tlm_buffer_mark_empty(buf); 29967917SReza.Sabdar@Sun.COM for (index = 0, toread = read_size; toread > 0; ) { 29977917SReza.Sabdar@Sun.COM errno = 0; 29987917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "index: %d, toread: %d", index, toread); 29997917SReza.Sabdar@Sun.COM 30007917SReza.Sabdar@Sun.COM n = read(session->ns_mover.md_sock, &buf->tb_buffer_data[index], 30017917SReza.Sabdar@Sun.COM toread); 30027917SReza.Sabdar@Sun.COM if (n == 0) { 30037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d", n); 30047917SReza.Sabdar@Sun.COM break; 30057917SReza.Sabdar@Sun.COM } else if (n > 0) { 30067917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d", n); 30077917SReza.Sabdar@Sun.COM index += n; 30087917SReza.Sabdar@Sun.COM toread -= n; 30097917SReza.Sabdar@Sun.COM } else { 30107917SReza.Sabdar@Sun.COM buf->tb_eof = TRUE; 30117917SReza.Sabdar@Sun.COM buf->tb_errno = errno; 30127917SReza.Sabdar@Sun.COM buf->tb_buffer_size = 0; 30137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d, errno: %m", n); 30147917SReza.Sabdar@Sun.COM return (-1); 30157917SReza.Sabdar@Sun.COM } 30167917SReza.Sabdar@Sun.COM } 30177917SReza.Sabdar@Sun.COM 30187917SReza.Sabdar@Sun.COM if (index > 0) { 30197917SReza.Sabdar@Sun.COM buf->tb_full = TRUE; 30207917SReza.Sabdar@Sun.COM buf->tb_buffer_size = read_size; 30217917SReza.Sabdar@Sun.COM if (read_size > 0) 30227917SReza.Sabdar@Sun.COM (void) memset(&buf->tb_buffer_data[index], 0, 30237917SReza.Sabdar@Sun.COM read_size - index); 30247917SReza.Sabdar@Sun.COM } else { 30257917SReza.Sabdar@Sun.COM buf->tb_eof = TRUE; 30267917SReza.Sabdar@Sun.COM buf->tb_buffer_size = 0; 30277917SReza.Sabdar@Sun.COM } 30287917SReza.Sabdar@Sun.COM 30297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "full: %d, eot: %d, eof: %d," 30307917SReza.Sabdar@Sun.COM " errno: %d, size: %d, data: 0x%x", 30317917SReza.Sabdar@Sun.COM buf->tb_full, buf->tb_eot, buf->tb_eof, buf->tb_errno, 30327917SReza.Sabdar@Sun.COM buf->tb_buffer_size, buf->tb_buffer_data); 30337917SReza.Sabdar@Sun.COM 30347917SReza.Sabdar@Sun.COM return (0); 30357917SReza.Sabdar@Sun.COM } 30367917SReza.Sabdar@Sun.COM 30377917SReza.Sabdar@Sun.COM 30387917SReza.Sabdar@Sun.COM 30397917SReza.Sabdar@Sun.COM /* 30407917SReza.Sabdar@Sun.COM * mover_socket_reader 30417917SReza.Sabdar@Sun.COM * 30427917SReza.Sabdar@Sun.COM * Mover socket reader thread. This is used when reading data from the 30437917SReza.Sabdar@Sun.COM * network socket for performing remote backups. 30447917SReza.Sabdar@Sun.COM * 30457917SReza.Sabdar@Sun.COM * Parameters: 30467917SReza.Sabdar@Sun.COM * session (input) - session pointer. 30477917SReza.Sabdar@Sun.COM * 30487917SReza.Sabdar@Sun.COM * Returns: 30497917SReza.Sabdar@Sun.COM * 0: on success 30507917SReza.Sabdar@Sun.COM * -1: otherwise 30517917SReza.Sabdar@Sun.COM */ 30527917SReza.Sabdar@Sun.COM int 30537917SReza.Sabdar@Sun.COM mover_socket_reader(ndmpd_session_t *session) 30547917SReza.Sabdar@Sun.COM { 30557917SReza.Sabdar@Sun.COM int bidx; /* buffer index */ 30567917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 30577917SReza.Sabdar@Sun.COM tlm_buffer_t *buf; 30587917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 30597917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; /* Local command */ 30607917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; /* Commands structure */ 30617917SReza.Sabdar@Sun.COM static int nr = 0; 30627917SReza.Sabdar@Sun.COM 30637917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 30647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 30657917SReza.Sabdar@Sun.COM return (-1); 30667917SReza.Sabdar@Sun.COM } 30677917SReza.Sabdar@Sun.COM 30687917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 30697917SReza.Sabdar@Sun.COM lcmd = cmds->tcs_command; 30707917SReza.Sabdar@Sun.COM bufs = lcmd->tc_buffers; 30717917SReza.Sabdar@Sun.COM 30727917SReza.Sabdar@Sun.COM lcmd->tc_ref++; 30737917SReza.Sabdar@Sun.COM cmds->tcs_reader_count++; 30747917SReza.Sabdar@Sun.COM 30757917SReza.Sabdar@Sun.COM /* 30767917SReza.Sabdar@Sun.COM * Let our parent thread know that we are running. 30777917SReza.Sabdar@Sun.COM */ 30787917SReza.Sabdar@Sun.COM tlm_cmd_signal(cmds->tcs_command, TLM_SOCK_READER); 30797917SReza.Sabdar@Sun.COM 30807917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_in; 30817917SReza.Sabdar@Sun.COM while (cmds->tcs_reader == TLM_BACKUP_RUN && 30827917SReza.Sabdar@Sun.COM lcmd->tc_reader == TLM_BACKUP_RUN) { 30837917SReza.Sabdar@Sun.COM buf = &bufs->tbs_buffer[bidx]; 30847917SReza.Sabdar@Sun.COM 30857917SReza.Sabdar@Sun.COM if (buf->tb_full) { 30867917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "R%d", bidx); 30877917SReza.Sabdar@Sun.COM /* 30887917SReza.Sabdar@Sun.COM * The buffer is still full, wait for the consumer 30897917SReza.Sabdar@Sun.COM * thread to use it. 30907917SReza.Sabdar@Sun.COM */ 30917917SReza.Sabdar@Sun.COM tlm_buffer_out_buf_timed_wait(bufs, 100); 30927917SReza.Sabdar@Sun.COM } else { 30937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "r%d, nr: %d", bidx, ++nr); 30947917SReza.Sabdar@Sun.COM 30957917SReza.Sabdar@Sun.COM (void) mover_socket_read_one_buf(session, buf, 30967917SReza.Sabdar@Sun.COM bufs->tbs_data_transfer_size); 30977917SReza.Sabdar@Sun.COM 30987917SReza.Sabdar@Sun.COM /* 30997917SReza.Sabdar@Sun.COM * Can we do more buffering? 31007917SReza.Sabdar@Sun.COM */ 31017917SReza.Sabdar@Sun.COM if (is_buffer_erroneous(buf)) { 31027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 31037917SReza.Sabdar@Sun.COM "Exiting, errno: %d, eot: %d, eof: %d", 31047917SReza.Sabdar@Sun.COM buf->tb_errno, buf->tb_eot, buf->tb_eof); 31057917SReza.Sabdar@Sun.COM break; 31067917SReza.Sabdar@Sun.COM } 31077917SReza.Sabdar@Sun.COM 31087917SReza.Sabdar@Sun.COM (void) tlm_buffer_advance_in_idx(bufs); 31097917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 31107917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_in; 31117917SReza.Sabdar@Sun.COM } 31127917SReza.Sabdar@Sun.COM } 31137917SReza.Sabdar@Sun.COM 31147917SReza.Sabdar@Sun.COM if (cmds->tcs_reader != TLM_BACKUP_RUN) 31157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "cmds->tcs_reader != TLM_BACKUP_RUN"); 31167917SReza.Sabdar@Sun.COM if (lcmd->tc_reader != TLM_BACKUP_RUN) 31177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "lcmd->tc_reader != TLM_BACKUP_RUN"); 31187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nr: %d", nr); 31197917SReza.Sabdar@Sun.COM 31207917SReza.Sabdar@Sun.COM /* If the consumer is waiting for us, wake it up. */ 31217917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 31227917SReza.Sabdar@Sun.COM 31237917SReza.Sabdar@Sun.COM /* 31247917SReza.Sabdar@Sun.COM * Clean up. 31257917SReza.Sabdar@Sun.COM */ 31267917SReza.Sabdar@Sun.COM cmds->tcs_reader_count--; 31277917SReza.Sabdar@Sun.COM lcmd->tc_ref--; 31287917SReza.Sabdar@Sun.COM lcmd->tc_writer = TLM_STOP; 31297917SReza.Sabdar@Sun.COM return (0); 31307917SReza.Sabdar@Sun.COM } 31317917SReza.Sabdar@Sun.COM 31327917SReza.Sabdar@Sun.COM 31337917SReza.Sabdar@Sun.COM /* 31347917SReza.Sabdar@Sun.COM * mover_tape_writer_one_buf 31357917SReza.Sabdar@Sun.COM * 31367917SReza.Sabdar@Sun.COM * Write one buffer for the mover to the local tape device. This is 31377917SReza.Sabdar@Sun.COM * used by mover_tape_writer thread. 31387917SReza.Sabdar@Sun.COM * 31397917SReza.Sabdar@Sun.COM * Parameters: 31407917SReza.Sabdar@Sun.COM * session (input) - session pointer. 31417917SReza.Sabdar@Sun.COM * buf (input) - buffer read 31427917SReza.Sabdar@Sun.COM * 31437917SReza.Sabdar@Sun.COM * Returns: 31447917SReza.Sabdar@Sun.COM * 0: on success 31457917SReza.Sabdar@Sun.COM * -1: otherwise 31467917SReza.Sabdar@Sun.COM */ 31477917SReza.Sabdar@Sun.COM static int 31487917SReza.Sabdar@Sun.COM mover_tape_write_one_buf(ndmpd_session_t *session, tlm_buffer_t *buf) 31497917SReza.Sabdar@Sun.COM { 31507917SReza.Sabdar@Sun.COM int n; 31517917SReza.Sabdar@Sun.COM 31527917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "full: %d, eot: %d, eof: %d," 31537917SReza.Sabdar@Sun.COM " errno: %d, size: %d, data: 0x%x", 31547917SReza.Sabdar@Sun.COM buf->tb_full, buf->tb_eot, buf->tb_eof, buf->tb_errno, 31557917SReza.Sabdar@Sun.COM buf->tb_buffer_size, buf->tb_buffer_data); 31567917SReza.Sabdar@Sun.COM 31577917SReza.Sabdar@Sun.COM n = tape_write(session, buf->tb_buffer_data, buf->tb_buffer_size); 31587917SReza.Sabdar@Sun.COM 31597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d", n); 31607917SReza.Sabdar@Sun.COM 31617917SReza.Sabdar@Sun.COM if (n <= 0) { 31627917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, (n == 0 ? NDMP_MOVER_HALT_ABORTED 31637917SReza.Sabdar@Sun.COM : NDMP_MOVER_HALT_INTERNAL_ERROR)); 31647917SReza.Sabdar@Sun.COM return (-1); 31657917SReza.Sabdar@Sun.COM } 31667917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 31677917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 31687917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 31697917SReza.Sabdar@Sun.COM 31707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Calling tlm_buffer_mark_empty(buf)"); 31717917SReza.Sabdar@Sun.COM tlm_buffer_mark_empty(buf); 31727917SReza.Sabdar@Sun.COM 31737917SReza.Sabdar@Sun.COM return (0); 31747917SReza.Sabdar@Sun.COM } 31757917SReza.Sabdar@Sun.COM 31767917SReza.Sabdar@Sun.COM 31777917SReza.Sabdar@Sun.COM /* 31787917SReza.Sabdar@Sun.COM * mover_tape_writer 31797917SReza.Sabdar@Sun.COM * 31807917SReza.Sabdar@Sun.COM * Mover tape writer thread. This is used for performing remote backups 31817917SReza.Sabdar@Sun.COM * in a 3-way configuration. It writes the data from network socket to 31827917SReza.Sabdar@Sun.COM * the locally attached tape device. 31837917SReza.Sabdar@Sun.COM * 31847917SReza.Sabdar@Sun.COM * Parameters: 31857917SReza.Sabdar@Sun.COM * session (input) - session pointer. 31867917SReza.Sabdar@Sun.COM * 31877917SReza.Sabdar@Sun.COM * Returns: 31887917SReza.Sabdar@Sun.COM * 0: on success 31897917SReza.Sabdar@Sun.COM * -1: otherwise 31907917SReza.Sabdar@Sun.COM */ 31917917SReza.Sabdar@Sun.COM int 31927917SReza.Sabdar@Sun.COM mover_tape_writer(ndmpd_session_t *session) 31937917SReza.Sabdar@Sun.COM { 31947917SReza.Sabdar@Sun.COM int bidx; 31957917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 31967917SReza.Sabdar@Sun.COM tlm_buffer_t *buf; 31977917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 31987917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; 31997917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 32007917SReza.Sabdar@Sun.COM static int nw = 0; 32017917SReza.Sabdar@Sun.COM 32027917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 32037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 32047917SReza.Sabdar@Sun.COM return (-1); 32057917SReza.Sabdar@Sun.COM } 32067917SReza.Sabdar@Sun.COM 32077917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 32087917SReza.Sabdar@Sun.COM lcmd = cmds->tcs_command; 32097917SReza.Sabdar@Sun.COM bufs = lcmd->tc_buffers; 32107917SReza.Sabdar@Sun.COM 32117917SReza.Sabdar@Sun.COM lcmd->tc_ref++; 32127917SReza.Sabdar@Sun.COM cmds->tcs_writer_count++; 32137917SReza.Sabdar@Sun.COM 32147917SReza.Sabdar@Sun.COM /* 32157917SReza.Sabdar@Sun.COM * Let our parent thread know that we are running. 32167917SReza.Sabdar@Sun.COM */ 32177917SReza.Sabdar@Sun.COM tlm_cmd_signal(cmds->tcs_command, TLM_TAPE_WRITER); 32187917SReza.Sabdar@Sun.COM 32197917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_out; 32207917SReza.Sabdar@Sun.COM buf = &bufs->tbs_buffer[bidx]; 32217917SReza.Sabdar@Sun.COM while (cmds->tcs_writer != (int)TLM_ABORT && 32227917SReza.Sabdar@Sun.COM lcmd->tc_writer != (int)TLM_ABORT) { 32237917SReza.Sabdar@Sun.COM if (buf->tb_full) { 32247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "w%d, nw: %d", bidx, ++nw); 32257917SReza.Sabdar@Sun.COM 32267917SReza.Sabdar@Sun.COM if (mover_tape_write_one_buf(session, buf) < 0) { 32277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 32287917SReza.Sabdar@Sun.COM "mover_tape_write_one_buf() failed"); 32297917SReza.Sabdar@Sun.COM break; 32307917SReza.Sabdar@Sun.COM } 32317917SReza.Sabdar@Sun.COM 32327917SReza.Sabdar@Sun.COM (void) tlm_buffer_advance_out_idx(bufs); 32337917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(bufs); 32347917SReza.Sabdar@Sun.COM bidx = bufs->tbs_buffer_out; 32357917SReza.Sabdar@Sun.COM buf = &bufs->tbs_buffer[bidx]; 32367917SReza.Sabdar@Sun.COM } else { 32377917SReza.Sabdar@Sun.COM if (lcmd->tc_writer != TLM_BACKUP_RUN) { 32387917SReza.Sabdar@Sun.COM /* No more data is coming, time to exit */ 32397917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Time to exit"); 32407917SReza.Sabdar@Sun.COM break; 32417917SReza.Sabdar@Sun.COM } 32427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "W%d", bidx); 32437917SReza.Sabdar@Sun.COM /* 32447917SReza.Sabdar@Sun.COM * The buffer is not full, wait for the producer 32457917SReza.Sabdar@Sun.COM * thread to fill it. 32467917SReza.Sabdar@Sun.COM */ 32477917SReza.Sabdar@Sun.COM tlm_buffer_in_buf_timed_wait(bufs, 100); 32487917SReza.Sabdar@Sun.COM } 32497917SReza.Sabdar@Sun.COM } 32507917SReza.Sabdar@Sun.COM 32517917SReza.Sabdar@Sun.COM if (cmds->tcs_writer == (int)TLM_ABORT) 32527917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "cmds->tcs_writer == TLM_ABORT"); 32537917SReza.Sabdar@Sun.COM if (lcmd->tc_writer == (int)TLM_ABORT) 32547917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "lcmd->tc_writer == TLM_ABORT"); 32557917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nw: %d", nw); 32567917SReza.Sabdar@Sun.COM 32577917SReza.Sabdar@Sun.COM if (buf->tb_errno == 0) { 32587917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 32597917SReza.Sabdar@Sun.COM } else { 32607917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "buf->tb_errno: %d", buf->tb_errno); 32617917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR); 32627917SReza.Sabdar@Sun.COM } 32637917SReza.Sabdar@Sun.COM 32647917SReza.Sabdar@Sun.COM /* If the producer is waiting for us, wake it up. */ 32657917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(bufs); 32667917SReza.Sabdar@Sun.COM 32677917SReza.Sabdar@Sun.COM /* 32687917SReza.Sabdar@Sun.COM * Clean up. 32697917SReza.Sabdar@Sun.COM */ 32707917SReza.Sabdar@Sun.COM cmds->tcs_writer_count--; 32717917SReza.Sabdar@Sun.COM lcmd->tc_ref--; 32727917SReza.Sabdar@Sun.COM lcmd->tc_reader = TLM_STOP; 32737917SReza.Sabdar@Sun.COM return (0); 32747917SReza.Sabdar@Sun.COM } 32757917SReza.Sabdar@Sun.COM 32767917SReza.Sabdar@Sun.COM 32777917SReza.Sabdar@Sun.COM /* 32787917SReza.Sabdar@Sun.COM * start_mover_for_backup 32797917SReza.Sabdar@Sun.COM * 32807917SReza.Sabdar@Sun.COM * Starts a remote backup by running socket reader and tape 32817917SReza.Sabdar@Sun.COM * writer threads. The mover runs a remote backup in a 3-way backup 32827917SReza.Sabdar@Sun.COM * configuration. 32837917SReza.Sabdar@Sun.COM * 32847917SReza.Sabdar@Sun.COM * Parameters: 32857917SReza.Sabdar@Sun.COM * session (input) - session pointer. 32867917SReza.Sabdar@Sun.COM * 32877917SReza.Sabdar@Sun.COM * Returns: 32887917SReza.Sabdar@Sun.COM * 0: on success 32897917SReza.Sabdar@Sun.COM * -1: otherwise 32907917SReza.Sabdar@Sun.COM */ 32917917SReza.Sabdar@Sun.COM static int 32927917SReza.Sabdar@Sun.COM start_mover_for_backup(ndmpd_session_t *session) 32937917SReza.Sabdar@Sun.COM { 32947917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 32957917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 32967917SReza.Sabdar@Sun.COM int rc; 32977917SReza.Sabdar@Sun.COM 32987917SReza.Sabdar@Sun.COM if ((nlp = ndmp_get_nlp(session)) == NULL) { 32997917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "nlp == NULL"); 33007917SReza.Sabdar@Sun.COM return (-1); 33017917SReza.Sabdar@Sun.COM } 33027917SReza.Sabdar@Sun.COM 33037917SReza.Sabdar@Sun.COM cmds = &nlp->nlp_cmds; 33047917SReza.Sabdar@Sun.COM (void) memset(cmds, 0, sizeof (*cmds)); 33057917SReza.Sabdar@Sun.COM cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN; 33067917SReza.Sabdar@Sun.COM cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, 33077917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 33087917SReza.Sabdar@Sun.COM if (cmds->tcs_command == NULL) 33097917SReza.Sabdar@Sun.COM return (-1); 33107917SReza.Sabdar@Sun.COM 33117917SReza.Sabdar@Sun.COM cmds->tcs_command->tc_reader = TLM_BACKUP_RUN; 33127917SReza.Sabdar@Sun.COM cmds->tcs_command->tc_writer = TLM_BACKUP_RUN; 33137917SReza.Sabdar@Sun.COM 33147917SReza.Sabdar@Sun.COM /* 33157917SReza.Sabdar@Sun.COM * We intentionally don't wait for the threads to start since the 33167917SReza.Sabdar@Sun.COM * reply of the request (which resulted in calling this function) 33177917SReza.Sabdar@Sun.COM * must be sent to the client before probable errors are sent 33187917SReza.Sabdar@Sun.COM * to the client. 33197917SReza.Sabdar@Sun.COM */ 33207917SReza.Sabdar@Sun.COM rc = pthread_create(NULL, NULL, (funct_t)mover_socket_reader, session); 33217917SReza.Sabdar@Sun.COM if (rc == 0) { 33227917SReza.Sabdar@Sun.COM tlm_cmd_wait(cmds->tcs_command, TLM_SOCK_READER); 33237917SReza.Sabdar@Sun.COM } else { 33247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Launch mover_socket_reader: %s", 33257917SReza.Sabdar@Sun.COM strerror(rc)); 33267917SReza.Sabdar@Sun.COM return (-1); 33277917SReza.Sabdar@Sun.COM } 33287917SReza.Sabdar@Sun.COM 33297917SReza.Sabdar@Sun.COM rc = pthread_create(NULL, NULL, (funct_t)mover_tape_writer, session); 33307917SReza.Sabdar@Sun.COM if (rc == 0) { 33317917SReza.Sabdar@Sun.COM tlm_cmd_wait(cmds->tcs_command, TLM_TAPE_WRITER); 33327917SReza.Sabdar@Sun.COM } else { 33337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Launch mover_tape_writer: %s", 33347917SReza.Sabdar@Sun.COM strerror(rc)); 33357917SReza.Sabdar@Sun.COM return (-1); 33367917SReza.Sabdar@Sun.COM } 33377917SReza.Sabdar@Sun.COM 33387917SReza.Sabdar@Sun.COM tlm_release_reader_writer_ipc(cmds->tcs_command); 33397917SReza.Sabdar@Sun.COM return (0); 33407917SReza.Sabdar@Sun.COM } 33417917SReza.Sabdar@Sun.COM 33427917SReza.Sabdar@Sun.COM 33437917SReza.Sabdar@Sun.COM /* 33447917SReza.Sabdar@Sun.COM * is_writer_running 33457917SReza.Sabdar@Sun.COM * 33467917SReza.Sabdar@Sun.COM * Find out if the writer thread has started or not. 33477917SReza.Sabdar@Sun.COM * 33487917SReza.Sabdar@Sun.COM * Parameters: 33497917SReza.Sabdar@Sun.COM * session (input) - session pointer. 33507917SReza.Sabdar@Sun.COM * 33517917SReza.Sabdar@Sun.COM * Returns: 33527917SReza.Sabdar@Sun.COM * 0: not started 33537917SReza.Sabdar@Sun.COM * non-zero: started 33547917SReza.Sabdar@Sun.COM */ 33557917SReza.Sabdar@Sun.COM static boolean_t 33567917SReza.Sabdar@Sun.COM is_writer_running(ndmpd_session_t *session) 33577917SReza.Sabdar@Sun.COM { 33587917SReza.Sabdar@Sun.COM boolean_t rv; 33597917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 33607917SReza.Sabdar@Sun.COM 33617917SReza.Sabdar@Sun.COM if (session == NULL) 33627917SReza.Sabdar@Sun.COM rv = 0; 33637917SReza.Sabdar@Sun.COM else if ((nlp = ndmp_get_nlp(session)) == NULL) 33647917SReza.Sabdar@Sun.COM rv = 0; 33657917SReza.Sabdar@Sun.COM else 33667917SReza.Sabdar@Sun.COM rv = (nlp->nlp_cmds.tcs_writer_count > 0); 33677917SReza.Sabdar@Sun.COM 33687917SReza.Sabdar@Sun.COM return (rv); 33697917SReza.Sabdar@Sun.COM } 33707917SReza.Sabdar@Sun.COM 33717917SReza.Sabdar@Sun.COM 33727917SReza.Sabdar@Sun.COM /* 33737917SReza.Sabdar@Sun.COM * is_writer_running_v3 33747917SReza.Sabdar@Sun.COM * 33757917SReza.Sabdar@Sun.COM * Find out if the writer thread has started or not. 33767917SReza.Sabdar@Sun.COM * 33777917SReza.Sabdar@Sun.COM * Parameters: 33787917SReza.Sabdar@Sun.COM * session (input) - session pointer. 33797917SReza.Sabdar@Sun.COM * 33807917SReza.Sabdar@Sun.COM * Returns: 33817917SReza.Sabdar@Sun.COM * 0: not started 33827917SReza.Sabdar@Sun.COM * non-zero: started 33837917SReza.Sabdar@Sun.COM */ 33847917SReza.Sabdar@Sun.COM static boolean_t 33857917SReza.Sabdar@Sun.COM is_writer_running_v3(ndmpd_session_t *session) 33867917SReza.Sabdar@Sun.COM { 33877917SReza.Sabdar@Sun.COM boolean_t rv; 33887917SReza.Sabdar@Sun.COM ndmp_lbr_params_t *nlp; 33897917SReza.Sabdar@Sun.COM 33907917SReza.Sabdar@Sun.COM if (session == NULL) 33917917SReza.Sabdar@Sun.COM rv = 0; 33927917SReza.Sabdar@Sun.COM else if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_TCP) 33937917SReza.Sabdar@Sun.COM rv = 1; 33947917SReza.Sabdar@Sun.COM else if ((nlp = ndmp_get_nlp(session)) == NULL) 33957917SReza.Sabdar@Sun.COM rv = 0; 33967917SReza.Sabdar@Sun.COM else 33977917SReza.Sabdar@Sun.COM rv = (nlp->nlp_cmds.tcs_writer_count > 0); 33987917SReza.Sabdar@Sun.COM 33997917SReza.Sabdar@Sun.COM return (rv); 34007917SReza.Sabdar@Sun.COM } 34017917SReza.Sabdar@Sun.COM 34027917SReza.Sabdar@Sun.COM 34037917SReza.Sabdar@Sun.COM /* 34047917SReza.Sabdar@Sun.COM * ndmpd_mover_wait_v3 34057917SReza.Sabdar@Sun.COM * 34067917SReza.Sabdar@Sun.COM * Take the mover state to PAUSED state 34077917SReza.Sabdar@Sun.COM * 34087917SReza.Sabdar@Sun.COM * Parameters: 34097917SReza.Sabdar@Sun.COM * session (input) - session pointer. 34107917SReza.Sabdar@Sun.COM * 34117917SReza.Sabdar@Sun.COM * Returns: 34127917SReza.Sabdar@Sun.COM * 0: on success 34137917SReza.Sabdar@Sun.COM * -1: otherwise 34147917SReza.Sabdar@Sun.COM */ 34157917SReza.Sabdar@Sun.COM int 34167917SReza.Sabdar@Sun.COM ndmpd_mover_wait_v3(ndmpd_session_t *session) 34177917SReza.Sabdar@Sun.COM { 34187917SReza.Sabdar@Sun.COM int rv = 0; 34197917SReza.Sabdar@Sun.COM 34207917SReza.Sabdar@Sun.COM nlp_ref_nw(session); 34217917SReza.Sabdar@Sun.COM for (; ; ) { 34227917SReza.Sabdar@Sun.COM nlp_wait_nw(session); 34237917SReza.Sabdar@Sun.COM 34247917SReza.Sabdar@Sun.COM if (nlp_event_rv_get(session) < 0) { 34257917SReza.Sabdar@Sun.COM rv = -1; 34267917SReza.Sabdar@Sun.COM break; 34277917SReza.Sabdar@Sun.COM } 34287917SReza.Sabdar@Sun.COM if (session->ns_eof) { 34297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "session->ns_eof"); 34307917SReza.Sabdar@Sun.COM rv = -1; 34317917SReza.Sabdar@Sun.COM break; 34327917SReza.Sabdar@Sun.COM } 34337917SReza.Sabdar@Sun.COM if (session->ns_data.dd_abort) { 34347917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "data.abort"); 34357917SReza.Sabdar@Sun.COM rv = -1; 34367917SReza.Sabdar@Sun.COM break; 34377917SReza.Sabdar@Sun.COM } 34387917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE) { 34397917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 34407917SReza.Sabdar@Sun.COM "mover.state: NDMP_MOVER_STATE_ACTIVE"); 34417917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 34427917SReza.Sabdar@Sun.COM rv = 0; 34437917SReza.Sabdar@Sun.COM break; 34447917SReza.Sabdar@Sun.COM } else if (session->ns_mover.md_state == 34457917SReza.Sabdar@Sun.COM NDMP_MOVER_STATE_PAUSED) { 34467917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 34477917SReza.Sabdar@Sun.COM "mover.state: NDMP_MOVER_STATE_PAUSED"); 34487917SReza.Sabdar@Sun.COM } else { 34497917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "default"); 34507917SReza.Sabdar@Sun.COM rv = -1; 34517917SReza.Sabdar@Sun.COM break; 34527917SReza.Sabdar@Sun.COM } 34537917SReza.Sabdar@Sun.COM } 34547917SReza.Sabdar@Sun.COM 34557917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_NA; 34567917SReza.Sabdar@Sun.COM nlp_unref_nw(session); 34577917SReza.Sabdar@Sun.COM return (rv); 34587917SReza.Sabdar@Sun.COM } 34597917SReza.Sabdar@Sun.COM 34607917SReza.Sabdar@Sun.COM /* 34617917SReza.Sabdar@Sun.COM * ndmpd_mover_error_send 34627917SReza.Sabdar@Sun.COM * 34637917SReza.Sabdar@Sun.COM * This function sends the notify message to the client. 34647917SReza.Sabdar@Sun.COM * 34657917SReza.Sabdar@Sun.COM * Parameters: 34667917SReza.Sabdar@Sun.COM * session (input) - session pointer. 34677917SReza.Sabdar@Sun.COM * reason (input) - halt reason. 34687917SReza.Sabdar@Sun.COM * 34697917SReza.Sabdar@Sun.COM * Returns: 34707917SReza.Sabdar@Sun.COM * Error code 34717917SReza.Sabdar@Sun.COM */ 34727917SReza.Sabdar@Sun.COM int 34737917SReza.Sabdar@Sun.COM ndmpd_mover_error_send(ndmpd_session_t *session, ndmp_mover_halt_reason reason) 34747917SReza.Sabdar@Sun.COM { 34757917SReza.Sabdar@Sun.COM ndmp_notify_mover_halted_request req; 34767917SReza.Sabdar@Sun.COM 34777917SReza.Sabdar@Sun.COM req.reason = reason; 34787917SReza.Sabdar@Sun.COM req.text_reason = ""; 34797917SReza.Sabdar@Sun.COM 34807917SReza.Sabdar@Sun.COM return (ndmp_send_request(session->ns_connection, 34817917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_HALTED, NDMP_NO_ERR, (void *)&req, 0)); 34827917SReza.Sabdar@Sun.COM } 34837917SReza.Sabdar@Sun.COM 34847917SReza.Sabdar@Sun.COM 34857917SReza.Sabdar@Sun.COM /* 34867917SReza.Sabdar@Sun.COM * ndmpd_mover_error_send_v4 34877917SReza.Sabdar@Sun.COM * 34887917SReza.Sabdar@Sun.COM * This function sends the notify message to the client. 34897917SReza.Sabdar@Sun.COM * 34907917SReza.Sabdar@Sun.COM * Parameters: 34917917SReza.Sabdar@Sun.COM * session (input) - session pointer. 34927917SReza.Sabdar@Sun.COM * reason (input) - halt reason. 34937917SReza.Sabdar@Sun.COM * 34947917SReza.Sabdar@Sun.COM * Returns: 34957917SReza.Sabdar@Sun.COM * Error code 34967917SReza.Sabdar@Sun.COM */ 34977917SReza.Sabdar@Sun.COM int 34987917SReza.Sabdar@Sun.COM ndmpd_mover_error_send_v4(ndmpd_session_t *session, 34997917SReza.Sabdar@Sun.COM ndmp_mover_halt_reason reason) 35007917SReza.Sabdar@Sun.COM { 35017917SReza.Sabdar@Sun.COM ndmp_notify_mover_halted_request_v4 req; 35027917SReza.Sabdar@Sun.COM 35037917SReza.Sabdar@Sun.COM req.reason = reason; 35047917SReza.Sabdar@Sun.COM 35057917SReza.Sabdar@Sun.COM return (ndmp_send_request(session->ns_connection, 35067917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_HALTED, NDMP_NO_ERR, (void *)&req, 0)); 35077917SReza.Sabdar@Sun.COM } 35087917SReza.Sabdar@Sun.COM 35097917SReza.Sabdar@Sun.COM 35107917SReza.Sabdar@Sun.COM /* 35117917SReza.Sabdar@Sun.COM * ndmpd_mover_error 35127917SReza.Sabdar@Sun.COM * 35137917SReza.Sabdar@Sun.COM * This function is called when an unrecoverable mover error 35147917SReza.Sabdar@Sun.COM * has been detected. A notify message is sent to the client and the 35157917SReza.Sabdar@Sun.COM * mover is placed into the halted state. 35167917SReza.Sabdar@Sun.COM * 35177917SReza.Sabdar@Sun.COM * Parameters: 35187917SReza.Sabdar@Sun.COM * session (input) - session pointer. 35197917SReza.Sabdar@Sun.COM * reason (input) - halt reason. 35207917SReza.Sabdar@Sun.COM * 35217917SReza.Sabdar@Sun.COM * Returns: 35227917SReza.Sabdar@Sun.COM * void. 35237917SReza.Sabdar@Sun.COM */ 35247917SReza.Sabdar@Sun.COM void 35257917SReza.Sabdar@Sun.COM ndmpd_mover_error(ndmpd_session_t *session, ndmp_mover_halt_reason reason) 35267917SReza.Sabdar@Sun.COM { 35277917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED || 35287917SReza.Sabdar@Sun.COM (session->ns_protocol_version > NDMPV2 && 35297917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE)) 35307917SReza.Sabdar@Sun.COM return; 35317917SReza.Sabdar@Sun.COM 35327917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4) { 35337917SReza.Sabdar@Sun.COM if (ndmpd_mover_error_send_v4(session, reason) < 0) 35347917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 35357917SReza.Sabdar@Sun.COM "Error sending notify_mover_halted request"); 35367917SReza.Sabdar@Sun.COM } else { 35377917SReza.Sabdar@Sun.COM /* No media error in V3 */ 35387917SReza.Sabdar@Sun.COM if (reason == NDMP_MOVER_HALT_MEDIA_ERROR) 35397917SReza.Sabdar@Sun.COM reason = NDMP_MOVER_HALT_INTERNAL_ERROR; 35407917SReza.Sabdar@Sun.COM if (ndmpd_mover_error_send(session, reason) < 0) 35417917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 35427917SReza.Sabdar@Sun.COM "Error sending notify_mover_halted request"); 35437917SReza.Sabdar@Sun.COM } 35447917SReza.Sabdar@Sun.COM 35457917SReza.Sabdar@Sun.COM if (session->ns_mover.md_listen_sock != -1) { 35467917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, 35477917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock); 35487917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 35497917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 35507917SReza.Sabdar@Sun.COM } 35517917SReza.Sabdar@Sun.COM if (session->ns_mover.md_sock != -1) { 35527917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, 35537917SReza.Sabdar@Sun.COM session->ns_mover.md_sock); 35547917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_sock); 35557917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = -1; 35567917SReza.Sabdar@Sun.COM } 35577917SReza.Sabdar@Sun.COM 35587917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_HALTED; 35597917SReza.Sabdar@Sun.COM session->ns_mover.md_halt_reason = reason; 35607917SReza.Sabdar@Sun.COM } 35617917SReza.Sabdar@Sun.COM 35627917SReza.Sabdar@Sun.COM 35637917SReza.Sabdar@Sun.COM /* 35647917SReza.Sabdar@Sun.COM * mover_pause_v3 35657917SReza.Sabdar@Sun.COM * 35667917SReza.Sabdar@Sun.COM * Send an ndmp_notify_mover_paused request to the 35677917SReza.Sabdar@Sun.COM * NDMP client to inform the client that its attention is required. 35687917SReza.Sabdar@Sun.COM * Process messages until the data/mover operation is either aborted 35697917SReza.Sabdar@Sun.COM * or continued. 35707917SReza.Sabdar@Sun.COM * 35717917SReza.Sabdar@Sun.COM * Parameters: 35727917SReza.Sabdar@Sun.COM * client_data (input) - session pointer. 35737917SReza.Sabdar@Sun.COM * reason (input) - pause reason. 35747917SReza.Sabdar@Sun.COM * 35757917SReza.Sabdar@Sun.COM * Returns: 35767917SReza.Sabdar@Sun.COM * 0 - operation has been continued. 35777917SReza.Sabdar@Sun.COM * -1 - operation has been aborted. 35787917SReza.Sabdar@Sun.COM */ 35797917SReza.Sabdar@Sun.COM static int 35807917SReza.Sabdar@Sun.COM mover_pause_v3(ndmpd_session_t *session, ndmp_mover_pause_reason reason) 35817917SReza.Sabdar@Sun.COM { 35827917SReza.Sabdar@Sun.COM int rv; 35837917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request request; 35847917SReza.Sabdar@Sun.COM 35857917SReza.Sabdar@Sun.COM rv = 0; 35867917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 35877917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = reason; 35887917SReza.Sabdar@Sun.COM session->ns_mover.md_pre_cond = FALSE; 35897917SReza.Sabdar@Sun.COM 35907917SReza.Sabdar@Sun.COM request.reason = session->ns_mover.md_pause_reason; 35917917SReza.Sabdar@Sun.COM request.seek_position = 35927917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_position); 35937917SReza.Sabdar@Sun.COM 35947917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, NDMP_NOTIFY_MOVER_PAUSED, 35957917SReza.Sabdar@Sun.COM NDMP_NO_ERR, (void *)&request, 0) < 0) { 35967917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 35977917SReza.Sabdar@Sun.COM "Error sending notify_mover_paused_request"); 35987917SReza.Sabdar@Sun.COM return (-1); 35997917SReza.Sabdar@Sun.COM } 36007917SReza.Sabdar@Sun.COM 36017917SReza.Sabdar@Sun.COM /* 36027917SReza.Sabdar@Sun.COM * 3-way operations are single-thread. The same thread 36037917SReza.Sabdar@Sun.COM * should process the messages. 36047917SReza.Sabdar@Sun.COM * 36057917SReza.Sabdar@Sun.COM * 2-way operations are multi-thread. The main thread 36067917SReza.Sabdar@Sun.COM * processes the messages. We just need to wait and 36077917SReza.Sabdar@Sun.COM * see if the mover state changes or the operation aborts. 36087917SReza.Sabdar@Sun.COM */ 36097917SReza.Sabdar@Sun.COM if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_TCP) { 36107917SReza.Sabdar@Sun.COM /* 36117917SReza.Sabdar@Sun.COM * Process messages until the state is changed by 36127917SReza.Sabdar@Sun.COM * an abort, continue, or close request . 36137917SReza.Sabdar@Sun.COM */ 36147917SReza.Sabdar@Sun.COM for (; ; ) { 36157917SReza.Sabdar@Sun.COM if (ndmpd_select(session, TRUE, HC_CLIENT) < 0) 36167917SReza.Sabdar@Sun.COM return (-1); 36177917SReza.Sabdar@Sun.COM 36187917SReza.Sabdar@Sun.COM if (session->ns_eof == TRUE) 36197917SReza.Sabdar@Sun.COM return (-1); 36207917SReza.Sabdar@Sun.COM 36217917SReza.Sabdar@Sun.COM switch (session->ns_mover.md_state) { 36227917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_ACTIVE: 36237917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 36247917SReza.Sabdar@Sun.COM return (0); 36257917SReza.Sabdar@Sun.COM 36267917SReza.Sabdar@Sun.COM case NDMP_MOVER_STATE_PAUSED: 36277917SReza.Sabdar@Sun.COM continue; 36287917SReza.Sabdar@Sun.COM 36297917SReza.Sabdar@Sun.COM default: 36307917SReza.Sabdar@Sun.COM return (-1); 36317917SReza.Sabdar@Sun.COM } 36327917SReza.Sabdar@Sun.COM } 36337917SReza.Sabdar@Sun.COM 36347917SReza.Sabdar@Sun.COM } else { 36357917SReza.Sabdar@Sun.COM if (session->ns_mover.md_data_addr.addr_type == 36367917SReza.Sabdar@Sun.COM NDMP_ADDR_LOCAL) { 36377917SReza.Sabdar@Sun.COM rv = ndmpd_mover_wait_v3(session); 36387917SReza.Sabdar@Sun.COM } else { 36397917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid address type %d", 36407917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type); 36417917SReza.Sabdar@Sun.COM rv = -1; 36427917SReza.Sabdar@Sun.COM } 36437917SReza.Sabdar@Sun.COM } 36447917SReza.Sabdar@Sun.COM 36457917SReza.Sabdar@Sun.COM return (rv); 36467917SReza.Sabdar@Sun.COM } 36477917SReza.Sabdar@Sun.COM 36487917SReza.Sabdar@Sun.COM 36497917SReza.Sabdar@Sun.COM /* 36507917SReza.Sabdar@Sun.COM * mover_tape_write_v3 36517917SReza.Sabdar@Sun.COM * 36527917SReza.Sabdar@Sun.COM * Writes a data record to tape. Detects and handles EOT conditions. 36537917SReza.Sabdar@Sun.COM * 36547917SReza.Sabdar@Sun.COM * Parameters: 36557917SReza.Sabdar@Sun.COM * session (input) - session pointer. 36567917SReza.Sabdar@Sun.COM * data (input) - data to be written. 36577917SReza.Sabdar@Sun.COM * length (input) - length of data to be written. 36587917SReza.Sabdar@Sun.COM * 36597917SReza.Sabdar@Sun.COM * Returns: 36607917SReza.Sabdar@Sun.COM * 0 - operation aborted by client. 36617917SReza.Sabdar@Sun.COM * -1 - error. 36627917SReza.Sabdar@Sun.COM * otherwise - number of bytes written. 36637917SReza.Sabdar@Sun.COM */ 36647917SReza.Sabdar@Sun.COM static int 36657917SReza.Sabdar@Sun.COM mover_tape_write_v3(ndmpd_session_t *session, char *data, ssize_t length) 36667917SReza.Sabdar@Sun.COM { 36677917SReza.Sabdar@Sun.COM ssize_t n; 36687917SReza.Sabdar@Sun.COM int err; 36697917SReza.Sabdar@Sun.COM 36707917SReza.Sabdar@Sun.COM for (; ; ) { 36717917SReza.Sabdar@Sun.COM /* 36727917SReza.Sabdar@Sun.COM * Refer to the comment at the top of ndmpd_tape.c file for 36737917SReza.Sabdar@Sun.COM * Mammoth2 tape drives. 36747917SReza.Sabdar@Sun.COM */ 36757917SReza.Sabdar@Sun.COM if (session->ns_tape.td_eom_seen) { 36767917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "eom_seen"); 36777917SReza.Sabdar@Sun.COM 36787917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 36797917SReza.Sabdar@Sun.COM /* 36807917SReza.Sabdar@Sun.COM * End of media reached. 36817917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 36827917SReza.Sabdar@Sun.COM * either abort the operation or continue the 36837917SReza.Sabdar@Sun.COM * operation after changing the tape. 36847917SReza.Sabdar@Sun.COM */ 36857917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 36867917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 36877917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape"); 36887917SReza.Sabdar@Sun.COM 36897917SReza.Sabdar@Sun.COM err = mover_pause_v3(session, NDMP_MOVER_PAUSE_EOM); 36907917SReza.Sabdar@Sun.COM 36917917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 36927917SReza.Sabdar@Sun.COM if (err < 0) 36937917SReza.Sabdar@Sun.COM return (-1); 36947917SReza.Sabdar@Sun.COM 36957917SReza.Sabdar@Sun.COM /* Retry the write to the new tape. */ 36967917SReza.Sabdar@Sun.COM continue; 36977917SReza.Sabdar@Sun.COM } 36987917SReza.Sabdar@Sun.COM 36997917SReza.Sabdar@Sun.COM /* 37007917SReza.Sabdar@Sun.COM * Enforce mover window on write. 37017917SReza.Sabdar@Sun.COM */ 37027917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position >= 37037917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 37047917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) { 37057917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "MOVER_PAUSE_EOW"); 37067917SReza.Sabdar@Sun.COM 37077917SReza.Sabdar@Sun.COM err = mover_pause_v3(session, NDMP_MOVER_PAUSE_EOW); 37087917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 37097917SReza.Sabdar@Sun.COM if (err < 0) 37107917SReza.Sabdar@Sun.COM return (-1); 37117917SReza.Sabdar@Sun.COM 37127917SReza.Sabdar@Sun.COM } 37137917SReza.Sabdar@Sun.COM 37147917SReza.Sabdar@Sun.COM n = write(session->ns_tape.td_fd, data, length); 37157917SReza.Sabdar@Sun.COM if (n < 0) { 37167917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape write error: %m."); 37177917SReza.Sabdar@Sun.COM return (-1); 37187917SReza.Sabdar@Sun.COM } 37197917SReza.Sabdar@Sun.COM NS_ADD(wtape, n); 37207917SReza.Sabdar@Sun.COM 37217917SReza.Sabdar@Sun.COM if (n == 0 || n != length) { 37227917SReza.Sabdar@Sun.COM if (n != 0) { 37237917SReza.Sabdar@Sun.COM /* 37247917SReza.Sabdar@Sun.COM * Backup one record since the record 37257917SReza.Sabdar@Sun.COM * hits the EOM. 37267917SReza.Sabdar@Sun.COM */ 37277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Back up one record"); 37287917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, 37297917SReza.Sabdar@Sun.COM MTBSR, 1); 37307917SReza.Sabdar@Sun.COM 37317917SReza.Sabdar@Sun.COM /* setting logical EOM */ 37327917SReza.Sabdar@Sun.COM ndmpd_write_eom(session->ns_tape.td_fd); 37337917SReza.Sabdar@Sun.COM } 37347917SReza.Sabdar@Sun.COM 37357917SReza.Sabdar@Sun.COM /* 37367917SReza.Sabdar@Sun.COM * End of media reached. 37377917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 37387917SReza.Sabdar@Sun.COM * either abort the operation or continue the 37397917SReza.Sabdar@Sun.COM * operation after changing the tape. 37407917SReza.Sabdar@Sun.COM */ 37417917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 37427917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 37437917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape"); 37447917SReza.Sabdar@Sun.COM 37457917SReza.Sabdar@Sun.COM err = mover_pause_v3(session, NDMP_MOVER_PAUSE_EOM); 37467917SReza.Sabdar@Sun.COM 37477917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 37487917SReza.Sabdar@Sun.COM if (err < 0) 37497917SReza.Sabdar@Sun.COM return (-1); 37507917SReza.Sabdar@Sun.COM 37517917SReza.Sabdar@Sun.COM /* Retry the write to the new tape. */ 37527917SReza.Sabdar@Sun.COM continue; 37537917SReza.Sabdar@Sun.COM } 37547917SReza.Sabdar@Sun.COM 37557917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count++; 37567917SReza.Sabdar@Sun.COM return (n); 37577917SReza.Sabdar@Sun.COM } 37587917SReza.Sabdar@Sun.COM } 37597917SReza.Sabdar@Sun.COM 37607917SReza.Sabdar@Sun.COM 37617917SReza.Sabdar@Sun.COM /* 37627917SReza.Sabdar@Sun.COM * mover_tape_flush_v3 37637917SReza.Sabdar@Sun.COM * 37647917SReza.Sabdar@Sun.COM * Writes all remaining buffered data to tape. A partial record is 37657917SReza.Sabdar@Sun.COM * padded out to a full record with zeros. 37667917SReza.Sabdar@Sun.COM * 37677917SReza.Sabdar@Sun.COM * Parameters: 37687917SReza.Sabdar@Sun.COM * session (input) - session pointer. 37697917SReza.Sabdar@Sun.COM * data (input) - data to be written. 37707917SReza.Sabdar@Sun.COM * length (input) - length of data to be written. 37717917SReza.Sabdar@Sun.COM * 37727917SReza.Sabdar@Sun.COM * Returns: 37737917SReza.Sabdar@Sun.COM * -1 - error. 37747917SReza.Sabdar@Sun.COM * otherwise - number of bytes written. 37757917SReza.Sabdar@Sun.COM */ 37767917SReza.Sabdar@Sun.COM static int 37777917SReza.Sabdar@Sun.COM mover_tape_flush_v3(ndmpd_session_t *session) 37787917SReza.Sabdar@Sun.COM { 37797917SReza.Sabdar@Sun.COM int n; 37807917SReza.Sabdar@Sun.COM 37817917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0) 37827917SReza.Sabdar@Sun.COM return (0); 37837917SReza.Sabdar@Sun.COM 37847917SReza.Sabdar@Sun.COM (void) memset((void*)&session->ns_mover.md_buf[session-> 37857917SReza.Sabdar@Sun.COM ns_mover.md_w_index], 0, 37867917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size - session->ns_mover.md_w_index); 37877917SReza.Sabdar@Sun.COM 37887917SReza.Sabdar@Sun.COM n = mover_tape_write_v3(session, session->ns_mover.md_buf, 37897917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 37907917SReza.Sabdar@Sun.COM if (n < 0) { 37917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape write error: %m."); 37927917SReza.Sabdar@Sun.COM return (-1); 37937917SReza.Sabdar@Sun.COM } 37947917SReza.Sabdar@Sun.COM 37957917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 37967917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 37977917SReza.Sabdar@Sun.COM return (n); 37987917SReza.Sabdar@Sun.COM } 37997917SReza.Sabdar@Sun.COM 38007917SReza.Sabdar@Sun.COM 38017917SReza.Sabdar@Sun.COM /* 38027917SReza.Sabdar@Sun.COM * ndmpd_local_write_v3 38037917SReza.Sabdar@Sun.COM * 38047917SReza.Sabdar@Sun.COM * Buffers and writes data to the tape device. 38057917SReza.Sabdar@Sun.COM * A full tape record is buffered before being written. 38067917SReza.Sabdar@Sun.COM * 38077917SReza.Sabdar@Sun.COM * Parameters: 38087917SReza.Sabdar@Sun.COM * session (input) - session pointer. 38097917SReza.Sabdar@Sun.COM * data (input) - data to be written. 38107917SReza.Sabdar@Sun.COM * length (input) - data length. 38117917SReza.Sabdar@Sun.COM * 38127917SReza.Sabdar@Sun.COM * Returns: 38137917SReza.Sabdar@Sun.COM * 0 - data successfully written. 38147917SReza.Sabdar@Sun.COM * -1 - error. 38157917SReza.Sabdar@Sun.COM */ 38167917SReza.Sabdar@Sun.COM int 38177917SReza.Sabdar@Sun.COM ndmpd_local_write_v3(ndmpd_session_t *session, char *data, ulong_t length) 38187917SReza.Sabdar@Sun.COM { 38197917SReza.Sabdar@Sun.COM ulong_t count = 0; 38207917SReza.Sabdar@Sun.COM ssize_t n; 38217917SReza.Sabdar@Sun.COM ulong_t len; 38227917SReza.Sabdar@Sun.COM 38237917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 38247917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 38257917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 38267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mover state to write data"); 38277917SReza.Sabdar@Sun.COM return (-1); 38287917SReza.Sabdar@Sun.COM } 38297917SReza.Sabdar@Sun.COM 38307917SReza.Sabdar@Sun.COM /* 38317917SReza.Sabdar@Sun.COM * A length of 0 indicates that any buffered data should be 38327917SReza.Sabdar@Sun.COM * flushed to tape. 38337917SReza.Sabdar@Sun.COM */ 38347917SReza.Sabdar@Sun.COM if (length == 0) { 38357917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0) 38367917SReza.Sabdar@Sun.COM return (0); 38377917SReza.Sabdar@Sun.COM 38387917SReza.Sabdar@Sun.COM (void) memset((void*)&session->ns_mover.md_buf[session-> 38397917SReza.Sabdar@Sun.COM ns_mover.md_w_index], 0, session->ns_mover.md_record_size - 38407917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index); 38417917SReza.Sabdar@Sun.COM 38427917SReza.Sabdar@Sun.COM n = mover_tape_write_v3(session, session->ns_mover.md_buf, 38437917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 38447917SReza.Sabdar@Sun.COM if (n <= 0) { 38457917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 38467917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 38477917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 38487917SReza.Sabdar@Sun.COM return (-1); 38497917SReza.Sabdar@Sun.COM } 38507917SReza.Sabdar@Sun.COM 38517917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 38527917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 38537917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 38547917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 38557917SReza.Sabdar@Sun.COM return (0); 38567917SReza.Sabdar@Sun.COM } 38577917SReza.Sabdar@Sun.COM 38587917SReza.Sabdar@Sun.COM /* Break the data into records. */ 38597917SReza.Sabdar@Sun.COM while (count < length) { 38607917SReza.Sabdar@Sun.COM /* 38617917SReza.Sabdar@Sun.COM * Determine if data needs to be buffered or 38627917SReza.Sabdar@Sun.COM * can be written directly from user supplied location. 38637917SReza.Sabdar@Sun.COM * We can fast path the write if there is no pending 38647917SReza.Sabdar@Sun.COM * buffered data and there is at least a full records worth 38657917SReza.Sabdar@Sun.COM * of data to be written. 38667917SReza.Sabdar@Sun.COM */ 38677917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0 && 38687917SReza.Sabdar@Sun.COM length - count >= session->ns_mover.md_record_size) { 38697917SReza.Sabdar@Sun.COM n = mover_tape_write_v3(session, &data[count], 38707917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 38717917SReza.Sabdar@Sun.COM if (n <= 0) { 38727917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 38737917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 38747917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 38757917SReza.Sabdar@Sun.COM return (-1); 38767917SReza.Sabdar@Sun.COM } 38777917SReza.Sabdar@Sun.COM 38787917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 38797917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 38807917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 38817917SReza.Sabdar@Sun.COM count += n; 38827917SReza.Sabdar@Sun.COM continue; 38837917SReza.Sabdar@Sun.COM } 38847917SReza.Sabdar@Sun.COM 38857917SReza.Sabdar@Sun.COM /* Buffer the data */ 38867917SReza.Sabdar@Sun.COM len = length - count; 38877917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_record_size - 38887917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index) 38897917SReza.Sabdar@Sun.COM len = session->ns_mover.md_record_size - 38907917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index; 38917917SReza.Sabdar@Sun.COM 38927917SReza.Sabdar@Sun.COM (void) memcpy(&session->ns_mover.md_buf[session-> 38937917SReza.Sabdar@Sun.COM ns_mover.md_w_index], &data[count], len); 38947917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index += len; 38957917SReza.Sabdar@Sun.COM count += len; 38967917SReza.Sabdar@Sun.COM 38977917SReza.Sabdar@Sun.COM /* Write the buffer if its full */ 38987917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 38997917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size) { 39007917SReza.Sabdar@Sun.COM n = mover_tape_write_v3(session, 39017917SReza.Sabdar@Sun.COM session->ns_mover.md_buf, 39027917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 39037917SReza.Sabdar@Sun.COM if (n < 0) { 39047917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 39057917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 39067917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 39077917SReza.Sabdar@Sun.COM return (-1); 39087917SReza.Sabdar@Sun.COM } 39097917SReza.Sabdar@Sun.COM 39107917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 39117917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 39127917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 39137917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 39147917SReza.Sabdar@Sun.COM } 39157917SReza.Sabdar@Sun.COM } 39167917SReza.Sabdar@Sun.COM 39177917SReza.Sabdar@Sun.COM return (0); 39187917SReza.Sabdar@Sun.COM } 39197917SReza.Sabdar@Sun.COM 39207917SReza.Sabdar@Sun.COM 39217917SReza.Sabdar@Sun.COM /* 39227917SReza.Sabdar@Sun.COM * mover_data_read_v3 39237917SReza.Sabdar@Sun.COM * 39247917SReza.Sabdar@Sun.COM * Reads backup data from the data connection and writes the 39257917SReza.Sabdar@Sun.COM * received data to the tape device. 39267917SReza.Sabdar@Sun.COM * 39277917SReza.Sabdar@Sun.COM * Parameters: 39287917SReza.Sabdar@Sun.COM * cookie (input) - session pointer. 39297917SReza.Sabdar@Sun.COM * fd (input) - file descriptor. 39307917SReza.Sabdar@Sun.COM * mode (input) - select mode. 39317917SReza.Sabdar@Sun.COM * 39327917SReza.Sabdar@Sun.COM * Returns: 39337917SReza.Sabdar@Sun.COM * void. 39347917SReza.Sabdar@Sun.COM */ 39357917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 39367917SReza.Sabdar@Sun.COM static void 39377917SReza.Sabdar@Sun.COM mover_data_read_v3(void *cookie, int fd, ulong_t mode) 39387917SReza.Sabdar@Sun.COM { 39397917SReza.Sabdar@Sun.COM ndmpd_session_t *session = (ndmpd_session_t *)cookie; 39407917SReza.Sabdar@Sun.COM int n; 39417917SReza.Sabdar@Sun.COM ulong_t index; 39427917SReza.Sabdar@Sun.COM 39437917SReza.Sabdar@Sun.COM n = read(fd, &session->ns_mover.md_buf[session->ns_mover.md_w_index], 39447917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size - session->ns_mover.md_w_index); 39457917SReza.Sabdar@Sun.COM 39467917SReza.Sabdar@Sun.COM /* 39477917SReza.Sabdar@Sun.COM * Since this function is only called when select believes data 39487917SReza.Sabdar@Sun.COM * is available to be read, a return of zero indicates the 39497917SReza.Sabdar@Sun.COM * connection has been closed. 39507917SReza.Sabdar@Sun.COM */ 39517917SReza.Sabdar@Sun.COM if (n <= 0) { 39527917SReza.Sabdar@Sun.COM if (n < 0 && errno == EWOULDBLOCK) { 39537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n %d errno %d", n, errno); 39547917SReza.Sabdar@Sun.COM return; 39557917SReza.Sabdar@Sun.COM } 39567917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n %d errno %d", n, errno); 39577917SReza.Sabdar@Sun.COM 39587917SReza.Sabdar@Sun.COM /* Save the index since mover_tape_flush_v3 resets it. */ 39597917SReza.Sabdar@Sun.COM index = session->ns_mover.md_w_index; 39607917SReza.Sabdar@Sun.COM 39617917SReza.Sabdar@Sun.COM /* Flush any buffered data to tape. */ 39627917SReza.Sabdar@Sun.COM if (mover_tape_flush_v3(session) > 0) { 39637917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += index; 39647917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 39657917SReza.Sabdar@Sun.COM } 39667917SReza.Sabdar@Sun.COM 39677917SReza.Sabdar@Sun.COM if (n == 0) 39687917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 39697917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_CONNECT_CLOSED); 39707917SReza.Sabdar@Sun.COM else 39717917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 39727917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 39737917SReza.Sabdar@Sun.COM 39747917SReza.Sabdar@Sun.COM return; 39757917SReza.Sabdar@Sun.COM } 39767917SReza.Sabdar@Sun.COM 39777917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n %d", n); 39787917SReza.Sabdar@Sun.COM 39797917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index += n; 39807917SReza.Sabdar@Sun.COM 39817917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == session->ns_mover.md_record_size) { 39827917SReza.Sabdar@Sun.COM n = mover_tape_write_v3(session, session->ns_mover.md_buf, 39837917SReza.Sabdar@Sun.COM session->ns_mover.md_record_size); 39847917SReza.Sabdar@Sun.COM if (n <= 0) { 39857917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 39867917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 39877917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 39887917SReza.Sabdar@Sun.COM return; 39897917SReza.Sabdar@Sun.COM } 39907917SReza.Sabdar@Sun.COM 39917917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 39927917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 39937917SReza.Sabdar@Sun.COM session->ns_mover.md_data_written += n; 39947917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 39957917SReza.Sabdar@Sun.COM } 39967917SReza.Sabdar@Sun.COM } 39977917SReza.Sabdar@Sun.COM 39987917SReza.Sabdar@Sun.COM /* 39997917SReza.Sabdar@Sun.COM * mover_tape_read_v3 40007917SReza.Sabdar@Sun.COM * 40017917SReza.Sabdar@Sun.COM * Reads a data record from tape. Detects and handles EOT conditions. 40027917SReza.Sabdar@Sun.COM * 40037917SReza.Sabdar@Sun.COM * Parameters: 40047917SReza.Sabdar@Sun.COM * session (input) - session pointer. 40057917SReza.Sabdar@Sun.COM * data (input) - location to read data to. 40067917SReza.Sabdar@Sun.COM * 40077917SReza.Sabdar@Sun.COM * Returns: 40087917SReza.Sabdar@Sun.COM * 0 - operation aborted. 40097917SReza.Sabdar@Sun.COM * TAPE_READ_ERR - tape read IO error. 40107917SReza.Sabdar@Sun.COM * TAPE_NO_WRITER_ERR - no writer is running during tape read 40117917SReza.Sabdar@Sun.COM * otherwise - number of bytes read. 40127917SReza.Sabdar@Sun.COM */ 40137917SReza.Sabdar@Sun.COM static int 40147917SReza.Sabdar@Sun.COM mover_tape_read_v3(ndmpd_session_t *session, char *data) 40157917SReza.Sabdar@Sun.COM { 40167917SReza.Sabdar@Sun.COM ssize_t n; 40177917SReza.Sabdar@Sun.COM int err; 40187917SReza.Sabdar@Sun.COM int count; 40197917SReza.Sabdar@Sun.COM 40207917SReza.Sabdar@Sun.COM count = session->ns_mover.md_record_size; 40217917SReza.Sabdar@Sun.COM for (; ; ) { 40227917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, data, count); 40237917SReza.Sabdar@Sun.COM if (n < 0) { 40247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape read error: %m."); 40257917SReza.Sabdar@Sun.COM return (TAPE_READ_ERR); 40267917SReza.Sabdar@Sun.COM } 40277917SReza.Sabdar@Sun.COM NS_ADD(rtape, n); 40287917SReza.Sabdar@Sun.COM 40297917SReza.Sabdar@Sun.COM if (n == 0) { 40307917SReza.Sabdar@Sun.COM if (!is_writer_running_v3(session)) 40317917SReza.Sabdar@Sun.COM return (TAPE_NO_WRITER_ERR); 40327917SReza.Sabdar@Sun.COM 40337917SReza.Sabdar@Sun.COM /* 40347917SReza.Sabdar@Sun.COM * End of media reached. 40357917SReza.Sabdar@Sun.COM * Notify client and wait for the client to 40367917SReza.Sabdar@Sun.COM * either abort the data operation or continue the 40377917SReza.Sabdar@Sun.COM * operation after changing the tape. 40387917SReza.Sabdar@Sun.COM */ 40397917SReza.Sabdar@Sun.COM NDMP_APILOG((void*)session, NDMP_LOG_NORMAL, 40407917SReza.Sabdar@Sun.COM ++ndmp_log_msg_id, 40417917SReza.Sabdar@Sun.COM "End of tape reached. Load next tape"); 40427917SReza.Sabdar@Sun.COM 40437917SReza.Sabdar@Sun.COM err = mover_pause_v3(session, NDMP_MOVER_PAUSE_EOF); 40447917SReza.Sabdar@Sun.COM 40457917SReza.Sabdar@Sun.COM /* Operation aborted or connection terminated? */ 40467917SReza.Sabdar@Sun.COM if (err < 0) { 40477917SReza.Sabdar@Sun.COM /* 40487917SReza.Sabdar@Sun.COM * Back up one record if it's read but not 40497917SReza.Sabdar@Sun.COM * used. 40507917SReza.Sabdar@Sun.COM */ 40517917SReza.Sabdar@Sun.COM if (count != session->ns_mover.md_record_size) 40527917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl( 40537917SReza.Sabdar@Sun.COM session->ns_tape.td_fd, MTBSR, 1); 40547917SReza.Sabdar@Sun.COM return (0); 40557917SReza.Sabdar@Sun.COM } 40567917SReza.Sabdar@Sun.COM 40577917SReza.Sabdar@Sun.COM /* Retry the read from the new tape. */ 40587917SReza.Sabdar@Sun.COM continue; 40597917SReza.Sabdar@Sun.COM } 40607917SReza.Sabdar@Sun.COM 40617917SReza.Sabdar@Sun.COM data += n; 40627917SReza.Sabdar@Sun.COM count -= n; 40637917SReza.Sabdar@Sun.COM if (count <= 0) { 40647917SReza.Sabdar@Sun.COM session->ns_mover.md_record_num++; 40657917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count++; 40667917SReza.Sabdar@Sun.COM return (n); 40677917SReza.Sabdar@Sun.COM } 40687917SReza.Sabdar@Sun.COM } 40697917SReza.Sabdar@Sun.COM } 40707917SReza.Sabdar@Sun.COM 40717917SReza.Sabdar@Sun.COM 40727917SReza.Sabdar@Sun.COM /* 40737917SReza.Sabdar@Sun.COM * mover_data_write_v3 40747917SReza.Sabdar@Sun.COM * 40757917SReza.Sabdar@Sun.COM * Reads backup data from the tape device and writes the 40767917SReza.Sabdar@Sun.COM * data to the data connection. 40777917SReza.Sabdar@Sun.COM * This function is called by ndmpd_select when the data connection 40787917SReza.Sabdar@Sun.COM * is ready for more data to be written. 40797917SReza.Sabdar@Sun.COM * 40807917SReza.Sabdar@Sun.COM * Parameters: 40817917SReza.Sabdar@Sun.COM * cookie (input) - session pointer. 40827917SReza.Sabdar@Sun.COM * fd (input) - file descriptor. 40837917SReza.Sabdar@Sun.COM * mode (input) - select mode. 40847917SReza.Sabdar@Sun.COM * 40857917SReza.Sabdar@Sun.COM * Returns: 40867917SReza.Sabdar@Sun.COM * void. 40877917SReza.Sabdar@Sun.COM */ 40887917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 40897917SReza.Sabdar@Sun.COM static void 40907917SReza.Sabdar@Sun.COM mover_data_write_v3(void *cookie, int fd, ulong_t mode) 40917917SReza.Sabdar@Sun.COM { 40927917SReza.Sabdar@Sun.COM ndmpd_session_t *session = (ndmpd_session_t *)cookie; 40937917SReza.Sabdar@Sun.COM int n; 40947917SReza.Sabdar@Sun.COM ulong_t len; 40957917SReza.Sabdar@Sun.COM u_longlong_t wlen; 40967917SReza.Sabdar@Sun.COM ndmp_notify_mover_paused_request pause_request; 40977917SReza.Sabdar@Sun.COM 40987917SReza.Sabdar@Sun.COM /* 40997917SReza.Sabdar@Sun.COM * If the end of the mover window has been reached, 41007917SReza.Sabdar@Sun.COM * then notify the client that a seek is needed. 41017917SReza.Sabdar@Sun.COM * Remove the file handler to prevent this function from 41027917SReza.Sabdar@Sun.COM * being called. The handler will be reinstalled in 41037917SReza.Sabdar@Sun.COM * ndmpd_mover_continue. 41047917SReza.Sabdar@Sun.COM */ 41057917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position >= session->ns_mover.md_window_offset 41067917SReza.Sabdar@Sun.COM + session->ns_mover.md_window_length) { 41077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 41087917SReza.Sabdar@Sun.COM "MOVER_PAUSE_SEEK(%llu)", session->ns_mover.md_position); 41097917SReza.Sabdar@Sun.COM 41107917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 41117917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 41127917SReza.Sabdar@Sun.COM 41137917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_PAUSED; 41147917SReza.Sabdar@Sun.COM session->ns_mover.md_pause_reason = NDMP_MOVER_PAUSE_SEEK; 41157917SReza.Sabdar@Sun.COM pause_request.reason = NDMP_MOVER_PAUSE_SEEK; 41167917SReza.Sabdar@Sun.COM pause_request.seek_position = 41177917SReza.Sabdar@Sun.COM long_long_to_quad(session->ns_mover.md_position); 41187917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position = 41197917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 41207917SReza.Sabdar@Sun.COM 41217917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, fd); 41227917SReza.Sabdar@Sun.COM 41237917SReza.Sabdar@Sun.COM if (ndmp_send_request(session->ns_connection, 41247917SReza.Sabdar@Sun.COM NDMP_NOTIFY_MOVER_PAUSED, NDMP_NO_ERR, 41257917SReza.Sabdar@Sun.COM (void *)&pause_request, 0) < 0) { 41267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 41277917SReza.Sabdar@Sun.COM "Sending notify_mover_paused request"); 41287917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 41297917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 41307917SReza.Sabdar@Sun.COM } 41317917SReza.Sabdar@Sun.COM return; 41327917SReza.Sabdar@Sun.COM } 41337917SReza.Sabdar@Sun.COM 41347917SReza.Sabdar@Sun.COM /* 41357917SReza.Sabdar@Sun.COM * Read more data into the tape buffer if the buffer is empty. 41367917SReza.Sabdar@Sun.COM */ 41377917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index == 0) { 41387917SReza.Sabdar@Sun.COM n = mover_tape_read_v3(session, session->ns_mover.md_buf); 41397917SReza.Sabdar@Sun.COM 41407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 41417917SReza.Sabdar@Sun.COM "read %u bytes from tape", n); 41427917SReza.Sabdar@Sun.COM 41437917SReza.Sabdar@Sun.COM if (n <= 0) { 41447917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, (n == 0 ? 41457917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_ABORTED 41467917SReza.Sabdar@Sun.COM : NDMP_MOVER_HALT_MEDIA_ERROR)); 41477917SReza.Sabdar@Sun.COM return; 41487917SReza.Sabdar@Sun.COM } 41497917SReza.Sabdar@Sun.COM 41507917SReza.Sabdar@Sun.COM /* 41517917SReza.Sabdar@Sun.COM * Discard data if the current data stream position is 41527917SReza.Sabdar@Sun.COM * prior to the seek position. This is necessary if a seek 41537917SReza.Sabdar@Sun.COM * request set the seek pointer to a position that is not a 41547917SReza.Sabdar@Sun.COM * record boundary. The seek request handler can only position 41557917SReza.Sabdar@Sun.COM * to the start of a record. 41567917SReza.Sabdar@Sun.COM */ 41577917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position < 41587917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position) { 41597917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 41607917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position - 41617917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 41627917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 41637917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position; 41647917SReza.Sabdar@Sun.COM } 41657917SReza.Sabdar@Sun.COM 41667917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = n; 41677917SReza.Sabdar@Sun.COM } 41687917SReza.Sabdar@Sun.COM 41697917SReza.Sabdar@Sun.COM /* 41707917SReza.Sabdar@Sun.COM * The limit on the total amount of data to be sent can be 41717917SReza.Sabdar@Sun.COM * dictated by either the end of the mover window or the end of the 41727917SReza.Sabdar@Sun.COM * seek window. 41737917SReza.Sabdar@Sun.COM * First determine which window applies and then determine if the 41747917SReza.Sabdar@Sun.COM * send length needs to be less than a full record to avoid 41757917SReza.Sabdar@Sun.COM * exceeding the window. 41767917SReza.Sabdar@Sun.COM */ 41777917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position + 41787917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read > 41797917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 41807917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) 41817917SReza.Sabdar@Sun.COM wlen = session->ns_mover.md_window_offset + 41827917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length - 41837917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 41847917SReza.Sabdar@Sun.COM else 41857917SReza.Sabdar@Sun.COM wlen = session->ns_mover.md_bytes_left_to_read; 41867917SReza.Sabdar@Sun.COM 41877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "wlen window restrictions: %llu", wlen); 41887917SReza.Sabdar@Sun.COM 41897917SReza.Sabdar@Sun.COM /* 41907917SReza.Sabdar@Sun.COM * Now limit the length to the amount of data in the buffer. 41917917SReza.Sabdar@Sun.COM */ 41927917SReza.Sabdar@Sun.COM if (wlen > session->ns_mover.md_w_index - session->ns_mover.md_r_index) 41937917SReza.Sabdar@Sun.COM wlen = session->ns_mover.md_w_index - 41947917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index; 41957917SReza.Sabdar@Sun.COM 41967917SReza.Sabdar@Sun.COM len = wlen & 0xffffffff; 41977917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 41987917SReza.Sabdar@Sun.COM "buffer restrictions: wlen %llu len %u", wlen, len); 41997917SReza.Sabdar@Sun.COM 42007917SReza.Sabdar@Sun.COM /* 42017917SReza.Sabdar@Sun.COM * Write the data to the data connection. 42027917SReza.Sabdar@Sun.COM */ 42037917SReza.Sabdar@Sun.COM n = write(session->ns_mover.md_sock, 42047917SReza.Sabdar@Sun.COM &session->ns_mover.md_buf[session->ns_mover.md_r_index], len); 42057917SReza.Sabdar@Sun.COM 42067917SReza.Sabdar@Sun.COM if (n < 0) { 42077917SReza.Sabdar@Sun.COM if (errno == EWOULDBLOCK) { 42087917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n %d errno %d", n, errno); 42097917SReza.Sabdar@Sun.COM return; 42107917SReza.Sabdar@Sun.COM } 42117917SReza.Sabdar@Sun.COM 42127917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n %d errno %d", n, errno); 42137917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED); 42147917SReza.Sabdar@Sun.COM return; 42157917SReza.Sabdar@Sun.COM } 42167917SReza.Sabdar@Sun.COM 42177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 42187917SReza.Sabdar@Sun.COM "wrote %u of %u bytes to data connection position %llu r_index %lu", 42197917SReza.Sabdar@Sun.COM n, len, session->ns_mover.md_position, 42207917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index); 42217917SReza.Sabdar@Sun.COM 42227917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index += n; 42237917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 42247917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= n; 42257917SReza.Sabdar@Sun.COM 42267917SReza.Sabdar@Sun.COM /* 42277917SReza.Sabdar@Sun.COM * If all data in the buffer has been written, 42287917SReza.Sabdar@Sun.COM * zero the buffer indices. The next call to this function 42297917SReza.Sabdar@Sun.COM * will read more data from the tape device into the buffer. 42307917SReza.Sabdar@Sun.COM */ 42317917SReza.Sabdar@Sun.COM if (session->ns_mover.md_r_index == session->ns_mover.md_w_index) { 42327917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 42337917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = 0; 42347917SReza.Sabdar@Sun.COM } 42357917SReza.Sabdar@Sun.COM 42367917SReza.Sabdar@Sun.COM /* 42377917SReza.Sabdar@Sun.COM * If the read limit has been reached, 42387917SReza.Sabdar@Sun.COM * then remove the file handler to prevent this 42397917SReza.Sabdar@Sun.COM * function from getting called. The next mover_read request 42407917SReza.Sabdar@Sun.COM * will reinstall the handler. 42417917SReza.Sabdar@Sun.COM */ 42427917SReza.Sabdar@Sun.COM if (session->ns_mover.md_bytes_left_to_read == 0) 42437917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, fd); 42447917SReza.Sabdar@Sun.COM } 42457917SReza.Sabdar@Sun.COM 42467917SReza.Sabdar@Sun.COM 42477917SReza.Sabdar@Sun.COM /* 42487917SReza.Sabdar@Sun.COM * accept_connection_v3 42497917SReza.Sabdar@Sun.COM * 42507917SReza.Sabdar@Sun.COM * Accept a data connection from a data server. 42517917SReza.Sabdar@Sun.COM * Called by ndmpd_select when a connection is pending on 42527917SReza.Sabdar@Sun.COM * the mover listen socket. 42537917SReza.Sabdar@Sun.COM * 42547917SReza.Sabdar@Sun.COM * Parameters: 42557917SReza.Sabdar@Sun.COM * cookie (input) - session pointer. 42567917SReza.Sabdar@Sun.COM * fd (input) - file descriptor. 42577917SReza.Sabdar@Sun.COM * mode (input) - select mode. 42587917SReza.Sabdar@Sun.COM * 42597917SReza.Sabdar@Sun.COM * Returns: 42607917SReza.Sabdar@Sun.COM * void. 42617917SReza.Sabdar@Sun.COM */ 42627917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 42637917SReza.Sabdar@Sun.COM static void 42647917SReza.Sabdar@Sun.COM accept_connection_v3(void *cookie, int fd, ulong_t mode) 42657917SReza.Sabdar@Sun.COM { 42667917SReza.Sabdar@Sun.COM ndmpd_session_t *session = (ndmpd_session_t *)cookie; 42677917SReza.Sabdar@Sun.COM int from_len; 42687917SReza.Sabdar@Sun.COM struct sockaddr_in from; 42697917SReza.Sabdar@Sun.COM int flag = 1; 42707917SReza.Sabdar@Sun.COM 42717917SReza.Sabdar@Sun.COM from_len = sizeof (from); 42727917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = accept(fd, (struct sockaddr *)&from, 42737917SReza.Sabdar@Sun.COM &from_len); 42747917SReza.Sabdar@Sun.COM 42757917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s", ntohs(from.sin_port), 42767917SReza.Sabdar@Sun.COM inet_ntoa(IN_ADDR(from.sin_addr.s_addr))); 42777917SReza.Sabdar@Sun.COM 42787917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(session, fd); 42797917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 42807917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 42817917SReza.Sabdar@Sun.COM 42827917SReza.Sabdar@Sun.COM if (session->ns_mover.md_sock < 0) { 42837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Accept error: %m"); 42847917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_ERROR); 42857917SReza.Sabdar@Sun.COM return; 42867917SReza.Sabdar@Sun.COM } 42877917SReza.Sabdar@Sun.COM 42887917SReza.Sabdar@Sun.COM /* 42897917SReza.Sabdar@Sun.COM * Save the peer address. 42907917SReza.Sabdar@Sun.COM */ 42917917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_ip_v3 = from.sin_addr.s_addr; 42927917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_port_v3 = ntohs(from.sin_port); 42937917SReza.Sabdar@Sun.COM 42947917SReza.Sabdar@Sun.COM /* 42957917SReza.Sabdar@Sun.COM * Set the parameter of the new socket. 42967917SReza.Sabdar@Sun.COM */ 42977917SReza.Sabdar@Sun.COM (void) setsockopt(session->ns_mover.md_sock, SOL_SOCKET, SO_KEEPALIVE, 42987917SReza.Sabdar@Sun.COM &flag, sizeof (flag)); 42997917SReza.Sabdar@Sun.COM 43007917SReza.Sabdar@Sun.COM ndmp_set_socket_nodelay(session->ns_mover.md_sock); 43017917SReza.Sabdar@Sun.COM if (ndmp_sbs > 0) 43027917SReza.Sabdar@Sun.COM ndmp_set_socket_snd_buf(session->ns_mover.md_sock, 43037917SReza.Sabdar@Sun.COM ndmp_sbs*KILOBYTE); 43047917SReza.Sabdar@Sun.COM if (ndmp_rbs > 0) 43057917SReza.Sabdar@Sun.COM ndmp_set_socket_rcv_buf(session->ns_mover.md_sock, 43067917SReza.Sabdar@Sun.COM ndmp_rbs*KILOBYTE); 43077917SReza.Sabdar@Sun.COM 43087917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "sock fd: %d", session->ns_mover.md_sock); 43097917SReza.Sabdar@Sun.COM 43107917SReza.Sabdar@Sun.COM if (session->ns_mover.md_mode == NDMP_MOVER_MODE_READ) { 43117917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void*)session, 43127917SReza.Sabdar@Sun.COM session->ns_mover.md_sock, NDMPD_SELECT_MODE_READ, 43137917SReza.Sabdar@Sun.COM HC_MOVER, mover_data_read_v3) < 0) { 43147917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 43157917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 43167917SReza.Sabdar@Sun.COM return; 43177917SReza.Sabdar@Sun.COM } 43187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Backup connection established by %s:%d", 43197917SReza.Sabdar@Sun.COM inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 43207917SReza.Sabdar@Sun.COM ntohs(from.sin_port)); 43217917SReza.Sabdar@Sun.COM } else { 43227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Restore connection established by %s:%d", 43237917SReza.Sabdar@Sun.COM inet_ntoa(IN_ADDR(from.sin_addr.s_addr)), 43247917SReza.Sabdar@Sun.COM ntohs(from.sin_port)); 43257917SReza.Sabdar@Sun.COM } 43267917SReza.Sabdar@Sun.COM 43277917SReza.Sabdar@Sun.COM session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE; 43287917SReza.Sabdar@Sun.COM } 43297917SReza.Sabdar@Sun.COM 43307917SReza.Sabdar@Sun.COM 43317917SReza.Sabdar@Sun.COM /* 43327917SReza.Sabdar@Sun.COM * create_listen_socket_v3 43337917SReza.Sabdar@Sun.COM * 43347917SReza.Sabdar@Sun.COM * Creates a socket for listening for accepting data connections. 43357917SReza.Sabdar@Sun.COM * 43367917SReza.Sabdar@Sun.COM * Parameters: 43377917SReza.Sabdar@Sun.COM * session (input) - session pointer. 43387917SReza.Sabdar@Sun.COM * addr (output) - location to store address of socket. 43397917SReza.Sabdar@Sun.COM * port (output) - location to store port of socket. 43407917SReza.Sabdar@Sun.COM * 43417917SReza.Sabdar@Sun.COM * Returns: 43427917SReza.Sabdar@Sun.COM * 0 - success. 43437917SReza.Sabdar@Sun.COM * -1 - error. 43447917SReza.Sabdar@Sun.COM */ 43457917SReza.Sabdar@Sun.COM static int 43467917SReza.Sabdar@Sun.COM create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, ushort_t *port) 43477917SReza.Sabdar@Sun.COM { 43487917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = ndmp_create_socket(addr, port); 43497917SReza.Sabdar@Sun.COM if (session->ns_mover.md_listen_sock < 0) 43507917SReza.Sabdar@Sun.COM return (-1); 43517917SReza.Sabdar@Sun.COM 43527917SReza.Sabdar@Sun.COM /* 43537917SReza.Sabdar@Sun.COM * Add a file handler for the listen socket. 43547917SReza.Sabdar@Sun.COM * ndmpd_select will call accept_connection when a 43557917SReza.Sabdar@Sun.COM * connection is ready to be accepted. 43567917SReza.Sabdar@Sun.COM */ 43577917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void *) session, 43587917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER, 43597917SReza.Sabdar@Sun.COM accept_connection_v3) < 0) { 43607917SReza.Sabdar@Sun.COM (void) close(session->ns_mover.md_listen_sock); 43617917SReza.Sabdar@Sun.COM session->ns_mover.md_listen_sock = -1; 43627917SReza.Sabdar@Sun.COM return (-1); 43637917SReza.Sabdar@Sun.COM } 43647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "IP %s port %d", 43657917SReza.Sabdar@Sun.COM inet_ntoa(*(struct in_addr *)addr), ntohs(*port)); 43667917SReza.Sabdar@Sun.COM return (0); 43677917SReza.Sabdar@Sun.COM } 43687917SReza.Sabdar@Sun.COM 43697917SReza.Sabdar@Sun.COM 43707917SReza.Sabdar@Sun.COM /* 43717917SReza.Sabdar@Sun.COM * mover_connect_sock_v3 43727917SReza.Sabdar@Sun.COM * 43737917SReza.Sabdar@Sun.COM * Connect the mover to the specified address 43747917SReza.Sabdar@Sun.COM * 43757917SReza.Sabdar@Sun.COM * Parameters: 43767917SReza.Sabdar@Sun.COM * session (input) - session pointer. 43777917SReza.Sabdar@Sun.COM * mode (input) - mover mode. 43787917SReza.Sabdar@Sun.COM * addr (output) - location to store address of socket. 43797917SReza.Sabdar@Sun.COM * port (output) - location to store port of socket. 43807917SReza.Sabdar@Sun.COM * 43817917SReza.Sabdar@Sun.COM * Returns: 43827917SReza.Sabdar@Sun.COM * error code. 43837917SReza.Sabdar@Sun.COM */ 43847917SReza.Sabdar@Sun.COM static ndmp_error 43857917SReza.Sabdar@Sun.COM mover_connect_sock_v3(ndmpd_session_t *session, ndmp_mover_mode mode, 43867917SReza.Sabdar@Sun.COM ulong_t addr, ushort_t port) 43877917SReza.Sabdar@Sun.COM { 43887917SReza.Sabdar@Sun.COM int sock; 43897917SReza.Sabdar@Sun.COM 43907917SReza.Sabdar@Sun.COM sock = ndmp_connect_sock_v3(addr, port); 43917917SReza.Sabdar@Sun.COM if (sock < 0) 43927917SReza.Sabdar@Sun.COM return (NDMP_CONNECT_ERR); 43937917SReza.Sabdar@Sun.COM 43947917SReza.Sabdar@Sun.COM if (mode == NDMP_MOVER_MODE_READ) { 43957917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(session, (void*)session, sock, 43967917SReza.Sabdar@Sun.COM NDMPD_SELECT_MODE_READ, HC_MOVER, mover_data_read_v3) < 0) { 43977917SReza.Sabdar@Sun.COM (void) close(sock); 43987917SReza.Sabdar@Sun.COM return (NDMP_CONNECT_ERR); 43997917SReza.Sabdar@Sun.COM } 44007917SReza.Sabdar@Sun.COM } 44017917SReza.Sabdar@Sun.COM session->ns_mover.md_sock = sock; 44027917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.addr_type = NDMP_ADDR_TCP; 44037917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_ip_v3 = ntohl(addr); 44047917SReza.Sabdar@Sun.COM session->ns_mover.md_data_addr.tcp_port_v3 = port; 44057917SReza.Sabdar@Sun.COM return (NDMP_NO_ERR); 44067917SReza.Sabdar@Sun.COM } 44077917SReza.Sabdar@Sun.COM 44087917SReza.Sabdar@Sun.COM 44097917SReza.Sabdar@Sun.COM /* 44107917SReza.Sabdar@Sun.COM * ndmpd_local_read_v3 44117917SReza.Sabdar@Sun.COM * 44127917SReza.Sabdar@Sun.COM * Reads data from the local tape device. 44137917SReza.Sabdar@Sun.COM * Full tape records are read and buffered. 44147917SReza.Sabdar@Sun.COM * 44157917SReza.Sabdar@Sun.COM * Parameters: 44167917SReza.Sabdar@Sun.COM * session (input) - session pointer. 44177917SReza.Sabdar@Sun.COM * data (input) - location to store data. 44187917SReza.Sabdar@Sun.COM * length (input) - data length. 44197917SReza.Sabdar@Sun.COM * 44207917SReza.Sabdar@Sun.COM * Returns: 44217917SReza.Sabdar@Sun.COM * 1 - no read error but no writer running 44227917SReza.Sabdar@Sun.COM * 0 - data successfully read. 44237917SReza.Sabdar@Sun.COM * -1 - error. 44247917SReza.Sabdar@Sun.COM */ 44257917SReza.Sabdar@Sun.COM int 44267917SReza.Sabdar@Sun.COM ndmpd_local_read_v3(ndmpd_session_t *session, char *data, ulong_t length) 44277917SReza.Sabdar@Sun.COM { 44287917SReza.Sabdar@Sun.COM ulong_t count; 44297917SReza.Sabdar@Sun.COM ulong_t len; 44307917SReza.Sabdar@Sun.COM ssize_t n; 44317917SReza.Sabdar@Sun.COM 44327917SReza.Sabdar@Sun.COM count = 0; 44337917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_IDLE || 44347917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 44357917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_HALTED) { 44367917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Invalid mover state to read data"); 44377917SReza.Sabdar@Sun.COM return (-1); 44387917SReza.Sabdar@Sun.COM } 44397917SReza.Sabdar@Sun.COM 44407917SReza.Sabdar@Sun.COM /* 44417917SReza.Sabdar@Sun.COM * Automatically increase the seek window if necessary. 44427917SReza.Sabdar@Sun.COM * This is needed in the event the module attempts to read 44437917SReza.Sabdar@Sun.COM * past a seek window set via a prior call to ndmpd_seek() or 44447917SReza.Sabdar@Sun.COM * the module has not issued a seek. If no seek was issued then 44457917SReza.Sabdar@Sun.COM * pretend that a seek was issued to read the entire tape. 44467917SReza.Sabdar@Sun.COM */ 44477917SReza.Sabdar@Sun.COM if (length > session->ns_mover.md_bytes_left_to_read) { 44487917SReza.Sabdar@Sun.COM /* ndmpd_seek() never called? */ 44497917SReza.Sabdar@Sun.COM if (session->ns_data.dd_read_length == 0) { 44507917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = ~0LL; 44517917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 0LL; 44527917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = ~0LL; 44537917SReza.Sabdar@Sun.COM } else { 44547917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read = length; 44557917SReza.Sabdar@Sun.COM session->ns_data.dd_read_offset = 44567917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 44577917SReza.Sabdar@Sun.COM session->ns_data.dd_read_length = length; 44587917SReza.Sabdar@Sun.COM } 44597917SReza.Sabdar@Sun.COM } 44607917SReza.Sabdar@Sun.COM 44617917SReza.Sabdar@Sun.COM /* 44627917SReza.Sabdar@Sun.COM * Read as many records as necessary to satisfy the request. 44637917SReza.Sabdar@Sun.COM */ 44647917SReza.Sabdar@Sun.COM while (count < length) { 44657917SReza.Sabdar@Sun.COM /* 44667917SReza.Sabdar@Sun.COM * If the end of the mover window has been reached, 44677917SReza.Sabdar@Sun.COM * then notify the client that a new data window is needed. 44687917SReza.Sabdar@Sun.COM */ 44697917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position >= 44707917SReza.Sabdar@Sun.COM session->ns_mover.md_window_offset + 44717917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length) { 44727917SReza.Sabdar@Sun.COM if (mover_pause_v3(session, 44737917SReza.Sabdar@Sun.COM NDMP_MOVER_PAUSE_SEEK) < 0) { 44747917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 44757917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_INTERNAL_ERROR); 44767917SReza.Sabdar@Sun.COM return (-1); 44777917SReza.Sabdar@Sun.COM } 44787917SReza.Sabdar@Sun.COM continue; 44797917SReza.Sabdar@Sun.COM } 44807917SReza.Sabdar@Sun.COM 44817917SReza.Sabdar@Sun.COM len = length - count; 44827917SReza.Sabdar@Sun.COM 44837917SReza.Sabdar@Sun.COM /* 44847917SReza.Sabdar@Sun.COM * Prevent reading past the end of the window. 44857917SReza.Sabdar@Sun.COM */ 44867917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_window_offset + 44877917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length - 44887917SReza.Sabdar@Sun.COM session->ns_mover.md_position) 44897917SReza.Sabdar@Sun.COM len = session->ns_mover.md_window_offset + 44907917SReza.Sabdar@Sun.COM session->ns_mover.md_window_length - 44917917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 44927917SReza.Sabdar@Sun.COM 44937917SReza.Sabdar@Sun.COM /* 44947917SReza.Sabdar@Sun.COM * Copy from the data buffer first. 44957917SReza.Sabdar@Sun.COM */ 44967917SReza.Sabdar@Sun.COM if (session->ns_mover.md_w_index - 44977917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index != 0) { 44987917SReza.Sabdar@Sun.COM /* 44997917SReza.Sabdar@Sun.COM * Limit the copy to the amount of data in the buffer. 45007917SReza.Sabdar@Sun.COM */ 45017917SReza.Sabdar@Sun.COM if (len > session->ns_mover.md_w_index - 45027917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index) 45037917SReza.Sabdar@Sun.COM len = session->ns_mover.md_w_index - 45047917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index; 45057917SReza.Sabdar@Sun.COM (void) memcpy((void*)&data[count], 45067917SReza.Sabdar@Sun.COM &session->ns_mover.md_buf[session-> 45077917SReza.Sabdar@Sun.COM ns_mover.md_r_index], len); 45087917SReza.Sabdar@Sun.COM count += len; 45097917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index += len; 45107917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= len; 45117917SReza.Sabdar@Sun.COM session->ns_mover.md_position += len; 45127917SReza.Sabdar@Sun.COM continue; 45137917SReza.Sabdar@Sun.COM } 45147917SReza.Sabdar@Sun.COM 45157917SReza.Sabdar@Sun.COM /* 45167917SReza.Sabdar@Sun.COM * Determine if data needs to be buffered or 45177917SReza.Sabdar@Sun.COM * can be read directly to user supplied location. 45187917SReza.Sabdar@Sun.COM * We can fast path the read if at least a full record 45197917SReza.Sabdar@Sun.COM * needs to be read and there is no seek pending. 45207917SReza.Sabdar@Sun.COM * This is done to eliminate a buffer copy. 45217917SReza.Sabdar@Sun.COM */ 45227917SReza.Sabdar@Sun.COM if (len >= session->ns_mover.md_record_size && 45237917SReza.Sabdar@Sun.COM session->ns_mover.md_position >= 45247917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position) { 45257917SReza.Sabdar@Sun.COM n = mover_tape_read_v3(session, &data[count]); 45267917SReza.Sabdar@Sun.COM if (n <= 0) { 45277917SReza.Sabdar@Sun.COM if (n == TAPE_NO_WRITER_ERR) 45287917SReza.Sabdar@Sun.COM return (1); 45297917SReza.Sabdar@Sun.COM 45307917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 45317917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 45327917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 45337917SReza.Sabdar@Sun.COM return ((n == 0) ? 1 : -1); 45347917SReza.Sabdar@Sun.COM } 45357917SReza.Sabdar@Sun.COM 45367917SReza.Sabdar@Sun.COM count += n; 45377917SReza.Sabdar@Sun.COM session->ns_mover.md_bytes_left_to_read -= n; 45387917SReza.Sabdar@Sun.COM session->ns_mover.md_position += n; 45397917SReza.Sabdar@Sun.COM continue; 45407917SReza.Sabdar@Sun.COM } 45417917SReza.Sabdar@Sun.COM 45427917SReza.Sabdar@Sun.COM /* Read the next record into the buffer. */ 45437917SReza.Sabdar@Sun.COM n = mover_tape_read_v3(session, session->ns_mover.md_buf); 45447917SReza.Sabdar@Sun.COM if (n <= 0) { 45457917SReza.Sabdar@Sun.COM if (n == TAPE_NO_WRITER_ERR) 45467917SReza.Sabdar@Sun.COM return (1); 45477917SReza.Sabdar@Sun.COM 45487917SReza.Sabdar@Sun.COM ndmpd_mover_error(session, 45497917SReza.Sabdar@Sun.COM (n == 0 ? NDMP_MOVER_HALT_ABORTED : 45507917SReza.Sabdar@Sun.COM NDMP_MOVER_HALT_MEDIA_ERROR)); 45517917SReza.Sabdar@Sun.COM return ((n == 0) ? 1 : -1); 45527917SReza.Sabdar@Sun.COM } 45537917SReza.Sabdar@Sun.COM 45547917SReza.Sabdar@Sun.COM session->ns_mover.md_w_index = n; 45557917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 0; 45567917SReza.Sabdar@Sun.COM 45577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n: %d", n); 45587917SReza.Sabdar@Sun.COM 45597917SReza.Sabdar@Sun.COM /* 45607917SReza.Sabdar@Sun.COM * Discard data if the current data stream position is 45617917SReza.Sabdar@Sun.COM * prior to the seek position. This is necessary if a seek 45627917SReza.Sabdar@Sun.COM * request set the seek pointer to a position that is not a 45637917SReza.Sabdar@Sun.COM * record boundary. The seek request handler can only position 45647917SReza.Sabdar@Sun.COM * to the start of a record. 45657917SReza.Sabdar@Sun.COM */ 45667917SReza.Sabdar@Sun.COM if (session->ns_mover.md_position < 45677917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position) { 45687917SReza.Sabdar@Sun.COM session->ns_mover.md_r_index = 45697917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position - 45707917SReza.Sabdar@Sun.COM session->ns_mover.md_position; 45717917SReza.Sabdar@Sun.COM session->ns_mover.md_position = 45727917SReza.Sabdar@Sun.COM session->ns_mover.md_seek_position; 45737917SReza.Sabdar@Sun.COM } 45747917SReza.Sabdar@Sun.COM } 45757917SReza.Sabdar@Sun.COM 45767917SReza.Sabdar@Sun.COM return (0); 45777917SReza.Sabdar@Sun.COM } 4578