/* * Return the index of the given IOS ID or a negative error code on failure. */ int _mds_repl_ios_lookup(int vfsid, struct slash_inode_handle *ih, sl_ios_id_t ios, int flag) { int locked, rc; struct slm_inox_od *ix = NULL; struct sl_resource *res; struct fidc_membh *f; sl_replica_t *repl; uint32_t i, j, nr; char buf[LINE_MAX]; switch (flag) { case IOSV_LOOKUPF_ADD: OPSTAT_INCR("replicate-add"); break; case IOSV_LOOKUPF_DEL: OPSTAT_INCR("replicate-del"); break; case IOSV_LOOKUPF_LOOKUP: OPSTAT_INCR("replicate-lookup"); break; default: psc_fatalx("Invalid IOS lookup flag %d", flag); } /* * Can I assume that IOS ID are non-zeros. If so, I can use * zero to mark a free slot. See sl_global_id_build(). */ f = inoh_2_fcmh(ih); nr = ih->inoh_ino.ino_nrepls; repl = ih->inoh_ino.ino_repls; locked = INOH_RLOCK(ih); psc_assert(nr <= SL_MAX_REPLICAS); if (nr == SL_MAX_REPLICAS && flag == IOSV_LOOKUPF_ADD) { DEBUG_INOH(PLL_WARN, ih, buf, "too many replicas"); PFL_GOTOERR(out, rc = -ENOSPC); } res = libsl_id2res(ios); if (res == NULL || !RES_ISFS(res)) PFL_GOTOERR(out, rc = -SLERR_RES_BADTYPE); /* * 09/29/2016: Hit SLERR_SHORTIO in the function. Need more investigation. */ /* * Return ENOENT by default for IOSV_LOOKUPF_DEL & IOSV_LOOKUPF_LOOKUP. */ rc = -ENOENT; /* * Search the existing replicas to see if the given IOS is * already there. * * The following code can step through zero IOS IDs just fine. * */ for (i = 0, j = 0; i < nr; i++, j++) { if (i == SL_DEF_REPLICAS) { /* * The first few replicas are in the inode * itself, the rest are in the extra inode * block. */ rc = mds_inox_ensure_loaded(ih); if (rc) goto out; ix = ih->inoh_extras; repl = ix->inox_repls; j = 0; } DEBUG_INOH(PLL_DEBUG, ih, buf, "is rep[%u](=%u) == %u ?", j, repl[j].bs_id, ios); if (repl[j].bs_id == ios) { /* * Luckily, this code is only called by mds_repl_delrq() * for directories. * * Make sure that the logic works for at least the following * edge cases: * * (1) There is only one item in the basic array. * (2) There is only one item in the extra array. * (3) The number of items is SL_DEF_REPLICAS. * (4) The number of items is SL_MAX_REPLICAS. */ if (flag == IOSV_LOOKUPF_DEL) { /* * Compact the array if the IOS is not the last * one. The last one will be either overwritten * or zeroed. Note that we might move extra * garbage at the end if the total number is less * than SL_DEF_REPLICAS. */ if (i < SL_DEF_REPLICAS - 1) { memmove(&repl[j], &repl[j + 1], (SL_DEF_REPLICAS - j - 1) * sizeof(*repl)); } /* * All items in the basic array, zero the last * one and we are done. */ if (nr <= SL_DEF_REPLICAS) { repl[nr-1].bs_id = 0; goto syncit; } /* * Now we know we have more than SL_DEF_REPLICAS * items. However, if we are in the basic array, * we have not read the extra array yet. In this * case, we should also move the first item from * the extra array to the last one in the basic * array (overwrite). */ if (i < SL_DEF_REPLICAS) { rc = mds_inox_ensure_loaded(ih); if (rc) goto out; ix = ih->inoh_extras; repl[SL_DEF_REPLICAS - 1].bs_id = ix->inox_repls[0].bs_id; repl = ix->inox_repls; j = 0; } /* * Compact the extra array unless the IOS is * the last one, which will be zeroed. */ if (i < SL_MAX_REPLICAS - 1) { memmove(&repl[j], &repl[j + 1], (SL_INOX_NREPLICAS - j - 1) * sizeof(*repl)); } repl[nr-SL_DEF_REPLICAS-1].bs_id = 0; syncit: ih->inoh_ino.ino_nrepls = nr - 1; rc = mds_inodes_odsync(vfsid, f, mdslog_ino_repls); if (rc) goto out; } /* XXX EEXIST for IOSV_LOOKUPF_ADD? */ rc = i; goto out; } } /* It doesn't exist; add to inode replica table if requested. */ if (flag == IOSV_LOOKUPF_ADD) { /* paranoid */ psc_assert(i == nr); if (nr >= SL_DEF_REPLICAS) { /* be careful with the case of nr = SL_DEF_REPLICAS */ rc = mds_inox_ensure_loaded(ih); if (rc) goto out; repl = ih->inoh_extras->inox_repls; j = i - SL_DEF_REPLICAS; } else { repl = ih->inoh_ino.ino_repls; j = i; } repl[j].bs_id = ios; DEBUG_INOH(PLL_DIAG, ih, buf, "add IOS(%u) at idx %d", ios, i); ih->inoh_ino.ino_nrepls = nr + 1; rc = mds_inodes_odsync(vfsid, f, mdslog_ino_repls); if (!rc) rc = i; } out: INOH_URLOCK(ih, locked); return (rc); }
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); }