Print this page
NEX-1348 It takes 23 hours and 37 minutes to run NDMP backup 43.9 GB with10000000 3KB files
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-13094 Netbackup 8.0 failed to back up files in NDMP certification test
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9532 NDMP: readdir errors when file/directory has special characters
Reviewed by: Peer Dampmann <peer.dampmann@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@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-2947 Volumes with more than a small fixed about don't traverse properly
NEX-2911 NDMP logging should use syslog and is too chatty
NEX-2692 ndmpd intermittently dumps core due to SIGABRT in umem
SUP-898 nscd is extremely slow when a local file is missing
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
NEX-2500 Conflict between NDMP backup job and 'zfs send' leads to NDMP job abort.
        
*** 33,42 ****
--- 33,44 ----
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   */
+ /* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
+ 
  /*
   * This file implemets the post-order, pre-order and level-order
   * traversing of the file system.  The related macros and constants
   * are defined in traverse.h.
   */
*** 78,88 ****
  /*
   * Macros on fs_traverse flags.
   */
  #define STOP_ONERR(f)   ((f)->ft_flags & FST_STOP_ONERR)
  #define STOP_ONLONG(f)  ((f)->ft_flags & FST_STOP_ONLONG)
- #define VERBOSE(f)      ((f)->ft_flags & FST_VERBOSE)
  
  #define CALLBACK(pp, ep)        \
          (*(ftp)->ft_callbk)((ftp)->ft_arg, pp, ep)
  
  #define NEGATE(rv)      ((rv) = -(rv))
--- 80,89 ----
*** 102,135 ****
          long ts_dpos; /* position in the directory when reading its entries */
          fs_fhandle_t ts_fh;
          struct stat64 ts_st;
  } traverse_state_t;
  
