Beispiel #1
0
/*
 * For the given bmap, change the status of all its replicas marked
 * "valid" to "invalid" except for the replica specified.
 *
 * This is a high-level convenience call provided to easily update
 * status after an ION has received some new I/O, which would make all
 * other existing copies of the bmap on any other replicas old.
 * @b: the bmap.
 * @iosidx: the index of the only ION resource in the inode replica
 *	table that should be marked "valid".
 *
 * Note: All callers must journal log these bmap replica changes
 *	themselves.  In addition, they must log any changes to the inode
 *	_before_ the bmap changes.  Otherwise, we could end up actually
 *	having bmap replicas that are not recognized by the information
 *	stored in the inode during log replay.
 */
int
mds_repl_inv_except(struct bmap *b, int iosidx)
{
	int rc, logit = 0, tract[NBREPLST], retifset[NBREPLST];
	uint32_t policy;

	/* Ensure replica on active IOS is marked valid. */
	brepls_init(tract, -1);
	tract[BREPLST_INVALID] = BREPLST_VALID;
	tract[BREPLST_GARBAGE_SCHED] = BREPLST_VALID;
	tract[BREPLST_GARBAGE_QUEUED] = BREPLST_VALID;

	/*
	 * The old state for this bmap on the given IOS is
	 * either valid or invalid.
	 */
	brepls_init_idx(retifset);
	retifset[BREPLST_INVALID] = 0;
	retifset[BREPLST_VALID] = 0;

	/*
	 * XXX on full truncate, the metafile will exist, which means
	 * the bmap states will exist, which means a new IOS will be
	 * selected which will probably be GARBAGE after truncate
	 * happens a few times.
	 */
	rc = mds_repl_bmap_walk(b, tract, retifset, 0, &iosidx, 1);
	if (rc) {
		psclog_errorx("bcs_repls has active IOS marked in a "
		    "weird state while invalidating other replicas; "
		    "fid="SLPRI_FID" bmap=%d iosidx=%d state=%d",
		    fcmh_2_fid(b->bcm_fcmh), b->bcm_bmapno, iosidx, rc);
	}

	policy = bmap_2_replpol(b);

	/*
	 * Invalidate all other replicas.
	 * Note: if the status is SCHED here, don't do anything; once
	 * the replication status update comes from the ION, we will
	 * know he copied an old bmap and mark it OLD then.
	 */
	brepls_init(tract, -1);
	tract[BREPLST_VALID] = policy == BRPOL_PERSIST ?
	    BREPLST_REPL_QUEUED : BREPLST_GARBAGE_QUEUED;
	tract[BREPLST_REPL_SCHED] = BREPLST_REPL_QUEUED;

	brepls_init(retifset, 0);
	retifset[BREPLST_VALID] = 1;
	retifset[BREPLST_REPL_SCHED] = 1;

	if (_mds_repl_bmap_walk(b, tract, retifset, REPL_WALKF_MODOTH,
	    &iosidx, 1, NULL, NULL)) {
		logit = 1;
		BHGEN_INCREMENT(b);
	}
	if (logit)
		rc = mds_bmap_write_logrepls(b);
	else
		rc = mds_bmap_write(b, NULL, NULL);

	/*
	 * If this bmap is marked for persistent replication, the repl
	 * request must exist and should be marked such that the
	 * replication monitors do not release it in the midst of
	 * processing it as this activity now means they have more to
	 * do.
	 */
	if (policy == BRPOL_PERSIST)
		upsch_enqueue(&bmap_2_bmi(b)->bmi_upd);
	return (rc);
}
Beispiel #2
0
int
mds_inode_dump(int vfsid, struct sl_ino_compat *sic,
    struct slash_inode_handle *ih, void *readh)
{
	struct fidc_membh *f;
	struct bmapc_memb *b;
	struct mio_fh *fh;
	sl_bmapno_t i;
	int rc, fl;
	void *th;

	f = inoh_2_fcmh(ih);
	th = inoh_2_mfh(ih);
	fh = inoh_2_mfh(ih);

	fl = BMAPGETF_CREATE | BMAPGETF_NOAUTOINST;
	if (sic)
		fl |= BMAPGETF_NORETRIEVE;

	for (i = 0; ; i++) {
		fh->fh = readh;
		rc = bmap_getf(f, i, SL_WRITE, fl, &b);
		fh->fh = th;

		if (rc == SLERR_BMAP_INVALID) {
			(void)INOH_RLOCK(ih);
			break;
		}

		if (rc)
			return (rc);

		if (sic) {
			rc = sic->sic_read_bmap(b, readh);
			if (rc) {
				bmap_op_done(b);
				(void)INOH_RLOCK(ih);
				if (rc == SLERR_BMAP_INVALID)
					break;
				return (rc);
			}
		}

		rc = mds_bmap_write(b, NULL, NULL);
		bmap_op_done(b);
		(void)INOH_RLOCK(ih);
		if (rc)
			return (rc);
	}

	rc = mds_inox_write(vfsid, ih, NULL, NULL);
	if (rc)
		return (rc);

	rc = mds_inode_write(vfsid, ih, NULL, NULL);
	if (rc)
		return (rc);

	mdsio_fsync(vfsid, &rootcreds, 1, th);
	return (0);
}