int mds_bmap_read_v1(struct bmapc_memb *b, void *readh) { struct { uint8_t crcstates[128]; uint8_t repls[24]; uint64_t crcs[128]; uint32_t gen; uint32_t replpol; } bod; struct fidc_membh *f; struct iovec iovs[2]; uint64_t crc, od_crc; int i, rc, vfsid; size_t nb, bsz; struct bmap_mds_info *bmi = bmap_2_bmi(b); bsz = sizeof(bod) + sizeof(crc); iovs[0].iov_base = &bod; iovs[0].iov_len = sizeof(bod); iovs[1].iov_base = &od_crc; iovs[1].iov_len = sizeof(od_crc); f = b->bcm_fcmh; slfid_to_vfsid(fcmh_2_fid(f), &vfsid); rc = mdsio_preadv(vfsid, &rootcreds, iovs, nitems(iovs), &nb, bsz * b->bcm_bmapno + 0x1000, readh); if (rc) return (rc); if (nb == 0) return (SLERR_BMAP_INVALID); if (nb != bsz) return (SLERR_SHORTIO); psc_crc64_calc(&crc, &bod, sizeof(bod)); if (crc != od_crc) return (PFLERR_BADCRC); for (i = 0; i < 128; i++) bmi->bmi_crcstates[i] = bod.crcstates[i]; for (i = 0; i < 24; i++) bmi->bmi_repls[i] = bod.repls[i]; for (i = 0; i < 128; i++) bmap_2_crcs(b, i) = bod.crcs[i]; bmap_2_bgen(b) = bod.gen; bmap_2_replpol(b) = bod.replpol; return (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); }