1 /* 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 3 */ 4 5 /* 6 * BSD 3 Clause License 7 * 8 * Copyright (c) 2007, The Storage Networking Industry Association. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * - Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * - Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * - Neither the name of The Storage Networking Industry Association (SNIA) 22 * nor the names of its contributors may be used to endorse or promote 23 * products derived from this software without specific prior written 24 * permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 #include <sys/errno.h> 39 #include <ctype.h> 40 #include <stdlib.h> 41 #include <time.h> 42 #include <sys/types.h> 43 #include <unistd.h> 44 #include <libzfs.h> 45 #include <pthread.h> 46 #include "tlm.h" 47 #include "tlm_proto.h" 48 #include <ndmpd_prop.h> 49 #include <sys/mtio.h> 50 #include <sys/mnttab.h> 51 #include <sys/mntent.h> 52 #include <sys/statvfs.h> 53 #include <sys/scsi/impl/uscsi.h> 54 #include <sys/scsi/scsi.h> 55 #include <sys/mtio.h> 56 #include <thread.h> 57 #include <synch.h> 58 #include <sys/mutex.h> 59 #include <sys/sysmacros.h> 60 #include <sys/mkdev.h> 61 62 /* 63 * Tar archiving ops vector 64 */ 65 tm_ops_t tm_tar_ops = { 66 "tar", 67 tar_putfile, 68 tar_putdir, 69 NULL, 70 tar_getfile, 71 tar_getdir, 72 NULL 73 }; 74 75 extern libzfs_handle_t *zlibh; 76 extern mutex_t zlib_mtx; 77 78 /* 79 * get the next tape buffer from the drive's pool of buffers 80 */ 81 /*ARGSUSED*/ 82 char * 83 tlm_get_write_buffer(long want, long *actual_size, 84 tlm_buffers_t *buffers, int zero) 85 { 86 int buf = buffers->tbs_buffer_in; 87 tlm_buffer_t *buffer = &buffers->tbs_buffer[buf]; 88 int align_size = RECORDSIZE - 1; 89 char *rec; 90 91 /* 92 * make sure the allocation is in chunks of 512 bytes 93 */ 94 want += align_size; 95 want &= ~align_size; 96 97 *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 98 if (*actual_size <= 0) { 99 /* 100 * no room, send this one 101 * and wait for a free one 102 */ 103 if (!buffer->tb_full) { 104 /* 105 * we are now ready to send a full buffer 106 * instead of trying to get a new buffer 107 * 108 * do not send if we failed to get a buffer 109 * on the previous call 110 */ 111 buffer->tb_full = TRUE; 112 113 /* 114 * tell the writer that a buffer is available 115 */ 116 tlm_buffer_release_in_buf(buffers); 117 118 buffer = tlm_buffer_advance_in_idx(buffers); 119 } 120 121 buffer = tlm_buffer_in_buf(buffers, NULL); 122 123 if (buffer->tb_full) { 124 /* 125 * wait for the writer to free up a buffer 126 */ 127 tlm_buffer_out_buf_timed_wait(buffers, 500); 128 } 129 130 buffer = tlm_buffer_in_buf(buffers, NULL); 131 if (buffer->tb_full) { 132 /* 133 * the next buffer is still full 134 * of data from previous activity 135 * 136 * nothing has changed. 137 */ 138 return (0); 139 } 140 141 buffer->tb_buffer_spot = 0; 142 *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 143 } 144 145 *actual_size = min(want, *actual_size); 146 rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot]; 147 buffer->tb_buffer_spot += *actual_size; 148 buffers->tbs_offset += *actual_size; 149 if (zero) { 150 (void) memset(rec, 0, *actual_size); 151 } 152 return (rec); 153 } 154 155 /* 156 * get a read record from the tape buffer, 157 * and read a tape block if necessary 158 */ 159 /*ARGSUSED*/ 160 char * 161 tlm_get_read_buffer(int want, int *error, 162 tlm_buffers_t *buffers, int *actual_size) 163 { 164 tlm_buffer_t *buffer; 165 int align_size = RECORDSIZE - 1; 166 int buf; 167 int current_size; 168 char *rec; 169 170 buf = buffers->tbs_buffer_out; 171 buffer = &buffers->tbs_buffer[buf]; 172 173 /* 174 * make sure the allocation is in chunks of 512 bytes 175 */ 176 want += align_size; 177 want &= ~align_size; 178 179 current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 180 if (buffer->tb_full && current_size <= 0) { 181 /* 182 * no more data, release this 183 * one and go get another 184 */ 185 186 /* 187 * tell the reader that a buffer is available 188 */ 189 buffer->tb_full = FALSE; 190 tlm_buffer_release_out_buf(buffers); 191 192 buffer = tlm_buffer_advance_out_idx(buffers); 193 current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 194 } 195 196 if (!buffer->tb_full) { 197 /* 198 * next buffer is not full yet. 199 * wait for the reader. 200 */ 201 tlm_buffer_in_buf_timed_wait(buffers, 500); 202 203 buffer = tlm_buffer_out_buf(buffers, NULL); 204 if (!buffer->tb_full) { 205 /* 206 * we do not have anything from the tape yet 207 */ 208 return (0); 209 } 210 211 current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot; 212 } 213 214 /* Make sure we got something */ 215 if (current_size <= 0) 216 return (NULL); 217 218 current_size = min(want, current_size); 219 rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot]; 220 buffer->tb_buffer_spot += current_size; 221 *actual_size = current_size; 222 223 /* 224 * the error flag is only sent back one time, 225 * since the flag refers to a previous read 226 * attempt, not the data in this buffer. 227 */ 228 *error = buffer->tb_errno; 229 230 return (rec); 231 } 232 233 234 /* 235 * unread a previously read buffer back to the tape buffer 236 */ 237 void 238 tlm_unget_read_buffer(tlm_buffers_t *buffers, int size) 239 { 240 tlm_buffer_t *buffer; 241 int align_size = RECORDSIZE - 1; 242 int buf; 243 int current_size; 244 245 buf = buffers->tbs_buffer_out; 246 buffer = &buffers->tbs_buffer[buf]; 247 248 /* 249 * make sure the allocation is in chunks of 512 bytes 250 */ 251 size += align_size; 252 size &= ~align_size; 253 254 current_size = min(size, buffer->tb_buffer_spot); 255 buffer->tb_buffer_spot -= current_size; 256 } 257 258 259 /* 260 * unwrite a previously written buffer 261 */ 262 void 263 tlm_unget_write_buffer(tlm_buffers_t *buffers, int size) 264 { 265 tlm_buffer_t *buffer; 266 int align_size = RECORDSIZE - 1; 267 int buf; 268 int current_size; 269 270 buf = buffers->tbs_buffer_in; 271 buffer = &buffers->tbs_buffer[buf]; 272 273 /* 274 * make sure the allocation is in chunks of 512 bytes 275 */ 276 size += align_size; 277 size &= ~align_size; 278 279 current_size = min(size, buffer->tb_buffer_spot); 280 buffer->tb_buffer_spot -= current_size; 281 } 282 283 284 /* 285 * build a checksum for a TAR header record 286 */ 287 void 288 tlm_build_header_checksum(tlm_tar_hdr_t *r) 289 { 290 int i; 291 int sum = 0; 292 char *c = (char *)r; 293 294 (void) memcpy(r->th_chksum, CHKBLANKS, strlen(CHKBLANKS)); 295 for (i = 0; i < RECORDSIZE; i++) { 296 sum += c[i] & 0xFF; 297 } 298 (void) snprintf(r->th_chksum, sizeof (r->th_chksum), "%6o", sum); 299 } 300 301 /* 302 * verify the tar header checksum 303 */ 304 int 305 tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr) 306 { 307 int chksum = oct_atoi(tar_hdr->th_chksum); 308 uchar_t *p = (uchar_t *)tar_hdr; 309 int sum = 0; /* initial value of checksum */ 310 int i; /* loop counter */ 311 312 /* 313 * compute the checksum 314 */ 315 for (i = 0; i < RECORDSIZE; i++) { 316 sum += p[i] & 0xFF; 317 } 318 319 if (sum == 0) { 320 NDMP_LOG(LOG_DEBUG, 321 "should be %d, is 0", chksum); 322 /* a zero record ==> end of tar file */ 323 return (0); 324 } 325 326 /* 327 * subtract out the label's checksum values 328 * this lets us undo the old checksum "in- 329 * place", no need to swap blanks in and out 330 */ 331 for (i = 0; i < 8; i++) { 332 sum -= 0xFF & tar_hdr->th_chksum[i]; 333 } 334 335 /* 336 * replace the old checksum field with blanks 337 */ 338 sum += ' ' * 8; 339 340 if (sum != chksum) 341 NDMP_LOG(LOG_DEBUG, 342 "should be %d, is %d", chksum, sum); 343 344 return ((sum == chksum) ? 1 : -1); 345 } 346 347 /* 348 * get internal scsi_sasd entry for this tape drive 349 */ 350 int 351 tlm_get_scsi_sasd_entry(int lib, int drv) 352 { 353 int entry; 354 int i, n; 355 scsi_link_t *sl; 356 tlm_drive_t *dp; 357 358 entry = -1; 359 dp = tlm_drive(lib, drv); 360 if (!dp) { 361 NDMP_LOG(LOG_DEBUG, "NULL dp for (%d.%d)", lib, drv); 362 } else if (!dp->td_slink) { 363 NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink for (%d.%d)", lib, drv); 364 } else if (!dp->td_slink->sl_sa) { 365 NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink->sl_sa for (%d.%d)", 366 lib, drv); 367 } else { 368 /* search through the SASD table */ 369 n = sasd_dev_count(); 370 for (i = 0; i < n; i++) { 371 sl = sasd_dev_slink(i); 372 if (!sl) 373 continue; 374 375 if (dp->td_slink->sl_sa == sl->sl_sa && 376 dp->td_scsi_id == sl->sl_sid && 377 dp->td_lun == sl->sl_lun) { 378 /* all 3 variables match */ 379 entry = i; 380 break; 381 } 382 } 383 } 384 385 return (entry); 386 } 387 388 /* 389 * get the OS device name for this tape 390 */ 391 char * 392 tlm_get_tape_name(int lib, int drv) 393 { 394 int entry; 395 396 entry = tlm_get_scsi_sasd_entry(lib, drv); 397 if (entry >= 0) { 398 sasd_drive_t *sd; 399 400 if ((sd = sasd_drive(entry)) != 0) 401 return (sd->sd_name); 402 } 403 404 return (""); 405 } 406 407 /* 408 * create the IPC area between the reader and writer 409 */ 410 tlm_cmd_t * 411 tlm_create_reader_writer_ipc(boolean_t write, long data_transfer_size) 412 { 413 tlm_cmd_t *cmd; 414 415 cmd = ndmp_malloc(sizeof (tlm_cmd_t)); 416 if (cmd == NULL) 417 return (NULL); 418 419 cmd->tc_reader = TLM_BACKUP_RUN; 420 cmd->tc_writer = TLM_BACKUP_RUN; 421 cmd->tc_ref = 1; 422 423 cmd->tc_buffers = tlm_allocate_buffers(write, data_transfer_size); 424 if (cmd->tc_buffers == NULL) { 425 free(cmd); 426 return (NULL); 427 } 428 429 (void) mutex_init(&cmd->tc_mtx, 0, NULL); 430 (void) cond_init(&cmd->tc_cv, 0, NULL); 431 432 return (cmd); 433 } 434 435 /* 436 * release(destroy) the IPC between the reader and writer 437 */ 438 void 439 tlm_release_reader_writer_ipc(tlm_cmd_t *cmd) 440 { 441 if (--cmd->tc_ref <= 0) { 442 (void) mutex_lock(&cmd->tc_mtx); 443 tlm_release_buffers(cmd->tc_buffers); 444 (void) cond_destroy(&cmd->tc_cv); 445 (void) mutex_unlock(&cmd->tc_mtx); 446 (void) mutex_destroy(&cmd->tc_mtx); 447 free(cmd); 448 } 449 } 450 451 452 /* 453 * NDMP support begins here. 454 */ 455 456 /* 457 * Initialize the file history callback functions 458 */ 459 lbr_fhlog_call_backs_t * 460 lbrlog_callbacks_init(void *cookie, path_hist_func_t log_pname_func, 461 dir_hist_func_t log_dir_func, node_hist_func_t log_node_func) 462 { 463 lbr_fhlog_call_backs_t *p; 464 465 p = ndmp_malloc(sizeof (lbr_fhlog_call_backs_t)); 466 if (p == NULL) 467 return (NULL); 468 469 p->fh_cookie = cookie; 470 p->fh_logpname = (func_t)log_pname_func; 471 p->fh_log_dir = (func_t)log_dir_func; 472 p->fh_log_node = (func_t)log_node_func; 473 return (p); 474 } 475 476 /* 477 * Cleanup the callbacks 478 */ 479 void 480 lbrlog_callbacks_done(lbr_fhlog_call_backs_t *p) 481 { 482 if (p != NULL) 483 (void) free((char *)p); 484 } 485 486 /* 487 * Call back for file history directory info 488 */ 489 int 490 tlm_log_fhdir(tlm_job_stats_t *job_stats, char *dir, struct stat64 *stp, 491 fs_fhandle_t *fhp) 492 { 493 int rv; 494 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 495 496 rv = 0; 497 if (job_stats == NULL) { 498 NDMP_LOG(LOG_DEBUG, "log_fhdir: jstat is NULL"); 499 } else if (dir == NULL) { 500 NDMP_LOG(LOG_DEBUG, "log_fhdir: dir is NULL"); 501 } else if (stp == NULL) { 502 NDMP_LOG(LOG_DEBUG, "log_fhdir: stp is NULL"); 503 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 504 == NULL) { 505 NDMP_LOG(LOG_DEBUG, "log_fhdir: cbp is NULL"); 506 } else if (cbp->fh_log_dir == NULL) { 507 NDMP_LOG(LOG_DEBUG, "log_fhdir: callback is NULL"); 508 } else 509 rv = (*cbp->fh_log_dir)(cbp, dir, stp, fhp); 510 511 return (rv); 512 } 513 514 /* 515 * Call back for file history node info 516 */ 517 int 518 tlm_log_fhnode(tlm_job_stats_t *job_stats, char *dir, char *file, 519 struct stat64 *stp, u_longlong_t off) 520 { 521 int rv; 522 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 523 524 rv = 0; 525 if (job_stats == NULL) { 526 NDMP_LOG(LOG_DEBUG, "log_fhnode: jstat is NULL"); 527 } else if (dir == NULL) { 528 NDMP_LOG(LOG_DEBUG, "log_fhnode: dir is NULL"); 529 } else if (file == NULL) { 530 NDMP_LOG(LOG_DEBUG, "log_fhnode: file is NULL"); 531 } else if (stp == NULL) { 532 NDMP_LOG(LOG_DEBUG, "log_fhnode: stp is NULL"); 533 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 534 == NULL) { 535 NDMP_LOG(LOG_DEBUG, "log_fhnode: cbp is NULL"); 536 } else if (cbp->fh_log_node == NULL) { 537 NDMP_LOG(LOG_DEBUG, "log_fhnode: callback is NULL"); 538 } else 539 rv = (*cbp->fh_log_node)(cbp, dir, file, stp, off); 540 541 return (rv); 542 } 543 544 /* 545 * Call back for file history path info 546 */ 547 int 548 tlm_log_fhpath_name(tlm_job_stats_t *job_stats, char *pathname, 549 struct stat64 *stp, u_longlong_t off) 550 { 551 int rv; 552 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 553 554 rv = 0; 555 if (!job_stats) { 556 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: jstat is NULL"); 557 } else if (!pathname) { 558 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: pathname is NULL"); 559 } else if (!stp) { 560 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: stp is NULL"); 561 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks) 562 == 0) { 563 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: cbp is NULL"); 564 } else if (!cbp->fh_logpname) { 565 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: callback is NULL"); 566 } else 567 rv = (*cbp->fh_logpname)(cbp, pathname, stp, off); 568 569 return (rv); 570 } 571 572 573 /* 574 * Log call back to report the entry recovery 575 */ 576 int 577 tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos) 578 { 579 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */ 580 581 NDMP_LOG(LOG_DEBUG, "name: \"%s\", pos: %d", name, pos); 582 583 if (job_stats == NULL) { 584 NDMP_LOG(LOG_DEBUG, "entry_restored: jstat is NULL"); 585 return (0); 586 } 587 cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks; 588 if (cbp == NULL) { 589 NDMP_LOG(LOG_DEBUG, "entry_restored is NULL"); 590 return (0); 591 } 592 return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos); 593 } 594 /* 595 * NDMP support ends here. 596 */ 597 598 /* 599 * Function: tlm_cat_path 600 * Concatenates two path names 601 * or directory name and file name 602 * into a buffer passed by the caller. A slash 603 * is inserted if required. Buffer is assumed 604 * to hold PATH_MAX characters. 605 * 606 * Parameters: 607 * char *buf - buffer to write new dir/name string 608 * char *dir - directory name 609 * char *name - file name 610 * 611 * Returns: 612 * TRUE - No errors. buf contains the dir/name string 613 * FALSE - Error. buf is not modified. 614 */ 615 boolean_t 616 tlm_cat_path(char *buf, char *dir, char *name) 617 { 618 char *fmt; 619 int dirlen = strlen(dir); 620 int filelen = strlen(name); 621 622 if ((dirlen + filelen + 1) >= PATH_MAX) { 623 return (FALSE); 624 } 625 626 if (*dir == '\0' || *name == '\0' || dir[dirlen - 1] == '/' || 627 *name == '/') { 628 fmt = "%s%s"; 629 } else { 630 fmt = "%s/%s"; 631 } 632 633 /* check for ".../" and "/...." */ 634 if ((dirlen > 0) && (dir[dirlen - 1] == '/') && (*name == '/')) 635 name += strspn(name, "/"); 636 637 /* LINTED variable format */ 638 (void) snprintf(buf, TLM_MAX_PATH_NAME, fmt, dir, name); 639 640 return (TRUE); 641 } 642 643 /* 644 * Get the checkpoint (snapshot) creation time. 645 * This is necessary to check for checkpoints not being stale. 646 */ 647 int 648 tlm_get_chkpnt_time(char *path, int auto_checkpoint, time_t *tp, char *jname) 649 { 650 char volname[TLM_VOLNAME_MAX_LENGTH]; 651 char chk_name[PATH_MAX]; 652 char *cp_nm; 653 654 NDMP_LOG(LOG_DEBUG, "path [%s] auto_checkpoint: %d", 655 path, auto_checkpoint); 656 657 if (path == NULL || *path == '\0' || tp == NULL) 658 return (-1); 659 660 if (get_zfsvolname(volname, TLM_VOLNAME_MAX_LENGTH, 661 path) == -1) 662 return (-1); 663 664 if (auto_checkpoint) { 665 NDMP_LOG(LOG_DEBUG, "volname [%s]", volname); 666 (void) snprintf(chk_name, PATH_MAX, "%s", jname); 667 return (chkpnt_creationtime_bypattern(volname, chk_name, tp)); 668 } 669 cp_nm = strchr(volname, '@'); 670 NDMP_LOG(LOG_DEBUG, "volname [%s] cp_nm [%s]", volname, cp_nm); 671 672 return (chkpnt_creationtime_bypattern(volname, cp_nm, tp)); 673 } 674 675 /* 676 * Release an array of pointers and the pointers themselves. 677 */ 678 void 679 tlm_release_list(char **lpp) 680 { 681 char **save; 682 683 if ((save = lpp) == 0) 684 return; 685 686 while (*lpp) 687 free(*lpp++); 688 689 free(save); 690 } 691 692 /* 693 * Print the list of array of strings in the backup log 694 */ 695 void 696 tlm_log_list(char *title, char **lpp) 697 { 698 int i; 699 700 if (!lpp) 701 return; 702 703 NDMP_LOG(LOG_DEBUG, "%s:", title); 704 705 for (i = 0; *lpp; lpp++, i++) 706 NDMP_LOG(LOG_DEBUG, "%d: [%s]", i, *lpp); 707 } 708 709 /* 710 * Insert the backup snapshot name into the path. 711 * 712 * Input: 713 * name: Original path name. 714 * 715 * Output: 716 * name: Original name modified to include a snapshot. 717 * 718 * Returns: 719 * Original name modified to include a snapshot. 720 */ 721 char * 722 tlm_build_snapshot_name(char *name, char *sname, char *jname) 723 { 724 zfs_handle_t *zhp; 725 char *rest; 726 char volname[ZFS_MAXNAMELEN]; 727 char mountpoint[PATH_MAX]; 728 729 if (get_zfsvolname(volname, ZFS_MAXNAMELEN, name) == -1) 730 goto notzfs; 731 732 (void) mutex_lock(&zlib_mtx); 733 if ((zlibh == NULL) || 734 (zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == NULL) { 735 (void) mutex_unlock(&zlib_mtx); 736 goto notzfs; 737 } 738 739 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, PATH_MAX, NULL, 740 NULL, 0, B_FALSE) != 0) { 741 zfs_close(zhp); 742 (void) mutex_unlock(&zlib_mtx); 743 goto notzfs; 744 } 745 746 zfs_close(zhp); 747 (void) mutex_unlock(&zlib_mtx); 748 749 rest = name + strlen(mountpoint); 750 (void) snprintf(sname, TLM_MAX_PATH_NAME, "%s/%s/%s%s", mountpoint, 751 TLM_SNAPSHOT_DIR, jname, rest); 752 753 return (sname); 754 755 notzfs: 756 (void) strlcpy(sname, name, TLM_MAX_PATH_NAME); 757 return (sname); 758 } 759 760 /* 761 * Remove the checkpoint from a path name. 762 * 763 * Input: 764 * name: Full pathname with checkpoint embeded. 765 * 766 * Output: 767 * unchkp_name: real pathname with no checkpoint. 768 * 769 * Returns: 770 * Pointer to the un-checkpointed path. 771 */ 772 char * 773 tlm_remove_checkpoint(char *name, char *unchkp_name) 774 { 775 char *cp; 776 int i; 777 int plen; 778 779 unchkp_name[0] = name[0]; 780 plen = strlen(TLM_SNAPSHOT_PREFIX); 781 for (i = 1; i <= TLM_VOLNAME_MAX_LENGTH + 1; i++) { 782 switch (name[i]) { 783 case '.': 784 if (strncmp(&name[i], TLM_SNAPSHOT_PREFIX, 785 plen) == 0) { 786 unchkp_name[i] = '\0'; 787 i += plen; 788 if (name[i] == '\0') { 789 /* 790 * name == "/v1.chkpnt" 791 */ 792 return (unchkp_name); 793 } 794 if ((cp = strchr(&name[++i], '/')) != NULL) { 795 (void) strlcat(unchkp_name, cp, 796 TLM_VOLNAME_MAX_LENGTH + 1); 797 } 798 return (unchkp_name); 799 } else { 800 unchkp_name[i] = name[i]; 801 } 802 break; 803 case '/': 804 return (name); 805 case 0: 806 return (name); 807 default: 808 unchkp_name[i] = name[i]; 809 break; 810 } 811 } 812 return (name); 813 } 814 815 /* 816 * see if we should exclude this file. 817 */ 818 boolean_t 819 tlm_is_excluded(char *dir, char *name, char **excl_files) 820 { 821 int i; 822 char full_name[TLM_MAX_PATH_NAME]; 823 824 if (!dir || !name || !excl_files) 825 return (FALSE); 826 827 if (!tlm_cat_path(full_name, dir, name)) { 828 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", 829 dir, name); 830 return (FALSE); 831 } 832 for (i = 0; excl_files[i] != 0; i++) { 833 if (match(excl_files[i], full_name)) { 834 return (TRUE); 835 } 836 } 837 return (FALSE); 838 } 839 840 /* 841 * Check if the path is too long 842 */ 843 boolean_t 844 tlm_is_too_long(int checkpointed, char *dir, char *nm) 845 { 846 int nlen, tot; 847 848 tot = 0; 849 if (dir) 850 tot += strlen(dir); 851 if (checkpointed) 852 tot += strlen(TLM_SNAPSHOT_DIR) + 1; 853 if (nm) { 854 if ((nlen = strlen(nm)) > 0) 855 tot += nlen + 1; 856 } 857 return ((tot >= PATH_MAX) ? TRUE : FALSE); 858 } 859 860 /* 861 * Get the data offset of inside the buffer 862 */ 863 longlong_t 864 tlm_get_data_offset(tlm_cmd_t *lcmds) 865 { 866 if (!lcmds) 867 return (0LL); 868 869 return (lcmds->tc_buffers->tbs_offset); 870 } 871 872 /* 873 * Enable the barcode capability on the library 874 */ 875 void 876 tlm_enable_barcode(int l) 877 { 878 tlm_library_t *lp; 879 880 if ((lp = tlm_library(l))) { 881 lp->tl_capability_barcodes = TRUE; 882 NDMP_LOG(LOG_DEBUG, 883 "Barcode capability on library %d enabled.", l); 884 } 885 } 886 887 /* 888 * SASD SCSI support 889 */ 890 static scsi_adapter_t my_sa; 891 static int sasd_drive_count = 0; 892 static scsi_sasd_drive_t *scsi_sasd_drives[128]; 893 894 /* 895 * Count of SCSI devices 896 */ 897 int 898 sasd_dev_count(void) 899 { 900 return (sasd_drive_count); 901 } 902 903 /* 904 * Return the SCSI device name 905 */ 906 char * 907 sasd_slink_name(scsi_link_t *slink) 908 { 909 int i; 910 911 for (i = 0; i < sasd_drive_count; i++) { 912 if (&scsi_sasd_drives[i]->ss_slink == slink) 913 return (scsi_sasd_drives[i]->ss_sd.sd_name); 914 } 915 return (NULL); 916 } 917 918 /* 919 * Return the SCSI drive structure 920 */ 921 sasd_drive_t * 922 sasd_slink_drive(scsi_link_t *slink) 923 { 924 int i; 925 926 for (i = 0; i < sasd_drive_count; i++) { 927 if (&scsi_sasd_drives[i]->ss_slink == slink) 928 return (&scsi_sasd_drives[i]->ss_sd); 929 } 930 return (NULL); 931 } 932 933 /* 934 * Return the SCSI link pointer for the given index 935 */ 936 scsi_link_t * 937 sasd_dev_slink(int entry) 938 { 939 scsi_link_t *rv; 940 941 if (entry >= 0 && entry < sasd_drive_count) 942 rv = &scsi_sasd_drives[entry]->ss_slink; 943 else 944 rv = NULL; 945 946 return (rv); 947 } 948 949 /* 950 * Return the SCSI drive for the given index 951 */ 952 sasd_drive_t * 953 sasd_drive(int entry) 954 { 955 sasd_drive_t *rv; 956 957 if (entry >= 0 && entry < sasd_drive_count) 958 rv = &scsi_sasd_drives[entry]->ss_sd; 959 else 960 rv = NULL; 961 962 return (rv); 963 } 964 965 /* 966 * Attach the SCSI device by updating the structures 967 */ 968 void 969 scsi_sasd_attach(scsi_adapter_t *sa, int sid, int lun, char *name, 970 int type) 971 { 972 scsi_link_t *sl, *next; 973 scsi_sasd_drive_t *ssd; 974 975 ssd = ndmp_malloc(sizeof (scsi_sasd_drive_t)); 976 if (ssd == NULL) 977 return; 978 979 scsi_sasd_drives[sasd_drive_count++] = ssd; 980 981 switch (type) { 982 case DTYPE_CHANGER: 983 (void) snprintf(ssd->ss_sd.sd_name, 984 sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_CHANGER_DIR, 985 name); 986 break; 987 case DTYPE_SEQUENTIAL: 988 (void) snprintf(ssd->ss_sd.sd_name, 989 sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_TAPE_DIR, name); 990 break; 991 } 992 993 sl = &ssd->ss_slink; 994 sl->sl_type = type; 995 sl->sl_sa = sa; 996 sl->sl_lun = lun; 997 sl->sl_sid = sid; 998 sl->sl_requested_max_active = 1; 999 1000 /* Insert slink */ 1001 next = sa->sa_link_head.sl_next; 1002 sa->sa_link_head.sl_next = sl; 1003 sl->sl_next = next; 1004 } 1005 1006 /* 1007 * Go through the attached devices and detect the tape 1008 * and robot by checking the /dev entries 1009 */ 1010 int 1011 probe_scsi(void) 1012 { 1013 DIR *dirp; 1014 struct dirent *dp; 1015 scsi_adapter_t *sa = &my_sa; 1016 char *p; 1017 int lun = 0; 1018 int sid = 0; 1019 char *drive_type; 1020 1021 /* Initialize the scsi adapter link */ 1022 sa->sa_link_head.sl_next = &sa->sa_link_head; 1023 1024 /* Scan for the changer */ 1025 dirp = opendir(SCSI_CHANGER_DIR); 1026 if (dirp == NULL) { 1027 NDMP_LOG(LOG_DEBUG, 1028 "Changer directory read error %s", SCSI_CHANGER_DIR); 1029 } else { 1030 while ((dp = readdir(dirp)) != NULL) { 1031 if ((strcmp(dp->d_name, ".") == 0) || 1032 (strcmp(dp->d_name, "..") == 0)) 1033 continue; 1034 1035 if ((p = strchr(dp->d_name, 'd')) != NULL) { 1036 lun = atoi(++p); 1037 p = strchr(dp->d_name, 't'); 1038 sid = atoi(++p); 1039 } 1040 else 1041 sid = atoi(dp->d_name); 1042 1043 scsi_sasd_attach(sa, 0, lun, dp->d_name, 1044 DTYPE_CHANGER); 1045 } 1046 (void) closedir(dirp); 1047 } 1048 1049 /* Scan for tape drives */ 1050 dirp = opendir(SCSI_TAPE_DIR); 1051 if (dirp == NULL) { 1052 NDMP_LOG(LOG_DEBUG, 1053 "Tape directory read error %s", SCSI_TAPE_DIR); 1054 } else { 1055 drive_type = ndmpd_get_prop(NDMP_DRIVE_TYPE); 1056 1057 if ((strcasecmp(drive_type, "sysv") != 0) && 1058 (strcasecmp(drive_type, "bsd") != 0)) { 1059 NDMP_LOG(LOG_ERR, "Invalid ndmpd/drive-type value. " 1060 "Valid values are 'sysv' and 'bsd'."); 1061 return (-1); 1062 } 1063 1064 while ((dp = readdir(dirp)) != NULL) { 1065 if ((strcmp(dp->d_name, ".") == 0) || 1066 (strcmp(dp->d_name, "..") == 0)) 1067 continue; 1068 1069 /* Skip special modes */ 1070 if (strpbrk(dp->d_name, "chlmu") != NULL) 1071 continue; 1072 1073 /* Pick the non-rewind device */ 1074 if (strchr(dp->d_name, 'n') == NULL) 1075 continue; 1076 1077 if (strcasecmp(drive_type, "sysv") == 0) { 1078 if (strchr(dp->d_name, 'b') != NULL) 1079 continue; 1080 } else if (strcasecmp(drive_type, "bsd") == 0) { 1081 if (strchr(dp->d_name, 'b') == NULL) 1082 continue; 1083 } 1084 1085 sid = atoi(dp->d_name); 1086 1087 /* 1088 * SCSI ID should match with the ID of the device 1089 * (will be checked by SCSI get elements page later) 1090 */ 1091 scsi_sasd_attach(sa, sid, 0, dp->d_name, 1092 DTYPE_SEQUENTIAL); 1093 } 1094 (void) closedir(dirp); 1095 } 1096 1097 return (0); 1098 } 1099 1100 /* 1101 * Get the SCSI device type (tape, robot) 1102 */ 1103 /*ARGSUSED*/ 1104 int 1105 scsi_get_devtype(char *adapter, int sid, int lun) 1106 { 1107 int rv; 1108 scsi_adapter_t *sa = &my_sa; 1109 scsi_link_t *sl, *sh; 1110 1111 rv = -1; 1112 sh = &sa->sa_link_head; 1113 for (sl = sh->sl_next; sl != sh; sl = sl->sl_next) 1114 if (sl->sl_sid == sid && sl->sl_lun == lun) 1115 rv = sl->sl_type; 1116 1117 return (rv); 1118 } 1119 1120 1121 /* 1122 * Check if the SCSI device exists 1123 */ 1124 /*ARGSUSED*/ 1125 int 1126 scsi_dev_exists(char *adapter, int sid, int lun) 1127 { 1128 scsi_adapter_t *sa = &my_sa; 1129 scsi_link_t *sl, *sh; 1130 1131 sh = &sa->sa_link_head; 1132 for (sl = sh->sl_next; sl != sh; sl = sl->sl_next) 1133 if (sl->sl_sid == sid && sl->sl_lun == lun) 1134 return (1); 1135 return (0); 1136 } 1137 1138 1139 /* 1140 * Count of SCSI adapters 1141 */ 1142 int 1143 scsi_get_adapter_count(void) 1144 { 1145 /* Currently support one adapter only */ 1146 return (1); 1147 } 1148 1149 /* 1150 * Return the SCSI adapter structure 1151 */ 1152 /*ARGSUSED*/ 1153 scsi_adapter_t * 1154 scsi_get_adapter(int adapter) 1155 { 1156 return (&my_sa); 1157 } 1158 1159 /* 1160 * IOCTL wrapper with retries 1161 */ 1162 int 1163 tlm_ioctl(int fd, int cmd, void *data) 1164 { 1165 int retries = 0; 1166 1167 NDMP_LOG(LOG_DEBUG, "tlm_ioctl fd %d cmd %d", fd, cmd); 1168 if (fd == 0 || data == NULL) 1169 return (EINVAL); 1170 1171 do { 1172 if (ioctl(fd, cmd, data) == 0) 1173 break; 1174 1175 if (errno != EIO && errno != 0) { 1176 NDMP_LOG(LOG_ERR, 1177 "Failed to send command to device: %m."); 1178 NDMP_LOG(LOG_DEBUG, "IOCTL error %d", errno); 1179 return (errno); 1180 } 1181 (void) sleep(1); 1182 } while (retries++ < MAXIORETRY); 1183 1184 return (0); 1185 } 1186 1187 /* 1188 * Checkpoint or snapshot calls 1189 */ 1190 1191 /* 1192 * Get the snapshot creation time 1193 */ 1194 int 1195 chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp) 1196 { 1197 char chk_name[PATH_MAX]; 1198 zfs_handle_t *zhp; 1199 char *p; 1200 1201 if (!volname || !*volname) 1202 return (-1); 1203 1204 /* Should also return -1 if checkpoint not enabled */ 1205 1206 /* Remove the leading slash */ 1207 p = volname; 1208 while (*p == '/') 1209 p++; 1210 1211 (void) strlcpy(chk_name, p, PATH_MAX); 1212 (void) strlcat(chk_name, "@", PATH_MAX); 1213 (void) strlcat(chk_name, pattern, PATH_MAX); 1214 1215 (void) mutex_lock(&zlib_mtx); 1216 if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) { 1217 NDMP_LOG(LOG_DEBUG, "chkpnt_creationtime: open %s failed", 1218 chk_name); 1219 (void) mutex_unlock(&zlib_mtx); 1220 return (-1); 1221 } 1222 1223 *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION); 1224 zfs_close(zhp); 1225 (void) mutex_unlock(&zlib_mtx); 1226 1227 return (0); 1228 } 1229 1230 1231 /* 1232 * Get the ZFS volume name out of the given path 1233 */ 1234 int 1235 get_zfsvolname(char *volname, int len, char *path) 1236 { 1237 struct stat64 stbuf; 1238 struct extmnttab ent; 1239 FILE *mntfp; 1240 int rv; 1241 1242 *volname = '\0'; 1243 if (stat64(path, &stbuf) != 0) { 1244 return (-1); 1245 } 1246 1247 if ((mntfp = fopen(MNTTAB, "r")) == NULL) { 1248 return (-1); 1249 } 1250 while ((rv = getextmntent(mntfp, &ent, 0)) == 0) { 1251 if (makedevice(ent.mnt_major, ent.mnt_minor) == 1252 stbuf.st_dev) 1253 break; 1254 } 1255 1256 if (rv == 0 && 1257 strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0) 1258 (void) strlcpy(volname, ent.mnt_special, len); 1259 else 1260 rv = -1; 1261 1262 (void) fclose(mntfp); 1263 return (rv); 1264 } 1265 1266 1267 /* 1268 * Check if the volume type is snapshot volume 1269 */ 1270 boolean_t 1271 fs_is_chkpntvol(char *path) 1272 { 1273 zfs_handle_t *zhp; 1274 char vol[ZFS_MAXNAMELEN]; 1275 1276 if (!path || !*path) 1277 return (FALSE); 1278 1279 if (get_zfsvolname(vol, sizeof (vol), path) == -1) 1280 return (FALSE); 1281 1282 (void) mutex_lock(&zlib_mtx); 1283 if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) { 1284 (void) mutex_unlock(&zlib_mtx); 1285 return (FALSE); 1286 } 1287 1288 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 1289 zfs_close(zhp); 1290 (void) mutex_unlock(&zlib_mtx); 1291 return (FALSE); 1292 } 1293 zfs_close(zhp); 1294 (void) mutex_unlock(&zlib_mtx); 1295 1296 return (TRUE); 1297 } 1298 1299 /* 1300 * Check if the volume is capable of checkpoints 1301 */ 1302 boolean_t 1303 fs_is_chkpnt_enabled(char *path) 1304 { 1305 zfs_handle_t *zhp; 1306 char vol[ZFS_MAXNAMELEN]; 1307 1308 if (!path || !*path) 1309 return (FALSE); 1310 1311 (void) mutex_lock(&zlib_mtx); 1312 if (get_zfsvolname(vol, sizeof (vol), path) == -1) { 1313 (void) mutex_unlock(&zlib_mtx); 1314 return (FALSE); 1315 } 1316 1317 if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) { 1318 (void) mutex_unlock(&zlib_mtx); 1319 return (FALSE); 1320 } 1321 zfs_close(zhp); 1322 (void) mutex_unlock(&zlib_mtx); 1323 1324 return (TRUE); 1325 } 1326 1327 /* 1328 * Check if the volume is read-only 1329 */ 1330 boolean_t 1331 fs_is_rdonly(char *path) 1332 { 1333 return (fs_is_chkpntvol(path)); 1334 } 1335 1336 /* 1337 * Min/max functions 1338 */ 1339 unsigned 1340 min(a, b) 1341 unsigned a, b; 1342 { 1343 return (a < b ? a : b); 1344 } 1345 1346 unsigned 1347 max(a, b) 1348 unsigned a, b; 1349 { 1350 return (a > b ? a : b); 1351 } 1352 1353 longlong_t 1354 llmin(longlong_t a, longlong_t b) 1355 { 1356 return (a < b ? a : b); 1357 } 1358