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