Print this page
NEX-13374 NDMP should be able to backup unmounted ZFS filesystems
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Revert "NEX-5801 Snapshots left over after failed backups"
This reverts commit f182fb95f09036db71fbfc6f0a6b90469b761f21.
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-2911 NDMP logging should use syslog and is too chatty


  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.


 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,


 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 = &mp;
 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.


 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  */


 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 = &mp;
 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 = &mp;
 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 = &mp;
 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


 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:


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 }


  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.


 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,


 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.


 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  */


 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


 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:


 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 }