17917SReza.Sabdar@Sun.COM /* 2*12186SJanice.Chang@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 37917SReza.Sabdar@Sun.COM */ 47917SReza.Sabdar@Sun.COM 57917SReza.Sabdar@Sun.COM /* 67917SReza.Sabdar@Sun.COM * BSD 3 Clause License 77917SReza.Sabdar@Sun.COM * 87917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association. 97917SReza.Sabdar@Sun.COM * 107917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without 117917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions 127917SReza.Sabdar@Sun.COM * are met: 137917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright 147917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer. 157917SReza.Sabdar@Sun.COM * 167917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright 177917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in 187917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the 197917SReza.Sabdar@Sun.COM * distribution. 207917SReza.Sabdar@Sun.COM * 217917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA) 227917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote 237917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written 247917SReza.Sabdar@Sun.COM * permission. 257917SReza.Sabdar@Sun.COM * 267917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 277917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 287917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 297917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 307917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 317917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 327917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 337917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 347917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 357917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 367917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 377917SReza.Sabdar@Sun.COM */ 387917SReza.Sabdar@Sun.COM #include <sys/errno.h> 397917SReza.Sabdar@Sun.COM #include <ctype.h> 407917SReza.Sabdar@Sun.COM #include <stdlib.h> 417917SReza.Sabdar@Sun.COM #include <time.h> 427917SReza.Sabdar@Sun.COM #include <sys/types.h> 437917SReza.Sabdar@Sun.COM #include <unistd.h> 447917SReza.Sabdar@Sun.COM #include <libzfs.h> 457917SReza.Sabdar@Sun.COM #include <pthread.h> 467917SReza.Sabdar@Sun.COM #include "tlm.h" 477917SReza.Sabdar@Sun.COM #include "tlm_proto.h" 487917SReza.Sabdar@Sun.COM #include <sys/mtio.h> 497917SReza.Sabdar@Sun.COM #include <sys/mnttab.h> 507917SReza.Sabdar@Sun.COM #include <sys/mntent.h> 517917SReza.Sabdar@Sun.COM #include <sys/statvfs.h> 527917SReza.Sabdar@Sun.COM #include <sys/scsi/impl/uscsi.h> 537917SReza.Sabdar@Sun.COM #include <sys/scsi/scsi.h> 547917SReza.Sabdar@Sun.COM #include <sys/mtio.h> 557917SReza.Sabdar@Sun.COM #include <thread.h> 567917SReza.Sabdar@Sun.COM #include <synch.h> 577917SReza.Sabdar@Sun.COM #include <sys/mutex.h> 587917SReza.Sabdar@Sun.COM #include <sys/sysmacros.h> 597917SReza.Sabdar@Sun.COM #include <sys/mkdev.h> 607917SReza.Sabdar@Sun.COM 617917SReza.Sabdar@Sun.COM /* 627917SReza.Sabdar@Sun.COM * Tar archiving ops vector 637917SReza.Sabdar@Sun.COM */ 647917SReza.Sabdar@Sun.COM tm_ops_t tm_tar_ops = { 657917SReza.Sabdar@Sun.COM "tar", 667917SReza.Sabdar@Sun.COM tar_putfile, 677917SReza.Sabdar@Sun.COM tar_putdir, 687917SReza.Sabdar@Sun.COM NULL, 697917SReza.Sabdar@Sun.COM tar_getfile, 707917SReza.Sabdar@Sun.COM tar_getdir, 717917SReza.Sabdar@Sun.COM NULL 727917SReza.Sabdar@Sun.COM }; 737917SReza.Sabdar@Sun.COM 747917SReza.Sabdar@Sun.COM extern libzfs_handle_t *zlibh; 757917SReza.Sabdar@Sun.COM extern mutex_t zlib_mtx; 767917SReza.Sabdar@Sun.COM 777917SReza.Sabdar@Sun.COM /* 787917SReza.Sabdar@Sun.COM * get the next tape buffer from the drive's pool of buffers 797917SReza.Sabdar@Sun.COM */ 807917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 817917SReza.Sabdar@Sun.COM char * 827917SReza.Sabdar@Sun.COM tlm_get_write_buffer(long want, long *actual_size, 837917SReza.Sabdar@Sun.COM tlm_buffers_t *buffers, int zero) 847917SReza.Sabdar@Sun.COM { 857917SReza.Sabdar@Sun.COM int buf = buffers->tbs_buffer_in; 867917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer = &buffers->tbs_buffer[buf]; 877917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1; 887917SReza.Sabdar@Sun.COM char *rec; 897917SReza.Sabdar@Sun.COM 907917SReza.Sabdar@Sun.COM /* 917917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes 927917SReza.Sabdar@Sun.COM */ 937917SReza.Sabdar@Sun.COM want += align_size; 947917SReza.Sabdar@Sun.COM want &= ~align_size; 957917SReza.Sabdar@Sun.COM 967917SReza.Sabdar@Sun.COM *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 977917SReza.Sabdar@Sun.COM if (*actual_size <= 0) { 987917SReza.Sabdar@Sun.COM /* 997917SReza.Sabdar@Sun.COM * no room, send this one 1007917SReza.Sabdar@Sun.COM * and wait for a free one 1017917SReza.Sabdar@Sun.COM */ 1027917SReza.Sabdar@Sun.COM if (!buffer->tb_full) { 1037917SReza.Sabdar@Sun.COM /* 1047917SReza.Sabdar@Sun.COM * we are now ready to send a full buffer 1057917SReza.Sabdar@Sun.COM * instead of trying to get a new buffer 1067917SReza.Sabdar@Sun.COM * 1077917SReza.Sabdar@Sun.COM * do not send if we failed to get a buffer 1087917SReza.Sabdar@Sun.COM * on the previous call 1097917SReza.Sabdar@Sun.COM */ 1107917SReza.Sabdar@Sun.COM buffer->tb_full = TRUE; 1117917SReza.Sabdar@Sun.COM 1127917SReza.Sabdar@Sun.COM /* 1137917SReza.Sabdar@Sun.COM * tell the writer that a buffer is available 1147917SReza.Sabdar@Sun.COM */ 1157917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(buffers); 1167917SReza.Sabdar@Sun.COM 1177917SReza.Sabdar@Sun.COM buffer = tlm_buffer_advance_in_idx(buffers); 1187917SReza.Sabdar@Sun.COM } 1197917SReza.Sabdar@Sun.COM 1207917SReza.Sabdar@Sun.COM buffer = tlm_buffer_in_buf(buffers, NULL); 1217917SReza.Sabdar@Sun.COM 1227917SReza.Sabdar@Sun.COM if (buffer->tb_full) { 1237917SReza.Sabdar@Sun.COM /* 1247917SReza.Sabdar@Sun.COM * wait for the writer to free up a buffer 1257917SReza.Sabdar@Sun.COM */ 1267917SReza.Sabdar@Sun.COM tlm_buffer_out_buf_timed_wait(buffers, 500); 1277917SReza.Sabdar@Sun.COM } 1287917SReza.Sabdar@Sun.COM 1297917SReza.Sabdar@Sun.COM buffer = tlm_buffer_in_buf(buffers, NULL); 1307917SReza.Sabdar@Sun.COM if (buffer->tb_full) { 1317917SReza.Sabdar@Sun.COM /* 1327917SReza.Sabdar@Sun.COM * the next buffer is still full 1337917SReza.Sabdar@Sun.COM * of data from previous activity 1347917SReza.Sabdar@Sun.COM * 1357917SReza.Sabdar@Sun.COM * nothing has changed. 1367917SReza.Sabdar@Sun.COM */ 1377917SReza.Sabdar@Sun.COM return (0); 1387917SReza.Sabdar@Sun.COM } 1397917SReza.Sabdar@Sun.COM 1407917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot = 0; 1417917SReza.Sabdar@Sun.COM *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 1427917SReza.Sabdar@Sun.COM } 1437917SReza.Sabdar@Sun.COM 1447917SReza.Sabdar@Sun.COM *actual_size = min(want, *actual_size); 1457917SReza.Sabdar@Sun.COM rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot]; 1467917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot += *actual_size; 1477917SReza.Sabdar@Sun.COM buffers->tbs_offset += *actual_size; 1487917SReza.Sabdar@Sun.COM if (zero) { 1497917SReza.Sabdar@Sun.COM (void) memset(rec, 0, *actual_size); 1507917SReza.Sabdar@Sun.COM } 1517917SReza.Sabdar@Sun.COM return (rec); 1527917SReza.Sabdar@Sun.COM } 1537917SReza.Sabdar@Sun.COM 1547917SReza.Sabdar@Sun.COM /* 1557917SReza.Sabdar@Sun.COM * get a read record from the tape buffer, 1567917SReza.Sabdar@Sun.COM * and read a tape block if necessary 1577917SReza.Sabdar@Sun.COM */ 1587917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 1597917SReza.Sabdar@Sun.COM char * 1607917SReza.Sabdar@Sun.COM tlm_get_read_buffer(int want, int *error, 1617917SReza.Sabdar@Sun.COM tlm_buffers_t *buffers, int *actual_size) 1627917SReza.Sabdar@Sun.COM { 1637917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer; 1647917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1; 1657917SReza.Sabdar@Sun.COM int buf; 1667917SReza.Sabdar@Sun.COM int current_size; 1677917SReza.Sabdar@Sun.COM char *rec; 1687917SReza.Sabdar@Sun.COM 1697917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_out; 1707917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf]; 1717917SReza.Sabdar@Sun.COM 1727917SReza.Sabdar@Sun.COM /* 1737917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes 1747917SReza.Sabdar@Sun.COM */ 1757917SReza.Sabdar@Sun.COM want += align_size; 1767917SReza.Sabdar@Sun.COM want &= ~align_size; 1777917SReza.Sabdar@Sun.COM 1787917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 1797917SReza.Sabdar@Sun.COM if (buffer->tb_full && current_size <= 0) { 1807917SReza.Sabdar@Sun.COM /* 1817917SReza.Sabdar@Sun.COM * no more data, release this 1827917SReza.Sabdar@Sun.COM * one and go get another 1837917SReza.Sabdar@Sun.COM */ 1847917SReza.Sabdar@Sun.COM 1857917SReza.Sabdar@Sun.COM /* 1867917SReza.Sabdar@Sun.COM * tell the reader that a buffer is available 1877917SReza.Sabdar@Sun.COM */ 1887917SReza.Sabdar@Sun.COM buffer->tb_full = FALSE; 1897917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(buffers); 1907917SReza.Sabdar@Sun.COM 1917917SReza.Sabdar@Sun.COM buffer = tlm_buffer_advance_out_idx(buffers); 1927917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 1937917SReza.Sabdar@Sun.COM } 1947917SReza.Sabdar@Sun.COM 1957917SReza.Sabdar@Sun.COM if (!buffer->tb_full) { 1967917SReza.Sabdar@Sun.COM /* 1977917SReza.Sabdar@Sun.COM * next buffer is not full yet. 1987917SReza.Sabdar@Sun.COM * wait for the reader. 1997917SReza.Sabdar@Sun.COM */ 2007917SReza.Sabdar@Sun.COM tlm_buffer_in_buf_timed_wait(buffers, 500); 2017917SReza.Sabdar@Sun.COM 2027917SReza.Sabdar@Sun.COM buffer = tlm_buffer_out_buf(buffers, NULL); 2037917SReza.Sabdar@Sun.COM if (!buffer->tb_full) { 2047917SReza.Sabdar@Sun.COM /* 2057917SReza.Sabdar@Sun.COM * we do not have anything from the tape yet 2067917SReza.Sabdar@Sun.COM */ 2077917SReza.Sabdar@Sun.COM return (0); 2087917SReza.Sabdar@Sun.COM } 2097917SReza.Sabdar@Sun.COM 2107917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 2117917SReza.Sabdar@Sun.COM } 2127917SReza.Sabdar@Sun.COM 2137917SReza.Sabdar@Sun.COM /* Make sure we got something */ 2147917SReza.Sabdar@Sun.COM if (current_size <= 0) 2157917SReza.Sabdar@Sun.COM return (NULL); 2167917SReza.Sabdar@Sun.COM 2177917SReza.Sabdar@Sun.COM current_size = min(want, current_size); 2187917SReza.Sabdar@Sun.COM rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot]; 2197917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot += current_size; 2207917SReza.Sabdar@Sun.COM *actual_size = current_size; 2217917SReza.Sabdar@Sun.COM 2227917SReza.Sabdar@Sun.COM /* 2237917SReza.Sabdar@Sun.COM * the error flag is only sent back one time, 2247917SReza.Sabdar@Sun.COM * since the flag refers to a previous read 2257917SReza.Sabdar@Sun.COM * attempt, not the data in this buffer. 2267917SReza.Sabdar@Sun.COM */ 2277917SReza.Sabdar@Sun.COM *error = buffer->tb_errno; 2287917SReza.Sabdar@Sun.COM 2297917SReza.Sabdar@Sun.COM return (rec); 2307917SReza.Sabdar@Sun.COM } 2317917SReza.Sabdar@Sun.COM 2327917SReza.Sabdar@Sun.COM 2337917SReza.Sabdar@Sun.COM /* 2347917SReza.Sabdar@Sun.COM * unread a previously read buffer back to the tape buffer 2357917SReza.Sabdar@Sun.COM */ 2367917SReza.Sabdar@Sun.COM void 2377917SReza.Sabdar@Sun.COM tlm_unget_read_buffer(tlm_buffers_t *buffers, int size) 2387917SReza.Sabdar@Sun.COM { 2397917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer; 2407917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1; 2417917SReza.Sabdar@Sun.COM int buf; 2427917SReza.Sabdar@Sun.COM int current_size; 2437917SReza.Sabdar@Sun.COM 2447917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_out; 2457917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf]; 2467917SReza.Sabdar@Sun.COM 2477917SReza.Sabdar@Sun.COM /* 2487917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes 2497917SReza.Sabdar@Sun.COM */ 2507917SReza.Sabdar@Sun.COM size += align_size; 2517917SReza.Sabdar@Sun.COM size &= ~align_size; 2527917SReza.Sabdar@Sun.COM 2537917SReza.Sabdar@Sun.COM current_size = min(size, buffer->tb_buffer_spot); 2547917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot -= current_size; 2557917SReza.Sabdar@Sun.COM } 2567917SReza.Sabdar@Sun.COM 2577917SReza.Sabdar@Sun.COM 2587917SReza.Sabdar@Sun.COM /* 2597917SReza.Sabdar@Sun.COM * unwrite a previously written buffer 2607917SReza.Sabdar@Sun.COM */ 2617917SReza.Sabdar@Sun.COM void 2627917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(tlm_buffers_t *buffers, int size) 2637917SReza.Sabdar@Sun.COM { 2647917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer; 2657917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1; 2667917SReza.Sabdar@Sun.COM int buf; 2677917SReza.Sabdar@Sun.COM int current_size; 2687917SReza.Sabdar@Sun.COM 2697917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_in; 2707917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf]; 2717917SReza.Sabdar@Sun.COM 2727917SReza.Sabdar@Sun.COM /* 2737917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes 2747917SReza.Sabdar@Sun.COM */ 2757917SReza.Sabdar@Sun.COM size += align_size; 2767917SReza.Sabdar@Sun.COM size &= ~align_size; 2777917SReza.Sabdar@Sun.COM 2787917SReza.Sabdar@Sun.COM current_size = min(size, buffer->tb_buffer_spot); 2797917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot -= current_size; 2807917SReza.Sabdar@Sun.COM } 2817917SReza.Sabdar@Sun.COM 2827917SReza.Sabdar@Sun.COM 2837917SReza.Sabdar@Sun.COM /* 2847917SReza.Sabdar@Sun.COM * build a checksum for a TAR header record 2857917SReza.Sabdar@Sun.COM */ 2867917SReza.Sabdar@Sun.COM void 2877917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tlm_tar_hdr_t *r) 2887917SReza.Sabdar@Sun.COM { 2897917SReza.Sabdar@Sun.COM int i; 2907917SReza.Sabdar@Sun.COM int sum = 0; 2917917SReza.Sabdar@Sun.COM char *c = (char *)r; 2927917SReza.Sabdar@Sun.COM 2937917SReza.Sabdar@Sun.COM (void) memcpy(r->th_chksum, CHKBLANKS, strlen(CHKBLANKS)); 2947917SReza.Sabdar@Sun.COM for (i = 0; i < RECORDSIZE; i++) { 2957917SReza.Sabdar@Sun.COM sum += c[i] & 0xFF; 2967917SReza.Sabdar@Sun.COM } 2977917SReza.Sabdar@Sun.COM (void) snprintf(r->th_chksum, sizeof (r->th_chksum), "%6o", sum); 2987917SReza.Sabdar@Sun.COM } 2997917SReza.Sabdar@Sun.COM 3007917SReza.Sabdar@Sun.COM /* 3017917SReza.Sabdar@Sun.COM * verify the tar header checksum 3027917SReza.Sabdar@Sun.COM */ 3037917SReza.Sabdar@Sun.COM int 3047917SReza.Sabdar@Sun.COM tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr) 3057917SReza.Sabdar@Sun.COM { 3067917SReza.Sabdar@Sun.COM int chksum = oct_atoi(tar_hdr->th_chksum); 3077917SReza.Sabdar@Sun.COM uchar_t *p = (uchar_t *)tar_hdr; 3087917SReza.Sabdar@Sun.COM int sum = 0; /* initial value of checksum */ 3097917SReza.Sabdar@Sun.COM int i; /* loop counter */ 3107917SReza.Sabdar@Sun.COM 3117917SReza.Sabdar@Sun.COM /* 3127917SReza.Sabdar@Sun.COM * compute the checksum 3137917SReza.Sabdar@Sun.COM */ 3147917SReza.Sabdar@Sun.COM for (i = 0; i < RECORDSIZE; i++) { 3157917SReza.Sabdar@Sun.COM sum += p[i] & 0xFF; 3167917SReza.Sabdar@Sun.COM } 3177917SReza.Sabdar@Sun.COM 3187917SReza.Sabdar@Sun.COM if (sum == 0) { 3197917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 3207917SReza.Sabdar@Sun.COM "should be %d, is 0", chksum); 3217917SReza.Sabdar@Sun.COM /* a zero record ==> end of tar file */ 3227917SReza.Sabdar@Sun.COM return (0); 3237917SReza.Sabdar@Sun.COM } 3247917SReza.Sabdar@Sun.COM 3257917SReza.Sabdar@Sun.COM /* 3267917SReza.Sabdar@Sun.COM * subtract out the label's checksum values 3277917SReza.Sabdar@Sun.COM * this lets us undo the old checksum "in- 3287917SReza.Sabdar@Sun.COM * place", no need to swap blanks in and out 3297917SReza.Sabdar@Sun.COM */ 3307917SReza.Sabdar@Sun.COM for (i = 0; i < 8; i++) { 3317917SReza.Sabdar@Sun.COM sum -= 0xFF & tar_hdr->th_chksum[i]; 3327917SReza.Sabdar@Sun.COM } 3337917SReza.Sabdar@Sun.COM 3347917SReza.Sabdar@Sun.COM /* 3357917SReza.Sabdar@Sun.COM * replace the old checksum field with blanks 3367917SReza.Sabdar@Sun.COM */ 3377917SReza.Sabdar@Sun.COM sum += ' ' * 8; 3387917SReza.Sabdar@Sun.COM 3397917SReza.Sabdar@Sun.COM if (sum != chksum) 3407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 3417917SReza.Sabdar@Sun.COM "should be %d, is %d", chksum, sum); 3427917SReza.Sabdar@Sun.COM 3437917SReza.Sabdar@Sun.COM return ((sum == chksum) ? 1 : -1); 3447917SReza.Sabdar@Sun.COM } 3457917SReza.Sabdar@Sun.COM 3467917SReza.Sabdar@Sun.COM /* 3477917SReza.Sabdar@Sun.COM * get internal scsi_sasd entry for this tape drive 3487917SReza.Sabdar@Sun.COM */ 3497917SReza.Sabdar@Sun.COM int 3507917SReza.Sabdar@Sun.COM tlm_get_scsi_sasd_entry(int lib, int drv) 3517917SReza.Sabdar@Sun.COM { 3527917SReza.Sabdar@Sun.COM int entry; 3537917SReza.Sabdar@Sun.COM int i, n; 3547917SReza.Sabdar@Sun.COM scsi_link_t *sl; 3557917SReza.Sabdar@Sun.COM tlm_drive_t *dp; 3567917SReza.Sabdar@Sun.COM 3577917SReza.Sabdar@Sun.COM entry = -1; 3587917SReza.Sabdar@Sun.COM dp = tlm_drive(lib, drv); 3597917SReza.Sabdar@Sun.COM if (!dp) { 3607917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp for (%d.%d)", lib, drv); 3617917SReza.Sabdar@Sun.COM } else if (!dp->td_slink) { 3627917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink for (%d.%d)", lib, drv); 3637917SReza.Sabdar@Sun.COM } else if (!dp->td_slink->sl_sa) { 3647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink->sl_sa for (%d.%d)", 3657917SReza.Sabdar@Sun.COM lib, drv); 3667917SReza.Sabdar@Sun.COM } else { 3677917SReza.Sabdar@Sun.COM /* search through the SASD table */ 3687917SReza.Sabdar@Sun.COM n = sasd_dev_count(); 3697917SReza.Sabdar@Sun.COM for (i = 0; i < n; i++) { 3707917SReza.Sabdar@Sun.COM sl = sasd_dev_slink(i); 3717917SReza.Sabdar@Sun.COM if (!sl) 3727917SReza.Sabdar@Sun.COM continue; 3737917SReza.Sabdar@Sun.COM 3747917SReza.Sabdar@Sun.COM if (dp->td_slink->sl_sa == sl->sl_sa && 3757917SReza.Sabdar@Sun.COM dp->td_scsi_id == sl->sl_sid && 3767917SReza.Sabdar@Sun.COM dp->td_lun == sl->sl_lun) { 3777917SReza.Sabdar@Sun.COM /* all 3 variables match */ 3787917SReza.Sabdar@Sun.COM entry = i; 3797917SReza.Sabdar@Sun.COM break; 3807917SReza.Sabdar@Sun.COM } 3817917SReza.Sabdar@Sun.COM } 3827917SReza.Sabdar@Sun.COM } 3837917SReza.Sabdar@Sun.COM 3847917SReza.Sabdar@Sun.COM return (entry); 3857917SReza.Sabdar@Sun.COM } 3867917SReza.Sabdar@Sun.COM 3877917SReza.Sabdar@Sun.COM /* 3887917SReza.Sabdar@Sun.COM * get the OS device name for this tape 3897917SReza.Sabdar@Sun.COM */ 3907917SReza.Sabdar@Sun.COM char * 3917917SReza.Sabdar@Sun.COM tlm_get_tape_name(int lib, int drv) 3927917SReza.Sabdar@Sun.COM { 3937917SReza.Sabdar@Sun.COM int entry; 3947917SReza.Sabdar@Sun.COM 3957917SReza.Sabdar@Sun.COM entry = tlm_get_scsi_sasd_entry(lib, drv); 3967917SReza.Sabdar@Sun.COM if (entry >= 0) { 3977917SReza.Sabdar@Sun.COM sasd_drive_t *sd; 3987917SReza.Sabdar@Sun.COM 3997917SReza.Sabdar@Sun.COM if ((sd = sasd_drive(entry)) != 0) 4007917SReza.Sabdar@Sun.COM return (sd->sd_name); 4017917SReza.Sabdar@Sun.COM } 4027917SReza.Sabdar@Sun.COM 4037917SReza.Sabdar@Sun.COM return (""); 4047917SReza.Sabdar@Sun.COM } 4057917SReza.Sabdar@Sun.COM 4067917SReza.Sabdar@Sun.COM /* 4077917SReza.Sabdar@Sun.COM * create the IPC area between the reader and writer 4087917SReza.Sabdar@Sun.COM */ 4097917SReza.Sabdar@Sun.COM tlm_cmd_t * 4107917SReza.Sabdar@Sun.COM tlm_create_reader_writer_ipc(boolean_t write, long data_transfer_size) 4117917SReza.Sabdar@Sun.COM { 4127917SReza.Sabdar@Sun.COM tlm_cmd_t *cmd; 4137917SReza.Sabdar@Sun.COM 4147917SReza.Sabdar@Sun.COM cmd = ndmp_malloc(sizeof (tlm_cmd_t)); 4157917SReza.Sabdar@Sun.COM if (cmd == NULL) 4167917SReza.Sabdar@Sun.COM return (NULL); 4177917SReza.Sabdar@Sun.COM 4187917SReza.Sabdar@Sun.COM cmd->tc_reader = TLM_BACKUP_RUN; 4197917SReza.Sabdar@Sun.COM cmd->tc_writer = TLM_BACKUP_RUN; 4207917SReza.Sabdar@Sun.COM cmd->tc_ref = 1; 4217917SReza.Sabdar@Sun.COM 4227917SReza.Sabdar@Sun.COM cmd->tc_buffers = tlm_allocate_buffers(write, data_transfer_size); 4237917SReza.Sabdar@Sun.COM if (cmd->tc_buffers == NULL) { 4247917SReza.Sabdar@Sun.COM free(cmd); 4257917SReza.Sabdar@Sun.COM return (NULL); 4267917SReza.Sabdar@Sun.COM } 4277917SReza.Sabdar@Sun.COM 4287917SReza.Sabdar@Sun.COM (void) mutex_init(&cmd->tc_mtx, 0, NULL); 4297917SReza.Sabdar@Sun.COM (void) cond_init(&cmd->tc_cv, 0, NULL); 4307917SReza.Sabdar@Sun.COM 4317917SReza.Sabdar@Sun.COM return (cmd); 4327917SReza.Sabdar@Sun.COM } 4337917SReza.Sabdar@Sun.COM 4347917SReza.Sabdar@Sun.COM /* 4357917SReza.Sabdar@Sun.COM * release(destroy) the IPC between the reader and writer 4367917SReza.Sabdar@Sun.COM */ 4377917SReza.Sabdar@Sun.COM void 4387917SReza.Sabdar@Sun.COM tlm_release_reader_writer_ipc(tlm_cmd_t *cmd) 4397917SReza.Sabdar@Sun.COM { 4407917SReza.Sabdar@Sun.COM if (--cmd->tc_ref <= 0) { 4417917SReza.Sabdar@Sun.COM (void) mutex_lock(&cmd->tc_mtx); 4427917SReza.Sabdar@Sun.COM tlm_release_buffers(cmd->tc_buffers); 4437917SReza.Sabdar@Sun.COM (void) cond_destroy(&cmd->tc_cv); 4447917SReza.Sabdar@Sun.COM (void) mutex_unlock(&cmd->tc_mtx); 4457917SReza.Sabdar@Sun.COM (void) mutex_destroy(&cmd->tc_mtx); 4467917SReza.Sabdar@Sun.COM free(cmd); 4477917SReza.Sabdar@Sun.COM } 4487917SReza.Sabdar@Sun.COM } 4497917SReza.Sabdar@Sun.COM 4507917SReza.Sabdar@Sun.COM 4517917SReza.Sabdar@Sun.COM /* 4527917SReza.Sabdar@Sun.COM * NDMP support begins here. 4537917SReza.Sabdar@Sun.COM */ 4547917SReza.Sabdar@Sun.COM 4557917SReza.Sabdar@Sun.COM /* 4567917SReza.Sabdar@Sun.COM * Initialize the file history callback functions 4577917SReza.Sabdar@Sun.COM */ 4587917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t * 4597917SReza.Sabdar@Sun.COM lbrlog_callbacks_init(void *cookie, path_hist_func_t log_pname_func, 4607917SReza.Sabdar@Sun.COM dir_hist_func_t log_dir_func, node_hist_func_t log_node_func) 4617917SReza.Sabdar@Sun.COM { 4627917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *p; 4637917SReza.Sabdar@Sun.COM 4647917SReza.Sabdar@Sun.COM p = ndmp_malloc(sizeof (lbr_fhlog_call_backs_t)); 4657917SReza.Sabdar@Sun.COM if (p == NULL) 4667917SReza.Sabdar@Sun.COM return (NULL); 4677917SReza.Sabdar@Sun.COM 4687917SReza.Sabdar@Sun.COM p->fh_cookie = cookie; 4697917SReza.Sabdar@Sun.COM p->fh_logpname = (func_t)log_pname_func; 4707917SReza.Sabdar@Sun.COM p->fh_log_dir = (func_t)log_dir_func; 4717917SReza.Sabdar@Sun.COM p->fh_log_node = (func_t)log_node_func; 4727917SReza.Sabdar@Sun.COM return (p); 4737917SReza.Sabdar@Sun.COM } 4747917SReza.Sabdar@Sun.COM 4757917SReza.Sabdar@Sun.COM /* 4767917SReza.Sabdar@Sun.COM * Cleanup the callbacks 4777917SReza.Sabdar@Sun.COM */ 4787917SReza.Sabdar@Sun.COM void 4797917SReza.Sabdar@Sun.COM lbrlog_callbacks_done(lbr_fhlog_call_backs_t *p) 4807917SReza.Sabdar@Sun.COM { 4817917SReza.Sabdar@Sun.COM if (p != NULL) 4827917SReza.Sabdar@Sun.COM (void) free((char *)p); 4837917SReza.Sabdar@Sun.COM } 4847917SReza.Sabdar@Sun.COM 4857917SReza.Sabdar@Sun.COM /* 4867917SReza.Sabdar@Sun.COM * Call back for file history directory info 4877917SReza.Sabdar@Sun.COM */ 4887917SReza.Sabdar@Sun.COM int 4897917SReza.Sabdar@Sun.COM tlm_log_fhdir(tlm_job_stats_t *job_stats, char *dir, struct stat64 *stp, 4907917SReza.Sabdar@Sun.COM fs_fhandle_t *fhp) 4917917SReza.Sabdar@Sun.COM { 4927917SReza.Sabdar@Sun.COM int rv; 4937917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 4947917SReza.Sabdar@Sun.COM 4957917SReza.Sabdar@Sun.COM rv = 0; 4967917SReza.Sabdar@Sun.COM if (job_stats == NULL) { 4977917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: jstat is NULL"); 4987917SReza.Sabdar@Sun.COM } else if (dir == NULL) { 4997917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: dir is NULL"); 5007917SReza.Sabdar@Sun.COM } else if (stp == NULL) { 5017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: stp is NULL"); 5027917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 5037917SReza.Sabdar@Sun.COM == NULL) { 5047917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: cbp is NULL"); 5057917SReza.Sabdar@Sun.COM } else if (cbp->fh_log_dir == NULL) { 5067917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: callback is NULL"); 5077917SReza.Sabdar@Sun.COM } else 5087917SReza.Sabdar@Sun.COM rv = (*cbp->fh_log_dir)(cbp, dir, stp, fhp); 5097917SReza.Sabdar@Sun.COM 5107917SReza.Sabdar@Sun.COM return (rv); 5117917SReza.Sabdar@Sun.COM } 5127917SReza.Sabdar@Sun.COM 5137917SReza.Sabdar@Sun.COM /* 5147917SReza.Sabdar@Sun.COM * Call back for file history node info 5157917SReza.Sabdar@Sun.COM */ 5167917SReza.Sabdar@Sun.COM int 5177917SReza.Sabdar@Sun.COM tlm_log_fhnode(tlm_job_stats_t *job_stats, char *dir, char *file, 5187917SReza.Sabdar@Sun.COM struct stat64 *stp, u_longlong_t off) 5197917SReza.Sabdar@Sun.COM { 5207917SReza.Sabdar@Sun.COM int rv; 5217917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 5227917SReza.Sabdar@Sun.COM 5237917SReza.Sabdar@Sun.COM rv = 0; 5247917SReza.Sabdar@Sun.COM if (job_stats == NULL) { 5257917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: jstat is NULL"); 5267917SReza.Sabdar@Sun.COM } else if (dir == NULL) { 5277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: dir is NULL"); 5287917SReza.Sabdar@Sun.COM } else if (file == NULL) { 5297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: file is NULL"); 5307917SReza.Sabdar@Sun.COM } else if (stp == NULL) { 5317917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: stp is NULL"); 5327917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 5337917SReza.Sabdar@Sun.COM == NULL) { 5347917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: cbp is NULL"); 5357917SReza.Sabdar@Sun.COM } else if (cbp->fh_log_node == NULL) { 5367917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: callback is NULL"); 5377917SReza.Sabdar@Sun.COM } else 5387917SReza.Sabdar@Sun.COM rv = (*cbp->fh_log_node)(cbp, dir, file, stp, off); 5397917SReza.Sabdar@Sun.COM 5407917SReza.Sabdar@Sun.COM return (rv); 5417917SReza.Sabdar@Sun.COM } 5427917SReza.Sabdar@Sun.COM 5437917SReza.Sabdar@Sun.COM /* 5447917SReza.Sabdar@Sun.COM * Call back for file history path info 5457917SReza.Sabdar@Sun.COM */ 5467917SReza.Sabdar@Sun.COM int 5477917SReza.Sabdar@Sun.COM tlm_log_fhpath_name(tlm_job_stats_t *job_stats, char *pathname, 5487917SReza.Sabdar@Sun.COM struct stat64 *stp, u_longlong_t off) 5497917SReza.Sabdar@Sun.COM { 5507917SReza.Sabdar@Sun.COM int rv; 5517917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 5527917SReza.Sabdar@Sun.COM 5537917SReza.Sabdar@Sun.COM rv = 0; 5547917SReza.Sabdar@Sun.COM if (!job_stats) { 5557917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: jstat is NULL"); 5567917SReza.Sabdar@Sun.COM } else if (!pathname) { 5577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: pathname is NULL"); 5587917SReza.Sabdar@Sun.COM } else if (!stp) { 5597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: stp is NULL"); 5607917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 5617917SReza.Sabdar@Sun.COM == 0) { 5627917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: cbp is NULL"); 5637917SReza.Sabdar@Sun.COM } else if (!cbp->fh_logpname) { 5647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: callback is NULL"); 5657917SReza.Sabdar@Sun.COM } else 5667917SReza.Sabdar@Sun.COM rv = (*cbp->fh_logpname)(cbp, pathname, stp, off); 5677917SReza.Sabdar@Sun.COM 5687917SReza.Sabdar@Sun.COM return (rv); 5697917SReza.Sabdar@Sun.COM } 5707917SReza.Sabdar@Sun.COM 5717917SReza.Sabdar@Sun.COM 5727917SReza.Sabdar@Sun.COM /* 5737917SReza.Sabdar@Sun.COM * Log call back to report the entry recovery 5747917SReza.Sabdar@Sun.COM */ 5757917SReza.Sabdar@Sun.COM int 5767917SReza.Sabdar@Sun.COM tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos) 5777917SReza.Sabdar@Sun.COM { 5787917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 5797917SReza.Sabdar@Sun.COM 5807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "name: \"%s\", pos: %d", name, pos); 5817917SReza.Sabdar@Sun.COM 5827917SReza.Sabdar@Sun.COM if (job_stats == NULL) { 5837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "entry_restored: jstat is NULL"); 5847917SReza.Sabdar@Sun.COM return (0); 5857917SReza.Sabdar@Sun.COM } 5867917SReza.Sabdar@Sun.COM cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks; 5877917SReza.Sabdar@Sun.COM if (cbp == NULL) { 5887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "entry_restored is NULL"); 5897917SReza.Sabdar@Sun.COM return (0); 5907917SReza.Sabdar@Sun.COM } 5917917SReza.Sabdar@Sun.COM return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos); 5927917SReza.Sabdar@Sun.COM } 5937917SReza.Sabdar@Sun.COM /* 5947917SReza.Sabdar@Sun.COM * NDMP support ends here. 5957917SReza.Sabdar@Sun.COM */ 5967917SReza.Sabdar@Sun.COM 5977917SReza.Sabdar@Sun.COM /* 5987917SReza.Sabdar@Sun.COM * Function: tlm_cat_path 5997917SReza.Sabdar@Sun.COM * Concatenates two path names 6007917SReza.Sabdar@Sun.COM * or directory name and file name 6017917SReza.Sabdar@Sun.COM * into a buffer passed by the caller. A slash 6027917SReza.Sabdar@Sun.COM * is inserted if required. Buffer is assumed 6037917SReza.Sabdar@Sun.COM * to hold PATH_MAX characters. 6047917SReza.Sabdar@Sun.COM * 6057917SReza.Sabdar@Sun.COM * Parameters: 6067917SReza.Sabdar@Sun.COM * char *buf - buffer to write new dir/name string 6077917SReza.Sabdar@Sun.COM * char *dir - directory name 6087917SReza.Sabdar@Sun.COM * char *name - file name 6097917SReza.Sabdar@Sun.COM * 6107917SReza.Sabdar@Sun.COM * Returns: 6117917SReza.Sabdar@Sun.COM * TRUE - No errors. buf contains the dir/name string 6127917SReza.Sabdar@Sun.COM * FALSE - Error. buf is not modified. 6137917SReza.Sabdar@Sun.COM */ 6147917SReza.Sabdar@Sun.COM boolean_t 6157917SReza.Sabdar@Sun.COM tlm_cat_path(char *buf, char *dir, char *name) 6167917SReza.Sabdar@Sun.COM { 6177917SReza.Sabdar@Sun.COM char *fmt; 6187917SReza.Sabdar@Sun.COM int dirlen = strlen(dir); 6197917SReza.Sabdar@Sun.COM int filelen = strlen(name); 6207917SReza.Sabdar@Sun.COM 6217917SReza.Sabdar@Sun.COM if ((dirlen + filelen + 1) >= PATH_MAX) { 6227917SReza.Sabdar@Sun.COM return (FALSE); 6237917SReza.Sabdar@Sun.COM } 6247917SReza.Sabdar@Sun.COM 6257917SReza.Sabdar@Sun.COM if (*dir == '\0' || *name == '\0' || dir[dirlen - 1] == '/' || 6267917SReza.Sabdar@Sun.COM *name == '/') { 6277917SReza.Sabdar@Sun.COM fmt = "%s%s"; 6287917SReza.Sabdar@Sun.COM } else { 6297917SReza.Sabdar@Sun.COM fmt = "%s/%s"; 6307917SReza.Sabdar@Sun.COM } 6317917SReza.Sabdar@Sun.COM 6327917SReza.Sabdar@Sun.COM /* check for ".../" and "/...." */ 6337917SReza.Sabdar@Sun.COM if ((dirlen > 0) && (dir[dirlen - 1] == '/') && (*name == '/')) 6347917SReza.Sabdar@Sun.COM name += strspn(name, "/"); 6357917SReza.Sabdar@Sun.COM 6367917SReza.Sabdar@Sun.COM /* LINTED variable format */ 6377917SReza.Sabdar@Sun.COM (void) snprintf(buf, TLM_MAX_PATH_NAME, fmt, dir, name); 6387917SReza.Sabdar@Sun.COM 6397917SReza.Sabdar@Sun.COM return (TRUE); 6407917SReza.Sabdar@Sun.COM } 6417917SReza.Sabdar@Sun.COM 6427917SReza.Sabdar@Sun.COM /* 6437917SReza.Sabdar@Sun.COM * Get the checkpoint (snapshot) creation time. 6447917SReza.Sabdar@Sun.COM * This is necessary to check for checkpoints not being stale. 6457917SReza.Sabdar@Sun.COM */ 6467917SReza.Sabdar@Sun.COM int 6477917SReza.Sabdar@Sun.COM tlm_get_chkpnt_time(char *path, int auto_checkpoint, time_t *tp, char *jname) 6487917SReza.Sabdar@Sun.COM { 6497917SReza.Sabdar@Sun.COM char volname[TLM_VOLNAME_MAX_LENGTH]; 6507917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX]; 6517917SReza.Sabdar@Sun.COM char *cp_nm; 6527917SReza.Sabdar@Sun.COM 6537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "path [%s] auto_checkpoint: %d", 6547917SReza.Sabdar@Sun.COM path, auto_checkpoint); 6557917SReza.Sabdar@Sun.COM 6567917SReza.Sabdar@Sun.COM if (path == NULL || *path == '\0' || tp == NULL) 6577917SReza.Sabdar@Sun.COM return (-1); 6587917SReza.Sabdar@Sun.COM 6597917SReza.Sabdar@Sun.COM if (get_zfsvolname(volname, TLM_VOLNAME_MAX_LENGTH, 6607917SReza.Sabdar@Sun.COM path) == -1) 6617917SReza.Sabdar@Sun.COM return (-1); 6627917SReza.Sabdar@Sun.COM 6637917SReza.Sabdar@Sun.COM if (auto_checkpoint) { 6647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "volname [%s]", volname); 665*12186SJanice.Chang@Sun.COM (void) snprintf(chk_name, PATH_MAX, "%s", jname); 6667917SReza.Sabdar@Sun.COM return (chkpnt_creationtime_bypattern(volname, chk_name, tp)); 6677917SReza.Sabdar@Sun.COM } 6687917SReza.Sabdar@Sun.COM cp_nm = strchr(volname, '@'); 6697917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "volname [%s] cp_nm [%s]", volname, cp_nm); 6707917SReza.Sabdar@Sun.COM 6717917SReza.Sabdar@Sun.COM return (chkpnt_creationtime_bypattern(volname, cp_nm, tp)); 6727917SReza.Sabdar@Sun.COM } 6737917SReza.Sabdar@Sun.COM 6747917SReza.Sabdar@Sun.COM /* 6757917SReza.Sabdar@Sun.COM * Release an array of pointers and the pointers themselves. 6767917SReza.Sabdar@Sun.COM */ 6777917SReza.Sabdar@Sun.COM void 6787917SReza.Sabdar@Sun.COM tlm_release_list(char **lpp) 6797917SReza.Sabdar@Sun.COM { 6807917SReza.Sabdar@Sun.COM char **save; 6817917SReza.Sabdar@Sun.COM 6827917SReza.Sabdar@Sun.COM if ((save = lpp) == 0) 6837917SReza.Sabdar@Sun.COM return; 6847917SReza.Sabdar@Sun.COM 6857917SReza.Sabdar@Sun.COM while (*lpp) 6867917SReza.Sabdar@Sun.COM free(*lpp++); 6877917SReza.Sabdar@Sun.COM 6887917SReza.Sabdar@Sun.COM free(save); 6897917SReza.Sabdar@Sun.COM } 6907917SReza.Sabdar@Sun.COM 6917917SReza.Sabdar@Sun.COM /* 6927917SReza.Sabdar@Sun.COM * Print the list of array of strings in the backup log 6937917SReza.Sabdar@Sun.COM */ 6947917SReza.Sabdar@Sun.COM void 6957917SReza.Sabdar@Sun.COM tlm_log_list(char *title, char **lpp) 6967917SReza.Sabdar@Sun.COM { 6977917SReza.Sabdar@Sun.COM int i; 6987917SReza.Sabdar@Sun.COM 6997917SReza.Sabdar@Sun.COM if (!lpp) 7007917SReza.Sabdar@Sun.COM return; 7017917SReza.Sabdar@Sun.COM 7027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "%s:", title); 7037917SReza.Sabdar@Sun.COM 7047917SReza.Sabdar@Sun.COM for (i = 0; *lpp; lpp++, i++) 7057917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "%d: [%s]", i, *lpp); 7067917SReza.Sabdar@Sun.COM } 7077917SReza.Sabdar@Sun.COM 7087917SReza.Sabdar@Sun.COM /* 7097917SReza.Sabdar@Sun.COM * Insert the backup snapshot name into the path. 7107917SReza.Sabdar@Sun.COM * 7117917SReza.Sabdar@Sun.COM * Input: 712*12186SJanice.Chang@Sun.COM * name: Original path name. 7137917SReza.Sabdar@Sun.COM * 7147917SReza.Sabdar@Sun.COM * Output: 715*12186SJanice.Chang@Sun.COM * name: Original name modified to include a snapshot. 7167917SReza.Sabdar@Sun.COM * 7177917SReza.Sabdar@Sun.COM * Returns: 718*12186SJanice.Chang@Sun.COM * Original name modified to include a snapshot. 7197917SReza.Sabdar@Sun.COM */ 7207917SReza.Sabdar@Sun.COM char * 7217917SReza.Sabdar@Sun.COM tlm_build_snapshot_name(char *name, char *sname, char *jname) 7227917SReza.Sabdar@Sun.COM { 7237917SReza.Sabdar@Sun.COM zfs_handle_t *zhp; 7247917SReza.Sabdar@Sun.COM char *rest; 7257917SReza.Sabdar@Sun.COM char volname[ZFS_MAXNAMELEN]; 7267917SReza.Sabdar@Sun.COM char mountpoint[PATH_MAX]; 7277917SReza.Sabdar@Sun.COM 7287917SReza.Sabdar@Sun.COM if (get_zfsvolname(volname, ZFS_MAXNAMELEN, name) == -1) 7297917SReza.Sabdar@Sun.COM goto notzfs; 7307917SReza.Sabdar@Sun.COM 7317917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 7327917SReza.Sabdar@Sun.COM if ((zlibh == NULL) || 7337917SReza.Sabdar@Sun.COM (zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == NULL) { 7347917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 7357917SReza.Sabdar@Sun.COM goto notzfs; 7367917SReza.Sabdar@Sun.COM } 7377917SReza.Sabdar@Sun.COM 7387917SReza.Sabdar@Sun.COM if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, PATH_MAX, NULL, 7397917SReza.Sabdar@Sun.COM NULL, 0, B_FALSE) != 0) { 7407917SReza.Sabdar@Sun.COM zfs_close(zhp); 7417917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 7427917SReza.Sabdar@Sun.COM goto notzfs; 7437917SReza.Sabdar@Sun.COM } 7447917SReza.Sabdar@Sun.COM 7457917SReza.Sabdar@Sun.COM zfs_close(zhp); 7467917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 7477917SReza.Sabdar@Sun.COM 7487917SReza.Sabdar@Sun.COM rest = name + strlen(mountpoint); 749*12186SJanice.Chang@Sun.COM (void) snprintf(sname, TLM_MAX_PATH_NAME, "%s/%s/%s%s", mountpoint, 7507917SReza.Sabdar@Sun.COM TLM_SNAPSHOT_DIR, jname, rest); 7517917SReza.Sabdar@Sun.COM 7527917SReza.Sabdar@Sun.COM return (sname); 7537917SReza.Sabdar@Sun.COM 7547917SReza.Sabdar@Sun.COM notzfs: 7557917SReza.Sabdar@Sun.COM (void) strlcpy(sname, name, TLM_MAX_PATH_NAME); 7567917SReza.Sabdar@Sun.COM return (sname); 7577917SReza.Sabdar@Sun.COM } 7587917SReza.Sabdar@Sun.COM 7597917SReza.Sabdar@Sun.COM /* 7607917SReza.Sabdar@Sun.COM * Remove the checkpoint from a path name. 7617917SReza.Sabdar@Sun.COM * 7627917SReza.Sabdar@Sun.COM * Input: 7637917SReza.Sabdar@Sun.COM * name: Full pathname with checkpoint embeded. 7647917SReza.Sabdar@Sun.COM * 7657917SReza.Sabdar@Sun.COM * Output: 7667917SReza.Sabdar@Sun.COM * unchkp_name: real pathname with no checkpoint. 7677917SReza.Sabdar@Sun.COM * 7687917SReza.Sabdar@Sun.COM * Returns: 7697917SReza.Sabdar@Sun.COM * Pointer to the un-checkpointed path. 7707917SReza.Sabdar@Sun.COM */ 7717917SReza.Sabdar@Sun.COM char * 7727917SReza.Sabdar@Sun.COM tlm_remove_checkpoint(char *name, char *unchkp_name) 7737917SReza.Sabdar@Sun.COM { 7747917SReza.Sabdar@Sun.COM char *cp; 7757917SReza.Sabdar@Sun.COM int i; 7767917SReza.Sabdar@Sun.COM int plen; 7777917SReza.Sabdar@Sun.COM 7787917SReza.Sabdar@Sun.COM unchkp_name[0] = name[0]; 7797917SReza.Sabdar@Sun.COM plen = strlen(TLM_SNAPSHOT_PREFIX); 7807917SReza.Sabdar@Sun.COM for (i = 1; i <= TLM_VOLNAME_MAX_LENGTH + 1; i++) { 7817917SReza.Sabdar@Sun.COM switch (name[i]) { 7827917SReza.Sabdar@Sun.COM case '.': 7837917SReza.Sabdar@Sun.COM if (strncmp(&name[i], TLM_SNAPSHOT_PREFIX, 7847917SReza.Sabdar@Sun.COM plen) == 0) { 7857917SReza.Sabdar@Sun.COM unchkp_name[i] = '\0'; 7867917SReza.Sabdar@Sun.COM i += plen; 7877917SReza.Sabdar@Sun.COM if (name[i] == '\0') { 7887917SReza.Sabdar@Sun.COM /* 7897917SReza.Sabdar@Sun.COM * name == "/v1.chkpnt" 7907917SReza.Sabdar@Sun.COM */ 7917917SReza.Sabdar@Sun.COM return (unchkp_name); 7927917SReza.Sabdar@Sun.COM } 7937917SReza.Sabdar@Sun.COM if ((cp = strchr(&name[++i], '/')) != NULL) { 7947917SReza.Sabdar@Sun.COM (void) strlcat(unchkp_name, cp, 7957917SReza.Sabdar@Sun.COM TLM_VOLNAME_MAX_LENGTH + 1); 7967917SReza.Sabdar@Sun.COM } 7977917SReza.Sabdar@Sun.COM return (unchkp_name); 7987917SReza.Sabdar@Sun.COM } else { 7997917SReza.Sabdar@Sun.COM unchkp_name[i] = name[i]; 8007917SReza.Sabdar@Sun.COM } 8017917SReza.Sabdar@Sun.COM break; 8027917SReza.Sabdar@Sun.COM case '/': 8037917SReza.Sabdar@Sun.COM return (name); 8047917SReza.Sabdar@Sun.COM case 0: 8057917SReza.Sabdar@Sun.COM return (name); 8067917SReza.Sabdar@Sun.COM default: 8077917SReza.Sabdar@Sun.COM unchkp_name[i] = name[i]; 8087917SReza.Sabdar@Sun.COM break; 8097917SReza.Sabdar@Sun.COM } 8107917SReza.Sabdar@Sun.COM } 8117917SReza.Sabdar@Sun.COM return (name); 8127917SReza.Sabdar@Sun.COM } 8137917SReza.Sabdar@Sun.COM 8147917SReza.Sabdar@Sun.COM /* 8157917SReza.Sabdar@Sun.COM * see if we should exclude this file. 8167917SReza.Sabdar@Sun.COM */ 8177917SReza.Sabdar@Sun.COM boolean_t 8187917SReza.Sabdar@Sun.COM tlm_is_excluded(char *dir, char *name, char **excl_files) 8197917SReza.Sabdar@Sun.COM { 8207917SReza.Sabdar@Sun.COM int i; 8217917SReza.Sabdar@Sun.COM char full_name[TLM_MAX_PATH_NAME]; 8227917SReza.Sabdar@Sun.COM 8237917SReza.Sabdar@Sun.COM if (!dir || !name || !excl_files) 8247917SReza.Sabdar@Sun.COM return (FALSE); 8257917SReza.Sabdar@Sun.COM 8267917SReza.Sabdar@Sun.COM if (!tlm_cat_path(full_name, dir, name)) { 8277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", 8287917SReza.Sabdar@Sun.COM dir, name); 8297917SReza.Sabdar@Sun.COM return (FALSE); 8307917SReza.Sabdar@Sun.COM } 8317917SReza.Sabdar@Sun.COM for (i = 0; excl_files[i] != 0; i++) { 8327917SReza.Sabdar@Sun.COM if (match(excl_files[i], full_name)) { 8337917SReza.Sabdar@Sun.COM return (TRUE); 8347917SReza.Sabdar@Sun.COM } 8357917SReza.Sabdar@Sun.COM } 8367917SReza.Sabdar@Sun.COM return (FALSE); 8377917SReza.Sabdar@Sun.COM } 8387917SReza.Sabdar@Sun.COM 8397917SReza.Sabdar@Sun.COM /* 8407917SReza.Sabdar@Sun.COM * Check if the path is too long 8417917SReza.Sabdar@Sun.COM */ 8427917SReza.Sabdar@Sun.COM boolean_t 8437917SReza.Sabdar@Sun.COM tlm_is_too_long(int checkpointed, char *dir, char *nm) 8447917SReza.Sabdar@Sun.COM { 8457917SReza.Sabdar@Sun.COM int nlen, tot; 8467917SReza.Sabdar@Sun.COM 8477917SReza.Sabdar@Sun.COM tot = 0; 8487917SReza.Sabdar@Sun.COM if (dir) 8497917SReza.Sabdar@Sun.COM tot += strlen(dir); 8507917SReza.Sabdar@Sun.COM if (checkpointed) 8517917SReza.Sabdar@Sun.COM tot += strlen(TLM_SNAPSHOT_DIR) + 1; 8527917SReza.Sabdar@Sun.COM if (nm) { 8537917SReza.Sabdar@Sun.COM if ((nlen = strlen(nm)) > 0) 8547917SReza.Sabdar@Sun.COM tot += nlen + 1; 8557917SReza.Sabdar@Sun.COM } 8567917SReza.Sabdar@Sun.COM return ((tot >= PATH_MAX) ? TRUE : FALSE); 8577917SReza.Sabdar@Sun.COM } 8587917SReza.Sabdar@Sun.COM 8597917SReza.Sabdar@Sun.COM /* 8607917SReza.Sabdar@Sun.COM * Get the data offset of inside the buffer 8617917SReza.Sabdar@Sun.COM */ 8627917SReza.Sabdar@Sun.COM longlong_t 8637917SReza.Sabdar@Sun.COM tlm_get_data_offset(tlm_cmd_t *lcmds) 8647917SReza.Sabdar@Sun.COM { 8657917SReza.Sabdar@Sun.COM if (!lcmds) 8667917SReza.Sabdar@Sun.COM return (0LL); 8677917SReza.Sabdar@Sun.COM 8687917SReza.Sabdar@Sun.COM return (lcmds->tc_buffers->tbs_offset); 8697917SReza.Sabdar@Sun.COM } 8707917SReza.Sabdar@Sun.COM 8717917SReza.Sabdar@Sun.COM /* 8727917SReza.Sabdar@Sun.COM * Enable the barcode capability on the library 8737917SReza.Sabdar@Sun.COM */ 8747917SReza.Sabdar@Sun.COM void 8757917SReza.Sabdar@Sun.COM tlm_enable_barcode(int l) 8767917SReza.Sabdar@Sun.COM { 8777917SReza.Sabdar@Sun.COM tlm_library_t *lp; 8787917SReza.Sabdar@Sun.COM 8797917SReza.Sabdar@Sun.COM if ((lp = tlm_library(l))) { 8807917SReza.Sabdar@Sun.COM lp->tl_capability_barcodes = TRUE; 8817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 8827917SReza.Sabdar@Sun.COM "Barcode capability on library %d enabled.", l); 8837917SReza.Sabdar@Sun.COM } 8847917SReza.Sabdar@Sun.COM } 8857917SReza.Sabdar@Sun.COM 8867917SReza.Sabdar@Sun.COM /* 8877917SReza.Sabdar@Sun.COM * SASD SCSI support 8887917SReza.Sabdar@Sun.COM */ 8897917SReza.Sabdar@Sun.COM static scsi_adapter_t my_sa; 8907917SReza.Sabdar@Sun.COM static int sasd_drive_count = 0; 8917917SReza.Sabdar@Sun.COM static scsi_sasd_drive_t *scsi_sasd_drives[128]; 8927917SReza.Sabdar@Sun.COM 8937917SReza.Sabdar@Sun.COM /* 8947917SReza.Sabdar@Sun.COM * Count of SCSI devices 8957917SReza.Sabdar@Sun.COM */ 8967917SReza.Sabdar@Sun.COM int 8977917SReza.Sabdar@Sun.COM sasd_dev_count(void) 8987917SReza.Sabdar@Sun.COM { 8997917SReza.Sabdar@Sun.COM return (sasd_drive_count); 9007917SReza.Sabdar@Sun.COM } 9017917SReza.Sabdar@Sun.COM 9027917SReza.Sabdar@Sun.COM /* 9037917SReza.Sabdar@Sun.COM * Return the SCSI device name 9047917SReza.Sabdar@Sun.COM */ 9057917SReza.Sabdar@Sun.COM char * 9067917SReza.Sabdar@Sun.COM sasd_slink_name(scsi_link_t *slink) 9077917SReza.Sabdar@Sun.COM { 9087917SReza.Sabdar@Sun.COM int i; 9097917SReza.Sabdar@Sun.COM 9107917SReza.Sabdar@Sun.COM for (i = 0; i < sasd_drive_count; i++) { 9117917SReza.Sabdar@Sun.COM if (&scsi_sasd_drives[i]->ss_slink == slink) 9127917SReza.Sabdar@Sun.COM return (scsi_sasd_drives[i]->ss_sd.sd_name); 9137917SReza.Sabdar@Sun.COM } 9147917SReza.Sabdar@Sun.COM return (NULL); 9157917SReza.Sabdar@Sun.COM } 9167917SReza.Sabdar@Sun.COM 9177917SReza.Sabdar@Sun.COM /* 9187917SReza.Sabdar@Sun.COM * Return the SCSI drive structure 9197917SReza.Sabdar@Sun.COM */ 9207917SReza.Sabdar@Sun.COM sasd_drive_t * 9217917SReza.Sabdar@Sun.COM sasd_slink_drive(scsi_link_t *slink) 9227917SReza.Sabdar@Sun.COM { 9237917SReza.Sabdar@Sun.COM int i; 9247917SReza.Sabdar@Sun.COM 9257917SReza.Sabdar@Sun.COM for (i = 0; i < sasd_drive_count; i++) { 9267917SReza.Sabdar@Sun.COM if (&scsi_sasd_drives[i]->ss_slink == slink) 9277917SReza.Sabdar@Sun.COM return (&scsi_sasd_drives[i]->ss_sd); 9287917SReza.Sabdar@Sun.COM } 9297917SReza.Sabdar@Sun.COM return (NULL); 9307917SReza.Sabdar@Sun.COM } 9317917SReza.Sabdar@Sun.COM 9327917SReza.Sabdar@Sun.COM /* 9337917SReza.Sabdar@Sun.COM * Return the SCSI link pointer for the given index 9347917SReza.Sabdar@Sun.COM */ 9357917SReza.Sabdar@Sun.COM scsi_link_t * 9367917SReza.Sabdar@Sun.COM sasd_dev_slink(int entry) 9377917SReza.Sabdar@Sun.COM { 9387917SReza.Sabdar@Sun.COM scsi_link_t *rv; 9397917SReza.Sabdar@Sun.COM 9407917SReza.Sabdar@Sun.COM if (entry >= 0 && entry < sasd_drive_count) 9417917SReza.Sabdar@Sun.COM rv = &scsi_sasd_drives[entry]->ss_slink; 9427917SReza.Sabdar@Sun.COM else 9437917SReza.Sabdar@Sun.COM rv = NULL; 9447917SReza.Sabdar@Sun.COM 9457917SReza.Sabdar@Sun.COM return (rv); 9467917SReza.Sabdar@Sun.COM } 9477917SReza.Sabdar@Sun.COM 9487917SReza.Sabdar@Sun.COM /* 9497917SReza.Sabdar@Sun.COM * Return the SCSI drive for the given index 9507917SReza.Sabdar@Sun.COM */ 9517917SReza.Sabdar@Sun.COM sasd_drive_t * 9527917SReza.Sabdar@Sun.COM sasd_drive(int entry) 9537917SReza.Sabdar@Sun.COM { 9547917SReza.Sabdar@Sun.COM sasd_drive_t *rv; 9557917SReza.Sabdar@Sun.COM 9567917SReza.Sabdar@Sun.COM if (entry >= 0 && entry < sasd_drive_count) 9577917SReza.Sabdar@Sun.COM rv = &scsi_sasd_drives[entry]->ss_sd; 9587917SReza.Sabdar@Sun.COM else 9597917SReza.Sabdar@Sun.COM rv = NULL; 9607917SReza.Sabdar@Sun.COM 9617917SReza.Sabdar@Sun.COM return (rv); 9627917SReza.Sabdar@Sun.COM } 9637917SReza.Sabdar@Sun.COM 9647917SReza.Sabdar@Sun.COM /* 9657917SReza.Sabdar@Sun.COM * Attach the SCSI device by updating the structures 9667917SReza.Sabdar@Sun.COM */ 9677917SReza.Sabdar@Sun.COM void 9687917SReza.Sabdar@Sun.COM scsi_sasd_attach(scsi_adapter_t *sa, int sid, int lun, char *name, 9697917SReza.Sabdar@Sun.COM int type) 9707917SReza.Sabdar@Sun.COM { 9717917SReza.Sabdar@Sun.COM scsi_link_t *sl, *next; 9727917SReza.Sabdar@Sun.COM scsi_sasd_drive_t *ssd; 9737917SReza.Sabdar@Sun.COM 9747917SReza.Sabdar@Sun.COM ssd = ndmp_malloc(sizeof (scsi_sasd_drive_t)); 9757917SReza.Sabdar@Sun.COM if (ssd == NULL) 9767917SReza.Sabdar@Sun.COM return; 9777917SReza.Sabdar@Sun.COM 9787917SReza.Sabdar@Sun.COM scsi_sasd_drives[sasd_drive_count++] = ssd; 9797917SReza.Sabdar@Sun.COM 9807917SReza.Sabdar@Sun.COM switch (type) { 9817917SReza.Sabdar@Sun.COM case DTYPE_CHANGER: 9827917SReza.Sabdar@Sun.COM (void) snprintf(ssd->ss_sd.sd_name, 9837917SReza.Sabdar@Sun.COM sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_CHANGER_DIR, 9847917SReza.Sabdar@Sun.COM name); 9857917SReza.Sabdar@Sun.COM break; 9867917SReza.Sabdar@Sun.COM case DTYPE_SEQUENTIAL: 9877917SReza.Sabdar@Sun.COM (void) snprintf(ssd->ss_sd.sd_name, 9887917SReza.Sabdar@Sun.COM sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_TAPE_DIR, name); 9897917SReza.Sabdar@Sun.COM break; 9907917SReza.Sabdar@Sun.COM } 9917917SReza.Sabdar@Sun.COM 9927917SReza.Sabdar@Sun.COM sl = &ssd->ss_slink; 9937917SReza.Sabdar@Sun.COM sl->sl_type = type; 9947917SReza.Sabdar@Sun.COM sl->sl_sa = sa; 9957917SReza.Sabdar@Sun.COM sl->sl_lun = lun; 9967917SReza.Sabdar@Sun.COM sl->sl_sid = sid; 9977917SReza.Sabdar@Sun.COM sl->sl_requested_max_active = 1; 9987917SReza.Sabdar@Sun.COM 9997917SReza.Sabdar@Sun.COM /* Insert slink */ 10007917SReza.Sabdar@Sun.COM next = sa->sa_link_head.sl_next; 10017917SReza.Sabdar@Sun.COM sa->sa_link_head.sl_next = sl; 10027917SReza.Sabdar@Sun.COM sl->sl_next = next; 10037917SReza.Sabdar@Sun.COM } 10047917SReza.Sabdar@Sun.COM 10057917SReza.Sabdar@Sun.COM /* 10067917SReza.Sabdar@Sun.COM * Go through the attached devices and detect the tape 10077917SReza.Sabdar@Sun.COM * and robot by checking the /dev entries 10087917SReza.Sabdar@Sun.COM */ 10097917SReza.Sabdar@Sun.COM int 10107917SReza.Sabdar@Sun.COM probe_scsi(void) 10117917SReza.Sabdar@Sun.COM { 10127917SReza.Sabdar@Sun.COM DIR *dirp; 10137917SReza.Sabdar@Sun.COM struct dirent *dp; 10147917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa; 10157917SReza.Sabdar@Sun.COM char *p; 10167917SReza.Sabdar@Sun.COM int lun = 0; 10177917SReza.Sabdar@Sun.COM int sid = 0; 10187917SReza.Sabdar@Sun.COM 10197917SReza.Sabdar@Sun.COM /* Initialize the scsi adapter link */ 10207917SReza.Sabdar@Sun.COM sa->sa_link_head.sl_next = &sa->sa_link_head; 10217917SReza.Sabdar@Sun.COM 10227917SReza.Sabdar@Sun.COM /* Scan for the changer */ 10237917SReza.Sabdar@Sun.COM dirp = opendir(SCSI_CHANGER_DIR); 10247917SReza.Sabdar@Sun.COM if (dirp == NULL) { 10257917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10267917SReza.Sabdar@Sun.COM "Changer directory read error %s", SCSI_CHANGER_DIR); 10277917SReza.Sabdar@Sun.COM } else { 10287917SReza.Sabdar@Sun.COM while ((dp = readdir(dirp)) != NULL) { 10297917SReza.Sabdar@Sun.COM if ((strcmp(dp->d_name, ".") == 0) || 10307917SReza.Sabdar@Sun.COM (strcmp(dp->d_name, "..") == 0)) 10317917SReza.Sabdar@Sun.COM continue; 10327917SReza.Sabdar@Sun.COM 10337917SReza.Sabdar@Sun.COM if ((p = strchr(dp->d_name, 'd')) != NULL) { 10347917SReza.Sabdar@Sun.COM lun = atoi(++p); 10357917SReza.Sabdar@Sun.COM p = strchr(dp->d_name, 't'); 10367917SReza.Sabdar@Sun.COM sid = atoi(++p); 10377917SReza.Sabdar@Sun.COM } 10387917SReza.Sabdar@Sun.COM else 10397917SReza.Sabdar@Sun.COM sid = atoi(dp->d_name); 10407917SReza.Sabdar@Sun.COM 10417917SReza.Sabdar@Sun.COM scsi_sasd_attach(sa, 0, lun, dp->d_name, 10427917SReza.Sabdar@Sun.COM DTYPE_CHANGER); 10437917SReza.Sabdar@Sun.COM } 10447917SReza.Sabdar@Sun.COM (void) closedir(dirp); 10457917SReza.Sabdar@Sun.COM } 10467917SReza.Sabdar@Sun.COM 10477917SReza.Sabdar@Sun.COM /* Scan for tape drives */ 10487917SReza.Sabdar@Sun.COM dirp = opendir(SCSI_TAPE_DIR); 10497917SReza.Sabdar@Sun.COM if (dirp == NULL) { 10507917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10517917SReza.Sabdar@Sun.COM "Tape directory read error %s", SCSI_TAPE_DIR); 10527917SReza.Sabdar@Sun.COM } else { 10537917SReza.Sabdar@Sun.COM while ((dp = readdir(dirp)) != NULL) { 10547917SReza.Sabdar@Sun.COM if ((strcmp(dp->d_name, ".") == 0) || 10557917SReza.Sabdar@Sun.COM (strcmp(dp->d_name, "..") == 0)) 10567917SReza.Sabdar@Sun.COM continue; 10577917SReza.Sabdar@Sun.COM 10587917SReza.Sabdar@Sun.COM /* Skip special modes */ 10597917SReza.Sabdar@Sun.COM if (strpbrk(dp->d_name, "bchlmu") != 0) 10607917SReza.Sabdar@Sun.COM continue; 10617917SReza.Sabdar@Sun.COM 10627917SReza.Sabdar@Sun.COM /* Pick the non-rewind device */ 10637917SReza.Sabdar@Sun.COM if (strchr(dp->d_name, 'n') == NULL) 10647917SReza.Sabdar@Sun.COM continue; 10657917SReza.Sabdar@Sun.COM 10667917SReza.Sabdar@Sun.COM sid = atoi(dp->d_name); 10677917SReza.Sabdar@Sun.COM 10687917SReza.Sabdar@Sun.COM /* 10697917SReza.Sabdar@Sun.COM * SCSI ID should match with the ID of the device 10707917SReza.Sabdar@Sun.COM * (will be checked by SCSI get elements page later) 10717917SReza.Sabdar@Sun.COM */ 10727917SReza.Sabdar@Sun.COM scsi_sasd_attach(sa, sid, 0, dp->d_name, 10737917SReza.Sabdar@Sun.COM DTYPE_SEQUENTIAL); 10747917SReza.Sabdar@Sun.COM } 10757917SReza.Sabdar@Sun.COM (void) closedir(dirp); 10767917SReza.Sabdar@Sun.COM } 10777917SReza.Sabdar@Sun.COM 10787917SReza.Sabdar@Sun.COM return (0); 10797917SReza.Sabdar@Sun.COM } 10807917SReza.Sabdar@Sun.COM 10817917SReza.Sabdar@Sun.COM /* 10827917SReza.Sabdar@Sun.COM * Get the SCSI device type (tape, robot) 10837917SReza.Sabdar@Sun.COM */ 10847917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 10857917SReza.Sabdar@Sun.COM int 10867917SReza.Sabdar@Sun.COM scsi_get_devtype(char *adapter, int sid, int lun) 10877917SReza.Sabdar@Sun.COM { 10887917SReza.Sabdar@Sun.COM int rv; 10897917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa; 10907917SReza.Sabdar@Sun.COM scsi_link_t *sl, *sh; 10917917SReza.Sabdar@Sun.COM 10927917SReza.Sabdar@Sun.COM rv = -1; 10937917SReza.Sabdar@Sun.COM sh = &sa->sa_link_head; 10947917SReza.Sabdar@Sun.COM for (sl = sh->sl_next; sl != sh; sl = sl->sl_next) 10957917SReza.Sabdar@Sun.COM if (sl->sl_sid == sid && sl->sl_lun == lun) 10967917SReza.Sabdar@Sun.COM rv = sl->sl_type; 10977917SReza.Sabdar@Sun.COM 10987917SReza.Sabdar@Sun.COM return (rv); 10997917SReza.Sabdar@Sun.COM } 11007917SReza.Sabdar@Sun.COM 11017917SReza.Sabdar@Sun.COM 11027917SReza.Sabdar@Sun.COM /* 11037917SReza.Sabdar@Sun.COM * Check if the SCSI device exists 11047917SReza.Sabdar@Sun.COM */ 11057917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 11067917SReza.Sabdar@Sun.COM int 11077917SReza.Sabdar@Sun.COM scsi_dev_exists(char *adapter, int sid, int lun) 11087917SReza.Sabdar@Sun.COM { 11097917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa; 11107917SReza.Sabdar@Sun.COM scsi_link_t *sl, *sh; 11117917SReza.Sabdar@Sun.COM 11127917SReza.Sabdar@Sun.COM sh = &sa->sa_link_head; 11137917SReza.Sabdar@Sun.COM for (sl = sh->sl_next; sl != sh; sl = sl->sl_next) 11147917SReza.Sabdar@Sun.COM if (sl->sl_sid == sid && sl->sl_lun == lun) 11157917SReza.Sabdar@Sun.COM return (1); 11167917SReza.Sabdar@Sun.COM return (0); 11177917SReza.Sabdar@Sun.COM } 11187917SReza.Sabdar@Sun.COM 11197917SReza.Sabdar@Sun.COM 11207917SReza.Sabdar@Sun.COM /* 11217917SReza.Sabdar@Sun.COM * Count of SCSI adapters 11227917SReza.Sabdar@Sun.COM */ 11237917SReza.Sabdar@Sun.COM int 11247917SReza.Sabdar@Sun.COM scsi_get_adapter_count(void) 11257917SReza.Sabdar@Sun.COM { 11267917SReza.Sabdar@Sun.COM /* Currently support one adapter only */ 11277917SReza.Sabdar@Sun.COM return (1); 11287917SReza.Sabdar@Sun.COM } 11297917SReza.Sabdar@Sun.COM 11307917SReza.Sabdar@Sun.COM /* 11317917SReza.Sabdar@Sun.COM * Return the SCSI adapter structure 11327917SReza.Sabdar@Sun.COM */ 11337917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 11347917SReza.Sabdar@Sun.COM scsi_adapter_t * 11357917SReza.Sabdar@Sun.COM scsi_get_adapter(int adapter) 11367917SReza.Sabdar@Sun.COM { 11377917SReza.Sabdar@Sun.COM return (&my_sa); 11387917SReza.Sabdar@Sun.COM } 11397917SReza.Sabdar@Sun.COM 11407917SReza.Sabdar@Sun.COM /* 11417917SReza.Sabdar@Sun.COM * IOCTL wrapper with retries 11427917SReza.Sabdar@Sun.COM */ 11437917SReza.Sabdar@Sun.COM int 11447917SReza.Sabdar@Sun.COM tlm_ioctl(int fd, int cmd, void *data) 11457917SReza.Sabdar@Sun.COM { 11467917SReza.Sabdar@Sun.COM int retries = 0; 11477917SReza.Sabdar@Sun.COM 11487917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "tlm_ioctl fd %d cmd %d", fd, cmd); 11497917SReza.Sabdar@Sun.COM if (fd == 0 || data == NULL) 11507917SReza.Sabdar@Sun.COM return (EINVAL); 11517917SReza.Sabdar@Sun.COM 11527917SReza.Sabdar@Sun.COM do { 11537917SReza.Sabdar@Sun.COM if (ioctl(fd, cmd, data) == 0) 11547917SReza.Sabdar@Sun.COM break; 11557917SReza.Sabdar@Sun.COM 11567917SReza.Sabdar@Sun.COM if (errno != EIO && errno != 0) { 11577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 11587917SReza.Sabdar@Sun.COM "Failed to send command to device: %m."); 11597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "IOCTL error %d", errno); 11607917SReza.Sabdar@Sun.COM return (errno); 11617917SReza.Sabdar@Sun.COM } 11627917SReza.Sabdar@Sun.COM (void) sleep(1); 11637917SReza.Sabdar@Sun.COM } while (retries++ < MAXIORETRY); 11647917SReza.Sabdar@Sun.COM 11657917SReza.Sabdar@Sun.COM return (0); 11667917SReza.Sabdar@Sun.COM } 11677917SReza.Sabdar@Sun.COM 11687917SReza.Sabdar@Sun.COM /* 11697917SReza.Sabdar@Sun.COM * Checkpoint or snapshot calls 11707917SReza.Sabdar@Sun.COM */ 11717917SReza.Sabdar@Sun.COM 11727917SReza.Sabdar@Sun.COM /* 11737917SReza.Sabdar@Sun.COM * Create a snapshot on the volume 11747917SReza.Sabdar@Sun.COM */ 11757917SReza.Sabdar@Sun.COM int 1176*12186SJanice.Chang@Sun.COM chkpnt_backup_prepare(char *volname, char *jname, boolean_t recursive) 11777917SReza.Sabdar@Sun.COM { 11787917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX]; 11797917SReza.Sabdar@Sun.COM char *p; 11807917SReza.Sabdar@Sun.COM int rv; 11817917SReza.Sabdar@Sun.COM 11827917SReza.Sabdar@Sun.COM if (!volname || !*volname) 11837917SReza.Sabdar@Sun.COM return (-1); 11847917SReza.Sabdar@Sun.COM 11857917SReza.Sabdar@Sun.COM /* Should also return -1 if checkpoint not enabled */ 11867917SReza.Sabdar@Sun.COM 11877917SReza.Sabdar@Sun.COM /* Remove the leading slash */ 11887917SReza.Sabdar@Sun.COM p = volname; 11897917SReza.Sabdar@Sun.COM while (*p == '/') 11907917SReza.Sabdar@Sun.COM p++; 11917917SReza.Sabdar@Sun.COM 1192*12186SJanice.Chang@Sun.COM (void) snprintf(chk_name, PATH_MAX, "%s@%s", p, jname); 11937917SReza.Sabdar@Sun.COM 11947917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 1195*12186SJanice.Chang@Sun.COM if ((rv = zfs_snapshot(zlibh, chk_name, recursive, NULL)) 1196*12186SJanice.Chang@Sun.COM == -1) { 11977917SReza.Sabdar@Sun.COM if (errno == EEXIST) { 11987917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 11997917SReza.Sabdar@Sun.COM return (0); 12007917SReza.Sabdar@Sun.COM } 12017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 1202*12186SJanice.Chang@Sun.COM "chkpnt_backup_prepare: %s failed (err=%d): %s", 1203*12186SJanice.Chang@Sun.COM chk_name, errno, libzfs_error_description(zlibh)); 12047917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12057917SReza.Sabdar@Sun.COM return (rv); 12067917SReza.Sabdar@Sun.COM } 12077917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12087917SReza.Sabdar@Sun.COM return (0); 12097917SReza.Sabdar@Sun.COM } 12107917SReza.Sabdar@Sun.COM 12117917SReza.Sabdar@Sun.COM /* 12127917SReza.Sabdar@Sun.COM * Remove the 'backup' snapshot if backup was successful 12137917SReza.Sabdar@Sun.COM */ 12147917SReza.Sabdar@Sun.COM int 1215*12186SJanice.Chang@Sun.COM chkpnt_backup_successful(char *volname, char *jname, boolean_t recursive, 1216*12186SJanice.Chang@Sun.COM int *zfs_err) 12177917SReza.Sabdar@Sun.COM { 12187917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX]; 12197917SReza.Sabdar@Sun.COM zfs_handle_t *zhp; 1220*12186SJanice.Chang@Sun.COM zfs_type_t ztype; 1221*12186SJanice.Chang@Sun.COM int err; 12227917SReza.Sabdar@Sun.COM char *p; 12237917SReza.Sabdar@Sun.COM 1224*12186SJanice.Chang@Sun.COM if (zfs_err) 1225*12186SJanice.Chang@Sun.COM *zfs_err = 0; 1226*12186SJanice.Chang@Sun.COM 12277917SReza.Sabdar@Sun.COM if (!volname || !*volname) 12287917SReza.Sabdar@Sun.COM return (-1); 12297917SReza.Sabdar@Sun.COM 12307917SReza.Sabdar@Sun.COM /* Should also return -1 if checkpoint not enabled */ 12317917SReza.Sabdar@Sun.COM 12327917SReza.Sabdar@Sun.COM /* Remove the leading slash */ 12337917SReza.Sabdar@Sun.COM p = volname; 12347917SReza.Sabdar@Sun.COM while (*p == '/') 12357917SReza.Sabdar@Sun.COM p++; 12367917SReza.Sabdar@Sun.COM 1237*12186SJanice.Chang@Sun.COM if (recursive) { 1238*12186SJanice.Chang@Sun.COM ztype = ZFS_TYPE_VOLUME | ZFS_TYPE_FILESYSTEM; 1239*12186SJanice.Chang@Sun.COM } else { 1240*12186SJanice.Chang@Sun.COM (void) snprintf(chk_name, PATH_MAX, "%s@%s", p, jname); 1241*12186SJanice.Chang@Sun.COM p = chk_name; 1242*12186SJanice.Chang@Sun.COM ztype = ZFS_TYPE_SNAPSHOT; 1243*12186SJanice.Chang@Sun.COM } 12447917SReza.Sabdar@Sun.COM 12457917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 1246*12186SJanice.Chang@Sun.COM if ((zhp = zfs_open(zlibh, p, ztype)) == NULL) { 12477917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "chkpnt_backup_successful: open %s failed", 1248*12186SJanice.Chang@Sun.COM p); 12497917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12507917SReza.Sabdar@Sun.COM return (-1); 12517917SReza.Sabdar@Sun.COM } 1252*12186SJanice.Chang@Sun.COM 1253*12186SJanice.Chang@Sun.COM if (recursive) { 1254*12186SJanice.Chang@Sun.COM err = zfs_destroy_snaps(zhp, jname, B_FALSE); 1255*12186SJanice.Chang@Sun.COM } else { 1256*12186SJanice.Chang@Sun.COM err = zfs_destroy(zhp, B_FALSE); 1257*12186SJanice.Chang@Sun.COM } 1258*12186SJanice.Chang@Sun.COM 1259*12186SJanice.Chang@Sun.COM if (err) { 1260*12186SJanice.Chang@Sun.COM NDMP_LOG(LOG_ERR, "%s (recursive destroy: %d): %d; %s; %s", 1261*12186SJanice.Chang@Sun.COM p, 1262*12186SJanice.Chang@Sun.COM recursive, 1263*12186SJanice.Chang@Sun.COM libzfs_errno(zlibh), 1264*12186SJanice.Chang@Sun.COM libzfs_error_action(zlibh), 1265*12186SJanice.Chang@Sun.COM libzfs_error_description(zlibh)); 1266*12186SJanice.Chang@Sun.COM 1267*12186SJanice.Chang@Sun.COM if (zfs_err) 1268*12186SJanice.Chang@Sun.COM *zfs_err = err; 1269*12186SJanice.Chang@Sun.COM } 1270*12186SJanice.Chang@Sun.COM 12717917SReza.Sabdar@Sun.COM zfs_close(zhp); 12727917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12737917SReza.Sabdar@Sun.COM 12747917SReza.Sabdar@Sun.COM return (0); 12757917SReza.Sabdar@Sun.COM } 12767917SReza.Sabdar@Sun.COM 12777917SReza.Sabdar@Sun.COM /* 12787917SReza.Sabdar@Sun.COM * Get the snapshot creation time 12797917SReza.Sabdar@Sun.COM */ 12807917SReza.Sabdar@Sun.COM int 12817917SReza.Sabdar@Sun.COM chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp) 12827917SReza.Sabdar@Sun.COM { 12837917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX]; 12847917SReza.Sabdar@Sun.COM zfs_handle_t *zhp; 12857917SReza.Sabdar@Sun.COM char *p; 12867917SReza.Sabdar@Sun.COM 12877917SReza.Sabdar@Sun.COM if (!volname || !*volname) 12887917SReza.Sabdar@Sun.COM return (-1); 12897917SReza.Sabdar@Sun.COM 12907917SReza.Sabdar@Sun.COM /* Should also return -1 if checkpoint not enabled */ 12917917SReza.Sabdar@Sun.COM 12927917SReza.Sabdar@Sun.COM /* Remove the leading slash */ 12937917SReza.Sabdar@Sun.COM p = volname; 12947917SReza.Sabdar@Sun.COM while (*p == '/') 12957917SReza.Sabdar@Sun.COM p++; 12967917SReza.Sabdar@Sun.COM 12977917SReza.Sabdar@Sun.COM (void) strlcpy(chk_name, p, PATH_MAX); 12987917SReza.Sabdar@Sun.COM (void) strlcat(chk_name, "@", PATH_MAX); 12997917SReza.Sabdar@Sun.COM (void) strlcat(chk_name, pattern, PATH_MAX); 13007917SReza.Sabdar@Sun.COM 13017917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 13027917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) { 13037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "chkpnt_creationtime: open %s failed", 13047917SReza.Sabdar@Sun.COM chk_name); 13057917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13067917SReza.Sabdar@Sun.COM return (-1); 13077917SReza.Sabdar@Sun.COM } 13087917SReza.Sabdar@Sun.COM 13097917SReza.Sabdar@Sun.COM *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION); 13107917SReza.Sabdar@Sun.COM zfs_close(zhp); 13117917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13127917SReza.Sabdar@Sun.COM 13137917SReza.Sabdar@Sun.COM return (0); 13147917SReza.Sabdar@Sun.COM } 13157917SReza.Sabdar@Sun.COM 13167917SReza.Sabdar@Sun.COM 13177917SReza.Sabdar@Sun.COM /* 13187917SReza.Sabdar@Sun.COM * Get the ZFS volume name out of the given path 13197917SReza.Sabdar@Sun.COM */ 13207917SReza.Sabdar@Sun.COM int 13217917SReza.Sabdar@Sun.COM get_zfsvolname(char *volname, int len, char *path) 13227917SReza.Sabdar@Sun.COM { 13237917SReza.Sabdar@Sun.COM struct stat64 stbuf; 13247917SReza.Sabdar@Sun.COM struct extmnttab ent; 13257917SReza.Sabdar@Sun.COM FILE *mntfp; 13267917SReza.Sabdar@Sun.COM int rv; 13277917SReza.Sabdar@Sun.COM 13287917SReza.Sabdar@Sun.COM *volname = '\0'; 13297917SReza.Sabdar@Sun.COM if (stat64(path, &stbuf) != 0) { 13307917SReza.Sabdar@Sun.COM return (-1); 13317917SReza.Sabdar@Sun.COM } 13327917SReza.Sabdar@Sun.COM 13337917SReza.Sabdar@Sun.COM if ((mntfp = fopen(MNTTAB, "r")) == NULL) { 13347917SReza.Sabdar@Sun.COM return (-1); 13357917SReza.Sabdar@Sun.COM } 13367917SReza.Sabdar@Sun.COM while ((rv = getextmntent(mntfp, &ent, 0)) == 0) { 13377917SReza.Sabdar@Sun.COM if (makedevice(ent.mnt_major, ent.mnt_minor) == 13387917SReza.Sabdar@Sun.COM stbuf.st_dev) 13397917SReza.Sabdar@Sun.COM break; 13407917SReza.Sabdar@Sun.COM } 13417917SReza.Sabdar@Sun.COM 13427917SReza.Sabdar@Sun.COM if (rv == 0 && 13437917SReza.Sabdar@Sun.COM strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0) 13447917SReza.Sabdar@Sun.COM (void) strlcpy(volname, ent.mnt_special, len); 13457917SReza.Sabdar@Sun.COM else 13467917SReza.Sabdar@Sun.COM rv = -1; 13477917SReza.Sabdar@Sun.COM 13487917SReza.Sabdar@Sun.COM (void) fclose(mntfp); 13497917SReza.Sabdar@Sun.COM return (rv); 13507917SReza.Sabdar@Sun.COM } 13517917SReza.Sabdar@Sun.COM 13527917SReza.Sabdar@Sun.COM 13537917SReza.Sabdar@Sun.COM /* 13547917SReza.Sabdar@Sun.COM * Check if the volume type is snapshot volume 13557917SReza.Sabdar@Sun.COM */ 13567917SReza.Sabdar@Sun.COM boolean_t 13577917SReza.Sabdar@Sun.COM fs_is_chkpntvol(char *path) 13587917SReza.Sabdar@Sun.COM { 13597917SReza.Sabdar@Sun.COM zfs_handle_t *zhp; 13607917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN]; 13617917SReza.Sabdar@Sun.COM 13627917SReza.Sabdar@Sun.COM if (!path || !*path) 13637917SReza.Sabdar@Sun.COM return (FALSE); 13647917SReza.Sabdar@Sun.COM 13657917SReza.Sabdar@Sun.COM if (get_zfsvolname(vol, sizeof (vol), path) == -1) 13667917SReza.Sabdar@Sun.COM return (FALSE); 13677917SReza.Sabdar@Sun.COM 13687917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 13697917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) { 13707917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13717917SReza.Sabdar@Sun.COM return (FALSE); 13727917SReza.Sabdar@Sun.COM } 13737917SReza.Sabdar@Sun.COM 13747917SReza.Sabdar@Sun.COM if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 13757917SReza.Sabdar@Sun.COM zfs_close(zhp); 13767917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13777917SReza.Sabdar@Sun.COM return (FALSE); 13787917SReza.Sabdar@Sun.COM } 13797917SReza.Sabdar@Sun.COM zfs_close(zhp); 13807917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13817917SReza.Sabdar@Sun.COM 13827917SReza.Sabdar@Sun.COM return (TRUE); 13837917SReza.Sabdar@Sun.COM } 13847917SReza.Sabdar@Sun.COM 13857917SReza.Sabdar@Sun.COM /* 13867917SReza.Sabdar@Sun.COM * Check if the volume is capable of checkpoints 13877917SReza.Sabdar@Sun.COM */ 13887917SReza.Sabdar@Sun.COM boolean_t 13897917SReza.Sabdar@Sun.COM fs_is_chkpnt_enabled(char *path) 13907917SReza.Sabdar@Sun.COM { 13917917SReza.Sabdar@Sun.COM zfs_handle_t *zhp; 13927917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN]; 13937917SReza.Sabdar@Sun.COM 13947917SReza.Sabdar@Sun.COM if (!path || !*path) 13957917SReza.Sabdar@Sun.COM return (FALSE); 13967917SReza.Sabdar@Sun.COM 13977917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 13987917SReza.Sabdar@Sun.COM if (get_zfsvolname(vol, sizeof (vol), path) == -1) { 13997917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 14007917SReza.Sabdar@Sun.COM return (FALSE); 14017917SReza.Sabdar@Sun.COM } 14027917SReza.Sabdar@Sun.COM 14037917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) { 14047917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 14057917SReza.Sabdar@Sun.COM return (FALSE); 14067917SReza.Sabdar@Sun.COM } 14077917SReza.Sabdar@Sun.COM zfs_close(zhp); 14087917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 14097917SReza.Sabdar@Sun.COM 14107917SReza.Sabdar@Sun.COM return (TRUE); 14117917SReza.Sabdar@Sun.COM } 14127917SReza.Sabdar@Sun.COM 14137917SReza.Sabdar@Sun.COM /* 14147917SReza.Sabdar@Sun.COM * Check if the volume is read-only 14157917SReza.Sabdar@Sun.COM */ 14167917SReza.Sabdar@Sun.COM boolean_t 14177917SReza.Sabdar@Sun.COM fs_is_rdonly(char *path) 14187917SReza.Sabdar@Sun.COM { 14197917SReza.Sabdar@Sun.COM return (fs_is_chkpntvol(path)); 14207917SReza.Sabdar@Sun.COM } 14217917SReza.Sabdar@Sun.COM 14227917SReza.Sabdar@Sun.COM /* 14237917SReza.Sabdar@Sun.COM * Min/max functions 14247917SReza.Sabdar@Sun.COM */ 14257917SReza.Sabdar@Sun.COM unsigned 14267917SReza.Sabdar@Sun.COM min(a, b) 14277917SReza.Sabdar@Sun.COM unsigned a, b; 14287917SReza.Sabdar@Sun.COM { 14297917SReza.Sabdar@Sun.COM return (a < b ? a : b); 14307917SReza.Sabdar@Sun.COM } 14317917SReza.Sabdar@Sun.COM 14327917SReza.Sabdar@Sun.COM unsigned 14337917SReza.Sabdar@Sun.COM max(a, b) 14347917SReza.Sabdar@Sun.COM unsigned a, b; 14357917SReza.Sabdar@Sun.COM { 14367917SReza.Sabdar@Sun.COM return (a > b ? a : b); 14377917SReza.Sabdar@Sun.COM } 14387917SReza.Sabdar@Sun.COM 14397917SReza.Sabdar@Sun.COM longlong_t 14407917SReza.Sabdar@Sun.COM llmin(longlong_t a, longlong_t b) 14417917SReza.Sabdar@Sun.COM { 14427917SReza.Sabdar@Sun.COM return (a < b ? a : b); 14437917SReza.Sabdar@Sun.COM } 1444