summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ndmpd/include/tlm.h
blob: e5e045d89a1fd7df305a92ad42328b6c66743579 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
/*
 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2015 by Delphix. All rights reserved.
 */

/*
 * BSD 3 Clause License
 *
 * Copyright (c) 2007, The Storage Networking Industry Association.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *	- Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 *
 *	- Redistributions in binary form must reproduce the above copyright
 *	  notice, this list of conditions and the following disclaimer in
 *	  the documentation and/or other materials provided with the
 *	  distribution.
 *
 *	- Neither the name of The Storage Networking Industry Association (SNIA)
 *	  nor the names of its contributors may be used to endorse or promote
 *	  products derived from this software without specific prior written
 *	  permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef	_TLM_H_
#define	_TLM_H_

#include <sys/types.h>
#include <synch.h>
#include <limits.h>
#include <cstack.h>
#include <sys/acl.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <strings.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/queue.h>
#include <sys/fs/zfs.h>
#include <libzfs.h>

#define	IS_SET(f, m)	(((f) & (m)) != 0)

#define	TLM_MAX_BACKUP_JOB_NAME	32	/* max size of a job's name */
#define	TLM_TAPE_BUFFERS	10	/* number of rotating tape buffers */
#define	TLM_LINE_SIZE		128	/* size of text messages */


#define	TLM_BACKUP_RUN		0x00000001
#define	TLM_RESTORE_RUN		0x00000002
#define	TLM_STOP		0x00000009	/* graceful stop */
#define	TLM_ABORT		0x99999999	/* abandon the run */

#define	TLM_EXTRA_SPACE		64
#define	TLM_MAX_PATH_NAME	(PATH_MAX + TLM_EXTRA_SPACE)

#define	ENTRYTYPELEN	14
#define	PERMS		4
#define	ID_STR_MAX	20
#define	APPENDED_ID_MAX	(ID_STR_MAX + 1)
#define	ACL_ENTRY_SIZE	(ENTRYTYPELEN + ID_STR_MAX + PERMS + APPENDED_ID_MAX)
#define	TLM_MAX_ACL_TXT	MAX_ACL_ENTRIES * ACL_ENTRY_SIZE


/* operation flags */
#define	TLM_OP_CHOOSE_ARCHIVE	0x00000001	/* look for archive bit */

/*
 * Synchronization flags used when launching the TLM threads.
 */
#define	TLM_TAPE_READER		0x00000001
#define	TLM_TAPE_WRITER		0x00000002
#define	TLM_SOCK_READER		0x00000004
#define	TLM_SOCK_WRITER		0x00000008
#define	TLM_BUF_READER		0x00000010
#define	TLM_BUF_WRITER		0x00000020
#define	TLM_TAR_READER		0x00000040
#define	TLM_TAR_WRITER		0x00000080

#define	SCSI_SERIAL_PAGE	0x80
#define	SCSI_DEVICE_IDENT_PAGE	0x83
#define	SCMD_READ_ELEMENT_STATUS	0xB8

#define	OCTAL7CHAR	07777777
#define	SYSATTR_RDONLY	"SUNWattr_ro"
#define	SYSATTR_RW	"SUNWattr_rw"

typedef	int (*func_t)();

typedef struct scsi_serial {
	int sr_flags;
	char sr_num[16];
} scsi_serial_t;

typedef struct fs_fhandle {
	int fh_fid;
	char *fh_fpath;
} fs_fhandle_t;

typedef struct scsi_link {
	struct scsi_link	*sl_next;
	struct scsi_link	*sl_prev;
	struct scsi_adapter	*sl_sa;
	unsigned int		sl_sid;
	unsigned int		sl_lun;
	unsigned int		sl_requested_max_active;
	unsigned int		sl_granted_max_active;
	unsigned int		sl_n_active;
	unsigned int		sl_type; /* SCSI device type */
} scsi_link_t;

typedef struct scsi_adapter {
	struct scsi_adapter	*sa_next;
	char			sa_name[16];
	struct scsi_link	sa_link_head;
} scsi_adapter_t;

