Пример #1
0
/*
 * Return the next SLASH2 FID to use.  Note that from ZFS point of view,
 * it is perfectly okay that we use the same SLASH2 FID to refer to
 * different files/directories.  However, doing so can confuse our
 * clients (think identity theft).  So we must make sure that we never
 * reuse a SLASH2 FID, even after a crash.
 *
 * The siteid has already been baked into the initial cursor file.
 */
int
slm_get_next_slashfid(slfid_t *fidp)
{
	uint64_t fid;

	spinlock(&slm_fid_lock);
	/*
	 * This should never happen.  If it does, we crash to let the
	 * sysadmin know.  He could fix this if there is still room in
	 * the cycle bits.  We have to let the sysadmin know otherwise
	 * they will not know to bump the cycle bits.
	 */
	if (FID_GET_INUM(slm_next_fid) >= FID_MAX_INUM) {
		psclog_warnx("max FID "SLPRI_FID" reached, manual "
		    "intervention needed (bump the cycle bits)",
		    slm_next_fid);
		freelock(&slm_fid_lock);
		return (ENOSPC);
	}
	fid = slm_next_fid++;
	freelock(&slm_fid_lock);

	psclog_diag("most recently allocated FID: "SLPRI_FID, fid);
	*fidp = fid;
	return (0);
}
Пример #2
0
int
main(int argc, char *argv[])
{
	char *p, tmbuf[PFL_CTIME_BUFSIZ], *cursor_file = NULL, c;
	uint64_t newtxg = 0, newfid = 0, fid, cycle, newcycle;
	int dump = 0, verbose = 0, fd, rc;
	struct psc_journal_cursor cursor;

	progname = argv[0];
	while ((c = getopt(argc, argv, "c:df:vx:")) != -1)
		switch (c) {
		case 'c':
			cursor_file = optarg;
			break;
		case 'd':
			dump = 1;
			break;
		case 'f':
			newfid = strtol(optarg, NULL, 0);
			break;
		case 'v':
			verbose = 1;
			break;
		case 'x':
			newtxg = strtol(optarg, NULL, 0);
			break;
		default:
			usage();
		}

	argc -= optind;
	if (argc || !cursor_file)
		usage();

	fd = open(cursor_file, O_RDWR);
	if (fd < 0)
		err(1, "failed to open %s", cursor_file);

	rc = pread(fd, &cursor, sizeof(struct psc_journal_cursor), 0);
	if (rc != sizeof(struct psc_journal_cursor))
		err(1, "cursor file read");

	ctime_r((time_t *)&cursor.pjc_timestamp, tmbuf);
	p = strchr(tmbuf, '\n');
	if (p)
		*p = '\0';

	cycle = FID_GET_CYCLE(cursor.pjc_fid);
	if (dump || verbose) {
		printf("Cursor contents of %s:\n"
		    "\tmagic		%"PRIx64"\n"
		    "\tversion		%"PRIx64"\n"
		    "\ttimestamp	%"PRId64" (%s)\n"
		    "\tuuid		%s\n"
		    "\tcommit_txg	%"PRId64"\n"
		    "\tdistill_xid	%"PRId64"\n"
		    "\tfid		%#"PRIx64" "
		      "(flag=%"PRIx64", siteid=%"PRIx64", "
		      "cycle=%"PRIx64", inum=%"PRIx64")\n"
		    "\tseqno_lwm	%"PRIx64"\n"
		    "\tseqno_hwm	%"PRIx64"\n"
		    "\ttail		%"PRIx64"\n"
		    "\tupdate_seqno	%"PRIx64"\n"
		    "\treclaim_seqno	%"PRIx64"\n"
		    "\treplay_xid	%"PRIx64"\n\n",
		    cursor_file,
		    cursor.pjc_magic,
		    cursor.pjc_version,
		    cursor.pjc_timestamp, tmbuf,
		    cursor.pjc_uuid,
		    cursor.pjc_commit_txg,
		    cursor.pjc_distill_xid,
		    cursor.pjc_fid,
		    FID_GET_FLAGS(cursor.pjc_fid),
		    FID_GET_SITEID(cursor.pjc_fid),
		    FID_GET_CYCLE(cursor.pjc_fid),
		    FID_GET_INUM(cursor.pjc_fid),
		    cursor.pjc_seqno_lwm, cursor.pjc_seqno_hwm,
		    cursor.pjc_tail, cursor.pjc_update_seqno,
		    cursor.pjc_reclaim_seqno, cursor.pjc_replay_xid);

		fid = cursor.pjc_fid;
		fid = fid | FID_MAX_INUM;

		printf("The max FID for this cycle is %#"PRIx64"\n", fid);

		if (cycle < ((UINT64_C(1) << SLASH_FID_CYCLE_BITS) - 1)) {
			fid++;
			printf("The first FID for the next cycle is %#"PRIx64"\n", fid);
		}

		if (dump)
			exit(0);
	}

	if (!newtxg && !newfid)
		errx(1, "neither fid nor txg was specified");

	if (newtxg)
		cursor.pjc_commit_txg = newtxg;

	if (newfid) {
		newcycle = FID_GET_CYCLE(newfid);
		if (newcycle <= cycle)
			errx(1, "cycle must be increased when setting a new FID");
		cursor.pjc_fid = newfid;
	}

	rc = pwrite(fd, &cursor, sizeof(struct psc_journal_cursor), 0);
	if (rc != sizeof(struct psc_journal_cursor))
		err(1, "cursor file write");
	if (close(fd) == -1)
		err(1, "cursor file close");
	exit(0);
}
Пример #3
0
/*
 * Update the high-level app stat(2)-like attribute buffer for a FID
 * cache member.
 * @f: FID cache member to update.
 * @sstb: incoming stat attributes.
 * @flags: behavioral flags.
 * Notes:
 *     (1) if SAVELOCAL has been specified, save local field values:
 *		(o) file size
 *		(o) mtime
 *     (2) This function should only be used by a client.
 */