- /*
-  * Statistics gathering structure.
-  */
- typedef struct traverse_statistics {
-         ulong_t fss_newdirs;
-         ulong_t fss_readdir_err;
-         ulong_t fss_longpath_err;
-         ulong_t fss_lookup_err;
-         ulong_t fss_nondir_calls;
-         ulong_t fss_dir_calls;
-         ulong_t fss_nondir_skipped;
-         ulong_t fss_dir_skipped;
-         ulong_t fss_pushes;
-         ulong_t fss_pops;
-         ulong_t fss_stack_residue;
- } traverse_statistics_t;
- 
- /*
-  * Global instance of statistics variable.
-  */
- traverse_statistics_t traverse_stats;
- 
- #define MAX_DENT_BUF_SIZE       (8 * 1024)
- 
  typedef struct {
          struct stat64 fd_attr;
          fs_fhandle_t fd_fh;
          short fd_len;
          char fd_name[1];
--- 103,112 ----
*** 140,184 ****
          int da_end;
          int da_size;
  } dent_arg_t;
  
  static int traverse_level_nondir(struct fs_traverse *ftp,
!     traverse_state_t *tsp, struct fst_node *pnp,
!     dent_arg_t *darg);
  
  /*
-  * Gather some directory entry information and return them
-  */
- static int
- fs_populate_dents(void *arg, int namelen,
-     char *name, long *countp, struct stat64 *attr,
-     fs_fhandle_t *fh)
- {
-         dent_arg_t *darg = (dent_arg_t *)arg;
-         int reclen = sizeof (fs_dent_info_t) + namelen;
-         fs_dent_info_t *dent;
- 
-         if ((darg->da_end + reclen) > darg->da_size)
-                 return (-1);
- 
-         /* LINTED improper alignment */
-         dent = (fs_dent_info_t *)(darg->da_buf + darg->da_end);
- 
-         dent->fd_attr = *attr;
-         dent->fd_fh = *fh;
-         (void) strcpy(dent->fd_name, name);
- 
-         dent->fd_len = reclen;
-         darg->da_end += reclen;
- 
-         if (countp)
-                 (*countp)++;
- 
-         return (0);
- }
- 
- /*
   * Creates a new traversing state based on the path passed to it.
   */
  static traverse_state_t *
  new_tsp(char *path)
  {
--- 117,129 ----
          int da_end;
          int da_size;
  } dent_arg_t;
  
  static int traverse_level_nondir(struct fs_traverse *ftp,
!     traverse_state_t *tsp, struct fst_node *pnp);
  
  /*
   * Creates a new traversing state based on the path passed to it.
   */
  static traverse_state_t *
  new_tsp(char *path)
  {
*** 200,211 ****
   * Create a file handle and get stats for the given path
   */
  int
  fs_getstat(char *path, fs_fhandle_t *fh, struct stat64 *st)
  {
!         if (lstat64(path, st) == -1)
                  return (errno);
  
          fh->fh_fid = st->st_ino;
  
          if (!S_ISDIR(st->st_mode))
                  fh->fh_fpath = NULL;
--- 145,159 ----
   * Create a file handle and get stats for the given path
   */
  int
  fs_getstat(char *path, fs_fhandle_t *fh, struct stat64 *st)
  {
!         if (lstat64(path, st) == -1) {
!                 syslog(LOG_INFO,
!                     "lstat64() says [%s] not found errno=(%d)", path, errno);
                  return (errno);
+         }
  
          fh->fh_fid = st->st_ino;
  
          if (!S_ISDIR(st->st_mode))
                  fh->fh_fpath = NULL;
*** 213,286 ****
                  fh->fh_fpath = strdup(path);
          return (0);
  }
  
  /*
-  * Get directory entries info and return in the buffer. Cookie
-  * will keep the state of each call
-  */
- static int
- fs_getdents(int fildes, struct dirent *buf, size_t *nbyte,
-     char *pn_path, long *dpos, longlong_t *cookie,
-     long *n_entries, dent_arg_t *darg)
- {
-         struct dirent *ptr;
-         char file_path[PATH_MAX + 1];
-         fs_fhandle_t fh;
-         struct stat64 st;
-         char *p;
-         int len;
-         int rv;
- 
-         if (*nbyte == 0) {
-                 (void) memset((char *)buf, 0, MAX_DENT_BUF_SIZE);
-                 *nbyte = rv = getdents(fildes, buf, darg->da_size);
-                 *cookie = 0LL;
- 
-                 if (rv <= 0)
-                         return (rv);
-         }
- 
-         p = (char *)buf + *cookie;
-         len = *nbyte;
-         do {
-                 /* LINTED improper alignment */
-                 ptr = (struct dirent *)p;
-                 *dpos =  ptr->d_off;
- 
-                 if (rootfs_dot_or_dotdot(ptr->d_name))
-                         goto skip_entry;
- 
-                 (void) snprintf(file_path, PATH_MAX, "%s/", pn_path);
-                 (void) strlcat(file_path, ptr->d_name, PATH_MAX + 1);
-                 (void) memset(&fh, 0, sizeof (fs_fhandle_t));
- 
-                 if (lstat64(file_path, &st) != 0) {
-                         rv = -1;
-                         break;
-                 }
- 
-                 fh.fh_fid = st.st_ino;
- 
-                 if (S_ISDIR(st.st_mode))
-                         goto skip_entry;
- 
-                 if (fs_populate_dents(darg, strlen(ptr->d_name),
-                     (char *)ptr->d_name, n_entries, &st, &fh) != 0)
-                         break;
- 
- skip_entry:
-                 p = p + ptr->d_reclen;
-                 len -= ptr->d_reclen;
-         } while (len);
- 
-         *cookie = (longlong_t)(p - (char *)buf);
-         *nbyte = len;
-         return (rv);
- }
- 
- /*
   * Read the directory entries and return the information about
   * each entry
   */
  int
  fs_readdir(fs_fhandle_t *ts_fh, char *path, long *dpos,
--- 161,170 ----
*** 336,375 ****
          struct stat64 pst, est;
          traverse_state_t *tsp;
          struct fst_node pn, en; /* parent and entry nodes */
  
          if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
-                 NDMP_LOG(LOG_DEBUG, "Invalid argument");
                  errno = EINVAL;
                  return (-1);
          }
  
          /* set the default log function if it's not already set */
          if (!ftp->ft_logfp) {
                  ftp->ft_logfp = (ft_log_t)syslog;
!                 NDMP_LOG(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
          }
  
          /* set the logical path to physical path if it's not already set */
          if (!ftp->ft_lpath) {
!                 NDMP_LOG(LOG_DEBUG,
                      "report the same paths: \"%s\"", ftp->ft_path);
                  ftp->ft_lpath = ftp->ft_path;
          }
  
          pl = strlen(ftp->ft_lpath);
          if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
!                 NDMP_LOG(LOG_DEBUG, "lpath too long \"%s\"", ftp->ft_path);
                  errno = ENAMETOOLONG;
                  return (-1);
          }
          (void) strcpy(path, ftp->ft_lpath);
          (void) memset(&pfh, 0, sizeof (pfh));
          rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
  
          if (rv != 0) {
!                 NDMP_LOG(LOG_DEBUG,
                      "Error %d on fs_getstat(%s)", rv, ftp->ft_path);
                  return (rv);
          }
  
          if (!S_ISDIR(pst.st_mode)) {
--- 220,258 ----
          struct stat64 pst, est;
          traverse_state_t *tsp;
          struct fst_node pn, en; /* parent and entry nodes */
  
          if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
                  errno = EINVAL;
                  return (-1);
          }
  
          /* set the default log function if it's not already set */
          if (!ftp->ft_logfp) {
                  ftp->ft_logfp = (ft_log_t)syslog;
!                 syslog(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
          }
  
          /* set the logical path to physical path if it's not already set */
          if (!ftp->ft_lpath) {
!                 syslog(LOG_DEBUG,
                      "report the same paths: \"%s\"", ftp->ft_path);
                  ftp->ft_lpath = ftp->ft_path;
          }
  
          pl = strlen(ftp->ft_lpath);
          if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
!                 syslog(LOG_ERR, "lpath too long \"%s\"", ftp->ft_path);
                  errno = ENAMETOOLONG;
                  return (-1);
          }
          (void) strcpy(path, ftp->ft_lpath);
          (void) memset(&pfh, 0, sizeof (pfh));
          rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
  
          if (rv != 0) {
!                 syslog(LOG_ERR,
                      "Error %d on fs_getstat(%s)", rv, ftp->ft_path);
                  return (rv);
          }
  
          if (!S_ISDIR(pst.st_mode)) {
*** 378,389 ****
                  pn.tn_st = &pst;
                  en.tn_path = NULL;
                  en.tn_fh = NULL;
                  en.tn_st = NULL;
                  rv = CALLBACK(&pn, &en);
-                 if (VERBOSE(ftp))
-                         NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
                  free(pfh.fh_fpath);
                  return (rv);
          }
  
          sp = cstack_new();
--- 261,270 ----
*** 408,422 ****
  
          rv = 0;
          next_dir = 1;
          do {
                  if (next_dir) {
-                         traverse_stats.fss_newdirs++;
- 
                          *tsp->ts_end = '\0';
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG, "pl %d \"%s\"", pl, path);
                  }
  
                  next_dir = 0;
                  do {
                          el = NAME_MAX;
--- 289,299 ----
*** 423,436 ****
                          rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
                              &tsp->ts_dpos, nm, &el,
                              &efh, &est);
  
                          if (rv != 0) {
!                                 free(efh.fh_fpath);
!                                 traverse_stats.fss_readdir_err++;
! 
!                                 NDMP_LOG(LOG_DEBUG,
                                      "Error %d on readdir(%s) pos %d",
                                      rv, path, tsp->ts_dpos);
                                  if (STOP_ONERR(ftp))
                                          break;
                                  rv = SKIP_ENTRY;
--- 300,310 ----
                          rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
                              &tsp->ts_dpos, nm, &el,
                              &efh, &est);
  
                          if (rv != 0) {
!                                 syslog(LOG_ERR,
                                      "Error %d on readdir(%s) pos %d",
                                      rv, path, tsp->ts_dpos);
                                  if (STOP_ONERR(ftp))
                                          break;
                                  rv = SKIP_ENTRY;
*** 438,467 ****
                                  continue;
                          }
  
                          /* done with this directory */
                          if (el == 0) {
-                                 if (VERBOSE(ftp))
-                                         NDMP_LOG(LOG_DEBUG,
-                                             "Done(%s)", pn.tn_path);
                                  break;
                          }
                          nm[el] = '\0';
  
                          if (rootfs_dot_or_dotdot(nm)) {
                                  free(efh.fh_fpath);
                                  continue;
                          }
  
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG, "%u dname: \"%s\"",
-                                     tsp->ts_dpos, nm);
- 
                          if (pl + 1 + el > PATH_MAX) {
!                                 traverse_stats.fss_longpath_err++;
! 
!                                 NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
                                      path, nm);
                                  if (STOP_ONLONG(ftp))
                                          rv = ENAMETOOLONG;
                                  free(efh.fh_fpath);
                                  continue;
--- 312,332 ----
                                  continue;
                          }
  
                          /* done with this directory */
                          if (el == 0) {
                                  break;
                          }
                          nm[el] = '\0';
  
                          if (rootfs_dot_or_dotdot(nm)) {
                                  free(efh.fh_fpath);
                                  continue;
                          }
  
                          if (pl + 1 + el > PATH_MAX) {
!                                 syslog(LOG_ERR, "Path %s/%s is too long.",
                                      path, nm);
                                  if (STOP_ONLONG(ftp))
                                          rv = ENAMETOOLONG;
                                  free(efh.fh_fpath);
                                  continue;
*** 477,487 ****
                                  if (cstack_push(sp, tsp, 0)) {
                                          rv = ENOMEM;
                                          free(efh.fh_fpath);
                                          break;
                                  }
-                                 traverse_stats.fss_pushes++;
  
                                  /*
                                   * Concatenate the current entry with the
                                   * current path.  This will be the path of
                                   * the new directory to be scanned.
--- 342,351 ----
*** 516,537 ****
                          } else {
                                  /*
                                   * The entry is not a directory so the
                                   * callback function must be called.
                                   */
-                                 traverse_stats.fss_nondir_calls++;
- 
                                  en.tn_path = nm;
                                  en.tn_fh = &efh;
                                  en.tn_st = &est;
                                  rv = CALLBACK(&pn, &en);
                                  free(efh.fh_fpath);
-                                 if (VERBOSE(ftp))
-                                         NDMP_LOG(LOG_DEBUG,
-                                             "CALLBACK(%s/%s): %d",
-                                             pn.tn_path, en.tn_path, rv);
- 
                                  if (rv != 0)
                                          break;
                          }
                  } while (rv == 0);
  
