/* * create_bitmap * * Create a dbitmap and return its descriptor. * * Parameters: * path (input) - path for which the bitmap should be created * value (input) - the initial value for the bitmap * * Returns: * the dbitmap descriptor */ static int create_bitmap(char *path, int value) { char bm_fname[PATH_MAX]; char buf[TLM_MAX_PATH_NAME]; char *livepath; ulong_t ninode; syslog(LOG_DEBUG, "path \"%s\"", path); if (fs_is_chkpntvol(path)) livepath = (char *)tlm_remove_checkpoint(path, buf); else livepath = path; ninode = 1024 * 1024 * 1024; if (ninode == 0) return (-1); (void) ndmpd_mk_temp(bm_fname); syslog(LOG_DEBUG, "path \"%s\"ninode %u bm_fname \"%s\"", livepath, ninode, bm_fname); return (dbm_alloc(bm_fname, (u_longlong_t)ninode, value)); }
/* * backup_work * * Start the NDMP backup (V2 only). */ int backup_work(char *bk_path, tlm_job_stats_t *job_stats, ndmp_run_args_t *np, tlm_commands_t *commands, ndmp_lbr_params_t *nlp) { struct full_dir_info dir_info; /* the blob to push/pop with cstack_t */ struct full_dir_info *t_dir_info, *p_dir_info; struct stat64 ret_attr; /* attributes of current file name */ fs_fhandle_t ret_fh; char *first_name; /* where the first name is located */ char *dname; int erc; int retval; cstack_t *stk; unsigned long fileid; tlm_acls_t tlm_acls; int dname_size; longlong_t fsize; bk_selector_t bks; tlm_cmd_t *local_commands; long dpos; NDMP_LOG(LOG_DEBUG, "nr_chkpnted %d nr_ldate: %u bk_path: \"%s\"", NLP_ISCHKPNTED(nlp), nlp->nlp_ldate, bk_path); /* Get every name in this directory */ dname = ndmp_malloc(TLM_MAX_PATH_NAME); if (dname == NULL) return (-ENOMEM); local_commands = commands->tcs_command; retval = 0; (void) memset(&bks, 0, sizeof (bks)); bks.bs_cookie = (void *)nlp; bks.bs_level = nlp->nlp_clevel; bks.bs_ldate = nlp->nlp_ldate; bks.bs_fn = timecmp; /* * should we skip the whole thing? */ if (tlm_is_excluded("", bk_path, np->nr_excls)) { NDMP_LOG(LOG_DEBUG, "%s excluded", bk_path); free(dname); return (0); } /* * Search for the top-level file-directory */ if (NLP_ISCHKPNTED(nlp)) { first_name = np->nr_chkp_nm; (void) strlcpy(first_name, bk_path, TLM_MAX_PATH_NAME); } else { first_name = tlm_build_snapshot_name(bk_path, np->nr_chkp_nm, nlp->nlp_jstat->js_job_name); } (void) memset(&ret_fh, 0, sizeof (ret_fh)); erc = fs_getstat(first_name, &ret_fh, &ret_attr); if (erc != 0) { NDMP_LOG(LOG_ERR, "Path %s not found.", first_name); free(dname); return (-EINVAL); } if ((stk = cstack_new()) == NULL) { free(dname); NDMP_LOG(LOG_DEBUG, "cstack_new failed"); return (-ENOMEM); } (void) strlcpy(dir_info.fd_dir_name, first_name, TLM_MAX_PATH_NAME); (void) memcpy(&dir_info.fd_dir_fh, &ret_fh, sizeof (fs_fhandle_t)); p_dir_info = dup_dir_info(&dir_info); /* * Push the first name onto the stack so that we can pop it back * off as part of the normal cycle */ if (cstack_push(stk, p_dir_info, 0)) { free(dname); free(p_dir_info); cstack_delete(stk); NDMP_LOG(LOG_DEBUG, "cstack_push failed"); return (-ENOMEM); } (void) memset(&tlm_acls, 0, sizeof (tlm_acls)); /* * Did NDMP create a checkpoint? */ if (NLP_ISCHKPNTED(nlp) || fs_is_rdonly(bk_path)) { tlm_acls.acl_checkpointed = FALSE; } else { /* Use the checkpoint created by NDMP */ tlm_acls.acl_checkpointed = TRUE; } /* * This is level-backup. It never resets the archive bit. */ tlm_acls.acl_clear_archive = FALSE; NDMP_LOG(LOG_DEBUG, "acls.chkpnt: %c acls.clear_arcbit: %c", NDMP_YORN(tlm_acls.acl_checkpointed), NDMP_YORN(tlm_acls.acl_clear_archive)); while (commands->tcs_reader == TLM_BACKUP_RUN && local_commands->tc_reader == TLM_BACKUP_RUN && cstack_pop(stk, (void **)&p_dir_info, 0) == 0) { if (NLP_ISCHKPNTED(nlp)) (void) strlcpy(np->nr_unchkp_nm, p_dir_info->fd_dir_name, TLM_MAX_PATH_NAME); else (void) tlm_remove_checkpoint(p_dir_info->fd_dir_name, np->nr_unchkp_nm); (void) backup_dir(np->nr_unchkp_nm, &tlm_acls, local_commands, job_stats, &bks); while (commands->tcs_reader == TLM_BACKUP_RUN && local_commands->tc_reader == TLM_BACKUP_RUN) { dname_size = TLM_MAX_PATH_NAME - 1; NDMP_LOG(LOG_DEBUG, "dir_name: %s", p_dir_info->fd_dir_name); (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); if (erc == 0) { fileid = ret_fh.fh_fid; } else { NDMP_LOG(LOG_DEBUG, "Filesystem readdir in [%s]", p_dir_info->fd_dir_name); retval = -ENOENT; break; } /* an empty name size marks the end of the list */ if (dname_size == 0) break; dname[dname_size] = '\0'; NDMP_LOG(LOG_DEBUG, "dname: \"%s\"", dname); /* * If name refers to a directory, push its file * handle onto the stack (skip "." and ".."). */ if (rootfs_dot_or_dotdot(dname)) { fileid = 0; continue; } /* * Skip the: * non-dir entries which should not be backed up * Or * dir-type entries which have have nothing under * their hierarchy to be backed up. */ if (!dbm_getone(nlp->nlp_bkmap, (u_longlong_t)fileid)) { NDMP_LOG(LOG_DEBUG, "Skipping %s/%s", p_dir_info->fd_dir_name, dname); fileid = 0; continue; } if (tlm_is_excluded(np->nr_unchkp_nm, dname, np->nr_excls)) { fileid = 0; continue; } if (S_ISDIR(ret_attr.st_mode)) { /* * only directories get pushed onto this stack, * so we do not have to test for regular files. */ t_dir_info = tlm_new_dir_info(&ret_fh, p_dir_info->fd_dir_name, dname); if (t_dir_info == NULL) { NDMP_LOG(LOG_DEBUG, "While backing up [%s][%s]", p_dir_info->fd_dir_name, dname); } else if (cstack_push(stk, t_dir_info, 0) != 0) { NDMP_LOG(LOG_DEBUG, "No enough memory stack_push"); retval = -ENOMEM; break; } } else if (S_ISREG(ret_attr.st_mode) || S_ISLNK(ret_attr.st_mode)) { fsize = backup_file(np->nr_unchkp_nm, dname, &tlm_acls, commands, local_commands, job_stats, &bks); if (fsize >= 0) { job_stats->js_files_so_far++; job_stats->js_bytes_total += fsize; } else job_stats->js_errors++; fileid = 0; } } fileid = 0; free(p_dir_info); if (retval != 0) break; } free(dname); while (cstack_pop(stk, (void **)&p_dir_info, 0) == 0) { free(p_dir_info); } cstack_delete(stk); return (retval); }