xref: /illumos-gate/usr/src/cmd/ndmpd/include/tlm.h (revision d0fccfcda73f8b52d101bd2b0f7885a766f7e354)
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 #ifndef	_TLM_H_
39 #define	_TLM_H_
40 
41 #include <sys/types.h>
42 #include <synch.h>
43 #include <limits.h>
44 #include <cstack.h>
45 #include <sys/acl.h>
46 #include <stdio.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <strings.h>
50 #include <sys/stat.h>
51 #include <time.h>
52 #include <sys/queue.h>
53 #include <sys/fs/zfs.h>
54 #include <libzfs.h>
55 
56 #define	IS_SET(f, m)	(((f) & (m)) != 0)
57 
58 #define	TLM_MAX_BACKUP_JOB_NAME	32	/* max size of a job's name */
59 #define	TLM_TAPE_BUFFERS	10	/* number of rotating tape buffers */
60 #define	TLM_LINE_SIZE		128	/* size of text messages */
61 
62 
63 #define	TLM_BACKUP_RUN		0x00000001
64 #define	TLM_RESTORE_RUN		0x00000002
65 #define	TLM_STOP		0x00000009	/* graceful stop */
66 #define	TLM_ABORT		0x99999999	/* abandon the run */
67 
68 #define	TLM_EXTRA_SPACE		64
69 #define	TLM_MAX_PATH_NAME	(PATH_MAX + TLM_EXTRA_SPACE)
70 
71 #define	ENTRYTYPELEN	14
72 #define	PERMS		4
73 #define	ID_STR_MAX	20
74 #define	APPENDED_ID_MAX	(ID_STR_MAX + 1)
75 #define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
76 #define	TLM_MAX_ACL_TXT	MAX_ACL_ENTRIES * ACL_ENTRY_SIZE
77 
78 
79 /* operation flags */
80 #define	TLM_OP_CHOOSE_ARCHIVE	0x00000001	/* look for archive bit */
81 
82 /*
83  * Synchronization flags used when launching the TLM threads.
84  */
85 #define	TLM_TAPE_READER		0x00000001
86 #define	TLM_TAPE_WRITER		0x00000002
87 #define	TLM_SOCK_READER		0x00000004
88 #define	TLM_SOCK_WRITER		0x00000008
89 #define	TLM_BUF_READER		0x00000010
90 #define	TLM_BUF_WRITER		0x00000020
91 #define	TLM_TAR_READER		0x00000040
92 #define	TLM_TAR_WRITER		0x00000080
93 
94 #define	SCSI_SERIAL_PAGE	0x80
95 #define	SCSI_DEVICE_IDENT_PAGE	0x83
96 #define	SCMD_READ_ELEMENT_STATUS	0xB8
97 
98 #define	OCTAL7CHAR	07777777
99 #define	SYSATTR_RDONLY	"SUNWattr_ro"
100 #define	SYSATTR_RW	"SUNWattr_rw"
101 
102 typedef	int (*func_t)();
103 
104 typedef struct scsi_serial {
105 	int sr_flags;
106 	char sr_num[16];
107 } scsi_serial_t;
108 
109 typedef struct fs_fhandle {
110 	int fh_fid;
111 	char *fh_fpath;
112 } fs_fhandle_t;
113 
114 typedef struct scsi_link {
115 	struct scsi_link 	*sl_next;
116 	struct scsi_link 	*sl_prev;
117 	struct scsi_adapter 	*sl_sa;
118 	unsigned int		sl_sid;
119 	unsigned int		sl_lun;
120 	unsigned int		sl_requested_max_active;
121 	unsigned int		sl_granted_max_active;
122 	unsigned int		sl_n_active;
123 	unsigned int		sl_type; /* SCSI device type */
124 } scsi_link_t;
125 
126 typedef struct scsi_adapter {
127 	struct scsi_adapter	*sa_next;
128 	char			sa_name[16];
129 	struct scsi_link	sa_link_head;
130 } scsi_adapter_t;
131 
132 typedef struct sasd_drive {
133 	char		sd_name[256];
134 	char		sd_vendor[8 + 1];
135 	char		sd_id[16 + 1];
136 	char		sd_rev[4 + 1];
137 	char		sd_serial[16 + 1];
138 	char		sd_wwn[32 + 1];
139 } sasd_drive_t;
140 
141 typedef struct scsi_sasd_drive {
142 	sasd_drive_t	ss_sd;
143 	scsi_link_t	ss_slink;
144 } scsi_sasd_drive_t;
145 
146 
147 #define	DEFAULT_SLINK_MAX_XFER	(64*1024)
148 
149 typedef struct	tlm_info {
150 	int			ti_init_done;	/* initialization done ? */
151 	int			ti_library_count; /* number of libraries */
152 	struct tlm_library	*ti_library;	/* first in chain */
153 	struct tlm_chain_link	*ti_job_stats;  /* chain of job statistics */
154 } tlm_info_t;
155 
156 typedef struct	tlm_chain_link {
157 	struct tlm_chain_link	*tc_next;	/* next blob of statistics */
158 	struct tlm_chain_link	*tc_prev;	/* previous blob in the chain */
159 	int	tc_ref_count;			/* number of routines */
160 	void	*tc_data;			/* the data blob */
161 } tlm_chain_link_t;
162 
163 typedef struct	tlm_robot {
164 	struct tlm_robot	*tr_next;
165 	struct tlm_library	*tr_library;
166 	int	tr_number;
167 } tlm_robot_t;
168 
169 typedef struct	tlm_drive {
170 	struct tlm_drive	*td_next;
171 	struct tlm_library	*td_library;
172 	char	td_job_name[TLM_MAX_BACKUP_JOB_NAME];
173 	int	td_number;		/* number of this tape drive */
174 	int	td_element;		/* the library's number for the drive */
175 	struct	scsi_link *td_slink;	/* because the drive may be connected */
176 					/* to a different SCSI card than the */
177 					/* library */
178 	short	td_scsi_id;
179 	short	td_lun;
180 	short	td_volume_number;	/* for current job */
181 					/*  an index into the tape set */
182 	int	td_fd;			/* I/O file descriptor */
183 	int	td_errno;		/* system error number */
184 	long	td_exists	: 1;
185 
186 } tlm_drive_t;
187 
188 typedef struct	tlm_slot {
189 	struct tlm_slot		*ts_next;
190 	struct tlm_library	*ts_library;
191 	int	ts_number;		/* number of this slot */
192 	int	ts_element;
193 	short	ts_use_count;		/* number of times used since loaded */
194 	long	ts_status_full		: 1;
195 } tlm_slot_t;
196 
197 typedef struct	tlm_library {
198 	struct tlm_library	*tl_next;
199 	int	tl_number;		/* number of this tape library */
200 	long	tl_capability_robot	: 1,
201 		tl_capability_door	: 1,
202 		tl_capability_lock	: 1,
203 		tl_capability_slots	: 1,
204 		tl_capability_export	: 1,
205 		tl_capability_drives	: 1,
206 		tl_capability_barcodes	: 1,
207 		tl_ghost_drives		: 1;
208 		/*
209 		 * "ghost_drives" is used to make sure that
210 		 * all drives claimed by the library really
211 		 * exist ... libraries have been known to lie.
212 		 */
213 	struct	scsi_link *tl_slink;
214 
215 	int		tl_robot_count;
216 	tlm_robot_t	*tl_robot;
217 	int		tl_drive_count;
218 	tlm_drive_t	*tl_drive;
219 	int		tl_slot_count;
220 	tlm_slot_t	*tl_slot;
221 } tlm_library_t;
222 
223 typedef struct {
224 #ifdef _BIG_ENDIAN
225 	uint8_t	di_peripheral_qual	: 3,
226 		di_peripheral_dev_type	: 5;
227 	uint8_t	di_page_code;
228 	uint16_t	di_page_length;
229 #else
230 	uint8_t	di_peripheral_dev_type	: 5,
231 		di_peripheral_qual	: 3;
232 	uint8_t	di_page_code;
233 	uint16_t	di_page_length;
234 #endif
235 } device_ident_header_t;
236 
237 typedef struct {
238 #ifdef _BIG_ENDIAN
239 	uint8_t	ni_proto_ident	: 4,
240 		ni_code_set	: 4;
241 
242 	uint8_t	ni_PIV		: 1,
243 				: 1,
244 		ni_asso		: 2,
245 		ni_ident_type	: 4;
246 
247 	uint8_t	ni_reserved;
248 	uint8_t	ni_ident_length;
249 #else
250 	uint8_t	ni_code_set	: 4,
251 		ni_proto_ident	: 4;
252 
253 	uint8_t	ni_ident_type	: 4,
254 		ni_asso		: 2,
255 				: 1,
256 		ni_PIV		: 1;
257 	uint8_t	ni_reserved;
258 	uint8_t	ni_ident_length;
259 #endif
260 } name_ident_t;
261 
262 #define	TLM_NO_ERRORS			0x00000000
263 #define	TLM_ERROR_BUSY			0x00000001
264 #define	TLM_ERROR_INTERNAL		0x00000002
265 #define	TLM_ERROR_NO_ROBOTS		0x00000003
266 #define	TLM_TIMEOUT			0x00000004
267 #define	TLM_ERROR_RANGE			0x00000005
268 #define	TLM_EMPTY			0x00000006
269 #define	TLM_DRIVE_NOT_ASSIGNED		0x00000007
270 #define	TLM_NO_TAPE_NAME		0x00000008
271 #define	TLM_NO_BACKUP_DIR		0x00000009
272 #define	TLM_NO_BACKUP_HARDWARE		0x0000000a
273 #define	TLM_NO_SOURCE_FILE		0x0000000b
274 #define	TLM_NO_FREE_TAPES		0x0000000c
275 #define	TLM_EOT				0x0000000d
276 #define	TLM_SERIAL_NOT_FOUND		0x0000000e
277 #define	TLM_SMALL_READ			0x0000000f
278 #define	TLM_NO_RESTORE_FILE		0x00000010
279 #define	TLM_EOF				0x00000011
280 #define	TLM_NO_DIRECTORY		0x00000012
281 #define	TLM_NO_MEMORY			0x00000013
282 #define	TLM_WRITE_ERROR			0x00000014
283 #define	TLM_NO_SCRATCH_SPACE		0x00000015
284 #define	TLM_INVALID			0x00000016
285 #define	TLM_MOVE			0x00000017
286 #define	TLM_SKIP			0x00000018
287 #define	TLM_OPEN_ERR			0x00000019
288 
289 
290 #define	TLM_MAX_TAPE_DRIVES	16
291 #define	TLM_NAME_SIZE		100
292 #define	TLM_MAX_TAR_IMAGE	017777777770
293 
294 #define	TLM_VOLNAME_MAX_LENGTH	255
295 #define	NAME_MAX		255
296 
297 #define	TLM_MAGIC		"ustar  "
298 #define	TLM_SNAPSHOT_PREFIX	".zfs"
299 #define	TLM_SNAPSHOT_DIR	".zfs/snapshot"
300 
301 #define	RECORDSIZE	512
302 #define	NAMSIZ	100
303 
304 typedef struct	tlm_tar_hdr {
305 	char	th_name[TLM_NAME_SIZE];
306 	char	th_mode[8];
307 	char	th_uid[8];
308 	char	th_gid[8];
309 	char	th_size[12];
310 	char	th_mtime[12];
311 	char	th_chksum[8];
312 	char	th_linkflag;
313 	char	th_linkname[TLM_NAME_SIZE];
314 	char	th_magic[8];
315 	char	th_uname[32];
316 	char	th_gname[32];
317 	union {
318 		struct {
319 			char	th_devmajor[8];
320 			char	th_devminor[8];
321 		} th_dev;
322 		char	th_hlink_ino[12];
323 	} th_shared;
324 } tlm_tar_hdr_t;
325 
326 
327 
328 /*
329  * The linkflag defines the type of file
330  */
331 #define	LF_OLDNORMAL	'\0'		/* Normal disk file, Unix compat */
332 #define	LF_NORMAL	'0'		/* Normal disk file */
333 #define	LF_LINK		'1'		/* Link to previously dumped file */
334 #define	LF_SYMLINK	'2'		/* Symbolic link */
335 #define	LF_CHR		'3'		/* Character special file */
336 #define	LF_BLK		'4'		/* Block special file */
337 #define	LF_DIR		'5'		/* Directory */
338 #define	LF_FIFO		'6'		/* FIFO special file */
339 #define	LF_CONTIG	'7'		/* Contiguous file */
340 /* Further link types may be defined later. */
341 
342 #define	LF_DUMPDIR	'D'
343 					/*
344 					 * This is a dir entry that contains
345 					 * the names of files that were in
346 					 * the dir at the time the dump
347 					 * was made
348 					 */
349 #define	LF_HUMONGUS	'H'
350 					/*
351 					 * Identifies the NEXT file on the tape
352 					 * as a HUGE file
353 					 */
354 #define	LF_LONGLINK	'K'
355 					/*
356 					 * Identifies the NEXT file on the tape
357 					 * as having a long linkname
358 					 */
359 #define	LF_LONGNAME	'L'
360 					/*
361 					 * Identifies the NEXT file on the tape
362 					 * as having a long name.
363 					 */
364 #define	LF_MULTIVOL	'M'
365 					/*
366 					 * This is the continuation
367 					 * of a file that began on another
368 					 * volume
369 					 */
370 
371 #define	LF_VOLHDR	'V'		/* This file is a tape/volume header */
372 					/* Ignore it on extraction */
373 
374 #define	LF_ACL		'A'		/* Access Control List */
375 
376 #define	LF_XATTR	'E'		/* Extended attribute */
377 
378 #define	KILOBYTE	1024
379 
380 
381 /*
382  * ACL support structure
383  */
384 typedef struct sec_attr {
385 	char attr_type;
386 	char attr_len[7];
387 	char attr_info[TLM_MAX_ACL_TXT];
388 } sec_attr_t;
389 
390 typedef struct	tlm_acls {
391 	int	acl_checkpointed	: 1,	/* are checkpoints active ? */
392 		acl_clear_archive	: 1,	/* clear archive bit ? */
393 		acl_overwrite		: 1,	/* always overwrite ? */
394 		acl_update		: 1,	/* only update ? */
395 		acl_non_trivial		: 1;	/* real ACLs? */
396 		/*
397 		 * The following fields are here to allow
398 		 * the backup reader to open a file one time
399 		 * and keep the information for ACL, ATTRs,
400 		 * and reading the file.
401 		 */
402 	sec_attr_t acl_info;
403 
404 	char acl_root_dir[TLM_VOLNAME_MAX_LENGTH]; /* name of root filesystem */
405 	fs_fhandle_t acl_dir_fh;		/* parent dir's info */
406 	fs_fhandle_t acl_fil_fh;		/* file's info */
407 	struct stat64 acl_attr;			/* file system attributes */
408 	char uname[32];
409 	char gname[32];
410 } tlm_acls_t;
411 
412 
413 /*
414  * Tape manager's data archiving ops vector
415  *
416  * This vector represents the granular operations for
417  * performing backup/restore. Each backend should provide
418  * such a vector interface in order to be invoked by NDMP
419  * server.
420  * The reserved callbacks are kept for different backup
421  * types which are volume-based rather than file-based
422  * e.g. zfs send.
423  */
424 typedef struct tm_ops {
425 	char *tm_name;
426 	int (*tm_putfile)();
427 	int (*tm_putdir)();
428 	int (*tm_putvol)();	/* Reserved */
429 	int (*tm_getfile)();
430 	int (*tm_getdir)();
431 	int (*tm_getvol)();	/* Reserved */
432 } tm_ops_t;
433 
434 /* The checksum field is filled with this while the checksum is computed. */
435 #define	CHKBLANKS	"        "	/* 8 blanks, no null */
436 
437 #define	LONGNAME_PREFIX	"././_LoNg_NaMe_"
438 extern void ndmp_log(ulong_t, char *, char *, ...);
439 char ndmp_log_info[256];
440 #define	NDMP_LOG(p, ...) { \
441 				(void) snprintf(ndmp_log_info, \
442 				    sizeof (ndmp_log_info), \
443 				    "[%d][%s:%d]", \
444 				    (int)pthread_self(), __func__, __LINE__); \
445 				ndmp_log(p, ndmp_log_info, __VA_ARGS__); \
446 			}
447 extern void *ndmp_malloc(size_t size);
448 
449 /*
450  * ZFS metadata plug-in module structures
451  */
452 #define	ZFS_MAX_PROPS		100
453 #define	ZFS_META_MAGIC		"ZFSMETA"
454 #define	ZFS_META_MAGIC_EXT	"ZFSMETA2"
455 
456 /* Add new major/minor for header changes */
457 typedef enum {
458 	META_HDR_MAJOR_0,	/* Original format */
459 	META_HDR_MAJOR_1,	/* Extended format */
460 } ndmp_metadata_header_major_t;
461 
462 #define	META_HDR_MAJOR_VERSION	META_HDR_MAJOR_1
463 
464 typedef enum {
465 	META_HDR_MINOR_0,
466 } ndmp_metadata_header_minor_t;
467 
468 #define	META_HDR_MINOR_VERSION	META_HDR_MINOR_0
469 
470 /* To support older backups */
471 typedef struct ndmp_metadata_property {
472 	char mp_name[NAME_MAX];
473 	char mp_value[NAME_MAX];
474 	char mp_source[NAME_MAX];
475 } ndmp_metadata_property_t;
476 
477 typedef struct ndmp_metadata_property_ext {
478 	char mp_name[ZFS_MAXNAMELEN];
479 	char mp_value[ZFS_MAXPROPLEN];
480 	char mp_source[ZFS_MAXPROPLEN];
481 } ndmp_metadata_property_ext_t;
482 
483 typedef struct ndmp_metadata_top_header {
484 	char th_plname[100];
485 	uint_t th_plversion;
486 	char th_magic[10];
487 	void *th_reserved_1;
488 	int th_count;
489 } ndmp_metadata_top_header_t;
490 
491 /* Original metadata format */
492 typedef struct ndmp_metadata_header {
493 	ndmp_metadata_top_header_t nh_hdr;
494 	char nh_dataset[NAME_MAX];
495 	ndmp_metadata_property_t nh_property[1];
496 } ndmp_metadata_header_t;
497 
498 /* Extended metadata format */
499 typedef struct ndmp_metadata_header_ext {
500 	ndmp_metadata_top_header_t nh_hdr;
501 	char nh_dataset[ZFS_MAXNAMELEN];
502 	int32_t nh_total_bytes;
503 	int32_t nh_major;
504 	int32_t nh_minor;
505 	ndmp_metadata_property_ext_t nh_property[1];
506 } ndmp_metadata_header_ext_t;
507 
508 #define	nh_plname	nh_hdr.th_plname
509 #define	nh_plversion	nh_hdr.th_plversion
510 #define	nh_magic	nh_hdr.th_magic
511 #define	nh_count	nh_hdr.th_count
512 
513 typedef struct ndmp_metadata_handle {
514 	void *ml_handle;
515 	int32_t ml_quota_prop;
516 	union {
517 		ndmp_metadata_header_t *u_hdr;
518 		ndmp_metadata_header_ext_t *u_xhdr;
519 	} ml_hdr_u;
520 } ndmp_metadata_handle_t;
521 
522 #define	ml_hdr	ml_hdr_u.u_hdr
523 #define	ml_xhdr	ml_hdr_u.u_xhdr
524 
525 /*
526  * Node in struct hardlink_q
527  *
528  * inode: the inode of the hardlink
529  * path: the name of the hardlink, used during restore
530  * offset: tape offset of the data records for the hardlink, used during backup
531  * is_tmp: indicate whether the file was created temporarily for restoring
532  * other links during a non-DAR partial restore
533  */
534 struct hardlink_node {
535 	unsigned long inode;
536 	char *path;
537 	unsigned long long offset;
538 	int is_tmp;
539 	SLIST_ENTRY(hardlink_node) next_hardlink;
540 };
541 
542 /*
543  * Hardlinks that have been backed up or restored.
544  *
545  * During backup, each node represents a file whose
546  *   (1) inode has multiple links
547  *   (2) data has been backed up
548  *
549  * When we run into a file with multiple links during backup,
550  * we first check the list to see whether a file with the same inode
551  * has been backed up.  If yes, we backup an empty record, while
552  * making the file history of this file contain the data offset
553  * of the offset of the file that has been backed up.  If no,
554  * we backup this file, and add an entry to the list.
555  *
556  * During restore, each node represents an LF_LINK type record whose
557  * data has been restored (v.s. a hard link has been created).
558  *
559  * During restore, when we run into a record of LF_LINK type, we
560  * first check the queue to see whether a file with the same inode
561  * has been restored.  If yes, we create a hardlink to it.
562  * If no, we restore the data, and add an entry to the list.
563  */
564 struct hardlink_q {
565 	struct hardlink_node *slh_first;
566 };
567 
568 /* Utility functions from handling hardlink */
569 extern struct hardlink_q *hardlink_q_init();
570 extern void hardlink_q_cleanup(struct hardlink_q *qhead);
571 extern int hardlink_q_get(struct hardlink_q *qhead, unsigned long inode,
572     unsigned long long *offset, char **path);
573 extern int hardlink_q_add(struct hardlink_q *qhead, unsigned long inode,
574     unsigned long long offset, char *path, int is_tmp);
575 
576 #endif	/* !_TLM_H_ */
577