--- 380,394 ----
*** 559,586 ****
                                  break;
  
                          assert(tsp != NULL);
                          pl = tsp->ts_end - path;
  
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG, "poped pl %d 0x%p \"%s\"",
-                                     pl, tsp, path);
- 
-                         traverse_stats.fss_pops++;
-                         traverse_stats.fss_dir_calls++;
- 
                          pn.tn_fh = &tsp->ts_fh;
                          pn.tn_st = &tsp->ts_st;
                          en.tn_path = lp + 1;
                          en.tn_fh = &efh;
                          en.tn_st = &est;
  
                          rv = CALLBACK(&pn, &en);
                          free(efh.fh_fpath);
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG, "CALLBACK(%s/%s): %d",
-                                     pn.tn_path, en.tn_path, rv);
                          /*
                           * Does not need to free tsp here.  It will be released
                           * later.
                           */
                  }
--- 416,433 ----
*** 594,621 ****
  
          /*
           * For the 'ftp->ft_path' directory itself.
           */
          if (rv == 0) {
-                 traverse_stats.fss_dir_calls++;
- 
                  pn.tn_fh = &efh;
                  pn.tn_st = &est;
                  en.tn_path = NULL;
                  en.tn_fh = NULL;
                  en.tn_st = NULL;
                  rv = CALLBACK(&pn, &en);
-                 if (VERBOSE(ftp))
-                         NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
          }
  
          /*
           * Pop and free all the remaining entries on the stack.
           */
          while (!cstack_pop(sp, (void **)&tsp, (int *)NULL)) {
-                 traverse_stats.fss_stack_residue++;
- 
                  free(tsp->ts_fh.fh_fpath);
                  free(tsp);
          }
  
          cstack_delete(sp);
