/* * Copyright 2009 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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 { unsigned char d_name[8]; } device_info_t; typedef struct { unsigned char p_number[4]; } port_info_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; typedef struct { device_ident_header_t np_header; name_ident_t np_node; device_info_t np_node_info; name_ident_t np_port; device_info_t np_port_info; name_ident_t np_portno; port_info_t np_portid; } device_name_page_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 */ 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" #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_MAXNAMELEN]; 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_MAXNAMELEN]; 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_ */