/* * mark_commonv3 * * Create the inode bitmap. If last date of the the * backup is epoch, then all the objects should be backed * up; there is no need to traverse the backup hierarchy * and mark the inodes. All the bits should be marked. * * Otherwise, the backup hierarchy should be traversed and * the objects should be marked. * * Parameters: * session (input) - pointer to the session * nlp (input) - pointer to the nlp structure * * Returns: * 0: on success. * != 0: on error. */ int mark_commonv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp) { char buf[TLM_MAX_PATH_NAME], *chkpath; int rv; if (NLP_ISCHKPNTED(nlp)) chkpath = nlp->nlp_backup_path; else chkpath = tlm_build_snapshot_name(nlp->nlp_backup_path, buf, nlp->nlp_jstat->js_job_name); if (NLP_ISSET(nlp, NLPF_TOKENBK)) rv = mark_tokv3(session, nlp, chkpath); else if (NLP_ISSET(nlp, NLPF_LBRBK)) rv = mark_lbrv3(session, nlp, chkpath); else if (NLP_ISSET(nlp, NLPF_LEVELBK)) { rv = mark_levelv3(session, nlp, chkpath); } else { rv = -1; syslog(LOG_ERR, "Unknown backup type for \"%s\"", nlp->nlp_backup_path); } return (rv); }
/* * 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); }
/* * ndmpd_tar_backup_starter (V2 only) * * The main backup starter function. It creates a snapshot if necessary * and calls ndmp_tar_backup to perform the actual backup. It does the cleanup * and release the snapshot at the end. */ int ndmpd_tar_backup_starter(void *arg) { ndmpd_module_params_t *mod_params = arg; int err; ndmpd_session_t *session; ndmp_lbr_params_t *nlp; session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie); *(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session); ndmp_session_ref(session); err = 0; if (fs_is_chkpntvol(nlp->nlp_backup_path) || fs_is_rdonly(nlp->nlp_backup_path) || !fs_is_chkpnt_enabled(nlp->nlp_backup_path)) NLP_SET(nlp, NLPF_CHKPNTED_PATH); else { NLP_UNSET(nlp, NLPF_CHKPNTED_PATH); if (ndmp_create_snapshot(nlp->nlp_backup_path, nlp->nlp_jstat->js_job_name) < 0) { MOD_LOG(mod_params, "Error: creating checkpoint on %s\n", nlp->nlp_backup_path); /* -1 causes halt reason to become internal error. */ err = -1; } } NDMP_LOG(LOG_DEBUG, "NLPF_CHKPNTED_PATH: %c", NDMP_YORN(NLP_ISCHKPNTED(nlp))); NDMP_LOG(LOG_DEBUG, "err: %d, update %c", err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp))); if (err == 0) { err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate, nlp->nlp_jstat->js_job_name); if (err != 0) { NDMP_LOG(LOG_DEBUG, "err %d", err); } else { log_bk_params_v2(session, mod_params, nlp); err = ndmpd_tar_backup(session, mod_params, nlp); } } if (nlp->nlp_bkmap >= 0) { (void) dbm_free(nlp->nlp_bkmap); nlp->nlp_bkmap = -1; } if (!NLP_ISCHKPNTED(nlp)) (void) ndmp_remove_snapshot(nlp->nlp_backup_path, nlp->nlp_jstat->js_job_name); NDMP_LOG(LOG_DEBUG, "err %d, update %c", err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp))); if (err == 0 && NLP_SHOULD_UPDATE(nlp)) { if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel, nlp->nlp_cdate) < 0) { err = EPERM; MOD_LOG(mod_params, "Error: updating the dumpdates file on %s\n", nlp->nlp_backup_path); } } MOD_DONE(mod_params, err); /* nlp_params is allocated in start_backup() */ NDMP_FREE(nlp->nlp_params); NS_DEC(nbk); ndmp_session_unref(session); return (err); }