--- 441,462 ----
*** 635,741 ****
   *    SKIP_ENTRY: Failed to get the directory entries, so the caller
   *        should skip this entry.
   */
  static int
  traverse_level_nondir(struct fs_traverse *ftp,
!     traverse_state_t *tsp, struct fst_node *pnp, dent_arg_t *darg)
  {
!         int pl; /* path length */
!         int rv;
          struct fst_node en; /* entry node */
!         longlong_t cookie_verf;
!         fs_dent_info_t *dent;
!         struct dirent *buf;
!         size_t len = 0;
!         int fd;
  
!         rv = 0;
!         pl = strlen(pnp->tn_path);
! 
!         buf = ndmp_malloc(MAX_DENT_BUF_SIZE);
!         if (buf == NULL)
                  return (errno);
  
!         fd = open(tsp->ts_fh.fh_fpath, O_RDONLY);
!         if (fd == -1) {
!                 free(buf);
!                 return (errno);
          }
  
!         while (rv == 0) {
!                 long i, n_entries;
! 
!                 darg->da_end = 0;
!                 n_entries = 0;
!                 rv = fs_getdents(fd, buf, &len, pnp->tn_path, &tsp->ts_dpos,
!                     &cookie_verf, &n_entries, darg);
!                 if (rv < 0) {
!                         traverse_stats.fss_readdir_err++;
! 
!                         NDMP_LOG(LOG_DEBUG, "Error %d on readdir(%s) pos %d",
!                             rv, pnp->tn_path, tsp->ts_dpos);
!                         if (STOP_ONERR(ftp))
!                                 break;
!                         /*
!                          * We cannot read the directory entry, we should
!                          * skip to the next directory.
!                          */
!                         rv = SKIP_ENTRY;
                          continue;
-                 } else {
-                         /* Break at the end of directory */
-                         if (rv > 0)
-                                 rv = 0;
-                         else
-                                 break;
                  }
  
!                 /* LINTED imporper alignment */
!                 dent = (fs_dent_info_t *)darg->da_buf;
!                 /* LINTED imporper alignment */
!                 for (i = 0; i < n_entries; i++, dent = (fs_dent_info_t *)
!                     ((char *)dent + dent->fd_len)) {
! 
!                         if (VERBOSE(ftp))
!                                 NDMP_LOG(LOG_DEBUG, "i %u dname: \"%s\"",
!                                     dent->fd_fh.fh_fid, dent->fd_name);
! 
!                         if ((pl + strlen(dent->fd_name)) > PATH_MAX) {
!                                 traverse_stats.fss_longpath_err++;
! 
!                                 NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
!                                     pnp->tn_path, dent->fd_name);
!                                 if (STOP_ONLONG(ftp))
!                                         rv = -ENAMETOOLONG;
!                                 free(dent->fd_fh.fh_fpath);
                                  continue;
                          }
  
                          /*
                           * The entry is not a directory so the callback
                           * function must be called.
                           */
!                         if (!S_ISDIR(dent->fd_attr.st_mode)) {
!                                 traverse_stats.fss_nondir_calls++;
! 
!                                 en.tn_path = dent->fd_name;
!                                 en.tn_fh = &dent->fd_fh;
!                                 en.tn_st = &dent->fd_attr;
                                  rv = CALLBACK(pnp, &en);
!                                 dent->fd_fh.fh_fpath = NULL;
!                                 if (rv < 0)
                                          break;
                                  if (rv == FST_SKIP) {
!                                         traverse_stats.fss_nondir_skipped++;
                                          break;
                                  }
                          }
                  }
-         }
  