typedef struct sasd_drive {
	char		sd_name[256];
	char		sd_vendor[8 + 1];
	char		sd_id[16 + 1];
	char		sd_rev[4 + 1];
	char		sd_serial[16 + 1];
	char		sd_wwn[32 + 1];
} sasd_drive_t;

typedef struct scsi_sasd_drive {
	sasd_drive_t	ss_sd;
	scsi_link_t	ss_slink;
} scsi_sasd_drive_t;


#define	DEFAULT_SLINK_MAX_XFER	(64*1024)

typedef struct	tlm_info {
	int			ti_init_done;	/* initialization done ? */
	int			ti_library_count; /* number of libraries */
	struct tlm_library	*ti_library;	/* first in chain */
	struct tlm_chain_link	*ti_job_stats;  /* chain of job statistics */
} tlm_info_t;

typedef struct	tlm_chain_link {
	struct tlm_chain_link	*tc_next;	/* next blob of statistics */
	struct tlm_chain_link	*tc_prev;	/* previous blob in the chain */
	int	tc_ref_count;			/* number of routines */
	void	*tc_data;			/* the data blob */
} tlm_chain_link_t;

typedef struct	tlm_robot {
	struct tlm_robot	*tr_next;
	struct tlm_library	*tr_library;
	int	tr_number;
} tlm_robot_t;

typedef struct	tlm_drive {
	struct tlm_drive	*td_next;
	struct tlm_library	*td_library;
	char	td_job_name[TLM_MAX_BACKUP_JOB_NAME];
	int	td_number;		/* number of this tape drive */
	int	td_element;		/* the library's number for the drive */
	struct	scsi_link *td_slink;	/* because the drive may be connected */
					/* to a different SCSI card than the */
					/* library */
	short	td_scsi_id;
	short	td_lun;
	short	td_volume_number;	/* for current job */
					/*  an index into the tape set */
	int	td_fd;			/* I/O file descriptor */
	int	td_errno;		/* system error number */
	long	td_exists	: 1;

} tlm_drive_t;

typedef struct	tlm_slot {
	struct tlm_slot		*ts_next;
	struct tlm_library	*ts_library;
	int	ts_number;		/* number of this slot */
	int	ts_element;
	short	ts_use_count;		/* number of times used since loaded */
	long	ts_status_full		: 1;
} tlm_slot_t;

typedef struct	tlm_library {
	struct tlm_library	*tl_next;
	int	tl_number;		/* number of this tape library */
	long	tl_capability_robot	: 1,
		tl_capability_door	: 1,
		tl_capability_lock	: 1,
		tl_capability_slots	: 1,
		tl_capability_export	: 1,
		tl_capability_drives	: 1,
		tl_capability_barcodes	: 1,
		tl_ghost_drives		: 1;
		/*
		 * "ghost_drives" is used to make sure that
		 * all drives claimed by the library really
		 * exist ... libraries have been known to lie.
		 */
	struct	scsi_link *tl_slink;

	int		tl_robot_count;
	tlm_robot_t	*tl_robot;
	int		tl_drive_count;
	tlm_drive_t	*tl_drive;
	int		tl_slot_count;
	tlm_slot_t	*tl_slot;
} tlm_library_t;

typedef struct {
#ifdef _BIG_ENDIAN
	uint8_t	di_peripheral_qual	: 3,
		di_peripheral_dev_type	: 5;
	uint8_t	di_page_code;
	uint16_t	di_page_length;
#else
	uint8_t	di_peripheral_dev_type	: 5,
		di_peripheral_qual	: 3;
	uint8_t	di_page_code;
	uint16_t	di_page_length;
#endif
} device_ident_header_t;

