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 *
tlm_get_write_buffer(long want,long * actual_size,tlm_buffers_t * buffers,int zero)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 *
tlm_get_read_buffer(int want,int * error,tlm_buffers_t * buffers,int * actual_size)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
tlm_unget_read_buffer(tlm_buffers_t * buffers,int size)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
tlm_unget_write_buffer(tlm_buffers_t * buffers,int size)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
tlm_build_header_checksum(tlm_tar_hdr_t * r)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
tlm_vfy_tar_checksum(tlm_tar_hdr_t * tar_hdr)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
tlm_get_scsi_sasd_entry(int lib,int drv)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 *
tlm_get_tape_name(int lib,int drv)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 *
tlm_create_reader_writer_ipc(boolean_t write,long data_transfer_size)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
tlm_release_reader_writer_ipc(tlm_cmd_t * cmd)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 *
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)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
lbrlog_callbacks_done(lbr_fhlog_call_backs_t * p)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
tlm_log_fhdir(tlm_job_stats_t * job_stats,char * dir,struct stat64 * stp,fs_fhandle_t * fhp)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
tlm_log_fhnode(tlm_job_stats_t * job_stats,char * dir,char * file,struct stat64 * stp,u_longlong_t off)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
tlm_log_fhpath_name(tlm_job_stats_t * job_stats,char * pathname,struct stat64 * stp,u_longlong_t off)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
tlm_entry_restored(tlm_job_stats_t * job_stats,char * name,int pos)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
tlm_cat_path(char * buf,char * dir,char * name)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
tlm_get_chkpnt_time(char * path,int auto_checkpoint,time_t * tp,char * jname)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
tlm_release_list(char ** lpp)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
tlm_log_list(char * title,char ** lpp)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 *
tlm_build_snapshot_name(char * name,char * sname,char * jname)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 *
tlm_remove_checkpoint(char * name,char * unchkp_name)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
tlm_is_excluded(char * dir,char * name,char ** excl_files)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
tlm_is_too_long(int checkpointed,char * dir,char * nm)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
tlm_get_data_offset(tlm_cmd_t * lcmds)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
tlm_enable_barcode(int l)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
sasd_dev_count(void)898 sasd_dev_count(void)
899 {
900 return (sasd_drive_count);
901 }
902
903 /*
904 * Return the SCSI device name
905 */
906 char *
sasd_slink_name(scsi_link_t * slink)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 *
sasd_slink_drive(scsi_link_t * slink)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 *
sasd_dev_slink(int entry)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 *
sasd_drive(int entry)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
scsi_sasd_attach(scsi_adapter_t * sa,int sid,int lun,char * name,int type)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
probe_scsi(void)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
scsi_get_devtype(char * adapter,int sid,int lun)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
scsi_dev_exists(char * adapter,int sid,int lun)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
scsi_get_adapter_count(void)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 *
scsi_get_adapter(int adapter)1154 scsi_get_adapter(int adapter)
1155 {
1156 return (&my_sa);
1157 }
1158
1159 /*
1160 * IOCTL wrapper with retries
1161 */
1162 int
tlm_ioctl(int fd,int cmd,void * data)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
chkpnt_creationtime_bypattern(char * volname,char * pattern,time_t * tp)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
get_zfsvolname(char * volname,int len,char * path)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
fs_is_chkpntvol(char * path)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
fs_is_chkpnt_enabled(char * path)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
fs_is_rdonly(char * path)1331 fs_is_rdonly(char *path)
1332 {
1333 return (fs_is_chkpntvol(path));
1334 }
1335
1336 /*
1337 * Min/max functions
1338 */
1339 unsigned
min(a,b)1340 min(a, b)
1341 unsigned a, b;
1342 {
1343 return (a < b ? a : b);
1344 }
1345
1346 unsigned
max(a,b)1347 max(a, b)
1348 unsigned a, b;
1349 {
1350 return (a > b ? a : b);
1351 }
1352
1353 longlong_t
llmin(longlong_t a,longlong_t b)1354 llmin(longlong_t a, longlong_t b)
1355 {
1356 return (a < b ? a : b);
1357 }
1358