!         free(buf);
!         (void) close(fd);
          return (rv);
  }
  
  /*
   * Traverse the file system in the level-order way.  The description
--- 476,546 ----
   *    SKIP_ENTRY: Failed to get the directory entries, so the caller
   *        should skip this entry.
   */
  static int
  traverse_level_nondir(struct fs_traverse *ftp,
!     traverse_state_t *tsp, struct fst_node *pnp)
  {
!         struct stat64 st;
!         fs_fhandle_t fh;
!         DIR *dp;
!         struct dirent *dirp;
          struct fst_node en; /* entry node */
!         char path[MAXPATHLEN+MAXNAMELEN+2];
!         int rv = 0;
  
!         if ((dp = opendir(tsp->ts_fh.fh_fpath)) == NULL) {
!                 syslog(LOG_ERR,
!                     "traverse_level_nondir: open directory "
!                     "%s failed: %m", tsp->ts_fh.fh_fpath);
                  return (errno);
+         }
  
!         while ((dirp = readdir(dp)) != NULL) {
!                 if ((strcmp(dirp->d_name, ".") == 0) ||
!                     (strcmp(dirp->d_name, "..") == 0)) {
!                         continue;
                  }
  
!                 if (!tlm_cat_path(path, tsp->ts_fh.fh_fpath,
!                     dirp->d_name)) {
                          continue;
                  }
  
!                 if (lstat64(path, &st) != 0) {
!                         syslog(LOG_ERR,
!                             "traverse_level_nondir: failed to get file"
!                             " status for %s skipping: %m", tsp->ts_fh.fh_fpath);
                          continue;
                  }
+                 fh.fh_fid = st.st_ino;
  
                  /*
                   * The entry is not a directory so the callback
                   * function must be called.
                   */
!                 if (!S_ISDIR(st.st_mode)) {
!                         en.tn_path = dirp->d_name;
!                         en.tn_fh = &fh;
!                         en.tn_st = &st;
                          rv = CALLBACK(pnp, &en);
!                         if (rv < 0) {
!                                 syslog(LOG_DEBUG,
!                                     "traverse_level_nondir: result is %d "
!                                     "with %s", rv, path);
                                  break;
+                         }
                          if (rv == FST_SKIP) {
!                                 syslog(LOG_DEBUG,
!                                     "traverse_level_nondir: skipping "
!                                     "%s", path);
                                  break;
                          }
                  }
          }
  
!         (void) closedir(dp);
          return (rv);
  }
  
  /*
   * Traverse the file system in the level-order way.  The description
*** 753,792 ****
          cstack_t *sp;
          fs_fhandle_t pfh, efh;
          struct stat64 pst, est;
          traverse_state_t *tsp;
          struct fst_node pn, en;  /* parent and entry nodes */