typedef struct {
#ifdef _BIG_ENDIAN
	uint8_t	ni_proto_ident	: 4,
		ni_code_set	: 4;

	uint8_t	ni_PIV		: 1,
				: 1,
		ni_asso		: 2,
		ni_ident_type	: 4;

	uint8_t	ni_reserved;
	uint8_t	ni_ident_length;
#else
	uint8_t	ni_code_set	: 4,
		ni_proto_ident	: 4;

	uint8_t	ni_ident_type	: 4,
		ni_asso		: 2,
				: 1,
		ni_PIV		: 1;
	uint8_t	ni_reserved;
	uint8_t	ni_ident_length;
#endif
} name_ident_t;

#define	TLM_NO_ERRORS			0x00000000
#define	TLM_ERROR_BUSY			0x00000001
#define	TLM_ERROR_INTERNAL		0x00000002
#define	TLM_ERROR_NO_ROBOTS		0x00000003
#define	TLM_TIMEOUT			0x00000004
#define	TLM_ERROR_RANGE			0x00000005
#define	TLM_EMPTY			0x00000006
#define	TLM_DRIVE_NOT_ASSIGNED		0x00000007
#define	TLM_NO_TAPE_NAME		0x00000008
#define	TLM_NO_BACKUP_DIR		0x00000009
#define	TLM_NO_BACKUP_HARDWARE		0x0000000a
#define	TLM_NO_SOURCE_FILE		0x0000000b
#define	TLM_NO_FREE_TAPES		0x0000000c
#define	TLM_EOT				0x0000000d
#define	TLM_SERIAL_NOT_FOUND		0x0000000e
#define	TLM_SMALL_READ			0x0000000f
#define	TLM_NO_RESTORE_FILE		0x00000010
#define	TLM_EOF				0x00000011
#define	TLM_NO_DIRECTORY		0x00000012
#define	TLM_NO_MEMORY			0x00000013
#define	TLM_WRITE_ERROR			0x00000014
#define	TLM_NO_SCRATCH_SPACE		0x00000015
#define	TLM_INVALID			0x00000016
#define	TLM_MOVE			0x00000017
#define	TLM_SKIP			0x00000018
#define	TLM_OPEN_ERR			0x00000019


#define	TLM_MAX_TAPE_DRIVES	16
#define	TLM_NAME_SIZE		100
#define	TLM_MAX_TAR_IMAGE	017777777770

#define	TLM_VOLNAME_MAX_LENGTH	255
#define	NAME_MAX		255

#define	TLM_MAGIC		"ustar  "
#define	TLM_SNAPSHOT_PREFIX	".zfs"
#define	TLM_SNAPSHOT_DIR	".zfs/snapshot"

#define	RECORDSIZE	512
#define	NAMSIZ	100

typedef struct	tlm_tar_hdr {
	char	th_name[TLM_NAME_SIZE];
	char	th_mode[8];
	char	th_uid[8];
	char	th_gid[8];
	char	th_size[12];
	char	th_mtime[12];
	char	th_chksum[8];
	char	th_linkflag;
	char	th_linkname[TLM_NAME_SIZE];
	char	th_magic[8];
	char	th_uname[32];
	char	th_gname[32];
	union {
		struct {
			char	th_devmajor[8];
			char	th_devminor[8];
		} th_dev;
		char	th_hlink_ino[12];
	} th_shared;
} tlm_tar_hdr_t;



/*
 * The linkflag defines the type of file
 */
#define	LF_OLDNORMAL	'\0'		/* Normal disk file, Unix compat */
#define	LF_NORMAL	'0'		/* Normal disk file */
#define	LF_LINK		'1'		/* Link to previously dumped file */
#define	LF_SYMLINK	'2'		/* Symbolic link */
#define	LF_CHR		'3'		/* Character special file */
#define	LF_BLK		'4'		/* Block special file */
#define	LF_DIR		'5'		/* Directory */
#define	LF_FIFO		'6'		/* FIFO special file */
#define	LF_CONTIG	'7'		/* Contiguous file */
/* Further link types may be defined later. */

#define	LF_DUMPDIR	'D'
					/*
					 * This is a dir entry that contains
					 * the names of files that were in
					 * the dir at the time the dump
					 * was made
					 */
