Beispiel #1
0
/*
 * Roll the embedded log, if any, and set up the global variables
 * islog and islogok.
 */
static int
logsetup(caddr_t devstr)
{
	void		*buf;
	extent_block_t	*ebp;
	ml_unit_t	*ul;
	ml_odunit_t	*ud;
	void		*ud_buf;
	int		badlog;

	islog = islogok = 0;
	if (bflag != 0)
		return (1); /* can't roll log while alternate sb specified */

	/*
	 * Roll the log, if any.  A bad sb implies we'll be using
	 * an alternate sb as far as logging goes, so just fail back
	 * to the caller if we can't read the default sb.  Suppress
	 * complaints, because the caller will be reading the same
	 * superblock again and running full verification on it, so
	 * whatever is bad will be reported then.
	 */
	sblock.fs_logbno = 0;
	badlog = 0;
	if (!read_super_block(0))
		return (1);

	/*
	 * Roll the log in 3 cases:
	 * 1. If it's unmounted (mount_point == NULL) and it's not marked
	 *    as fully rolled (sblock.fs_rolled != FS_ALL_ROLLED)
	 * 2. If it's mounted and anything other than a sanity
	 *    check fsck (mflag) is being done, as we have the current
	 *    super block. Note, only a sanity check is done for
	 *    root/usr at boot. If a roll were done then the expensive
	 *    ufs_flush() gets called, leading to a slower boot.
	 * 3. If anything other then a sanity check (mflag) is being done
	 *    to a mounted filesystem while it is in read-only state
	 *    (e.g. root during early boot stages) we have to detect this
	 *    and have to roll the log as well. NB. the read-only mount
	 *    will flip fs_clean from FSLOG to FSSTABLE and marks the
	 *    log as FS_NEED_ROLL.
	 */
	if (sblock.fs_logbno &&
	    (((mount_point == NULL) && (sblock.fs_rolled != FS_ALL_ROLLED)) ||
	    ((mount_point != NULL) && !mflag))) {
		int roll_log_err = 0;

		if (sblock.fs_ronly && (sblock.fs_clean == FSSTABLE) &&
			(sblock.fs_state + sblock.fs_time == FSOKAY)) {
			/*
			 * roll the log without a mount
			 */
			flush_fs();
		}
		if (sblock.fs_clean == FSLOG &&
			(sblock.fs_state + sblock.fs_time == FSOKAY)) {
			if (rl_roll_log(devstr) != RL_SUCCESS)
				roll_log_err = 1;
		}
		if (roll_log_err) {
			(void) printf("Can't roll the log for %s.\n", devstr);
			/*
			 * There are two cases where we want to set
			 * an error code and return:
			 *  - We're preening
			 *  - We're not on a live root and the user
			 *    chose *not* to ignore the log
			 * Otherwise, we want to mark the log as bad
			 * and continue to check the filesystem.  This
			 * has the side effect of destroying the log.
			 */
			if (preen || (!hotroot &&
			    reply(
			"DISCARDING THE LOG MAY DISCARD PENDING TRANSACTIONS.\n"
					"DISCARD THE LOG AND CONTINUE") == 0)) {
				exitstat = EXERRFATAL;
				return (0);
			}
			++badlog;
		}
	}

	/* Logging UFS may be enabled */
	if (sblock.fs_logbno) {
		++islog;

		/* log is not okay; check the fs */
		if (FSOKAY != (sblock.fs_state + sblock.fs_time))
			return (1);

		/*
		 * If logging or (stable and mounted) then continue
		 */
		if (!((sblock.fs_clean == FSLOG) ||
		    (sblock.fs_clean == FSSTABLE) && (mount_point != NULL)))
			return (1);

		/* get the log allocation block */
		buf = malloc(dev_bsize);
		if (buf == NULL) {
			return (1);
		}
		ud_buf = malloc(dev_bsize);
		if (ud_buf == NULL) {
			free(buf);
			return (1);
		}
		(void) fsck_bread(fsreadfd, buf,
		    logbtodb(&sblock, sblock.fs_logbno),
		    dev_bsize);
		ebp = (extent_block_t *)buf;

		/* log allocation block is not okay; check the fs */
		if (ebp->type != LUFS_EXTENTS) {
			free(buf);
			free(ud_buf);
			return (1);
		}

		/* get the log state block(s) */
		if (fsck_bread(fsreadfd, ud_buf,
		    (logbtodb(&sblock, ebp->extents[0].pbno)),
		    dev_bsize)) {
			(void) fsck_bread(fsreadfd, ud_buf,
			    (logbtodb(&sblock, ebp->extents[0].pbno)) + 1,
			    dev_bsize);
		}
		ud = (ml_odunit_t *)ud_buf;
		ul = (ml_unit_t *)malloc(sizeof (*ul));
		if (ul == NULL) {
			free(buf);
			free(ud_buf);
			return (1);
		}
		ul->un_ondisk = *ud;

		/* log state is okay; don't need to check the fs */
		if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
		    (ul->un_version == LUFS_VERSION_LATEST) &&
		    (ul->un_badlog == 0) && (!badlog)) {
			++islogok;
		}
		free(ud_buf);
		free(buf);
		free(ul);
	}

	return (1);
}
Beispiel #2
0
void
check(char *file)
{
	int i, j, c;

	fi = open64(file, 0);
	if (fi < 0) {
		(void) fprintf(stderr, "ncheck: cannot open %s\n", file);
		nerror++;
		return;
	}
	nhent = 0;
	(void) printf("%s:\n", file);
	sync();
	bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE);
	if ((sblock.fs_magic != FS_MAGIC) &&
	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
		(void) printf("%s: not a ufs file system\n", file);
		nerror++;
		return;
	}

	if ((sblock.fs_magic == FS_MAGIC) &&
	    ((sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2) &&
	    (sblock.fs_version != UFS_VERSION_MIN))) {
		(void) printf("%s: unrecognized ufs version number %d\n",
		    file, sblock.fs_version);
		nerror++;
		return;
	}

	if ((sblock.fs_magic == MTB_UFS_MAGIC) &&
	    ((sblock.fs_version > MTB_UFS_VERSION_1) ||
	    (sblock.fs_version < MTB_UFS_VERSION_MIN))) {
		(void) printf("%s: unrecognized ufs version number %d\n",
		    file, sblock.fs_version);
		nerror++;
		return;
	}

	/* If fs is logged, roll the log. */
	if (sblock.fs_logbno) {
		switch (rl_roll_log(file)) {
		case RL_SUCCESS:
			/*
			 * Reread the superblock.  Rolling the log may have
			 * changed it.
			 */
			bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE);
			break;
		case RL_SYSERR:
			(void) printf("Warning: cannot roll log for %s.  %s\n",
				file, strerror(errno));
			break;
		default:
			(void) printf("Warning: cannot roll log for %s.\n",
				file);
			break;
		}
	}

	itab = (struct dinode *)extend_tbl((uchar_t *)itab, &itab_size,
		(unsigned)(sblock.fs_ipg * sizeof (struct dinode)));
	if (itab == 0) {
		(void) fprintf(stderr,
			"ncheck: not enough memory for itab table\n");
		nerror++;
		return;
	}

	hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1;

	htab = (struct htab *)extend_tbl((uchar_t *)htab, &htab_size,
		(unsigned)(hsize * sizeof (struct htab)));
	if (htab == 0) {
		(void) fprintf(stderr,
			"ncheck: not enough memory for htab table\n");
		nerror++;
		return;
	}

	if (!extend_strngtab(AVG_PATH_LEN * hsize)) {
		(void) printf("not enough memory to allocate tables\n");
		nerror++;
		return;
	}
	strngloc = 0;

	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {
			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				if (itab[j].di_suid != UID_LONG)
					itab[j].di_uid = itab[j].di_suid;
				if (itab[j].di_sgid != GID_LONG)
					itab[j].di_gid = itab[j].di_sgid;
				pass1(&itab[j]);
			}
			ino++;
		}
	}
	ilist[ilist_index++].ino = 0;
	if (ilist_index > MAX_ILIST_INDEX())
		extend_ilist();
	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {

			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				pass2(&itab[j]);
			}
			ino++;
		}
	}
	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {
			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				pass3(&itab[j]);
			}
			ino++;
		}
	}
	(void) close(fi);

	/*
	 * Clear those elements after inodes specified by "-i" out of
	 * ilist.
	 */
	for (i = iflg; i < ilist_index; i++) {
		ilist[i].ino = 0;
	}
	ilist_index = iflg;
}
Beispiel #3
0
void
check(char *file)
{
	int i, j, c;

	fi = open64(file, 0);
	if (fi < 0) {
		(void) fprintf(stderr, "ff: cannot open %s\n", file);
		nerror++;
		return;
	}
	nhent = 0;
	(void) printf("%s:\n", file);
	sync();
	bread(SBLOCK, (char *)&sblock, SBSIZE);
	if ((sblock.fs_magic != FS_MAGIC) &&
	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
		(void) fprintf(stderr, "%s: not a ufs file system\n", file);
		nerror++;
		return;
	}

	if (sblock.fs_magic == FS_MAGIC &&
	    (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
	    sblock.fs_version != UFS_VERSION_MIN)) {
		(void) fprintf(stderr, "%s: unrecognized version of UFS: %d\n",
		    file, sblock.fs_version);
		nerror++;
		return;
	}

	if (sblock.fs_magic == MTB_UFS_MAGIC &&
	    (sblock.fs_version > MTB_UFS_VERSION_1 ||
	    sblock.fs_version < MTB_UFS_VERSION_MIN)) {
		(void) fprintf(stderr, "%s: unrecognized version of UFS: %d\n",
		    file, sblock.fs_version);
		nerror++;
		return;
	}

	/* If fs is logged, roll the log. */
	if (sblock.fs_logbno) {
		switch (rl_roll_log(file)) {
		case RL_SUCCESS:
			/*
			 * Reread the superblock.  Rolling the log may have
			 * changed it.
			 */
			bread(SBLOCK, (char *)&sblock, SBSIZE);
			break;
		case RL_SYSERR:
			(void) printf("Warning: Cannot roll log for %s.  %s\n",
				file, strerror(errno));
			break;
		default:
			(void) printf("Warning: Cannot roll log for %s.\n ",
				file);
			break;
		}
	}


	itab = (struct dinode *)calloc(sblock.fs_ipg, sizeof (struct dinode));
	imax = sblock.fs_ncg * sblock.fs_ipg;

	hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1;
	htab = (struct htab *)calloc(hsize, sizeof (struct htab));

	if (!extend_strngtab(AVG_PATH_LEN * hsize)) {
		(void) printf("not enough memory to allocate tables\n");
		nerror++;
		return;
	}
	strngloc = 0;

	if ((itab == NULL) || (htab == NULL)) {
		(void) printf("not enough memory to allocate tables\n");
		nerror++;
		return;
	}
	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {
			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				if (itab[j].di_suid != (o_uid_t)UID_LONG)
				itab[j].di_uid = (unsigned int)itab[j].di_suid;
				if (itab[j].di_sgid != GID_LONG)
				itab[j].di_gid = (unsigned int)itab[j].di_sgid;
				pass1(&itab[j]);
			}
			ino++;
		}
	}
	ilist[nxfile+1].ino = 0;
	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {
			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				pass2(&itab[j]);
			}
			ino++;
		}
	}
	ino = 0;
	for (c = 0; c < sblock.fs_ncg; c++) {
		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
		for (j = 0; j < sblock.fs_ipg; j++) {
			if (itab[j].di_smode != 0) {
				itab[j].di_mode = itab[j].di_smode;
				pass3(&itab[j]);
			}
			ino++;
		}
	}
	(void) close(fi);
	for (i = iflg; i < NB; i++)
		ilist[i].ino = 0;
	nxfile = iflg;
	free(itab);
	free(htab);
	free(strngtab);
}