-         dent_arg_t darg;
  
          if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
-                 NDMP_LOG(LOG_DEBUG, "Invalid argument");
                  errno = EINVAL;
                  return (-1);
          }
          /* set the default log function if it's not already set */
          if (!ftp->ft_logfp) {
                  ftp->ft_logfp = (ft_log_t)syslog;
!                 NDMP_LOG(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
          }
          if (!ftp->ft_lpath) {
!                 NDMP_LOG(LOG_DEBUG,
                      "report the same paths \"%s\"", ftp->ft_path);
                  ftp->ft_lpath = ftp->ft_path;
          }
  
          pl = strlen(ftp->ft_lpath);
          if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
!                 NDMP_LOG(LOG_DEBUG, "lpath too long \"%s\"", ftp->ft_path);
                  errno = ENAMETOOLONG;
                  return (-1);
          }
          (void) strcpy(path, ftp->ft_lpath);
          (void) memset(&pfh, 0, sizeof (pfh));
          rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
          if (rv != 0) {
!                 NDMP_LOG(LOG_DEBUG,
!                     "Error %d on fs_getstat(%s)", rv, ftp->ft_path);
                  return (-1);
          }
  
          en.tn_path = NULL;
          en.tn_fh = NULL;
--- 558,595 ----
          cstack_t *sp;
          fs_fhandle_t pfh, efh;
          struct stat64 pst, est;
          traverse_state_t *tsp;
          struct fst_node pn, en;  /* parent and entry nodes */
  
          if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
                  errno = EINVAL;
                  return (-1);
          }
          /* set the default log function if it's not already set */
          if (!ftp->ft_logfp) {
                  ftp->ft_logfp = (ft_log_t)syslog;
!                 syslog(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
          }
          if (!ftp->ft_lpath) {
!                 syslog(LOG_DEBUG,
                      "report the same paths \"%s\"", ftp->ft_path);
                  ftp->ft_lpath = ftp->ft_path;
          }
  
          pl = strlen(ftp->ft_lpath);
          if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
!                 syslog(LOG_ERR, "lpath too long \"%s\"", ftp->ft_path);
                  errno = ENAMETOOLONG;
                  return (-1);
          }
          (void) strcpy(path, ftp->ft_lpath);
          (void) memset(&pfh, 0, sizeof (pfh));
          rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
          if (rv != 0) {
!                 syslog(LOG_DEBUG,
!                     "Error %d on fs_getstat(%s)", rv, ftp->ft_lpath);
                  return (-1);
          }
  
          en.tn_path = NULL;
          en.tn_fh = NULL;