#define	LF_HUMONGUS	'H'
					/*
					 * Identifies the NEXT file on the tape
					 * as a HUGE file
					 */
#define	LF_LONGLINK	'K'
					/*
					 * Identifies the NEXT file on the tape
					 * as having a long linkname
					 */
#define	LF_LONGNAME	'L'
					/*
					 * Identifies the NEXT file on the tape
					 * as having a long name.
					 */
#define	LF_MULTIVOL	'M'
					/*
					 * This is the continuation
					 * of a file that began on another
					 * volume
					 */

#define	LF_VOLHDR	'V'		/* This file is a tape/volume header */
					/* Ignore it on extraction */

#define	LF_ACL		'A'		/* Access Control List */

#define	LF_XATTR	'E'		/* Extended attribute */

#define	KILOBYTE	1024


/*
 * ACL support structure
 */
typedef struct sec_attr {
	char attr_type;
	char attr_len[7];
	char attr_info[TLM_MAX_ACL_TXT];
} sec_attr_t;

typedef struct	tlm_acls {
	int	acl_checkpointed	: 1,	/* are checkpoints active ? */
		acl_clear_archive	: 1,	/* clear archive bit ? */
		acl_overwrite		: 1,	/* always overwrite ? */
		acl_update		: 1,	/* only update ? */
		acl_non_trivial		: 1;	/* real ACLs? */
		/*
		 * The following fields are here to allow
		 * the backup reader to open a file one time
		 * and keep the information for ACL, ATTRs,
		 * and reading the file.
		 */
	sec_attr_t acl_info;

	char acl_root_dir[TLM_VOLNAME_MAX_LENGTH]; /* name of root filesystem */
	fs_fhandle_t acl_dir_fh;		/* parent dir's info */
	fs_fhandle_t acl_fil_fh;		/* file's info */
	struct stat64 acl_attr;			/* file system attributes */
	char uname[32];
	char gname[32];
} tlm_acls_t;


/*
 * Tape manager's data archiving ops vector
 *
 * This vector represents the granular operations for
 * performing backup/restore. Each backend should provide
 * such a vector interface in order to be invoked by NDMP
 * server.
 * The reserved callbacks are kept for different backup
 * types which are volume-based rather than file-based
 * e.g. zfs send.
 */
typedef struct tm_ops {
	char *tm_name;
	int (*tm_putfile)();
	int (*tm_putdir)();
	int (*tm_putvol)();	/* Reserved */
	void * (*tm_getfile)(void *);
	int (*tm_getdir)();
	int (*tm_getvol)();	/* Reserved */
} tm_ops_t;

/* The checksum field is filled with this while the checksum is computed. */
#define	CHKBLANKS	"        "	/* 8 blanks, no null */

#define	LONGNAME_PREFIX	"././_LoNg_NaMe_"
extern void ndmp_log(ulong_t, char *, char *, ...);
extern char ndmp_log_info[256];
#define	NDMP_LOG(p, ...) { \
				(void) snprintf(ndmp_log_info, \
				    sizeof (ndmp_log_info), \
				    "[%d][%s:%d]", \
				    (int)pthread_self(), __func__, __LINE__); \
				ndmp_log(p, ndmp_log_info, __VA_ARGS__); \
			}
extern void *ndmp_malloc(size_t size);

/*
 * ZFS metadata plug-in module structures
 */
#define	ZFS_MAX_PROPS		100
#define	ZFS_META_MAGIC		"ZFSMETA"
#define	ZFS_META_MAGIC_EXT	"ZFSMETA2"

/* Add new major/minor for header changes */
typedef enum {
	META_HDR_MAJOR_0,	/* Original format */
	META_HDR_MAJOR_1,	/* Extended format */
} ndmp_metadata_header_major_t;

#define	META_HDR_MAJOR_VERSION	META_HDR_MAJOR_1

typedef enum {
	META_HDR_MINOR_0,
} ndmp_metadata_header_minor_t;

