Exemplo n.º 1
0
/**
 * _slm_fcmh_endow - "Endow" or apply inheritance to a new directory
 *	entry from its parent directory replica layout.
 * Note: the bulk of this is empty until we have a place to store such
 * info in the SLASH2 metafile.
 */
int
_slm_fcmh_endow(int vfsid, struct fidc_membh *p, struct fidc_membh *c,
    int wr)
{
	sl_replica_t repls[SL_MAX_REPLICAS];
	int nr, rc = 0;
	uint32_t pol;

	FCMH_LOCK(p);
	pol = fcmh_2_ino(p)->ino_replpol;
	nr = fcmh_2_nrepls(p);
	memcpy(repls, fcmh_2_ino(p)->ino_repls, sizeof(repls[0]) *
	    SL_DEF_REPLICAS);
	if (nr > SL_DEF_REPLICAS) {
		mds_inox_ensure_loaded(fcmh_2_inoh(p));
		memcpy(&repls[SL_DEF_REPLICAS],
		    fcmh_2_inox(p)->inox_repls, sizeof(repls[0]) *
		    SL_INOX_NREPLICAS);
	}
	FCMH_ULOCK(p);

	FCMH_WAIT_BUSY(c);
	fcmh_2_replpol(c) = pol;
	fcmh_2_ino(c)->ino_nrepls = nr;
	memcpy(fcmh_2_ino(c)->ino_repls, repls, sizeof(repls[0]) *
	    SL_DEF_REPLICAS);
	if (nr > SL_DEF_REPLICAS) {
		mds_inox_ensure_loaded(fcmh_2_inoh(c));
		memcpy(fcmh_2_inox(c)->inox_repls,
		    &repls[SL_DEF_REPLICAS], sizeof(repls[0]) *
		    SL_INOX_NREPLICAS);
	}
	if (wr)
		mds_inodes_odsync(vfsid, c, mdslog_ino_repls);
	FCMH_UNBUSY(c);
	return (rc);
}
Exemplo n.º 2
0
void
slm_pack_inode(struct fidc_membh *f, struct srt_inode *in)
{
	struct slash_inode_handle *ih;
	int rc;

	ih = fcmh_2_inoh(f);
	in->newreplpol = ih->inoh_ino.ino_replpol;
	in->nrepls = ih->inoh_ino.ino_nrepls;
	memcpy(in->reptbl, &ih->inoh_ino.ino_repls,
	    sizeof(ih->inoh_ino.ino_repls));

	if (in->nrepls > SL_DEF_REPLICAS) {
		rc = mds_inox_ensure_loaded(ih);
		if (!rc)
			memcpy(&in->reptbl[SL_DEF_REPLICAS],
			    &ih->inoh_extras->inox_repls,
			    sizeof(ih->inoh_extras->inox_repls));
	}
}
Exemplo n.º 3
0
int
mds_repl_delrq(const struct sl_fidgen *fgp, sl_bmapno_t bmapno,
    sl_bmapno_t *nbmaps, sl_replica_t *iosv, int nios)
{
	int tract[NBREPLST], rc, iosidx[SL_MAX_REPLICAS], flags;
	sl_bmapno_t nbmaps_processed = 0;
	struct slm_repl_valid replv;
	struct fidc_membh *f = NULL;
	struct bmap *b;

	if (nios < 1 || nios > SL_MAX_REPLICAS || *nbmaps == 0)
		return (-EINVAL);

	rc = slm_fcmh_get(fgp, &f);
	if (rc)
		return (-rc);

	FCMH_LOCK(f);
	if (fcmh_isdir(f))
		flags = IOSV_LOOKUPF_DEL;
	else
		flags = IOSV_LOOKUPF_LOOKUP;

	/* Find replica IOS indexes. */
	rc = -_mds_repl_iosv_lookup(current_vfsid, fcmh_2_inoh(f), iosv,
	    iosidx, nios, flags);

	if (fcmh_isdir(f) || rc)
		PFL_GOTOERR(out, rc);

	replv.nios = nios;
	replv.idx = iosidx;

	brepls_init(tract, -1);
	tract[BREPLST_REPL_QUEUED] = BREPLST_GARBAGE_QUEUED;
	tract[BREPLST_REPL_SCHED] = BREPLST_GARBAGE_QUEUED;
	tract[BREPLST_VALID] = BREPLST_GARBAGE_QUEUED;

	/* Wildcards shouldn't result in errors on zero-length files. */
	if (*nbmaps != (sl_bmapno_t)-1)
		rc = -SLERR_BMAP_INVALID;

	/*
 	 * The following loop will bail out on the very first error. 
 	 * However,  its previous action, if any, has already taken
 	 * effect.
 	 */
	for (; *nbmaps && bmapno < fcmh_nvalidbmaps(f);
	    bmapno++, --*nbmaps, nbmaps_processed++) {
		if (nbmaps_processed >= SLM_REPLRQ_NBMAPS_MAX)
			PFL_GOTOERR(out, rc = -PFLERR_WOULDBLOCK);

		rc = -bmap_get(f, bmapno, SL_WRITE, &b);
		if (rc)
			PFL_GOTOERR(out, rc);
		/*
		 * Before blindly doing the transition, we have to check
		 * to ensure this operation would retain at least one
		 * valid replica.
		 */
		replv.n = 0;
		mds_repl_bmap_walkcb(b, NULL, NULL, 0,
		    slm_repl_countvalid_cb, &replv);

		flags = 0;
		if (replv.n == 0)
			rc = -SLERR_LASTREPL;
		else {
			rc = _mds_repl_bmap_walk(b, tract, NULL, 0, iosidx,
			    nios, slm_repl_delrq_cb, &flags);
			psc_assert(!rc);
			if (flags & FLAG_DIRTY)
				rc = mds_bmap_write_logrepls(b);
		}
		bmap_op_done_type(b, BMAP_OPCNT_LOOKUP);
		if (rc)
			PFL_GOTOERR(out, rc);
	}

 out:
	if (f)
		fcmh_op_done(f);
	*nbmaps = nbmaps_processed;
	return (rc);
}
Exemplo n.º 4
0
/*
 * Handle a request to do replication from a client.  May also
 * reinitialize some parameters of the replication, such as priority, if
 * the request already exists in the system.
 */
