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