*** 794,806 ****
          if (!S_ISDIR(pst.st_mode)) {
                  pn.tn_path = ftp->ft_lpath;
                  pn.tn_fh = &pfh;
                  pn.tn_st = &pst;
                  rv = CALLBACK(&pn, &en);
-                 if (VERBOSE(ftp))
-                         NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
- 
                  free(pfh.fh_fpath);
                  return (rv);
          }
  
          sp = cstack_new();
--- 597,606 ----
*** 815,866 ****
                  free(pfh.fh_fpath);
                  errno = ENOMEM;
                  return (-1);
          }
  
-         darg.da_buf = ndmp_malloc(MAX_DENT_BUF_SIZE);
-         if (!darg.da_buf) {
-                 cstack_delete(sp);
-                 free(pfh.fh_fpath);
-                 free(tsp);
-                 errno = ENOMEM;
-                 return (-1);
-         }
-         darg.da_size = MAX_DENT_BUF_SIZE;
- 
          tsp->ts_ent = tsp->ts_end;
          tsp->ts_fh = pfh;
          tsp->ts_st = pst;
          pn.tn_path = path;
          pn.tn_fh = &tsp->ts_fh;
          pn.tn_st = &tsp->ts_st;
  
          /* call the callback function on the path itself */
-         traverse_stats.fss_dir_calls++;
          rv = CALLBACK(&pn, &en);
          if (rv < 0) {
                  free(tsp);
                  goto end;
          }
          if (rv == FST_SKIP) {
-                 traverse_stats.fss_dir_skipped++;
                  free(tsp);
                  rv = 0;
                  goto end;
          }
  
          rv = 0;
          next_dir = 1;
          do {
                  if (next_dir) {
-                         traverse_stats.fss_newdirs++;
- 
                          *tsp->ts_end = '\0';
!                         if (VERBOSE(ftp))
!                                 NDMP_LOG(LOG_DEBUG, "pl %d \"%s\"", pl, path);
! 
!                         rv = traverse_level_nondir(ftp, tsp, &pn, &darg);
                          if (rv < 0) {
                                  NEGATE(rv);
                                  free(tsp->ts_fh.fh_fpath);
                                  free(tsp);
                                  break;
--- 615,649 ----
                  free(pfh.fh_fpath);
                  errno = ENOMEM;
                  return (-1);
          }
  
          tsp->ts_ent = tsp->ts_end;
          tsp->ts_fh = pfh;
          tsp->ts_st = pst;
          pn.tn_path = path;
          pn.tn_fh = &tsp->ts_fh;
          pn.tn_st = &tsp->ts_st;
  
          /* call the callback function on the path itself */
          rv = CALLBACK(&pn, &en);
          if (rv < 0) {
                  free(tsp);
                  goto end;
          }
          if (rv == FST_SKIP) {
                  free(tsp);
                  rv = 0;
                  goto end;
          }
  
          rv = 0;
          next_dir = 1;
          do {
                  if (next_dir) {
                          *tsp->ts_end = '\0';
!                         rv = traverse_level_nondir(ftp, tsp, &pn);
                          if (rv < 0) {
                                  NEGATE(rv);
                                  free(tsp->ts_fh.fh_fpath);
                                  free(tsp);
                                  break;
*** 891,903 ****
                          el = NAME_MAX;
                          rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
                              &tsp->ts_dpos, nm, &el, &efh,
                              &est);
                          if (rv != 0) {
!                                 traverse_stats.fss_readdir_err++;
! 
!                                 NDMP_LOG(LOG_DEBUG,
                                      "Error %d on readdir(%s) pos %d",
                                      rv, path, tsp->ts_dpos);
                                  if (STOP_ONERR(ftp))
                                          break;
                                  rv = SKIP_ENTRY;
--- 674,684 ----
                          el = NAME_MAX;
                          rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
                              &tsp->ts_dpos, nm, &el, &efh,
                              &est);
                          if (rv != 0) {
!                                 syslog(LOG_DEBUG,
                                      "Error %d on readdir(%s) pos %d",
                                      rv, path, tsp->ts_dpos);
                                  if (STOP_ONERR(ftp))
                                          break;
                                  rv = SKIP_ENTRY;
*** 913,935 ****
                          if (rootfs_dot_or_dotdot(nm)) {
                                  free(efh.fh_fpath);
                                  continue;
                          }
  
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG, "%u dname: \"%s\"",
-                                     tsp->ts_dpos, nm);
- 
                          if (pl + 1 + el > PATH_MAX) {
                                  /*
                                   * The long paths were already encountered
                                   * when processing non-dir entries in.
                                   * traverse_level_nondir.
                                   * We don't increase fss_longpath_err
                                   * counter for them again here.
                                   */
!                                 NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
                                      path, nm);
                                  if (STOP_ONLONG(ftp))
                                          rv = ENAMETOOLONG;
                                  free(efh.fh_fpath);
                                  continue;
--- 694,712 ----
                          if (rootfs_dot_or_dotdot(nm)) {
                                  free(efh.fh_fpath);
                                  continue;
                          }
  
                          if (pl + 1 + el > PATH_MAX) {
                                  /*
                                   * The long paths were already encountered
                                   * when processing non-dir entries in.
                                   * traverse_level_nondir.
                                   * We don't increase fss_longpath_err
                                   * counter for them again here.
                                   */
!                                 syslog(LOG_ERR, "Path %s/%s is too long.",
                                      path, nm);
                                  if (STOP_ONLONG(ftp))
                                          rv = ENAMETOOLONG;
                                  free(efh.fh_fpath);
                                  continue;
*** 942,952 ****
                           * Call the callback function for the new
                           * directory found, then push the current
                           * directory on to the stack.  Then dive
                           * into the entry found.
                           */
-                         traverse_stats.fss_dir_calls++;
                          en.tn_path = nm;
                          en.tn_fh = &efh;
                          en.tn_st = &est;
                          rv = CALLBACK(&pn, &en);
  
--- 719,728 ----
*** 954,964 ****
                                  NEGATE(rv);
                                  free(efh.fh_fpath);
                                  break;
                          }
                          if (rv == FST_SKIP) {
-                                 traverse_stats.fss_dir_skipped++;
                                  free(efh.fh_fpath);
                                  rv = 0;
                                  continue;
                          }
  
--- 730,739 ----
*** 967,978 ****
                           * dive into the entry found.
                           */
                          if (cstack_push(sp, tsp, 0)) {
                                  rv = ENOMEM;
                          } else {
-                                 traverse_stats.fss_pushes++;
- 
                                  lp = tsp->ts_end;
                                  *tsp->ts_end = '/';
                                  (void) strcpy(tsp->ts_end + 1, nm);
  
                                  tsp = new_tsp(path);
--- 742,751 ----
*** 1009,1024 ****
  
                  if (rv == 0) {
                          if (cstack_pop(sp, (void **)&tsp, (int *)NULL))
                                  break;
  
-                         traverse_stats.fss_pops++;
- 
-                         if (VERBOSE(ftp))
-                                 NDMP_LOG(LOG_DEBUG,
-                                     "Poped pl %d \"%s\"", pl, path);
- 
                          *tsp->ts_end = '\0';
                          pl = tsp->ts_end - path;
                          pn.tn_fh = &tsp->ts_fh;
                          pn.tn_st = &tsp->ts_st;
                  }
--- 782,791 ----
*** 1026,1042 ****
  
          /*
           * Pop and free all the remaining entries on the stack.
           */
          while (!cstack_pop(sp, (void **)&tsp, (int *)NULL)) {
-                 traverse_stats.fss_stack_residue++;
- 
                  free(tsp->ts_fh.fh_fpath);
                  free(tsp);
          }
  end:
-         free(darg.da_buf);
          cstack_delete(sp);
          return (rv);
  }
  
  /*
--- 793,806 ----