Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
0
/*
 * mark_common_v2
 *
 * 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.
 */
static int
mark_common_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
{
    char buf[TLM_MAX_PATH_NAME], *chkpath;
    int rv;

    /*
     * Everything is needed for full backup.
     */
    if (nlp->nlp_ldate == (time_t)0)
        return (create_allset_bitmap(nlp));

    rv = 0;
    nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0);
    syslog(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);

    if (nlp->nlp_bkmap < 0) {
        syslog(LOG_ERR, "Failed to allocate bitmap in mark_common_v2");
        rv = -1;
    } else {
        if (fs_is_chkpntvol(nlp->nlp_backup_path))
            chkpath = nlp->nlp_backup_path;
        else
            chkpath = tlm_build_snapshot_name(
                          nlp->nlp_backup_path, buf,
                          nlp->nlp_jstat->js_job_name);
        rv = mark_inodes_v2(session, nlp, chkpath);
        (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE);
    }

    return (rv);
}
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
/*
 * get_dir_acl_info
 *
 * load up all ACL and attr info about a directory
 */
static int
get_dir_acl_info(char *dir, tlm_acls_t *tlm_acls, tlm_job_stats_t *js)
{
	int	erc;
	char	*checkpointed_dir;
	char	root_dir[TLM_VOLNAME_MAX_LENGTH];
	char	*spot;
	char	*fil;
	acl_t	*aclp = NULL;
	char 	*acltp;

	checkpointed_dir = ndmp_malloc(TLM_MAX_PATH_NAME);
	if (checkpointed_dir == NULL)
		return (-1);

	if (tlm_acls->acl_checkpointed)
		fil = tlm_build_snapshot_name(dir, checkpointed_dir,
		    js->js_job_name);
	else
		fil = dir;
	erc = lstat64(fil, &tlm_acls->acl_attr);
	if (erc != 0) {
		NDMP_LOG(LOG_ERR, "Could not find directory %s.", dir);
		free(checkpointed_dir);
		return (-1);
	}

	spot = strchr(&fil[1], '/');
	if (spot == NULL) {
		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
	} else {
		*spot = 0;
		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
		*spot = '/';
	}
	if (strcmp(root_dir, tlm_acls->acl_root_dir) != 0) {
		struct stat64 attr;

		erc = lstat64(root_dir, &attr);
		if (erc != 0) {
			NDMP_LOG(LOG_ERR, "Cannot find root directory %s.",
			    root_dir);
			free(checkpointed_dir);
			return (-1);
		}
		(void) strlcpy(tlm_acls->acl_root_dir, root_dir,
		    TLM_VOLNAME_MAX_LENGTH);
	}
	erc = acl_get(fil, ACL_NO_TRIVIAL, &aclp);
	if (erc != 0) {
		NDMP_LOG(LOG_DEBUG,
		    "Could not read metadata for directory [%s]", dir);
		free(checkpointed_dir);
		return (-1);
	}
	if (aclp && (acltp = acl_totext(aclp,
	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
		    TLM_MAX_ACL_TXT);
		acl_free(aclp);
		free(acltp);
	}

	free(checkpointed_dir);
	return (0);
}