Esempio n. 1
0
/*
 * 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);
}
Esempio n. 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);
}