summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReza Sabdar <Reza.Sabdar@Sun.COM>2009-05-23 19:32:05 -0700
committerReza Sabdar <Reza.Sabdar@Sun.COM>2009-05-23 19:32:05 -0700
commit84bf06e9e5fd6d61897cc8c298a0f3e807b27094 (patch)
treedaf0144542baff5dad4851cd52f1e56969aeab5b
parent6cd9e705a60bbefe49d1a9cfff2944eaf6312c8b (diff)
downloadillumos-gate-84bf06e9e5fd6d61897cc8c298a0f3e807b27094.tar.gz
6840645 7000 NDMP: Backup "Out of memory" error on NDMP client with 10million+ files in multiple subdirs
-rw-r--r--usr/src/cmd/ndmpd/include/traverse.h7
-rw-r--r--usr/src/cmd/ndmpd/ndmp/ndmpd.h6
-rw-r--r--usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c5
-rw-r--r--usr/src/cmd/ndmpd/tlm/tlm_traverse.c169
4 files changed, 51 insertions, 136 deletions
diff --git a/usr/src/cmd/ndmpd/include/traverse.h b/usr/src/cmd/ndmpd/include/traverse.h
index da70ad2ba4..02d84a3c23 100644
--- a/usr/src/cmd/ndmpd/include/traverse.h
+++ b/usr/src/cmd/ndmpd/include/traverse.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -278,11 +278,6 @@ typedef struct fst_node {
struct stat64 *tn_st;
} fst_node_t;
-typedef struct path_list {
- char *pl_path;
- struct path_list *pl_next;
-} path_list_t;
-
extern int traverse_post(fs_traverse_t *);
extern int traverse_pre(fs_traverse_t *);
extern int traverse_level(fs_traverse_t *);
diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd.h b/usr/src/cmd/ndmpd/ndmp/ndmpd.h
index 205bc8f709..fa4e682c36 100644
--- a/usr/src/cmd/ndmpd/ndmp/ndmpd.h
+++ b/usr/src/cmd/ndmpd/ndmp/ndmpd.h
@@ -987,11 +987,9 @@ extern void ndmp_stop_remote_reader();
extern boolean_t match(char *, char *);
extern char *trim_whitespace(char *);
-extern int fs_getstat(char *, struct fs_fhandle *, struct stat64 *,
- path_list_t *);
+extern int fs_getstat(char *, struct fs_fhandle *, struct stat64 *);
extern int fs_readdir(struct fs_fhandle *, char *, long *,
- char *, int *, struct fs_fhandle *, struct stat64 *,
- path_list_t *);
+ char *, int *, struct fs_fhandle *, struct stat64 *);
extern int iscreated(ndmp_lbr_params_t *nlp, char *name, tlm_acls_t *tacl,
time_t t);
diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c
index f8cd04a880..dd91065cac 100644
--- a/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c
+++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c
@@ -694,7 +694,7 @@ backup_work(char *bk_path, tlm_job_stats_t *job_stats,
}
(void) memset(&ret_fh, 0, sizeof (ret_fh));
- erc = fs_getstat(first_name, &ret_fh, &ret_attr, NULL);
+ erc = fs_getstat(first_name, &ret_fh, &ret_attr);
if (erc != 0) {
NDMP_LOG(LOG_ERR, "Path %s not found.", first_name);
free(dname);
@@ -768,8 +768,7 @@ backup_work(char *bk_path, tlm_job_stats_t *job_stats,
(void) memset(&ret_fh, 0, sizeof (ret_fh));
erc = fs_readdir(&p_dir_info->fd_dir_fh,
p_dir_info->fd_dir_name, &dpos,
- dname, &dname_size, &ret_fh, &ret_attr,
- NULL);
+ dname, &dname_size, &ret_fh, &ret_attr);
if (erc == 0) {
fileid = ret_fh.fh_fid;
} else {
diff --git a/usr/src/cmd/ndmpd/tlm/tlm_traverse.c b/usr/src/cmd/ndmpd/tlm/tlm_traverse.c
index 11f33cff0f..27c9b5d456 100644
--- a/usr/src/cmd/ndmpd/tlm/tlm_traverse.c
+++ b/usr/src/cmd/ndmpd/tlm/tlm_traverse.c
@@ -198,75 +198,18 @@ new_tsp(char *path)
}
/*
- * Initialize a list for path names
- */
-path_list_t *
-fs_init_pathlist()
-{
- path_list_t *pl_head;
-
- pl_head = ndmp_malloc(sizeof (path_list_t));
- return (pl_head);
-}
-
-/*
- * Free the list of path names
- */
-void
-fs_free_pathlist(path_list_t *pl_head)
-{
- path_list_t *p = pl_head;
-
- while (p) {
- p = pl_head->pl_next;
- free(pl_head->pl_path);
- free(pl_head);
- pl_head = p;
- }
-}
-
-/*
- * Add a path in the list of path names
- */
-char *
-fs_add_pathlist(char *path, path_list_t **pp)
-{
- char *tpath;
-
- if (*pp) {
- (*pp)->pl_path = strdup(path);
- if ((*pp)->pl_path == NULL)
- return (NULL);
- tpath = (*pp)->pl_path;
- (*pp)->pl_next = ndmp_malloc(sizeof (path_list_t));
- if ((*pp)->pl_next == NULL)
- return (NULL);
- *pp = (*pp)->pl_next;
- (*pp)->pl_path = NULL;
- (*pp)->pl_next = NULL;
- return (tpath);
- }
- return (NULL);
-}
-
-/*
* Create a file handle and get stats for the given path
*/
int
-fs_getstat(char *path, fs_fhandle_t *fh, struct stat64 *st, path_list_t **pl)
+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)) {
+ if (!S_ISDIR(st->st_mode))
fh->fh_fpath = NULL;
- return (0);
- }
-
- if (pl)
- fh->fh_fpath = fs_add_pathlist(path, pl);
else
fh->fh_fpath = strdup(path);
return (0);
@@ -279,7 +222,7 @@ fs_getstat(char *path, fs_fhandle_t *fh, struct stat64 *st, path_list_t **pl)
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, path_list_t **pl)
+ long *n_entries, dent_arg_t *darg)
{
struct dirent *ptr;
char file_path[PATH_MAX + 1];
@@ -304,14 +247,23 @@ fs_getdents(int fildes, struct dirent *buf, size_t *nbyte,
/* 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);
(void) memset(&fh, 0, sizeof (fs_fhandle_t));
- rv = fs_getstat(file_path, &fh, &st, pl);
+ rv = lstat64(file_path, &st);
if (rv != 0)
break;
+ fh.fh_fid = st.st_ino;
+
+ if (S_ISDIR(st.st_mode))
+ goto skip_entry;
+
rv = fs_populate_dents(darg, strlen(ptr->d_name),
(char *)ptr->d_name, n_entries, &st, &fh);
@@ -320,6 +272,7 @@ fs_getdents(int fildes, struct dirent *buf, size_t *nbyte,
break;
}
+skip_entry:
p = p + ptr->d_reclen;
len -= ptr->d_reclen;
} while (len);
@@ -335,8 +288,7 @@ fs_getdents(int fildes, struct dirent *buf, size_t *nbyte,
*/
int
fs_readdir(fs_fhandle_t *ts_fh, char *path, long *dpos,
- char *nm, int *el, fs_fhandle_t *efh, struct stat64 *est,
- path_list_t **pl)
+ char *nm, int *el, fs_fhandle_t *efh, struct stat64 *est)
{
struct dirent *dp;
char file_path[PATH_MAX + 1];
@@ -354,7 +306,7 @@ fs_readdir(fs_fhandle_t *ts_fh, char *path, long *dpos,
(void) snprintf(file_path, PATH_MAX, "%s/", path);
(void) strlcat(file_path, dp->d_name, PATH_MAX);
- rv = fs_getstat(file_path, efh, est, pl);
+ rv = fs_getstat(file_path, efh, est);
if (rv == 0) {
*dpos = telldir(dirp);
(void) strlcpy(nm, dp->d_name, NAME_MAX);
@@ -388,7 +340,6 @@ traverse_post(struct fs_traverse *ftp)
struct stat64 pst, est;
traverse_state_t *tsp;
struct fst_node pn, en; /* parent and entry nodes */
- path_list_t *plhead, *plist;
if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
NDMP_LOG(LOG_DEBUG, "Invalid argument");
@@ -417,7 +368,7 @@ traverse_post(struct fs_traverse *ftp)
}
(void) strcpy(path, ftp->ft_lpath);
(void) memset(&pfh, 0, sizeof (pfh));
- rv = fs_getstat(ftp->ft_lpath, &pfh, &pst, NULL);
+ rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
if (rv != 0) {
NDMP_LOG(LOG_DEBUG,
@@ -459,13 +410,6 @@ traverse_post(struct fs_traverse *ftp)
pn.tn_fh = &tsp->ts_fh;
pn.tn_st = &tsp->ts_st;
- if ((plist = fs_init_pathlist()) == NULL) {
- errno = ENOMEM;
- free(pfh.fh_fpath);
- return (-1);
- }
- plhead = plist;
-
rv = 0;
next_dir = 1;
do {
@@ -482,10 +426,10 @@ traverse_post(struct fs_traverse *ftp)
el = NAME_MAX;
rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
&tsp->ts_dpos, nm, &el,
- &efh, &est, &plist);
+ &efh, &est);
if (rv != 0) {
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
traverse_stats.fss_readdir_err++;
NDMP_LOG(LOG_DEBUG,
@@ -508,7 +452,7 @@ traverse_post(struct fs_traverse *ftp)
nm[el] = '\0';
if (rootfs_dot_or_dotdot(nm)) {
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
continue;
}
@@ -523,7 +467,7 @@ traverse_post(struct fs_traverse *ftp)
path, nm);
if (STOP_ONLONG(ftp))
rv = ENAMETOOLONG;
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
continue;
}
@@ -536,7 +480,7 @@ traverse_post(struct fs_traverse *ftp)
assert(tsp != NULL);
if (cstack_push(sp, tsp, 0)) {
rv = ENOMEM;
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
break;
}
traverse_stats.fss_pushes++;
@@ -561,7 +505,7 @@ traverse_post(struct fs_traverse *ftp)
tsp = new_tsp(path);
if (!tsp) {
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
rv = ENOMEM;
} else {
next_dir = 1;
@@ -584,7 +528,7 @@ traverse_post(struct fs_traverse *ftp)
en.tn_fh = &efh;
en.tn_st = &est;
rv = CALLBACK(&pn, &en);
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
if (VERBOSE(ftp))
NDMP_LOG(LOG_DEBUG,
"CALLBACK(%s/%s): %d",
@@ -635,7 +579,7 @@ traverse_post(struct fs_traverse *ftp)
en.tn_st = &est;
rv = CALLBACK(&pn, &en);
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
if (VERBOSE(ftp))
NDMP_LOG(LOG_DEBUG, "CALLBACK(%s/%s): %d",
pn.tn_path, en.tn_path, rv);
@@ -645,8 +589,10 @@ traverse_post(struct fs_traverse *ftp)
*/
}
- if (rv != 0 && tsp)
+ if (rv != 0 && tsp) {
+ free(tsp->ts_fh.fh_fpath);
free(tsp);
+ }
} while (rv == 0);
@@ -672,11 +618,10 @@ traverse_post(struct fs_traverse *ftp)
while (!cstack_pop(sp, (void **)&tsp, (int *)NULL)) {
traverse_stats.fss_stack_residue++;
+ free(tsp->ts_fh.fh_fpath);
free(tsp);
}
- fs_free_pathlist(plhead);
- free(pfh.fh_fpath);
cstack_delete(sp);
return (rv);
}
@@ -698,14 +643,13 @@ static int
traverse_level_nondir(struct fs_traverse *ftp,
traverse_state_t *tsp, struct fst_node *pnp, dent_arg_t *darg)
{
- int pl; /* patth length */
+ 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;
- path_list_t *plhead, *plist;
int fd;
rv = 0;
@@ -720,12 +664,6 @@ traverse_level_nondir(struct fs_traverse *ftp,
free(buf);
return (errno);
}
- if ((plist = fs_init_pathlist()) == NULL) {
- free(buf);
- (void) close(fd);
- return (errno);
- }
- plhead = plist;
while (rv == 0) {
long i, n_entries;
@@ -733,7 +671,7 @@ traverse_level_nondir(struct fs_traverse *ftp,
darg->da_end = 0;
n_entries = 0;
rv = fs_getdents(fd, buf, &len, pnp->tn_path, &tsp->ts_dpos,
- &cookie_verf, &n_entries, darg, &plist);
+ &cookie_verf, &n_entries, darg);
if (n_entries == 0)
break;
if (rv != 0) {
@@ -759,11 +697,6 @@ traverse_level_nondir(struct fs_traverse *ftp,
for (i = 0; i < n_entries; i++, dent = (fs_dent_info_t *)
((char *)dent + dent->fd_len)) {
- if (rootfs_dot_or_dotdot(dent->fd_name)) {
- dent->fd_fh.fh_fpath = NULL;
- continue;
- }
-
if (VERBOSE(ftp))
NDMP_LOG(LOG_DEBUG, "i %u dname: \"%s\"",
dent->fd_fh.fh_fid, dent->fd_name);
@@ -775,6 +708,7 @@ traverse_level_nondir(struct fs_traverse *ftp,
pnp->tn_path, dent->fd_name);
if (STOP_ONLONG(ftp))
rv = -ENAMETOOLONG;
+ free(dent->fd_fh.fh_fpath);
continue;
}
@@ -796,13 +730,10 @@ traverse_level_nondir(struct fs_traverse *ftp,
traverse_stats.fss_nondir_skipped++;
break;
}
- } else {
- dent->fd_fh.fh_fpath = NULL;
}
}
}
- fs_free_pathlist(plhead);
free(buf);
(void) close(fd);
return (rv);
@@ -827,7 +758,6 @@ traverse_level(struct fs_traverse *ftp)
traverse_state_t *tsp;
struct fst_node pn, en; /* parent and entry nodes */
dent_arg_t darg;
- path_list_t *plhead, *plist;
if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
NDMP_LOG(LOG_DEBUG, "Invalid argument");
@@ -853,7 +783,7 @@ traverse_level(struct fs_traverse *ftp)
}
(void) strcpy(path, ftp->ft_lpath);
(void) memset(&pfh, 0, sizeof (pfh));
- rv = fs_getstat(ftp->ft_lpath, &pfh, &pst, NULL);
+ 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);
@@ -906,15 +836,6 @@ traverse_level(struct fs_traverse *ftp)
pn.tn_fh = &tsp->ts_fh;
pn.tn_st = &tsp->ts_st;
- if ((plist = fs_init_pathlist()) == NULL) {
- cstack_delete(sp);
- free(pfh.fh_fpath);
- free(tsp);
- errno = ENOMEM;
- return (-1);
- }
- plhead = plist;
-
/* call the callback function on the path itself */
traverse_stats.fss_dir_calls++;
rv = CALLBACK(&pn, &en);
@@ -942,6 +863,7 @@ traverse_level(struct fs_traverse *ftp)
rv = traverse_level_nondir(ftp, tsp, &pn, &darg);
if (rv < 0) {
NEGATE(rv);
+ free(tsp->ts_fh.fh_fpath);
free(tsp);
break;
}
@@ -971,7 +893,7 @@ traverse_level(struct fs_traverse *ftp)
el = NAME_MAX;
rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
&tsp->ts_dpos, nm, &el, &efh,
- &est, &plist);
+ &est);
if (rv != 0) {
traverse_stats.fss_readdir_err++;
@@ -991,7 +913,7 @@ traverse_level(struct fs_traverse *ftp)
nm[el] = '\0';
if (rootfs_dot_or_dotdot(nm)) {
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
continue;
}
@@ -1011,14 +933,12 @@ traverse_level(struct fs_traverse *ftp)
path, nm);
if (STOP_ONLONG(ftp))
rv = ENAMETOOLONG;
- efh.fh_fpath = NULL;
+ free(efh.fh_fpath);
continue;
}
- if (!S_ISDIR(est.st_mode)) {
- efh.fh_fpath = NULL;
+ if (!S_ISDIR(est.st_mode))
continue;
- }
/*
* Call the callback function for the new
@@ -1034,10 +954,12 @@ traverse_level(struct fs_traverse *ftp)
if (rv < 0) {
NEGATE(rv);
+ free(efh.fh_fpath);
break;
}
if (rv == FST_SKIP) {
traverse_stats.fss_dir_skipped++;
+ free(efh.fh_fpath);
rv = 0;
continue;
}
@@ -1046,9 +968,9 @@ traverse_level(struct fs_traverse *ftp)
* Push the current directory on to the stack and
* dive into the entry found.
*/
- if (cstack_push(sp, tsp, 0))
+ if (cstack_push(sp, tsp, 0)) {
rv = ENOMEM;
- else {
+ } else {
traverse_stats.fss_pushes++;
lp = tsp->ts_end;
@@ -1079,8 +1001,10 @@ traverse_level(struct fs_traverse *ftp)
if (next_dir)
continue;
skip_dir:
- if (tsp)
+ if (tsp) {
+ free(tsp->ts_fh.fh_fpath);
free(tsp);
+ }
if (rv == SKIP_ENTRY)
rv = 0;
@@ -1108,12 +1032,11 @@ skip_dir:
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);
- free(pfh.fh_fpath);
- fs_free_pathlist(plhead);
cstack_delete(sp);
return (rv);
}