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