1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 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 20 * distribution. 21 * 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 25 * permission. 26 * 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. 38 */ 39 #include <sys/stat.h> 40 #include <sys/types.h> 41 #include <cstack.h> 42 #include <ctype.h> 43 #include <dirent.h> 44 #include <errno.h> 45 #include "ndmpd.h" 46 #include <bitmap.h> 47 #include <traverse.h> 48 #include <limits.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <time.h> 53 #include "tlm_buffers.h" 54 55 56 /* 57 * Parameter passed to traverse for marking inodes 58 * when traversing backup hierarchy in V2. It 59 * includes: 60 * mp_bmd: the bitmap describptor. 61 * mp_ddate: backup date. 62 * mp_session: pointer to the session structure. 63 * mp_nlp: pointer to the nlp. 64 * mp_tacl: pointer to the acl. 65 */ 66 typedef struct mark_param { 67 int mp_bmd; 68 time_t mp_ddate; 69 ndmpd_session_t *mp_session; 70 ndmp_lbr_params_t *mp_nlp; 71 tlm_acls_t *mp_tacl; 72 } mark_param_t; 73 74 75 /* 76 * Set this variable to non-zero to print the inodes 77 * marked after traversing file system. 78 */ 79 static int ndmpd_print_inodes = 0; 80 81 82 /* 83 * Flag passed to traverse_post. 84 */ 85 static int ndmpd_mark_flags = 0; 86 87 88 /* 89 * Verbose traversing prints the file/dir path names 90 * if they are being marked. 91 */ 92 static int ndmpd_verbose_traverse = 0; 93 94 95 /* 96 * Set this flag to count the number of inodes marked 97 * after traversing backup hierarchy. 98 */ 99 static int ndmpd_mark_count_flag = 0; 100 101 102 /* 103 * Set this variable to non-zero value to force traversing 104 * backup hierarchy for tar format. 105 */ 106 static int ndmp_tar_force_traverse = 0; 107 108 109 /* 110 * Set this variable to non-zero value to skip processing 111 * directories both for tar and dump. 112 */ 113 static int ndmp_skip_traverse = 0; 114 115 116 /* 117 * count_bits_cb 118 * 119 * Call back for counting the set bits in the dbitmap. 120 * 121 * Parameters: 122 * bmd (input) - bitmap descriptor 123 * bn (input) - the bit number 124 * arg (input) - pointer to the argument 125 * 126 * Returns: 127 * 0: always 128 */ 129 static int 130 count_bits_cb(int bmd, u_longlong_t bn, void *arg) 131 { 132 if (dbm_getone(bmd, bn)) { 133 (*(u_longlong_t *)arg)++; 134 if (ndmpd_print_inodes) 135 NDMP_LOG(LOG_DEBUG, "%llu", bn); 136 } 137 138 return (0); 139 } 140 141 142 /* 143 * count_set_bits 144 * 145 * Count bits set in the bitmap. 146 * 147 * Parameters: 148 * path (input) - the backup path 149 * bmd (input) - bitmap descriptor 150 * 151 * Returns: 152 * void 153 */ 154 void 155 count_set_bits(char *path, int bmd) 156 { 157 u_longlong_t cnt; 158 159 if (!ndmpd_mark_count_flag) 160 return; 161 162 cnt = 0; 163 (void) dbm_apply_ifset(bmd, count_bits_cb, &cnt); 164 NDMP_LOG(LOG_DEBUG, "%s %llu inodes marked", path, cnt); 165 } 166 167 168 /* 169 * traverse 170 * 171 * Starts the post-traverse the backup hierarchy. Checks 172 * for exceptional cases, like aborting operation and if 173 * asked, report detailed information after traversing. 174 * 175 * Parameters: 176 * session (input) - pointer to the session 177 * nlp (input) - pointer to the nlp structure 178 * ftp (input) - pointer to the traverse parameters 179 * 180 * Returns: 181 * 0: on success 182 * != 0: otherwise 183 */ 184 int 185 traverse(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, 186 fs_traverse_t *ftp) 187 { 188 int rv; 189 time_t s, e; 190 191 if (!session || !nlp || !ftp) { 192 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 193 return (-1); 194 } 195 NDMP_LOG(LOG_DEBUG, "Processing directories of \"%s\"", 196 nlp->nlp_backup_path); 197 198 (void) time(&s); 199 if (traverse_post(ftp) != 0) { 200 rv = -1; 201 if (!session->ns_data.dd_abort && !NLP_ISSET(nlp, 202 NLPF_ABORTED)) { 203 NDMP_LOG(LOG_DEBUG, 204 "Traversing backup path hierarchy \"%s\"", 205 nlp->nlp_backup_path); 206 } 207 } else { 208 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE); 209 rv = 0; 210 (void) time(&e); 211 NDMP_LOG(LOG_DEBUG, 212 "\"%s\" traversed in %u sec", nlp->nlp_backup_path, 213 (uint_t)(e-s)); 214 215 count_set_bits(nlp->nlp_backup_path, nlp->nlp_bkmap); 216 } 217 218 return (rv); 219 } 220 221 222 /* 223 * mark_cb 224 * 225 * The callback function, called by traverse_post to mark bits 226 * in the bitmap. 227 * 228 * Set the bit of the entry if it's been modified (obviously 229 * should be backed up) plus its parent directory. 230 * 231 * If the entry is a directory and is not modified itself, 232 * but it's marked, then there is something below it that 233 * is being backed up. It shows the the path, leads to 234 * an object that will be backed up. So the path should 235 * be marked too. 236 * 237 * The backup path itself is always marked. 238 * 239 * Parameters: 240 * arg (input) - pointer to the mark parameter 241 * pnp (input) - pointer to the path node 242 * enp (input) - pointer to the entry node 243 * 244 * Returns: 245 * 0: as long as traversing should continue 246 * != 0: if traversing should stop 247 */ 248 int 249 mark_cb(void *arg, fst_node_t *pnp, fst_node_t *enp) 250 { 251 int bmd; 252 int rv; 253 u_longlong_t bl; 254 time_t ddate; 255 fs_fhandle_t *pfhp, *efhp; 256 struct stat64 *pstp, *estp; 257 mark_param_t *mpp; 258 ndmp_lbr_params_t *nlp; 259 tlm_acls_t *tacl; 260 261 rv = 0; 262 mpp = (mark_param_t *)arg; 263 tacl = mpp->mp_tacl; 264 nlp = ndmp_get_nlp(mpp->mp_session); 265 if (!mpp) { 266 NDMP_LOG(LOG_DEBUG, "NULL argument passed"); 267 rv = -1; 268 } else if (mpp->mp_session->ns_eof) { 269 NDMP_LOG(LOG_INFO, "Connection to the client is closed"); 270 rv = -1; 271 } else if (mpp->mp_session->ns_data.dd_abort || 272 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) { 273 NDMP_LOG(LOG_INFO, "Processing directories aborted."); 274 rv = -1; 275 } 276 277 if (rv != 0) 278 return (rv); 279 280 ddate = mpp->mp_ddate; 281 bmd = mpp->mp_bmd; 282 bl = dbm_getlen(bmd); 283 284 pfhp = pnp->tn_fh; 285 pstp = pnp->tn_st; 286 287 /* sanity check on fh and stat of the path passed */ 288 if (pstp->st_ino > bl) { 289 NDMP_LOG(LOG_DEBUG, "Invalid path inode #%u", 290 (uint_t)pstp->st_ino); 291 return (-1); 292 } 293 if (pstp->st_ino != pfhp->fh_fid) { 294 NDMP_LOG(LOG_DEBUG, "Path ino mismatch %u %u", 295 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid); 296 return (-1); 297 } 298 299 /* 300 * Always mark the backup path inode number. 301 */ 302 if (!enp->tn_path) { 303 (void) dbm_setone(bmd, pstp->st_ino); 304 return (0); 305 } 306 307 efhp = enp->tn_fh; 308 estp = enp->tn_st; 309 310 /* sanity check on fh and stat of the entry passed */ 311 if (estp->st_ino > bl) { 312 NDMP_LOG(LOG_DEBUG, "Invalid entry inode #%u", 313 (uint_t)estp->st_ino); 314 return (-1); 315 } 316 if (estp->st_ino != efhp->fh_fid) { 317 NDMP_LOG(LOG_DEBUG, "Entry ino mismatch %u %u", estp->st_ino, 318 (uint_t)pfhp->fh_fid); 319 return (-1); 320 } 321 322 /* check the dates and mark the bitmap inode */ 323 if (ddate == 0) { 324 /* base backup */ 325 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); 326 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 327 if (ndmpd_verbose_traverse) { 328 NDMP_LOG(LOG_DEBUG, "Base Backup"); 329 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", 330 pnp->tn_path, enp->tn_path); 331 } 332 333 } else if (estp->st_mtime > ddate) { 334 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); 335 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 336 if (ndmpd_verbose_traverse) { 337 NDMP_LOG(LOG_DEBUG, 338 "m(%u,%u,%u,%u)", (uint_t)pstp->st_ino, 339 (uint_t)estp->st_ino, (uint_t)estp->st_mtime, 340 (uint_t)ddate); 341 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", 342 pnp->tn_path, enp->tn_path); 343 } 344 } else if (iscreated(nlp, NULL, tacl, ddate)) { 345 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); 346 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 347 if (ndmpd_verbose_traverse) { 348 NDMP_LOG(LOG_DEBUG, 349 "cr(%u,%u,%u,%u)", (uint_t)pstp->st_ino, 350 (uint_t)estp->st_ino, (uint_t)estp->st_mtime, 351 (uint_t)ddate); 352 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", 353 pnp->tn_path, enp->tn_path); 354 } 355 } else if (estp->st_ctime > ddate) { 356 if (!NLP_IGNCTIME(nlp)) { 357 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); 358 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 359 } 360 if (ndmpd_verbose_traverse) { 361 if (NLP_IGNCTIME(nlp)) { 362 NDMP_LOG(LOG_DEBUG, 363 "ign c(%u,%u,%u,%u)", (uint_t)pstp->st_ino, 364 (uint_t)estp->st_ino, 365 (uint_t)estp->st_ctime, (uint_t)ddate); 366 } else { 367 NDMP_LOG(LOG_DEBUG, 368 "c(%u,%u,%u,%u)", (uint_t)pstp->st_ino, 369 (uint_t)estp->st_ino, 370 (uint_t)estp->st_ctime, (uint_t)ddate); 371 } 372 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", 373 pnp->tn_path, enp->tn_path); 374 } 375 } else if (S_ISDIR(estp->st_mode) && 376 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) { 377 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 378 if (ndmpd_verbose_traverse) { 379 NDMP_LOG(LOG_DEBUG, "d(%u,%u)", 380 (uint_t)pstp->st_ino, (uint_t)estp->st_ino); 381 NDMP_LOG(LOG_DEBUG, "\"%s, %s\"", 382 pnp->tn_path, enp->tn_path); 383 } 384 } 385 386 return (0); 387 } 388 389 390 /* 391 * mark_inodes_v2 392 * 393 * Traverse the file system in post-order and mark 394 * all the modified objects and also directories leading 395 * to them. 396 * 397 * Parameters: 398 * session (input) - pointer to the session 399 * nlp (input) - pointer to the nlp structure 400 * path (input) - the physical path to traverse 401 * 402 * Returns: 403 * 0: on success. 404 * != 0: on error. 405 */ 406 int 407 mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path) 408 { 409 fs_traverse_t ft; 410 mark_param_t mp; 411 412 if (!session || !nlp || !path || !*path) { 413 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 414 return (-1); 415 } 416 417 NDMP_LOG(LOG_DEBUG, "path \"%s\"", path); 418 419 mp.mp_bmd = nlp->nlp_bkmap; 420 mp.mp_ddate = nlp->nlp_ldate; 421 mp.mp_session = session; 422 mp.mp_nlp = nlp; 423 424 ft.ft_path = path; 425 ft.ft_lpath = nlp->nlp_backup_path; 426 ft.ft_callbk = mark_cb; 427 ft.ft_arg = ∓ 428 ft.ft_logfp = (ft_log_t)ndmp_log; 429 ft.ft_flags = ndmpd_mark_flags; 430 431 return (traverse(session, nlp, &ft)); 432 } 433 434 435 /* 436 * create_bitmap 437 * 438 * Create a dbitmap and return its descriptor. 439 * 440 * Parameters: 441 * path (input) - path for which the bitmap should be created 442 * value (input) - the initial value for the bitmap 443 * 444 * Returns: 445 * the dbitmap descriptor 446 */ 447 static int 448 create_bitmap(char *path, int value) 449 { 450 char bm_fname[PATH_MAX]; 451 char buf[TLM_MAX_PATH_NAME]; 452 char *livepath; 453 ulong_t ninode; 454 455 NDMP_LOG(LOG_DEBUG, "path \"%s\"", path); 456 457 if (fs_is_chkpntvol(path)) 458 livepath = (char *)tlm_remove_checkpoint(path, buf); 459 else 460 livepath = path; 461 ninode = 1024 * 1024 * 1024; 462 if (ninode == 0) 463 return (-1); 464 (void) ndmpd_mk_temp(bm_fname); 465 466 NDMP_LOG(LOG_DEBUG, "path \"%s\"ninode %u bm_fname \"%s\"", 467 livepath, ninode, bm_fname); 468 469 return (dbm_alloc(bm_fname, (u_longlong_t)ninode, value)); 470 } 471 472 473 /* 474 * create_allset_bitmap 475 * 476 * A helper function to create a bitmap with all the 477 * values set to 1. 478 * 479 * Parameters: 480 * nlp (input) - pointer to the nlp structure 481 * 482 * Returns: 483 * the dbitmap descriptor 484 */ 485 static int 486 create_allset_bitmap(ndmp_lbr_params_t *nlp) 487 { 488 int rv; 489 490 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 1); 491 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap); 492 493 if (nlp->nlp_bkmap < 0) { 494 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap."); 495 rv = -1; 496 } else 497 rv = 0; 498 499 return (rv); 500 } 501 502 503 /* 504 * mark_common_v2 505 * 506 * Create the inode bitmap. If last date of the the 507 * backup is epoch, then all the objects should be backed 508 * up; there is no need to traverse the backup hierarchy 509 * and mark the inodes. All the bits should be marked. 510 * 511 * Otherwise, the backup hierarchy should be traversed and 512 * the objects should be marked. 513 * 514 * Parameters: 515 * session (input) - pointer to the session 516 * nlp (input) - pointer to the nlp structure 517 * 518 * Returns: 519 * 0: on success. 520 * != 0: on error. 521 */ 522 static int 523 mark_common_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 524 { 525 char buf[TLM_MAX_PATH_NAME], *chkpath; 526 int rv; 527 528 /* 529 * Everything is needed for full backup. 530 */ 531 if (nlp->nlp_ldate == (time_t)0) 532 return (create_allset_bitmap(nlp)); 533 534 rv = 0; 535 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0); 536 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap); 537 538 if (nlp->nlp_bkmap < 0) { 539 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap."); 540 rv = -1; 541 } else { 542 if (fs_is_chkpntvol(nlp->nlp_backup_path)) 543 chkpath = nlp->nlp_backup_path; 544 else 545 chkpath = tlm_build_snapshot_name( 546 nlp->nlp_backup_path, buf, 547 nlp->nlp_jstat->js_job_name); 548 rv = mark_inodes_v2(session, nlp, chkpath); 549 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE); 550 } 551 552 return (rv); 553 } 554 555 556 /* 557 * mark_tar_inodes_v2 558 * 559 * Create the bitmap for tar backup format. 560 * 561 * Parameters: 562 * session (input) - pointer to the session 563 * nlp (input) - pointer to the nlp structure 564 * 565 * Returns: 566 * 0: on success. 567 * != 0: on error. 568 */ 569 static int 570 mark_tar_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 571 { 572 int rv; 573 574 if (ndmp_tar_force_traverse) 575 rv = mark_common_v2(session, nlp); 576 else 577 rv = create_allset_bitmap(nlp); 578 579 return (rv); 580 } 581 582 583 /* 584 * mark_dump_inodes_v2 585 * 586 * Create the bitmap for dump backup format. 587 * 588 * Parameters: 589 * session (input) - pointer to the session 590 * nlp (input) - pointer to the nlp structure 591 * 592 * Returns: 593 * 0: on success. 594 * != 0: on error. 595 */ 596 static int 597 mark_dump_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 598 { 599 return (mark_common_v2(session, nlp)); 600 } 601 602 603 /* 604 * ndmpd_mark_inodes_v2 605 * 606 * Mark the inodes of the backup hierarchy if necessary. 607 * 608 * Parameters: 609 * session (input) - pointer to the session 610 * nlp (input) - pointer to the nlp structure 611 * 612 * Returns: 613 * 0: on success. 614 * != 0: on error. 615 */ 616 int 617 ndmpd_mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 618 { 619 int rv; 620 621 if (ndmp_skip_traverse) { 622 NDMP_LOG(LOG_INFO, "Skip processing directories \"%s\"", 623 nlp->nlp_backup_path); 624 rv = create_allset_bitmap(nlp); 625 } else { 626 if (NLP_ISTAR(nlp)) 627 rv = mark_tar_inodes_v2(session, nlp); 628 else if (NLP_ISDUMP(nlp)) 629 rv = mark_dump_inodes_v2(session, nlp); 630 else { 631 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"", 632 nlp->nlp_backup_path); 633 rv = -1; 634 } 635 } 636 637 return (rv); 638 } 639 640 641 /* 642 * ndmpd_abort_making_v2 643 * 644 * Abort the process of marking inodes. 645 * 646 * Parameters: 647 * session (input) - pointer to the session 648 * 649 * Returns: 650 * void 651 */ 652 void 653 ndmpd_abort_marking_v2(ndmpd_session_t *session) 654 { 655 ndmp_lbr_params_t *nlp; 656 657 nlp = ndmp_get_nlp(session); 658 if (nlp) 659 NLP_SET(nlp, NLPF_ABORTED); 660 } 661 662 663 /* 664 * mark_tokv3 665 * 666 * Traverse the backup hierarchy and mark the bits for the 667 * modified objects of directories leading to a modified 668 * object for the token-based backup. 669 * 670 * Parameters: 671 * session (input) - pointer to the session 672 * nlp (input) - pointer to the nlp structure 673 * path (input) - the physical path to traverse 674 * 675 * Returns: 676 * 0: on success 677 * != 0: otherwise 678 */ 679 int 680 mark_tokv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path) 681 { 682 fs_traverse_t ft; 683 mark_param_t mp; 684 685 if (!session || !nlp || !path || !*path) { 686 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 687 return (-1); 688 } 689 if (nlp->nlp_tokdate == (time_t)0) 690 return (create_allset_bitmap(nlp)); 691 692 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0); 693 if (nlp->nlp_bkmap < 0) { 694 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap."); 695 return (-1); 696 } 697 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap); 698 699 mp.mp_bmd = nlp->nlp_bkmap; 700 mp.mp_ddate = nlp->nlp_tokdate; 701 mp.mp_session = session; 702 mp.mp_nlp = nlp; 703 704 ft.ft_path = path; 705 ft.ft_lpath = nlp->nlp_backup_path; 706 ft.ft_callbk = mark_cb; 707 ft.ft_arg = ∓ 708 ft.ft_logfp = (ft_log_t)ndmp_log; 709 ft.ft_flags = ndmpd_mark_flags; 710 711 return (traverse(session, nlp, &ft)); 712 } 713 714 715 /* 716 * marklbrv3_cb 717 * 718 * The callback function, called by traverse_post to mark 719 * bits in the bitmap. 720 * 721 * It's so much like mark_cb for time-based (token-based 722 * and level-type) backup types, except that it looks at 723 * the archive bit of the objects instead of their timestamp. 724 * 725 * Parameters: 726 * arg (input) - pointer to the mark parameter 727 * pnp (input) - pointer to the path node 728 * enp (input) - pointer to the entry node 729 * 730 * Returns: 731 * 0: as long as traversing should continue 732 * != 0: if traversing should stop 733 */ 734 int 735 marklbrv3_cb(void *arg, fst_node_t *pnp, fst_node_t *enp) 736 { 737 int bmd; 738 u_longlong_t bl; 739 fs_fhandle_t *pfhp, *efhp; 740 struct stat64 *pstp, *estp; 741 mark_param_t *mpp; 742 ndmp_lbr_params_t *nlp; 743 744 mpp = (mark_param_t *)arg; 745 if (!mpp) { 746 NDMP_LOG(LOG_DEBUG, "NULL argument passed"); 747 return (-1); 748 } 749 nlp = ndmp_get_nlp(mpp->mp_session); 750 if (mpp->mp_session->ns_data.dd_abort || 751 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) { 752 NDMP_LOG(LOG_INFO, "Processing directories aborted."); 753 return (-1); 754 } 755 756 bmd = mpp->mp_bmd; 757 bl = dbm_getlen(bmd); 758 759 pfhp = pnp->tn_fh; 760 pstp = pnp->tn_st; 761 762 /* sanity check on fh and stat of the path passed */ 763 if (pstp->st_ino > bl) { 764 NDMP_LOG(LOG_DEBUG, "Invalid path inode #%u", 765 (uint_t)pstp->st_ino); 766 return (-1); 767 } 768 if (pstp->st_ino != pfhp->fh_fid) { 769 NDMP_LOG(LOG_DEBUG, "Path ino mismatch %u %u", 770 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid); 771 return (-1); 772 } 773 774 /* 775 * Always mark the backup path inode number. 776 */ 777 if (!enp->tn_path) { 778 (void) dbm_setone(bmd, pstp->st_ino); 779 if (ndmpd_verbose_traverse) { 780 NDMP_LOG(LOG_DEBUG, "d(%u)", (uint_t)pstp->st_ino); 781 NDMP_LOG(LOG_DEBUG, "\"%s\"", pnp->tn_path); 782 } 783 return (0); 784 } 785 786 efhp = enp->tn_fh; 787 estp = enp->tn_st; 788 789 /* sanity check on fh and stat of the entry passed */ 790 if (estp->st_ino > bl) { 791 NDMP_LOG(LOG_DEBUG, "Invalid entry inode #%u", 792 (uint_t)estp->st_ino); 793 return (-1); 794 } 795 if (estp->st_ino != efhp->fh_fid) { 796 NDMP_LOG(LOG_DEBUG, "Entry ino mismatch %u %u", estp->st_ino, 797 (uint_t)pfhp->fh_fid); 798 return (-1); 799 } 800 801 if (S_ISDIR(estp->st_mode) && 802 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) { 803 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); 804 if (ndmpd_verbose_traverse) { 805 NDMP_LOG(LOG_DEBUG, "d(%u,%u)", 806 (uint_t)pstp->st_ino, (uint_t)estp->st_ino); 807 NDMP_LOG(LOG_DEBUG, "\"%s, %s\"", 808 pnp->tn_path, enp->tn_path); 809 } 810 } 811 812 return (0); 813 } 814 815 816 /* 817 * mark_lbrv3 818 * 819 * Traverse the backup hierarchy and mark the bits for the 820 * modified objects of directories leading to a modified 821 * object for the LBR-type backup. 822 * 823 * Parameters: 824 * session (input) - pointer to the session 825 * nlp (input) - pointer to the nlp structure 826 * path (input) - the physical path to traverse 827 * 828 * Returns: 829 * 0: on success 830 * != 0: otherwise 831 */ 832 int 833 mark_lbrv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path) 834 { 835 char c; 836 fs_traverse_t ft; 837 mark_param_t mp; 838 839 if (!session || !nlp || !path || !*path) { 840 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 841 return (-1); 842 } 843 /* full and archive backups backup everything */ 844 c = toupper(nlp->nlp_clevel); 845 if (c == 'F' || c == 'A') 846 return (create_allset_bitmap(nlp)); 847 848 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0); 849 if (nlp->nlp_bkmap < 0) { 850 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap."); 851 return (-1); 852 } 853 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap); 854 855 mp.mp_bmd = nlp->nlp_bkmap; 856 mp.mp_ddate = 0; 857 mp.mp_session = session; 858 mp.mp_nlp = nlp; 859 860 ft.ft_path = path; 861 ft.ft_lpath = nlp->nlp_backup_path; 862 ft.ft_callbk = marklbrv3_cb; 863 ft.ft_arg = ∓ 864 ft.ft_logfp = (ft_log_t)ndmp_log; 865 ft.ft_flags = ndmpd_mark_flags; 866 867 return (traverse(session, nlp, &ft)); 868 } 869 870 871 /* 872 * mark_levelv3 873 * 874 * Traverse the backup hierarchy and mark the bits for the 875 * modified objects of directories leading to a modified 876 * object for the level-type backup. 877 * 878 * Parameters: 879 * session (input) - pointer to the session 880 * nlp (input) - pointer to the nlp structure 881 * path (input) - the physical path to traverse 882 * 883 * Returns: 884 * 0: on success 885 * != 0: otherwise 886 */ 887 int 888 mark_levelv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path) 889 { 890 fs_traverse_t ft; 891 mark_param_t mp; 892 tlm_acls_t traverse_acl; 893 894 if (!session || !nlp || !path || !*path) { 895 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 896 return (-1); 897 } 898 if (nlp->nlp_ldate == (time_t)0) 899 return (create_allset_bitmap(nlp)); 900 901 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0); 902 if (nlp->nlp_bkmap < 0) { 903 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap."); 904 return (-1); 905 } 906 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap); 907 908 /* 909 * We do not want to allocate memory for acl every time we 910 * process a file. 911 */ 912 (void) memset(&traverse_acl, 0, sizeof (traverse_acl)); 913 mp.mp_tacl = &traverse_acl; 914 915 mp.mp_bmd = nlp->nlp_bkmap; 916 mp.mp_ddate = nlp->nlp_ldate; 917 mp.mp_session = session; 918 mp.mp_nlp = nlp; 919 920 ft.ft_path = path; 921 ft.ft_lpath = nlp->nlp_backup_path; 922 ft.ft_callbk = mark_cb; 923 ft.ft_arg = ∓ 924 ft.ft_logfp = (ft_log_t)ndmp_log; 925 ft.ft_flags = ndmpd_mark_flags; 926 927 return (traverse(session, nlp, &ft)); 928 } 929 930 931 /* 932 * mark_commonv3 933 * 934 * Create the inode bitmap. If last date of the the 935 * backup is epoch, then all the objects should be backed 936 * up; there is no need to traverse the backup hierarchy 937 * and mark the inodes. All the bits should be marked. 938 * 939 * Otherwise, the backup hierarchy should be traversed and 940 * the objects should be marked. 941 * 942 * Parameters: 943 * session (input) - pointer to the session 944 * nlp (input) - pointer to the nlp structure 945 * 946 * Returns: 947 * 0: on success. 948 * != 0: on error. 949 */ 950 int 951 mark_commonv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 952 { 953 char buf[TLM_MAX_PATH_NAME], *chkpath; 954 int rv; 955 956 if (NLP_ISCHKPNTED(nlp)) 957 chkpath = nlp->nlp_backup_path; 958 else 959 chkpath = tlm_build_snapshot_name(nlp->nlp_backup_path, buf, 960 nlp->nlp_jstat->js_job_name); 961 962 if (NLP_ISSET(nlp, NLPF_TOKENBK)) 963 rv = mark_tokv3(session, nlp, chkpath); 964 else if (NLP_ISSET(nlp, NLPF_LBRBK)) 965 rv = mark_lbrv3(session, nlp, chkpath); 966 else if (NLP_ISSET(nlp, NLPF_LEVELBK)) { 967 rv = mark_levelv3(session, nlp, chkpath); 968 } else { 969 rv = -1; 970 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"", 971 nlp->nlp_backup_path); 972 } 973 974 return (rv); 975 } 976 977 978 /* 979 * mark_tar_inodesv3 980 * 981 * Mark bits for tar backup format of V3. Normally, the 982 * backup hierarchy is not traversed for tar format 983 * unless it's forced by setting the ndmp_tar_force_traverse 984 * to a non-zero value. 985 * 986 * Parameters: 987 * session (input) - pointer to the session 988 * nlp (input) - pointer to the nlp structure 989 * 990 * Returns: 991 * 0: on success 992 * != 0: otherwise 993 */ 994 int 995 mark_tar_inodesv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 996 { 997 int rv; 998 999 if (ndmp_tar_force_traverse) 1000 rv = mark_commonv3(session, nlp); 1001 else 1002 rv = create_allset_bitmap(nlp); 1003 1004 return (rv); 1005 } 1006 1007 1008 /* 1009 * ndmpd_mark_inodes_v3 1010 * 1011 * Mark the inodes of the backup hierarchy if necessary. 1012 * 1013 * Parameters: 1014 * session (input) - pointer to the session 1015 * nlp (input) - pointer to the nlp structure 1016 * 1017 * Returns: 1018 * 0: on success. 1019 * != 0: on error. 1020 */ 1021 int 1022 ndmpd_mark_inodes_v3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) 1023 { 1024 int rv; 1025 1026 if (ndmp_skip_traverse) { 1027 NDMP_LOG(LOG_INFO, "Skip processing directories \"%s\"", 1028 nlp->nlp_backup_path); 1029 rv = create_allset_bitmap(nlp); 1030 } else { 1031 if (NLP_ISTAR(nlp)) 1032 rv = mark_tar_inodesv3(session, nlp); 1033 else if (NLP_ISDUMP(nlp)) { 1034 rv = mark_commonv3(session, nlp); 1035 } else { 1036 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"", 1037 nlp->nlp_backup_path); 1038 rv = -1; 1039 } 1040 } 1041 1042 return (rv); 1043 } 1044