/* * 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); }
/* * ndmpd_fhnode_v3_cb * * Callback function for file history node information */ int ndmpd_fhnode_v3_cb(lbr_fhlog_call_backs_t *cbp, char *dir, char *file, struct stat64 *stp, u_longlong_t off) { int err; ulong_t ino; ndmp_lbr_params_t *nlp; ndmpd_module_params_t *params; if (!cbp) { err = -1; syslog(LOG_DEBUG, "cbp is NULL"); } else if (!cbp->fh_cookie) { err = -1; syslog(LOG_DEBUG, "cookie is NULL"); } else if (!dir) { err = -1; syslog(LOG_DEBUG, "dir is NULL"); } else if (!file) { err = -1; syslog(LOG_DEBUG, "file is NULL"); } else if (!stp) { err = -1; syslog(LOG_DEBUG, "stp is NULL"); } else if (!(nlp = ndmp_get_nlp(cbp->fh_cookie))) { err = -1; syslog(LOG_DEBUG, "nlp is NULL"); } else { err = 0; } if (err != 0) return (0); err = 0; if (NLP_ISSET(nlp, NLPF_FH)) { if (!NLP_ISSET(nlp, NLPF_DIRECT)) off = 0LL; if (stp->st_ino == nlp->nlp_bkdirino) { ino = ROOT_INODE; syslog(LOG_DEBUG, "bkroot %d -> %d", stp->st_ino, ROOT_INODE); } else ino = stp->st_ino; params = nlp->nlp_params; if (!params || !params->mp_file_history_node_func) err = -1; else if ((err = (*params->mp_file_history_node_func)(cbp-> fh_cookie, ino, stp, off)) < 0) syslog(LOG_ERR, "\"%s/%s\" %d", dir, file, err); } return (err); }
/* * fh_requested * * Check in LB parameters if file history is requested */ static boolean_t fh_requested(void *cookie) { ndmp_lbr_params_t *nlp; if ((nlp = ndmp_get_nlp(cookie)) == NULL) { syslog(LOG_DEBUG, "nlp is NULL"); return (FALSE); } syslog(LOG_DEBUG, "nlp_fh %c", NDMP_YORN(NLP_ISSET(nlp, NLPF_FH))); return (NLP_ISSET(nlp, NLPF_FH)); }
/* * ndmpd_fhpath_v3_cb * * Callback function for file history path information */ int ndmpd_fhpath_v3_cb(lbr_fhlog_call_backs_t *cbp, char *path, struct stat64 *stp, u_longlong_t off) { int err; ndmp_lbr_params_t *nlp; ndmpd_module_params_t *params; if (!cbp) { err = -1; syslog(LOG_DEBUG, "cbp is NULL"); } else if (!cbp->fh_cookie) { err = -1; syslog(LOG_DEBUG, "cookie is NULL"); } else if (!path) { err = -1; syslog(LOG_DEBUG, "path is NULL"); } else if (!(nlp = ndmp_get_nlp(cbp->fh_cookie))) { err = -1; syslog(LOG_DEBUG, "nlp is NULL"); } else err = 0; if (err != 0) return (0); err = 0; if (NLP_ISSET(nlp, NLPF_FH)) { if (!NLP_ISSET(nlp, NLPF_DIRECT)) { syslog(LOG_DEBUG, "DAR NOT SET!"); off = 0LL; } params = get_params(cbp->fh_cookie); if (!params || !params->mp_file_history_path_func) { err = -1; } else { char *p = ndmp_get_relative_path(get_backup_path_v3(params), path); if ((err = ndmpd_api_file_history_file_v3(cbp-> fh_cookie, p, stp, off)) < 0) syslog(LOG_DEBUG, "\"%s\" %d", path, err); } } return (err); }
/* * log_bk_params_v2 * * Dump the value of the parameters in the log file for debugging. */ void log_bk_params_v2(ndmpd_session_t *session, ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp) { MOD_LOG(params, "Date of this level %d on \"%s\": %s\n", nlp->nlp_clevel, nlp->nlp_backup_path, cctime(&nlp->nlp_cdate)); MOD_LOG(params, "Date of last level %d on \"%s\": %s\n", nlp->nlp_llevel, nlp->nlp_backup_path, cctime(&nlp->nlp_ldate)); MOD_LOG(params, "Backing up: \"%s\".\n", nlp->nlp_backup_path); MOD_LOG(params, "Record size: %d\n", session->ns_mover.md_record_size); MOD_LOG(params, "File history: %c.\n", NDMP_YORN(NLP_ISSET(nlp, NLPF_FH))); MOD_LOG(params, "Update: %s\n", NLP_ISSET(nlp, NLPF_UPDATE) ? "TRUE" : "FALSE"); }
/* * traverse * * Starts the post-traverse the backup hierarchy. Checks * for exceptional cases, like aborting operation and if * asked, report detailed information after traversing. * * Parameters: * session (input) - pointer to the session * nlp (input) - pointer to the nlp structure * ftp (input) - pointer to the traverse parameters * * Returns: * 0: on success * != 0: otherwise */ int traverse(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, fs_traverse_t *ftp) { int rv; time_t s, e; if (!session || !nlp || !ftp) { syslog(LOG_ERR, "Invalid argument in traverse"); return (-1); } syslog(LOG_DEBUG, "Processing directories of \"%s\"", nlp->nlp_backup_path); (void) time(&s); if (traverse_post(ftp) != 0) { rv = -1; if (!session->ns_data.dd_abort && !NLP_ISSET(nlp, NLPF_ABORTED)) { syslog(LOG_DEBUG, "Traversing backup path hierarchy \"%s\"", nlp->nlp_backup_path); } } else { (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE); rv = 0; (void) time(&e); syslog(LOG_DEBUG, "\"%s\" traversed in %u sec", nlp->nlp_backup_path, (uint_t)(e-s)); count_set_bits(nlp->nlp_backup_path, nlp->nlp_bkmap); } return (rv); }
/* * ndmpd_fhdir_v3_cb * * Callback function for file history dir information */ int ndmpd_fhdir_v3_cb(lbr_fhlog_call_backs_t *cbp, char *dir, struct stat64 *stp) { char nm[PATH_MAX+1]; int nml; int err; ulong_t ino, pino; ulong_t pos; ndmp_lbr_params_t *nlp; ndmpd_module_params_t *params; DIR *dirp; char dirpath[PATH_MAX]; if (!cbp) { err = -1; syslog(LOG_DEBUG, "cbp is NULL"); } else if (!cbp->fh_cookie) { err = -1; syslog(LOG_DEBUG, "cookie is NULL"); } else if (!dir) { err = -1; syslog(LOG_DEBUG, "dir is NULL"); } else if (!(nlp = ndmp_get_nlp(cbp->fh_cookie))) { err = -1; syslog(LOG_DEBUG, "nlp is NULL"); } else err = 0; if (err != 0) return (0); if (!NLP_ISSET(nlp, NLPF_FH)) return (0); /* * Veritas net_backup accepts only 2 as the inode number of the backup * root directory. The other way compares the path against the * backup path which is slower. */ if (stp->st_ino == nlp->nlp_bkdirino) pino = ROOT_INODE; else pino = stp->st_ino; /* * There is nothing below this directory to be backed up. * If there was, the bit for this directory would have * been set. Backup root directory is exception. We * always send the dir file history records of it. */ if (pino != ROOT_INODE && !dbm_getone(nlp->nlp_bkmap, (u_longlong_t)stp->st_ino)) { syslog(LOG_DEBUG, "nothing below here"); return (0); } params = nlp->nlp_params; if (!params || !params->mp_file_history_dir_func) return (-1); pos = 0; err = 0; dirp = opendir(dir); if (dirp == NULL) return (0); do { nml = PATH_MAX; err = dp_readdir(dirp, &pos, nm, &nml, &ino); if (err != 0) { syslog(LOG_DEBUG, "%d reading pos %u dir \"%s\"", err, pos, dir); break; } if (nml == 0) break; nm[nml] = '\0'; if (pino == ROOT_INODE) { if (rootfs_dot_or_dotdot(nm)) ino = ROOT_INODE; } else if (ino == nlp->nlp_bkdirino && IS_DOTDOT(nm)) { ino = ROOT_INODE; } if (!dbm_getone(nlp->nlp_bkmap, (u_longlong_t)ino)) continue; /* * If the entry is on exclusion list dont send the info */ if (tlm_is_excluded(dir, nm, ndmp_excl_list)) { syslog(LOG_DEBUG, "name \"%s\" skipped", nm == 0 ? "nil" : nm); continue; } err = (*params->mp_file_history_dir_func)(cbp->fh_cookie, nm, ino, pino); if (err < 0) { syslog(LOG_ERR, "\"%s\": %d", dir, err); break; } /* * This is a requirement by some DMA's (net_vault) that during * the incremental backup, the node info should also be sent * along with the dir info for all directories leading to a * backed up file. */ if (ndmp_fhinode) { struct stat64 ret_attr; (void) strlcpy(dirpath, dir, PATH_MAX); (void) strlcat(dirpath, "/", PATH_MAX); (void) strlcat(dirpath, nm, PATH_MAX); err = stat64(dirpath, &ret_attr); if (err != 0) { syslog(LOG_ERR, "Error looking up %s", nm); break; } if (S_ISDIR(ret_attr.st_mode)) { err = (*params->mp_file_history_node_func)(cbp-> fh_cookie, ino, &ret_attr, 0); if (err < 0) { syslog(LOG_ERR, "\"%s/\": %d", dir, err); break; } } } } while (err == 0); (void) closedir(dirp); return (err); }
/* * marklbrv3_cb * * The callback function, called by traverse_post to mark * bits in the bitmap. * * It's so much like mark_cb for time-based (token-based * and level-type) backup types, except that it looks at * the archive bit of the objects instead of their timestamp. * * Parameters: * arg (input) - pointer to the mark parameter * pnp (input) - pointer to the path node * enp (input) - pointer to the entry node * * Returns: * 0: as long as traversing should continue * != 0: if traversing should stop */ int marklbrv3_cb(void *arg, fst_node_t *pnp, fst_node_t *enp) { int bmd; u_longlong_t bl; fs_fhandle_t *pfhp, *efhp; struct stat64 *pstp, *estp; mark_param_t *mpp; ndmp_lbr_params_t *nlp; mpp = (mark_param_t *)arg; if (!mpp) { syslog(LOG_ERR, "NULL argument passed in marklbrv3"); return (-1); } nlp = ndmp_get_nlp(mpp->mp_session); if (mpp->mp_session->ns_data.dd_abort || (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) { syslog(LOG_ERR, "Processing directories aborted."); return (-1); } bmd = mpp->mp_bmd; bl = dbm_getlen(bmd); pfhp = pnp->tn_fh; pstp = pnp->tn_st; /* sanity check on fh and stat of the path passed */ if (pstp->st_ino > bl) { syslog(LOG_ERR, "Invalid path inode #%u", (uint_t)pstp->st_ino); return (-1); } if (pstp->st_ino != pfhp->fh_fid) { syslog(LOG_ERR, "Path ino mismatch %u %u", (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid); return (-1); } /* * Always mark the backup path inode number. */ if (!enp->tn_path) { (void) dbm_setone(bmd, pstp->st_ino); return (0); } efhp = enp->tn_fh; estp = enp->tn_st; /* sanity check on fh and stat of the entry passed */ if (estp->st_ino > bl) { syslog(LOG_DEBUG, "Invalid entry inode #%u", (uint_t)estp->st_ino); return (-1); } if (estp->st_ino != efhp->fh_fid) { syslog(LOG_DEBUG, "Entry ino mismatch %u %u", estp->st_ino, (uint_t)pfhp->fh_fid); return (-1); } if (S_ISDIR(estp->st_mode) && dbm_getone(bmd, (u_longlong_t)estp->st_ino)) { (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); } return (0); }
/* * mark_cb * * The callback function, called by traverse_post to mark bits * in the bitmap. * * Set the bit of the entry if it's been modified (obviously * should be backed up) plus its parent directory. * * If the entry is a directory and is not modified itself, * but it's marked, then there is something below it that * is being backed up. It shows the the path, leads to * an object that will be backed up. So the path should * be marked too. * * The backup path itself is always marked. * * Parameters: * arg (input) - pointer to the mark parameter * pnp (input) - pointer to the path node * enp (input) - pointer to the entry node * * Returns: * 0: as long as traversing should continue * != 0: if traversing should stop */ int mark_cb(void *arg, fst_node_t *pnp, fst_node_t *enp) { int bmd; int rv; u_longlong_t bl; time_t ddate; fs_fhandle_t *pfhp, *efhp; struct stat64 *pstp, *estp; mark_param_t *mpp; ndmp_lbr_params_t *nlp; tlm_acls_t *tacl; rv = 0; mpp = (mark_param_t *)arg; tacl = mpp->mp_tacl; nlp = ndmp_get_nlp(mpp->mp_session); if (!mpp) { syslog(LOG_ERR, "NULL argument passed"); rv = -1; } else if (mpp->mp_session->ns_eof) { syslog(LOG_INFO, "Connection to the client is closed"); rv = -1; } else if (mpp->mp_session->ns_data.dd_abort || (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) { syslog(LOG_INFO, "Processing directories aborted."); rv = -1; } if (rv != 0) return (rv); ddate = mpp->mp_ddate; bmd = mpp->mp_bmd; bl = dbm_getlen(bmd); pfhp = pnp->tn_fh; pstp = pnp->tn_st; /* sanity check on fh and stat of the path passed */ if (pstp->st_ino > bl) { syslog(LOG_ERR, "Invalid path inode #%u", (uint_t)pstp->st_ino); return (-1); } if (pstp->st_ino != pfhp->fh_fid) { syslog(LOG_ERR, "Path ino mismatch %u %u", (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid); return (-1); } /* * Always mark the backup path inode number. */ if (!enp->tn_path) { (void) dbm_setone(bmd, pstp->st_ino); return (0); } efhp = enp->tn_fh; estp = enp->tn_st; /* sanity check on fh and stat of the entry passed */ if (estp->st_ino > bl) { syslog(LOG_ERR, "Invalid entry inode #%u", (uint_t)estp->st_ino); return (-1); } if (estp->st_ino != efhp->fh_fid) { syslog(LOG_ERR, "Entry ino mismatch %u %u", estp->st_ino, (uint_t)pfhp->fh_fid); return (-1); } /* check the dates and mark the bitmap inode */ if (ddate == 0) { /* base backup */ (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); } else if (estp->st_mtime > ddate) { (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); if (ndmpd_verbose_traverse) { syslog(LOG_DEBUG, "m(%u,%u,%u,%u)", (uint_t)pstp->st_ino, (uint_t)estp->st_ino, (uint_t)estp->st_mtime, (uint_t)ddate); syslog(LOG_DEBUG, "\"%s/%s\"", pnp->tn_path, enp->tn_path); } } else if (iscreated(nlp, NULL, tacl, ddate)) { (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); if (ndmpd_verbose_traverse) { syslog(LOG_DEBUG, "cr(%u,%u,%u,%u)", (uint_t)pstp->st_ino, (uint_t)estp->st_ino, (uint_t)estp->st_mtime, (uint_t)ddate); syslog(LOG_DEBUG, "\"%s/%s\"", pnp->tn_path, enp->tn_path); } } else if (estp->st_ctime > ddate) { if (!NLP_IGNCTIME(nlp)) { (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino); (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); } if (ndmpd_verbose_traverse) { if (NLP_IGNCTIME(nlp)) { syslog(LOG_DEBUG, "ign c(%u,%u,%u,%u)", (uint_t)pstp->st_ino, (uint_t)estp->st_ino, (uint_t)estp->st_ctime, (uint_t)ddate); } else { syslog(LOG_DEBUG, "c(%u,%u,%u,%u)", (uint_t)pstp->st_ino, (uint_t)estp->st_ino, (uint_t)estp->st_ctime, (uint_t)ddate); } syslog(LOG_DEBUG, "\"%s/%s\"", pnp->tn_path, enp->tn_path); } } else if (S_ISDIR(estp->st_mode) && dbm_getone(bmd, (u_longlong_t)estp->st_ino)) { (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino); } return (0); }