tlm.h revision 2654012f83cec5dc15b61dfe3e4a4915f186e7a6
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* 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>
#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 SCMD_READ_ELEMENT_STATUS 0xB8
typedef int (*func_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];
} 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;
#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
#define TUNMLEN 32
#define TGNMLEN 32
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[TUNMLEN];
char th_gname[TGNMLEN];
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 */
} 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 */
int (*tm_getfile)();
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 *, ...);
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"
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_header {
char nh_plname[100];
uint_t nh_plversion;
char nh_magic[10];
void *nh_handle;
int nh_count;
char nh_dataset[NAME_MAX];
ndmp_metadata_property_t nh_property[1];
} ndmp_metadata_header_t;
/*
* 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_ */