#define	META_HDR_MINOR_VERSION	META_HDR_MINOR_0

/* To support older backups */
typedef struct ndmp_metadata_property {
	char mp_name[NAME_MAX];
	char mp_value[NAME_MAX];
	char mp_source[NAME_MAX];
} ndmp_metadata_property_t;

typedef struct ndmp_metadata_property_ext {
	char mp_name[ZFS_MAX_DATASET_NAME_LEN];
	char mp_value[ZFS_MAXPROPLEN];
	char mp_source[ZFS_MAXPROPLEN];
} ndmp_metadata_property_ext_t;

typedef struct ndmp_metadata_top_header {
	char th_plname[100];
	uint_t th_plversion;
	char th_magic[10];
	void *th_reserved_1;
	int th_count;
} ndmp_metadata_top_header_t;

/* Original metadata format */
typedef struct ndmp_metadata_header {
	ndmp_metadata_top_header_t nh_hdr;
	char nh_dataset[NAME_MAX];
	ndmp_metadata_property_t nh_property[1];
} ndmp_metadata_header_t;

/* Extended metadata format */
typedef struct ndmp_metadata_header_ext {
	ndmp_metadata_top_header_t nh_hdr;
	char nh_dataset[ZFS_MAX_DATASET_NAME_LEN];
	int32_t nh_total_bytes;
	int32_t nh_major;
	int32_t nh_minor;
	ndmp_metadata_property_ext_t nh_property[1];
} ndmp_metadata_header_ext_t;

#define	nh_plname	nh_hdr.th_plname
#define	nh_plversion	nh_hdr.th_plversion
#define	nh_magic	nh_hdr.th_magic
#define	nh_count	nh_hdr.th_count

typedef struct ndmp_metadata_handle {
	void *ml_handle;
	int32_t ml_quota_prop;
	union {
		ndmp_metadata_header_t *u_hdr;
		ndmp_metadata_header_ext_t *u_xhdr;
	} ml_hdr_u;
} ndmp_metadata_handle_t;

#define	ml_hdr	ml_hdr_u.u_hdr
#define	ml_xhdr	ml_hdr_u.u_xhdr

/*
 * Node in struct hardlink_q
 *
 * inode: the inode of the hardlink
 * path: the name of the hardlink, used during restore
 * offset: tape offset of the data records for the hardlink, used during backup
 * is_tmp: indicate whether the file was created temporarily for restoring
 * other links during a non-DAR partial restore
 */
struct hardlink_node {
	unsigned long inode;
	char *path;
	unsigned long long offset;
	int is_tmp;
	SLIST_ENTRY(hardlink_node) next_hardlink;
};

/*
 * Hardlinks that have been backed up or restored.
 *
 * During backup, each node represents a file whose
 *   (1) inode has multiple links
 *   (2) data has been backed up
 *
 * When we run into a file with multiple links during backup,
 * we first check the list to see whether a file with the same inode
 * has been backed up.  If yes, we backup an empty record, while
 * making the file history of this file contain the data offset
 * of the offset of the file that has been backed up.  If no,
 * we backup this file, and add an entry to the list.
 *
 * During restore, each node represents an LF_LINK type record whose
 * data has been restored (v.s. a hard link has been created).
 *
 * During restore, when we run into a record of LF_LINK type, we
 * first check the queue to see whether a file with the same inode
 * has been restored.  If yes, we create a hardlink to it.
 * If no, we restore the data, and add an entry to the list.
 */
struct hardlink_q {
	struct hardlink_node *slh_first;
};

/* Utility functions from handling hardlink */
extern struct hardlink_q *hardlink_q_init();
extern void hardlink_q_cleanup(struct hardlink_q *qhead);
extern int hardlink_q_get(struct hardlink_q *qhead, unsigned long inode,
    unsigned long long *offset, char **path);
extern int hardlink_q_add(struct hardlink_q *qhead, unsigned long inode,
    unsigned long long offset, char *path, int is_tmp);

#endif	/* !_TLM_H_ */