2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2015 by Delphix. All rights reserved.
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
48 #include <sys/fs/zfs.h>
49 #include <sys/mkdev.h>
51 #include <libcmdutils.h>
54 #include "tlm_proto.h"
57 static char *get_write_buffer(long size
,
61 static int output_acl_header(sec_attr_t
*,
63 static int output_file_header(char *name
,
68 static int output_xattr_header(char *fname
,
75 extern libzfs_handle_t
*zlibh
;
76 extern mutex_t zlib_mtx
;
78 #define S_ISPECIAL(a) (S_ISLNK(a) || S_ISFIFO(a) || S_ISBLK(a) || \
84 * Gets a IO write buffer and copies memory to the that.
87 output_mem(tlm_cmd_t
*local_commands
, char *mem
,
90 long actual_size
, rec_size
;
94 rec
= get_write_buffer(len
, &actual_size
,
95 FALSE
, local_commands
);
96 rec_size
= min(actual_size
, len
);
97 (void) memcpy(rec
, mem
, rec_size
);
106 * Put the directory information into the output buffers.
109 tlm_output_dir(char *name
, tlm_acls_t
*tlm_acls
,
110 tlm_cmd_t
*local_commands
, tlm_job_stats_t
*job_stats
)
115 * Send the node or path history of the directory itself.
117 pos
= tlm_get_data_offset(local_commands
);
118 NDMP_LOG(LOG_DEBUG
, "pos: %10lld [%s]", pos
, name
);
119 (void) tlm_log_fhnode(job_stats
, name
, "", &tlm_acls
->acl_attr
, pos
);
120 (void) tlm_log_fhpath_name(job_stats
, name
, &tlm_acls
->acl_attr
, pos
);
121 /* fhdir_cb is handled in ndmpd_tar3.c */
123 (void) output_acl_header(&tlm_acls
->acl_info
,
125 (void) output_file_header(name
, "", tlm_acls
, 0,
134 * Main dir backup function for tar
137 tar_putdir(char *name
, tlm_acls_t
*tlm_acls
,
138 tlm_cmd_t
*local_commands
, tlm_job_stats_t
*job_stats
)
142 rv
= tlm_output_dir(name
, tlm_acls
, local_commands
, job_stats
);
143 return (rv
< 0 ? rv
: 0);
149 * output the ACL header record and data
152 output_acl_header(sec_attr_t
*acl_info
,
153 tlm_cmd_t
*local_commands
)
156 tlm_tar_hdr_t
*tar_hdr
;
159 if ((acl_info
== NULL
) || (*acl_info
->attr_info
== '\0'))
162 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
163 &actual_size
, TRUE
, local_commands
);
167 tar_hdr
->th_linkflag
= LF_ACL
;
168 acl_info
->attr_type
= UFSD_ACL
;
169 (void) snprintf(acl_info
->attr_len
, sizeof (acl_info
->attr_len
),
170 "%06o", strlen(acl_info
->attr_info
));
172 acl_size
= sizeof (*acl_info
);
173 (void) strlcpy(tar_hdr
->th_name
, "UFSACL", TLM_NAME_SIZE
);
174 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
), "%011o ",
176 (void) snprintf(tar_hdr
->th_mode
, sizeof (tar_hdr
->th_mode
), "%06o ",
178 (void) snprintf(tar_hdr
->th_uid
, sizeof (tar_hdr
->th_uid
), "%06o ", 0);
179 (void) snprintf(tar_hdr
->th_gid
, sizeof (tar_hdr
->th_gid
), "%06o ", 0);
180 (void) snprintf(tar_hdr
->th_mtime
, sizeof (tar_hdr
->th_mtime
),
182 (void) strlcpy(tar_hdr
->th_magic
, TLM_MAGIC
,
183 sizeof (tar_hdr
->th_magic
));
185 tlm_build_header_checksum(tar_hdr
);
187 (void) output_mem(local_commands
, (void *)acl_info
, acl_size
);
192 * output_humongus_header
194 * output a special header record for HUGE files
195 * output is: 1) a TAR "HUGE" header redord
196 * 2) a "file" of size, name
199 output_humongus_header(char *fullname
, longlong_t file_size
,
200 tlm_cmd_t
*local_commands
)
205 tlm_tar_hdr_t
*tar_hdr
;
208 * buf will contain: "%llu %s":
209 * - 20 is the maximum length of 'ulong_tlong' decimal notation.
210 * - The first '1' is for the ' ' between the "%llu" and the fullname.
211 * - The last '1' is for the null-terminator of fullname.
213 len
= 20 + 1 + strlen(fullname
) + 1;
215 if ((buf
= ndmp_malloc(sizeof (char) * len
)) == NULL
)
218 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
219 &actual_size
, TRUE
, local_commands
);
225 tar_hdr
->th_linkflag
= LF_HUMONGUS
;
226 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
), "%011o ",
228 tlm_build_header_checksum(tar_hdr
);
229 (void) snprintf(buf
, len
, "%lld %s", file_size
, fullname
);
230 (void) output_mem(local_commands
, buf
, len
);
238 * output_xattr_header
240 * output the TAR header record for extended attributes
243 output_xattr_header(char *fname
, char *aname
, int fd
,
244 tlm_acls_t
*tlm_acls
, int section
, tlm_cmd_t
*local_commands
)
246 struct stat64
*attr
= &tlm_acls
->acl_attr
;
247 struct xattr_hdr
*xhdr
;
248 struct xattr_buf
*xbuf
;
249 tlm_tar_hdr_t
*tar_hdr
;
251 char *section_name
= ndmp_malloc(TLM_MAX_PATH_NAME
);
256 if (section_name
== NULL
)
257 return (-TLM_NO_SCRATCH_SPACE
);
259 if (fstat64(fd
, attr
) == -1) {
260 NDMP_LOG(LOG_DEBUG
, "output_file_header stat failed.");
262 return (-TLM_OPEN_ERR
);
266 * if the file has to go out in sections,
267 * we must mung the name.
270 (void) snprintf(section_name
, TLM_MAX_PATH_NAME
,
271 "/dev/null/%s.hdr", aname
);
273 (void) snprintf(section_name
,
274 TLM_MAX_PATH_NAME
, "%s.%03d", aname
, section
);
276 namesz
= strlen(section_name
) + strlen(fname
) + 2; /* 2 nulls */
277 hsize
= namesz
+ sizeof (struct xattr_hdr
) + sizeof (struct xattr_buf
);
278 comlen
= namesz
+ sizeof (struct xattr_buf
);
280 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
281 &actual_size
, TRUE
, local_commands
);
287 (void) strlcpy(tar_hdr
->th_name
, section_name
, TLM_NAME_SIZE
);
289 tar_hdr
->th_linkflag
= LF_XATTR
;
290 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
), "%011o ",
292 (void) snprintf(tar_hdr
->th_mode
, sizeof (tar_hdr
->th_mode
), "%06o ",
293 attr
->st_mode
& 07777);
294 (void) snprintf(tar_hdr
->th_uid
, sizeof (tar_hdr
->th_uid
), "%06o ",
296 (void) snprintf(tar_hdr
->th_gid
, sizeof (tar_hdr
->th_gid
), "%06o ",
298 (void) snprintf(tar_hdr
->th_mtime
, sizeof (tar_hdr
->th_mtime
), "%011o ",
300 (void) strlcpy(tar_hdr
->th_magic
, TLM_MAGIC
,
301 sizeof (tar_hdr
->th_magic
));
303 NDMP_LOG(LOG_DEBUG
, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
304 aname
, hsize
, attr
->st_mode
& 07777, attr
->st_uid
, attr
->st_gid
);
306 tlm_build_header_checksum(tar_hdr
);
308 xhdr
= (struct xattr_hdr
*)get_write_buffer(RECORDSIZE
,
309 &actual_size
, TRUE
, local_commands
);
315 (void) snprintf(xhdr
->h_version
, sizeof (xhdr
->h_version
), "%s",
317 (void) snprintf(xhdr
->h_size
, sizeof (xhdr
->h_size
), "%0*d",
318 sizeof (xhdr
->h_size
) - 1, hsize
);
319 (void) snprintf(xhdr
->h_component_len
, sizeof (xhdr
->h_component_len
),
320 "%0*d", sizeof (xhdr
->h_component_len
) - 1, comlen
);
321 (void) snprintf(xhdr
->h_link_component_len
,
322 sizeof (xhdr
->h_link_component_len
), "%0*d",
323 sizeof (xhdr
->h_link_component_len
) - 1, 0);
325 xbuf
= (struct xattr_buf
*)(((caddr_t
)xhdr
) +
326 sizeof (struct xattr_hdr
));
327 (void) snprintf(xbuf
->h_namesz
, sizeof (xbuf
->h_namesz
), "%0*d",
328 sizeof (xbuf
->h_namesz
) - 1, namesz
);
330 /* No support for links in extended attributes */
331 xbuf
->h_typeflag
= LF_NORMAL
;
333 (void) strlcpy(xbuf
->h_names
, fname
, TLM_NAME_SIZE
);
334 (void) strlcpy(&xbuf
->h_names
[strlen(fname
) + 1], aname
,
345 * output the TAR header record
348 output_file_header(char *name
, char *link
,
349 tlm_acls_t
*tlm_acls
, int section
, tlm_cmd_t
*local_commands
)
351 static longlong_t file_count
= 0;
352 struct stat64
*attr
= &tlm_acls
->acl_attr
;
353 tlm_tar_hdr_t
*tar_hdr
;
355 boolean_t long_name
= FALSE
;
356 boolean_t long_link
= FALSE
;
357 char *section_name
= ndmp_malloc(TLM_MAX_PATH_NAME
);
366 if (section_name
== NULL
)
367 return (-TLM_NO_SCRATCH_SPACE
);
370 * if the file has to go out in sections,
371 * we must mung the name.
374 (void) strlcpy(section_name
, name
, TLM_MAX_PATH_NAME
);
376 (void) snprintf(section_name
,
377 TLM_MAX_PATH_NAME
, "%s.%03d", name
, section
);
380 if ((pwd
= getpwuid(attr
->st_uid
)) != NULL
)
381 uname
= pwd
->pw_name
;
382 if ((grp
= getgrgid(attr
->st_gid
)) != NULL
)
383 gname
= grp
->gr_name
;
385 if ((ulong_t
)(uid
= attr
->st_uid
) > (ulong_t
)OCTAL7CHAR
)
387 if ((ulong_t
)(gid
= attr
->st_gid
) > (ulong_t
)OCTAL7CHAR
)
390 nmlen
= strlen(section_name
);
391 if (nmlen
>= NAMSIZ
) {
393 * file name is too big, it must go out
394 * in its own data file
396 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
397 &actual_size
, TRUE
, local_commands
);
402 (void) snprintf(tar_hdr
->th_name
,
403 sizeof (tar_hdr
->th_name
),
408 tar_hdr
->th_linkflag
= LF_LONGNAME
;
409 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
),
411 (void) snprintf(tar_hdr
->th_mode
, sizeof (tar_hdr
->th_mode
),
412 "%06o ", attr
->st_mode
& 07777);
413 (void) snprintf(tar_hdr
->th_uid
, sizeof (tar_hdr
->th_uid
),
415 (void) snprintf(tar_hdr
->th_gid
, sizeof (tar_hdr
->th_gid
),
417 (void) snprintf(tar_hdr
->th_uname
, sizeof (tar_hdr
->th_uname
),
419 (void) snprintf(tar_hdr
->th_gname
, sizeof (tar_hdr
->th_gname
),
421 (void) snprintf(tar_hdr
->th_mtime
, sizeof (tar_hdr
->th_mtime
),
422 "%011o ", attr
->st_mtime
);
423 (void) strlcpy(tar_hdr
->th_magic
, TLM_MAGIC
,
424 sizeof (tar_hdr
->th_magic
));
426 tlm_build_header_checksum(tar_hdr
);
428 (void) output_mem(local_commands
,
429 (void *)section_name
, nmlen
);
433 lnklen
= strlen(link
);
434 if (lnklen
>= NAMSIZ
) {
436 * link name is too big, it must go out
437 * in its own data file
439 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
440 &actual_size
, TRUE
, local_commands
);
445 (void) snprintf(tar_hdr
->th_linkname
,
446 sizeof (tar_hdr
->th_name
),
451 tar_hdr
->th_linkflag
= LF_LONGLINK
;
452 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
),
454 (void) snprintf(tar_hdr
->th_mode
, sizeof (tar_hdr
->th_mode
),
455 "%06o ", attr
->st_mode
& 07777);
456 (void) snprintf(tar_hdr
->th_uid
, sizeof (tar_hdr
->th_uid
),
458 (void) snprintf(tar_hdr
->th_gid
, sizeof (tar_hdr
->th_gid
),
460 (void) snprintf(tar_hdr
->th_uname
, sizeof (tar_hdr
->th_uname
),
462 (void) snprintf(tar_hdr
->th_gname
, sizeof (tar_hdr
->th_gname
),
464 (void) snprintf(tar_hdr
->th_mtime
, sizeof (tar_hdr
->th_mtime
),
465 "%011o ", attr
->st_mtime
);
466 (void) strlcpy(tar_hdr
->th_magic
, TLM_MAGIC
,
467 sizeof (tar_hdr
->th_magic
));
469 tlm_build_header_checksum(tar_hdr
);
471 (void) output_mem(local_commands
, (void *)link
,
475 tar_hdr
= (tlm_tar_hdr_t
*)get_write_buffer(RECORDSIZE
,
476 &actual_size
, TRUE
, local_commands
);
482 (void) snprintf(tar_hdr
->th_name
,
483 sizeof (tar_hdr
->th_name
),
488 (void) strlcpy(tar_hdr
->th_name
, section_name
, TLM_NAME_SIZE
);
491 NDMP_LOG(LOG_DEBUG
, "long_link: %s [%s]", long_link
? "TRUE" : "FALSE",
495 (void) snprintf(tar_hdr
->th_linkname
,
496 sizeof (tar_hdr
->th_name
),
501 (void) strlcpy(tar_hdr
->th_linkname
, link
, TLM_NAME_SIZE
);
503 switch (attr
->st_mode
& S_IFMT
) {
505 tar_hdr
->th_linkflag
= LF_DIR
;
508 tar_hdr
->th_linkflag
= LF_FIFO
;
512 if (S_ISBLK(attr
->st_mode
))
513 tar_hdr
->th_linkflag
= LF_BLK
;
515 tar_hdr
->th_linkflag
= LF_CHR
;
516 (void) snprintf(tar_hdr
->th_shared
.th_dev
.th_devmajor
,
517 sizeof (tar_hdr
->th_shared
.th_dev
.th_devmajor
), "%06o ",
518 major(attr
->st_rdev
));
519 (void) snprintf(tar_hdr
->th_shared
.th_dev
.th_devminor
,
520 sizeof (tar_hdr
->th_shared
.th_dev
.th_devminor
), "%06o ",
521 minor(attr
->st_rdev
));
524 if (attr
->st_nlink
> 1) {
525 /* mark file with hardlink LF_LINK */
526 tar_hdr
->th_linkflag
= LF_LINK
;
527 (void) snprintf(tar_hdr
->th_shared
.th_hlink_ino
,
528 sizeof (tar_hdr
->th_shared
.th_hlink_ino
),
529 "%011llo ", attr
->st_ino
);
531 tar_hdr
->th_linkflag
= *link
== 0 ? LF_NORMAL
:
533 NDMP_LOG(LOG_DEBUG
, "linkflag: '%c'",
534 tar_hdr
->th_linkflag
);
537 (void) snprintf(tar_hdr
->th_size
, sizeof (tar_hdr
->th_size
), "%011o ",
538 (long)attr
->st_size
);
539 (void) snprintf(tar_hdr
->th_mode
, sizeof (tar_hdr
->th_mode
), "%06o ",
540 attr
->st_mode
& 07777);
541 (void) snprintf(tar_hdr
->th_uid
, sizeof (tar_hdr
->th_uid
), "%06o ",
543 (void) snprintf(tar_hdr
->th_gid
, sizeof (tar_hdr
->th_gid
), "%06o ",
545 (void) snprintf(tar_hdr
->th_uname
, sizeof (tar_hdr
->th_uname
), "%.31s",
547 (void) snprintf(tar_hdr
->th_gname
, sizeof (tar_hdr
->th_gname
), "%.31s",
549 (void) snprintf(tar_hdr
->th_mtime
, sizeof (tar_hdr
->th_mtime
), "%011o ",
551 (void) strlcpy(tar_hdr
->th_magic
, TLM_MAGIC
,
552 sizeof (tar_hdr
->th_magic
));
554 tlm_build_header_checksum(tar_hdr
);
555 if (long_name
|| long_link
) {
556 if (file_count
> 99999990) {
568 * Read where the softlink points to. Read the link in the checkpointed
569 * path if the backup is being done on a checkpointed file system.
572 tlm_readlink(char *nm
, char *snap
, char *buf
, int bufsize
)
576 if ((len
= readlink(snap
, buf
, bufsize
)) >= 0) {
578 * realink(2) doesn't null terminate the link name. We must
583 NDMP_LOG(LOG_DEBUG
, "Error %d reading softlink of [%s]",
587 /* Backup the link if the destination missing */
597 * Read the system attribute file in a single buffer to write
598 * it as a single write. A partial write to system attribute would
599 * cause an EINVAL on write.
602 get_write_one_buf(char *buf
, char *rec
, int buf_size
, int rec_size
,
608 if (rec_size
> buf_size
)
612 (void) memcpy(rec
, buf
, len
);
614 while (rec_size
< buf_size
) {
615 rec
= get_write_buffer(buf_size
- rec_size
,
616 &write_size
, FALSE
, lc
);
620 len
= min(buf_size
- rec_size
, write_size
);
621 (void) memcpy(rec
, buf
, len
);
632 * Put this file into the output buffers.
636 tlm_output_xattr(char *dir
, char *name
, char *chkdir
,
637 tlm_acls_t
*tlm_acls
, tlm_commands_t
*commands
,
638 tlm_cmd_t
*local_commands
, tlm_job_stats_t
*job_stats
)
640 char *fullname
; /* directory + name */
641 char *snapname
; /* snapshot name */
642 int section
; /* section of a huge file */
645 longlong_t seek_spot
= 0; /* location in the file */
646 /* for Multi Volume record */
654 if (S_ISPECIAL(tlm_acls
->acl_attr
.st_mode
)) {
655 return (TLM_NO_SOURCE_FILE
);
658 fullname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
659 if (fullname
== NULL
) {
661 return (-TLM_NO_SCRATCH_SPACE
);
664 if (!tlm_cat_path(fullname
, dir
, name
)) {
665 NDMP_LOG(LOG_DEBUG
, "Path too long.");
667 return (-TLM_NO_SCRATCH_SPACE
);
670 if (pathconf(fullname
, _PC_XATTR_EXISTS
) != 1 &&
671 sysattr_support(fullname
, _PC_SATTR_EXISTS
) != 1) {
676 attrname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
677 snapname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
678 if (attrname
== NULL
|| snapname
== NULL
) {
679 rv
= -TLM_NO_SCRATCH_SPACE
;
683 if (!tlm_cat_path(snapname
, chkdir
, name
)) {
684 NDMP_LOG(LOG_DEBUG
, "Path too long.");
685 rv
= -TLM_NO_SCRATCH_SPACE
;
689 fnamep
= (tlm_acls
->acl_checkpointed
) ? snapname
: fullname
;
692 * Open the file for reading.
694 fd
= attropen(fnamep
, ".", O_RDONLY
);
696 NDMP_LOG(LOG_DEBUG
, "BACKUP> Can't open file [%s][%s]",
698 rv
= TLM_NO_SOURCE_FILE
;
702 pos
= tlm_get_data_offset(local_commands
);
703 NDMP_LOG(LOG_DEBUG
, "pos: %10lld [%s]", pos
, name
);
707 dp
= (DIR *)fdopendir(fd
);
709 NDMP_LOG(LOG_DEBUG
, "BACKUP> Can't open file [%s]", fullname
);
711 rv
= TLM_NO_SOURCE_FILE
;
715 while ((dtp
= readdir(dp
)) != NULL
) {
718 if (*dtp
->d_name
== '.')
721 if (sysattr_rdonly(dtp
->d_name
))
724 afd
= attropen(fnamep
, dtp
->d_name
, O_RDONLY
);
727 "problem(%d) opening xattr file [%s][%s]", errno
,
732 (void) output_xattr_header(fullname
, dtp
->d_name
, afd
,
733 tlm_acls
, section
, local_commands
);
734 (void) snprintf(attrname
, TLM_MAX_PATH_NAME
, "/dev/null/%s",
736 (void) output_file_header(attrname
, "", tlm_acls
, 0,
739 section_size
= (long)llmin(tlm_acls
->acl_attr
.st_size
,
740 (longlong_t
)TLM_MAX_TAR_IMAGE
);
742 /* We only can read upto one section extended attribute */
743 while (section_size
> 0) {
747 int sysattr_read
= 0;
752 * check for Abort commands
754 if (commands
->tcs_reader
!= TLM_BACKUP_RUN
) {
755 local_commands
->tc_writer
= TLM_ABORT
;
759 local_commands
->tc_buffers
->tbs_buffer
[
760 local_commands
->tc_buffers
->tbs_buffer_in
].
761 tb_file_size
= section_size
;
762 local_commands
->tc_buffers
->tbs_buffer
[
763 local_commands
->tc_buffers
->tbs_buffer_in
].
764 tb_seek_spot
= seek_spot
;
766 buf
= get_write_buffer(section_size
,
767 &actual_size
, FALSE
, local_commands
);
771 if ((actual_size
< section_size
) &&
772 sysattr_rw(dtp
->d_name
)) {
774 buf
= ndmp_malloc(section_size
);
778 actual_size
= section_size
;
783 * check for Abort commands
785 if (commands
->tcs_reader
!= TLM_BACKUP_RUN
) {
786 local_commands
->tc_writer
= TLM_ABORT
;
790 read_size
= min(section_size
, actual_size
);
791 if ((actual_size
= read(afd
, buf
, read_size
)) < 0)
795 if (get_write_one_buf(buf
, rec
, read_size
,
796 size
, local_commands
) == 0) {
804 NS_ADD(rdisk
, actual_size
);
807 if (actual_size
== -1) {
809 "problem(%d) reading file [%s][%s]",
810 errno
, fullname
, snapname
);
813 seek_spot
+= actual_size
;
814 section_size
-= actual_size
;
821 local_commands
->tc_buffers
->tbs_buffer
[
822 local_commands
->tc_buffers
->tbs_buffer_in
].tb_seek_spot
= 0;
827 /* closedir closes fd too */
841 * Put this file into the output buffers.
844 tlm_output_file(char *dir
, char *name
, char *chkdir
,
845 tlm_acls_t
*tlm_acls
, tlm_commands_t
*commands
, tlm_cmd_t
*local_commands
,
846 tlm_job_stats_t
*job_stats
, struct hardlink_q
*hardlink_q
)
848 char *fullname
; /* directory + name */
849 char *snapname
; /* snapshot name */
850 char *linkname
; /* where this file points */
851 int section
= 0; /* section of a huge file */
853 longlong_t real_size
; /* the origional file size */
854 longlong_t file_size
; /* real size of this file */
855 longlong_t seek_spot
= 0; /* location in the file */
856 /* for Multi Volume record */
860 /* Indicate whether a file with the same inode has been backed up. */
861 int hardlink_done
= 0;
864 * If a file with the same inode has been backed up, hardlink_pos holds
865 * the tape offset of the data record.
867 u_longlong_t hardlink_pos
= 0;
869 if (tlm_is_too_long(tlm_acls
->acl_checkpointed
, dir
, name
)) {
870 NDMP_LOG(LOG_DEBUG
, "Path too long [%s][%s]", dir
, name
);
871 return (-TLM_NO_SCRATCH_SPACE
);
874 fullname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
875 linkname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
876 snapname
= ndmp_malloc(TLM_MAX_PATH_NAME
);
877 if (fullname
== NULL
|| linkname
== NULL
|| snapname
== NULL
) {
878 real_size
= -TLM_NO_SCRATCH_SPACE
;
881 if (!tlm_cat_path(fullname
, dir
, name
) ||
882 !tlm_cat_path(snapname
, chkdir
, name
)) {
883 NDMP_LOG(LOG_DEBUG
, "Path too long.");
884 real_size
= -TLM_NO_SCRATCH_SPACE
;
888 pos
= tlm_get_data_offset(local_commands
);
889 NDMP_LOG(LOG_DEBUG
, "pos: %10lld [%s]", pos
, name
);
891 if (S_ISPECIAL(tlm_acls
->acl_attr
.st_mode
)) {
892 if (S_ISLNK(tlm_acls
->acl_attr
.st_mode
)) {
893 file_size
= tlm_readlink(fullname
, snapname
, linkname
,
894 TLM_MAX_PATH_NAME
-1);
902 * Since soft links can not be read(2), we should only
903 * backup the file header.
905 (void) output_file_header(fullname
,
911 (void) tlm_log_fhnode(job_stats
, dir
, name
,
912 &tlm_acls
->acl_attr
, pos
);
913 (void) tlm_log_fhpath_name(job_stats
, fullname
,
914 &tlm_acls
->acl_attr
, pos
);
922 fnamep
= (tlm_acls
->acl_checkpointed
) ? snapname
: fullname
;
925 * For hardlink, only read the data if no other link
926 * belonging to the same inode has been backed up.
928 if (tlm_acls
->acl_attr
.st_nlink
> 1) {
929 hardlink_done
= !hardlink_q_get(hardlink_q
,
930 tlm_acls
->acl_attr
.st_ino
, &hardlink_pos
, NULL
);
933 if (!hardlink_done
) {
935 * Open the file for reading.
937 fd
= open(fnamep
, O_RDONLY
);
940 "BACKUP> Can't open file [%s][%s] err(%d)",
941 fullname
, fnamep
, errno
);
942 real_size
= -TLM_NO_SOURCE_FILE
;
946 NDMP_LOG(LOG_DEBUG
, "found hardlink, inode = %llu, pos = %llu ",
947 tlm_acls
->acl_attr
.st_ino
, hardlink_pos
);
954 real_size
= tlm_acls
->acl_attr
.st_size
;
955 (void) output_acl_header(&tlm_acls
->acl_info
,
959 * section = 0: file is small enough for TAR
960 * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
961 * and the file name gets munged
963 file_size
= real_size
;
964 if (file_size
> TLM_MAX_TAR_IMAGE
) {
965 if (output_humongus_header(fullname
, file_size
,
966 local_commands
) < 0) {
968 real_size
= -TLM_NO_SCRATCH_SPACE
;
977 * For hardlink, if other link belonging to the same inode
978 * has been backed up, only backup an empty record.
986 if (file_size
== 0) {
987 (void) output_file_header(fullname
,
993 * this can fall right through since zero size files
994 * will be skipped by the WHILE loop anyway
998 while (file_size
> 0) {
999 int section_size
= llmin(file_size
,
1000 (longlong_t
)TLM_MAX_TAR_IMAGE
);
1002 tlm_acls
->acl_attr
.st_size
= (longlong_t
)section_size
;
1003 (void) output_file_header(fullname
,
1008 while (section_size
> 0) {
1014 * check for Abort commands
1016 if (commands
->tcs_reader
!= TLM_BACKUP_RUN
) {
1017 local_commands
->tc_writer
= TLM_ABORT
;
1021 local_commands
->tc_buffers
->tbs_buffer
[
1022 local_commands
->tc_buffers
->tbs_buffer_in
].
1023 tb_file_size
= section_size
;
1024 local_commands
->tc_buffers
->tbs_buffer
[
1025 local_commands
->tc_buffers
->tbs_buffer_in
].
1026 tb_seek_spot
= seek_spot
;
1028 buf
= get_write_buffer(section_size
,
1029 &actual_size
, FALSE
, local_commands
);
1034 * check for Abort commands
1036 if (commands
->tcs_reader
!= TLM_BACKUP_RUN
) {
1037 local_commands
->tc_writer
= TLM_ABORT
;
1041 read_size
= min(section_size
, actual_size
);
1042 actual_size
= read(fd
, buf
, read_size
);
1043 NS_ADD(rdisk
, actual_size
);
1046 if (actual_size
== 0)
1049 if (actual_size
== -1) {
1051 "problem(%d) reading file [%s][%s]",
1052 errno
, fullname
, snapname
);
1055 seek_spot
+= actual_size
;
1056 file_size
-= actual_size
;
1057 section_size
-= actual_size
;
1063 * If data belonging to this hardlink has been backed up, add the link
1064 * to hardlink queue.
1066 if (tlm_acls
->acl_attr
.st_nlink
> 1 && !hardlink_done
) {
1067 (void) hardlink_q_add(hardlink_q
, tlm_acls
->acl_attr
.st_ino
,
1070 "backed up hardlink file %s, inode = %llu, pos = %llu ",
1071 fullname
, tlm_acls
->acl_attr
.st_ino
, pos
);
1075 * For hardlink, if other link belonging to the same inode has been
1076 * backed up, no add_node entry should be sent for this link.
1078 if (hardlink_done
) {
1080 "backed up hardlink link %s, inode = %llu, pos = %llu ",
1081 fullname
, tlm_acls
->acl_attr
.st_ino
, hardlink_pos
);
1083 (void) tlm_log_fhnode(job_stats
, dir
, name
,
1084 &tlm_acls
->acl_attr
, pos
);
1087 (void) tlm_log_fhpath_name(job_stats
, fullname
, &tlm_acls
->acl_attr
,
1091 local_commands
->tc_buffers
->tbs_buffer
[
1092 local_commands
->tc_buffers
->tbs_buffer_in
].tb_seek_spot
= 0;
1106 * Main file backup function for tar
1109 tar_putfile(char *dir
, char *name
, char *chkdir
,
1110 tlm_acls_t
*tlm_acls
, tlm_commands_t
*commands
,
1111 tlm_cmd_t
*local_commands
, tlm_job_stats_t
*job_stats
,
1112 struct hardlink_q
*hardlink_q
)
1116 rv
= tlm_output_file(dir
, name
, chkdir
, tlm_acls
, commands
,
1117 local_commands
, job_stats
, hardlink_q
);
1121 rv
= tlm_output_xattr(dir
, name
, chkdir
, tlm_acls
, commands
,
1122 local_commands
, job_stats
);
1124 return (rv
< 0 ? rv
: 0);
1130 * a wrapper to tlm_get_write_buffer so that
1131 * we can cleanly detect ABORT commands
1132 * without involving the TLM library with
1136 get_write_buffer(long size
, long *actual_size
,
1137 boolean_t zero
, tlm_cmd_t
*local_commands
)
1139 while (local_commands
->tc_reader
== TLM_BACKUP_RUN
) {
1140 char *rec
= tlm_get_write_buffer(size
, actual_size
,
1141 local_commands
->tc_buffers
, zero
);
1149 #define NDMP_MORE_RECORDS 2
1154 * This function is initially written for NDMP support. It appends
1155 * two tar headers to the tar file, and also N more empty buffers
1156 * to make sure that the two tar headers will be read as a part of
1157 * a mover record and don't get locked because of EOM on the mover
1161 write_tar_eof(tlm_cmd_t
*local_commands
)
1165 tlm_buffers_t
*bufs
;
1168 * output 2 zero filled records,
1171 (void) get_write_buffer(sizeof (tlm_tar_hdr_t
),
1172 &actual_size
, TRUE
, local_commands
);
1173 (void) get_write_buffer(sizeof (tlm_tar_hdr_t
),
1174 &actual_size
, TRUE
, local_commands
);
1177 * NDMP: Clear the rest of the buffer and write two more buffers
1180 bufs
= local_commands
->tc_buffers
;
1181 (void) get_write_buffer(bufs
->tbs_data_transfer_size
,
1182 &actual_size
, TRUE
, local_commands
);
1184 for (i
= 0; i
< NDMP_MORE_RECORDS
&&
1185 local_commands
->tc_reader
== TLM_BACKUP_RUN
; i
++) {
1187 * We don't need the return value of get_write_buffer(),
1188 * since it's already zeroed out if the buffer is returned.
1190 (void) get_write_buffer(bufs
->tbs_data_transfer_size
,
1191 &actual_size
, TRUE
, local_commands
);
1194 bufs
->tbs_buffer
[bufs
->tbs_buffer_in
].tb_full
= TRUE
;
1195 tlm_buffer_release_in_buf(bufs
);
1199 * Callback to backup each ZFS property
1202 zfs_put_prop_cb(int prop
, void *pp
)
1204 ndmp_metadata_handle_t
*mhd
;
1205 ndmp_metadata_header_ext_t
*mhp
;
1206 ndmp_metadata_property_ext_t
*mpp
;
1207 char vbuf
[ZFS_MAXPROPLEN
];
1208 char sbuf
[ZFS_MAXPROPLEN
];
1209 zprop_source_t stype
;
1213 return (ZPROP_INVAL
);
1215 mhd
= (ndmp_metadata_handle_t
*)pp
;
1217 mpp
= &mhp
->nh_property
[mhp
->nh_count
];
1219 if (mhp
->nh_count
* sizeof (ndmp_metadata_property_ext_t
) +
1220 sizeof (ndmp_metadata_header_ext_t
) > mhp
->nh_total_bytes
)
1221 return (ZPROP_INVAL
);
1223 if (zfs_prop_get(mhd
->ml_handle
, prop
, vbuf
, sizeof (vbuf
),
1224 &stype
, sbuf
, sizeof (sbuf
), B_TRUE
) != 0) {
1226 return (ZPROP_CONT
);
1229 (void) strlcpy(mpp
->mp_name
, zfs_prop_to_name(prop
),
1230 ZFS_MAX_DATASET_NAME_LEN
);
1231 (void) strlcpy(mpp
->mp_value
, vbuf
, ZFS_MAXPROPLEN
);
1234 case ZPROP_SRC_NONE
:
1237 case ZPROP_SRC_RECEIVED
:
1238 sourcestr
= "received";
1240 case ZPROP_SRC_LOCAL
:
1241 sourcestr
= mhp
->nh_dataset
;
1243 case ZPROP_SRC_TEMPORARY
:
1244 sourcestr
= "temporary";
1246 case ZPROP_SRC_DEFAULT
:
1247 sourcestr
= "default";
1253 (void) strlcpy(mpp
->mp_source
, sourcestr
, ZFS_MAXPROPLEN
);
1256 return (ZPROP_CONT
);
1260 * Callback to backup each ZFS user/group quota
1263 zfs_put_quota_cb(void *pp
, const char *domain
, uid_t rid
, uint64_t space
)
1265 ndmp_metadata_handle_t
*mhd
;
1266 ndmp_metadata_header_ext_t
*mhp
;
1267 ndmp_metadata_property_ext_t
*mpp
;
1271 return (ZPROP_INVAL
);
1273 mhd
= (ndmp_metadata_handle_t
*)pp
;
1275 mpp
= &mhp
->nh_property
[mhp
->nh_count
];
1277 if (mhp
->nh_count
* sizeof (ndmp_metadata_property_ext_t
) +
1278 sizeof (ndmp_metadata_header_ext_t
) > mhp
->nh_total_bytes
)
1279 return (ZPROP_INVAL
);
1281 if (mhd
->ml_quota_prop
== ZFS_PROP_USERQUOTA
)
1282 typestr
= "userquota";
1284 typestr
= "groupquota";
1286 if (domain
== NULL
|| *domain
== '\0') {
1287 (void) snprintf(mpp
->mp_name
, ZFS_MAX_DATASET_NAME_LEN
,
1288 "%s@%llu", typestr
, (longlong_t
)rid
);
1290 (void) snprintf(mpp
->mp_name
, ZFS_MAX_DATASET_NAME_LEN
,
1291 "%s@%s-%llu", typestr
, domain
, (longlong_t
)rid
);
1293 (void) snprintf(mpp
->mp_value
, ZFS_MAXPROPLEN
, "%llu", space
);
1294 (void) strlcpy(mpp
->mp_source
, mhp
->nh_dataset
, ZFS_MAXPROPLEN
);
1301 * Callback to count each ZFS property
1305 zfs_count_prop_cb(int prop
, void *pp
)
1308 return (ZPROP_CONT
);
1312 * Callback to count each ZFS user/group quota
1316 zfs_count_quota_cb(void *pp
, const char *domain
, uid_t rid
, uint64_t space
)
1323 * Count the number of ZFS properties and user/group quotas
1326 zfs_get_prop_counts(zfs_handle_t
*zhp
)
1335 (void) zprop_iter(zfs_count_prop_cb
, &count
, TRUE
, TRUE
,
1336 ZFS_TYPE_VOLUME
| ZFS_TYPE_DATASET
);
1338 (void) zfs_userspace(zhp
, ZFS_PROP_USERQUOTA
, zfs_count_quota_cb
,
1340 (void) zfs_userspace(zhp
, ZFS_PROP_GROUPQUOTA
, zfs_count_quota_cb
,
1343 uprops
= zfs_get_user_props(zhp
);
1345 elp
= nvlist_next_nvpair(uprops
, NULL
);
1346 for (; elp
!= NULL
; elp
= nvlist_next_nvpair(uprops
, elp
))
1353 * Notifies ndmpd that the metadata associated with the given ZFS dataset
1354 * should be backed up.
1357 ndmp_include_zfs(ndmp_context_t
*nctx
, const char *dataset
)
1359 tlm_commands_t
*cmds
;
1360 ndmp_metadata_handle_t mhd
;
1361 ndmp_metadata_header_ext_t
*mhp
;
1362 ndmp_metadata_property_ext_t
*mpp
;
1366 nvlist_t
*uprops
, *ulist
;
1370 char *wbuf
, *pp
, *tp
;
1371 long size
, lsize
, sz
;
1372 int align
= RECORDSIZE
- 1;
1375 if (nctx
== NULL
|| (cmds
= (tlm_commands_t
*)nctx
->nc_cmds
) == NULL
)
1378 if ((lcmd
= cmds
->tcs_command
) == NULL
||
1379 lcmd
->tc_buffers
== NULL
)
1382 (void) mutex_lock(&zlib_mtx
);
1383 if ((zhp
= zfs_open(zlibh
, dataset
, ZFS_TYPE_DATASET
)) == NULL
) {
1384 (void) mutex_unlock(&zlib_mtx
);
1388 pcount
= zfs_get_prop_counts(zhp
);
1389 size
= sizeof (ndmp_metadata_header_ext_t
) +
1390 pcount
* sizeof (ndmp_metadata_property_ext_t
);
1395 if ((mhp
= malloc(size
)) == NULL
) {
1397 (void) mutex_unlock(&zlib_mtx
);
1401 (void) memset(mhp
, 0, size
);
1403 mhd
.ml_handle
= zhp
;
1405 mhp
->nh_total_bytes
= size
;
1406 mhp
->nh_major
= META_HDR_MAJOR_VERSION
;
1407 mhp
->nh_minor
= META_HDR_MINOR_VERSION
;
1408 mhp
->nh_plversion
= nctx
->nc_plversion
;
1410 (void) strlcpy(mhp
->nh_plname
, nctx
->nc_plname
,
1411 sizeof (mhp
->nh_plname
));
1412 (void) strlcpy(mhp
->nh_magic
, ZFS_META_MAGIC_EXT
,
1413 sizeof (mhp
->nh_magic
));
1414 (void) strlcpy(mhp
->nh_dataset
, dataset
, sizeof (mhp
->nh_dataset
));
1416 /* Get all the ZFS properties */
1417 (void) zprop_iter(zfs_put_prop_cb
, &mhd
, TRUE
, TRUE
,
1418 ZFS_TYPE_VOLUME
| ZFS_TYPE_DATASET
);
1420 /* Get user properties */
1421 uprops
= zfs_get_user_props(mhd
.ml_handle
);
1423 elp
= nvlist_next_nvpair(uprops
, NULL
);
1425 while (elp
!= NULL
) {
1426 mpp
= &mhp
->nh_property
[mhp
->nh_count
];
1427 if (nvpair_value_nvlist(elp
, &ulist
) != 0 ||
1428 nvlist_lookup_string(ulist
, ZPROP_VALUE
, &sval
) != 0 ||
1429 nvlist_lookup_string(ulist
, ZPROP_SOURCE
, &ssrc
) != 0) {
1430 zfs_close(mhd
.ml_handle
);
1431 (void) mutex_unlock(&zlib_mtx
);
1435 if ((pname
= nvpair_name(elp
)) != NULL
) {
1436 (void) strlcpy(mpp
->mp_name
, pname
,
1437 ZFS_MAX_DATASET_NAME_LEN
);
1440 (void) strlcpy(mpp
->mp_value
, sval
, ZFS_MAXPROPLEN
);
1441 (void) strlcpy(mpp
->mp_source
, ssrc
, ZFS_MAXPROPLEN
);
1443 elp
= nvlist_next_nvpair(uprops
, elp
);
1446 mhd
.ml_quota_prop
= ZFS_PROP_USERQUOTA
;
1447 (void) zfs_userspace(mhd
.ml_handle
, ZFS_PROP_USERQUOTA
,
1448 zfs_put_quota_cb
, &mhd
);
1449 mhd
.ml_quota_prop
= ZFS_PROP_GROUPQUOTA
;
1450 (void) zfs_userspace(mhd
.ml_handle
, ZFS_PROP_GROUPQUOTA
,
1451 zfs_put_quota_cb
, &mhd
);
1452 mhp
->nh_count
= pcount
;
1454 zfs_close(mhd
.ml_handle
);
1455 (void) mutex_unlock(&zlib_mtx
);
1457 if ((wbuf
= get_write_buffer(size
, &actual_size
, TRUE
,
1461 (void) memcpy(wbuf
, pp
, (actual_size
< size
) ?
1462 actual_size
: size
);
1463 pp
+= (actual_size
< size
) ? actual_size
: size
;
1467 ((tp
= get_write_buffer(size
- sz
, &lsize
,
1468 TRUE
, lcmd
))) != NULL
) {
1469 (void) memcpy(tp
, pp
, lsize
);
1474 tlm_unget_write_buffer(lcmd
->tc_buffers
, sz
- size
);