void
slc_fcmh_setattrf(struct fidc_membh *f, struct srt_stat *sstb,
    int flags)
{
	uidmap_int_stat(sstb);

	if (flags & FCMH_SETATTRF_HAVELOCK)
		FCMH_LOCK_ENSURE(f);
	else
		FCMH_LOCK(f);

	if (fcmh_2_gen(f) == FGEN_ANY)
		fcmh_2_gen(f) = sstb->sst_gen;

	if ((FID_GET_INUM(fcmh_2_fid(f))) != SLFID_ROOT &&
	    fcmh_2_gen(f) > sstb->sst_gen) {
		OPSTAT_INCR("msl.generation-backwards");
		DEBUG_FCMH(PLL_DIAG, f, "attempt to set attr with "
		    "gen %"PRIu64" from old gen %"PRIu64,
		    fcmh_2_gen(f), sstb->sst_gen);
		goto out;
	}

	/*
	 * If we don't have stat attributes, how can we save our local
	 * updates?
	 */
	if ((f->fcmh_flags & FCMH_HAVE_ATTRS) == 0)
		flags |= FCMH_SETATTRF_CLOBBER;

	/*
	 * Always update for roots because we might have faked them
	 * with readdir at the super root.
	 */
	if ((FID_GET_INUM(fcmh_2_fid(f))) == SLFID_ROOT)
		flags |= FCMH_SETATTRF_CLOBBER;

	psc_assert(sstb->sst_gen != FGEN_ANY);
	psc_assert(f->fcmh_fg.fg_fid == sstb->sst_fid);

	/*
	 * The default behavior is to save st_size and st_mtim since we
	 * might have done I/O that the MDS does not know about.
	 */
	if ((flags & FCMH_SETATTRF_CLOBBER) == 0 &&
	    fcmh_isreg(f)) {
		/*
		 * If generation numbers match, take the highest of the
		 * values.  Otherwise, disregard local values and
		 * blindly accept whatever the MDS tells us.
		 */
		if (fcmh_2_ptruncgen(f) == sstb->sst_ptruncgen &&
		    fcmh_2_gen(f) == sstb->sst_gen &&
		    fcmh_2_fsz(f) > sstb->sst_size)
			sstb->sst_size = fcmh_2_fsz(f);
		if (fcmh_2_utimgen(f) == sstb->sst_utimgen)
			sstb->sst_mtim = f->fcmh_sstb.sst_mtim;
	}

	COPY_SSTB(sstb, &f->fcmh_sstb);
	f->fcmh_flags |= FCMH_HAVE_ATTRS;
	f->fcmh_flags &= ~FCMH_GETTING_ATTRS;

	if (sl_fcmh_ops.sfop_postsetattr)
		sl_fcmh_ops.sfop_postsetattr(f);

	DEBUG_FCMH(PLL_DEBUG, f, "attr set");

 out:
	if (!(flags & FCMH_SETATTRF_HAVELOCK))
		FCMH_ULOCK(f);
}