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