int
mds_repl_addrq(const struct sl_fidgen *fgp, sl_bmapno_t bmapno,
    sl_bmapno_t *nbmaps, sl_replica_t *iosv, int nios, int sys_prio,
    int usr_prio)
{
	int tract[NBREPLST], ret_hasvalid[NBREPLST];
	int iosidx[SL_MAX_REPLICAS], rc, flags;
	sl_bmapno_t nbmaps_processed = 0;
	struct fidc_membh *f = NULL;
	struct bmap *b;

	/* Perform sanity checks on request. */
	if (nios < 1 || nios > SL_MAX_REPLICAS || *nbmaps == 0)
		return (-EINVAL);

	rc = slm_fcmh_get(fgp, &f);
	if (rc)
		return (-rc);

	if (!fcmh_isdir(f) && !fcmh_isreg(f))
		PFL_GOTOERR(out, rc = -PFLERR_NOTSUP);

	/* Lookup replica(s)' indexes in our replica table. */
	rc = -mds_repl_iosv_lookup_add(current_vfsid, fcmh_2_inoh(f),
	    iosv, iosidx, nios);
	if (rc)
		PFL_GOTOERR(out, rc);

	/*
	 * If we are modifying a directory, we are done as just the
	 * replica table needs to be updated.
	 */
	if (fcmh_isdir(f))
		PFL_GOTOERR(out, 0);

	/*
	 * Setup structure to ensure at least one VALID replica exists.
	 */
	brepls_init(ret_hasvalid, 0);
	ret_hasvalid[BREPLST_VALID] = 1;

	/*
	 * Setup transitions to enqueue a replication.
	 */
	brepls_init(tract, -1);
	tract[BREPLST_INVALID] = BREPLST_REPL_QUEUED;
	tract[BREPLST_GARBAGE_SCHED] = BREPLST_REPL_QUEUED;
	tract[BREPLST_GARBAGE_QUEUED] = BREPLST_REPL_QUEUED;

	/* Wildcards shouldn't result in errors on zero-length files. */
	if (*nbmaps != (sl_bmapno_t)-1)
		rc = -SLERR_BMAP_INVALID;

	for (; *nbmaps && bmapno < fcmh_nvalidbmaps(f);
	    bmapno++, --*nbmaps, nbmaps_processed++) {

		if (nbmaps_processed >= SLM_REPLRQ_NBMAPS_MAX) {
			rc = -PFLERR_WOULDBLOCK;
			break;
		}

		rc = -bmap_get(f, bmapno, SL_WRITE, &b);
		if (rc)
			PFL_GOTOERR(out, rc);

		/*
		 * If no VALID replicas exist, the bmap must be
		 * uninitialized/all zeroes; skip it.
		 */
		if (mds_repl_bmap_walk_all(b, NULL, ret_hasvalid,
		    REPL_WALKF_SCIRCUIT) == 0) {
			bmap_op_done(b);
			continue;
		}

		/*
		 * We do not follow the standard "retifset" API here
		 * because we need to preserve DIRTY if it gets set
		 * instead of some other state getting returned.
		 */
		flags = 0;
		_mds_repl_bmap_walk(b, tract, NULL, 0, iosidx, nios,
		    slm_repl_addrq_cb, &flags);

		/* both default to -1 in parse_replrq() */
		bmap_2_bmi(b)->bmi_sys_prio = sys_prio;
		bmap_2_bmi(b)->bmi_usr_prio = usr_prio;
		if (flags & FLAG_DIRTY)
			mds_bmap_write_logrepls(b);
		else if (sys_prio != -1 || usr_prio != -1)
			slm_repl_upd_write(b, 0);

		bmap_op_done_type(b, BMAP_OPCNT_LOOKUP);
		if (flags & FLAG_REPLICA_STATE_INVALID) {
			/* See pfl_register_errno() */
			rc = -SLERR_REPLICA_STATE_INVALID;
			break;
		}
	}

 out:
	if (f)
		fcmh_op_done(f);
	*nbmaps = nbmaps_processed;
	return (rc);
}
Exemplo n.º 5
0
void
slm_repl_upd_write(struct bmap *b, int rel)
{
	struct {
		sl_replica_t	 iosv[SL_MAX_REPLICAS];
		char		*stat[SL_MAX_REPLICAS];
		unsigned	 nios;
	} add, del, chg;

	int off, vold, vnew, sprio, uprio, rc;
	struct sl_mds_iosinfo *si;
	struct bmap_mds_info *bmi;
	struct fidc_membh *f;
	struct sl_resource *r;
	sl_ios_id_t resid;
	unsigned n, nrepls;

	bmi = bmap_2_bmi(b);
	f = b->bcm_fcmh;
	sprio = bmi->bmi_sys_prio;
	uprio = bmi->bmi_usr_prio;

	add.nios = 0;
	del.nios = 0;
	chg.nios = 0;
	nrepls = fcmh_2_nrepls(f);
	for (n = 0, off = 0; n < nrepls; n++, off += SL_BITS_PER_REPLICA) {

		if (n == SL_DEF_REPLICAS)
			mds_inox_ensure_loaded(fcmh_2_inoh(f));

		resid = fcmh_2_repl(f, n);
		vold = SL_REPL_GET_BMAP_IOS_STAT(bmi->bmi_orepls, off);
		vnew = SL_REPL_GET_BMAP_IOS_STAT(bmi->bmi_repls, off);

		r = libsl_id2res(resid);
		si = r ? res2iosinfo(r) : &slm_null_iosinfo;

		if (vold == vnew)
			;

		/* Work was added. */
		else if ((vold != BREPLST_REPL_SCHED &&
		    vold != BREPLST_GARBAGE_QUEUED &&
		    vold != BREPLST_GARBAGE_SCHED &&
		    vnew == BREPLST_REPL_QUEUED) ||
		    (vold != BREPLST_GARBAGE_SCHED &&
		     vnew == BREPLST_GARBAGE_QUEUED &&
		     (si->si_flags & SIF_PRECLAIM_NOTSUP) == 0)) {
			OPSTAT_INCR("repl-work-add");
			PUSH_IOS(b, &add, resid, NULL);
		}

		/* Work has finished. */
		else if ((vold == BREPLST_REPL_QUEUED ||
		     vold == BREPLST_REPL_SCHED ||
		     vold == BREPLST_TRUNC_SCHED ||
		     vold == BREPLST_TRUNC_QUEUED ||
		     vold == BREPLST_GARBAGE_SCHED ||
		     vold == BREPLST_VALID) &&
		    (((si->si_flags & SIF_PRECLAIM_NOTSUP) &&
		      vnew == BREPLST_GARBAGE_QUEUED) ||
		     vnew == BREPLST_VALID ||
		     vnew == BREPLST_INVALID)) {
			OPSTAT_INCR("repl-work-del");
			PUSH_IOS(b, &del, resid, NULL);
		}

		/*
		 * Work that was previously scheduled failed so 
		 * requeue it.
		 */
		else if (vold == BREPLST_REPL_SCHED ||
		    vold == BREPLST_GARBAGE_SCHED ||
		    vold == BREPLST_TRUNC_SCHED)
			PUSH_IOS(b, &chg, resid, "Q");

		/* Work was scheduled. */
		else if (vnew == BREPLST_REPL_SCHED ||
		    vnew == BREPLST_GARBAGE_SCHED ||
		    vnew == BREPLST_TRUNC_SCHED)
			PUSH_IOS(b, &chg, resid, "S");

		/* Work was reprioritized. */
		else if (sprio != -1 || uprio != -1)
			PUSH_IOS(b, &chg, resid, NULL);
	}

	for (n = 0; n < add.nios; n++) {
		rc = slm_upsch_insert(b, add.iosv[n].bs_id, sprio,
		    uprio);
		if (!rc)
			continue;
		psclog_warnx("upsch insert failed: bno = %d, "
		    "fid=%"PRId64", ios= %d, rc = %d",
		    b->bcm_bmapno, bmap_2_fid(b), 
		    add.iosv[n].bs_id, rc);
	}

	for (n = 0; n < del.nios; n++) {
		spinlock(&slm_upsch_lock);
		dbdo(NULL, NULL,
		    " DELETE FROM upsch"
		    " WHERE	resid = ?"
		    "   AND	fid = ?"
		    "   AND	bno = ?",
		    SQLITE_INTEGER, del.iosv[n].bs_id,
		    SQLITE_INTEGER64, bmap_2_fid(b),
		    SQLITE_INTEGER, b->bcm_bmapno);
		freelock(&slm_upsch_lock);
	}

	for (n = 0; n < chg.nios; n++) {
		spinlock(&slm_upsch_lock);
		dbdo(NULL, NULL,
		    " UPDATE	upsch"
		    " SET	status = IFNULL(?, status),"
		    "		sys_prio = IFNULL(?, sys_prio),"
		    "		usr_prio = IFNULL(?, usr_prio)"
		    " WHERE	resid = ?"
		    "	AND	fid = ?"
		    "	AND	bno = ?",
		    chg.stat[n] ? SQLITE_TEXT : SQLITE_NULL,
		    chg.stat[n] ? chg.stat[n] : 0,
		    sprio == -1 ? SQLITE_NULL : SQLITE_INTEGER,
		    sprio == -1 ? 0 : sprio,
		    uprio == -1 ? SQLITE_NULL : SQLITE_INTEGER,
		    uprio == -1 ? 0 : uprio,
		    SQLITE_INTEGER, chg.iosv[n].bs_id,
		    SQLITE_INTEGER64, bmap_2_fid(b),
		    SQLITE_INTEGER, b->bcm_bmapno);
		freelock(&slm_upsch_lock);
	}

	bmap_2_bmi(b)->bmi_sys_prio = -1;
	bmap_2_bmi(b)->bmi_usr_prio = -1;

	if (rel) {
		BMAP_LOCK(b);
		b->bcm_flags &= ~BMAPF_REPLMODWR;
		bmap_wake_locked(b);
		bmap_op_done_type(b, BMAP_OPCNT_WORK);
	}
}