/** * _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); }
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)); } }
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); }
/* * 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); }
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); } }