コード例 #1
0
ファイル: sb.c プロジェクト: chandanr/xfsprogs-dev
static int
do_version(xfs_agnumber_t agno, __uint16_t version, __uint32_t features)
{
	xfs_sb_t	tsb;

	if (!get_sb(agno, &tsb))
		return 0;

	if (xfs_sb_has_mismatched_features2(&tsb)) {
		dbprintf(_("Superblock has mismatched features2 fields, "
			   "skipping modification\n"));
		return 0;
	}

	if ((version & XFS_SB_VERSION_LOGV2BIT) &&
					!xfs_sb_version_haslogv2(&tsb)) {
		tsb.sb_logsunit = 1;
	}

	tsb.sb_versionnum = version;
	tsb.sb_features2 = features;
	tsb.sb_bad_features2 = features;
	libxfs_sb_to_disk(iocur_top->data, &tsb);
	write_cur();
	return 1;
}
コード例 #2
0
ファイル: sb.c プロジェクト: chandanr/xfsprogs-dev
static uuid_t *
do_uuid(xfs_agnumber_t agno, uuid_t *uuid)
{
	xfs_sb_t	tsb;
	static uuid_t	uu;

	if (!get_sb(agno, &tsb))
		return NULL;

	if (!uuid) {	/* get uuid */
		memcpy(&uu, &tsb.sb_uuid, sizeof(uuid_t));
		pop_cur();
		return &uu;
	}
	/* set uuid */
	if (!xfs_sb_version_hascrc(&tsb))
		goto write;
	/*
	 * If we have CRCs, and this UUID differs from that stamped in the
	 * metadata, set the incompat flag and copy the old one to the
	 * metadata-specific location.
	 *
	 * If we are setting the user-visible UUID back to match the metadata
	 * UUID, clear the metadata-specific location and the incompat flag.
	 */
	if (!xfs_sb_version_hasmetauuid(&tsb) &&
	    !uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) {
		mp->m_sb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID;
		tsb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID;
		memcpy(&tsb.sb_meta_uuid, &tsb.sb_uuid, sizeof(uuid_t));
	} else if (xfs_sb_version_hasmetauuid(&tsb) &&
		   uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) {
		memset(&tsb.sb_meta_uuid, 0, sizeof(uuid_t));
		/* Write those zeros now; it's ignored once we clear the flag */
		libxfs_sb_to_disk(iocur_top->data, &tsb);
		mp->m_sb.sb_features_incompat &=
						~XFS_SB_FEAT_INCOMPAT_META_UUID;
		tsb.sb_features_incompat &= ~XFS_SB_FEAT_INCOMPAT_META_UUID;
	}

write:
	memcpy(&tsb.sb_uuid, uuid, sizeof(uuid_t));
	libxfs_sb_to_disk(iocur_top->data, &tsb);
	write_cur();
	return uuid;
}
コード例 #3
0
ファイル: uuid.c プロジェクト: crossmeta/sgi
static uuid_t *
do_uuid(xfs_agnumber_t agno, uuid_t *uuid)
{
	xfs_sb_t	tsb;
	static uuid_t	uu;

	if (!get_sb(agno, &tsb))
		return NULL;

	if (!uuid) {	/* get uuid */
		memcpy(&uu, &tsb.sb_uuid, sizeof(uuid_t));
		pop_cur();
		return &uu;
	}
	/* set uuid */
	memcpy(&tsb.sb_uuid, uuid, sizeof(uuid_t));
	libxfs_xlate_sb(iocur_top->data, &tsb, -1, ARCH_CONVERT, XFS_SB_UUID);
	write_cur();
	return uuid;
}
コード例 #4
0
ファイル: uuid.c プロジェクト: crossmeta/sgi
static char *
do_label(xfs_agnumber_t agno, char *label)
{
	size_t		len;
	xfs_sb_t	tsb;
	static char 	lbl[sizeof(tsb.sb_fname) + 1];

	if (!get_sb(agno, &tsb))
		return NULL;

	memset(&lbl[0], 0, sizeof(lbl));

	if (!label) {	/* get label */
		pop_cur();
		memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname));
		return &lbl[0];
	}
	/* set label */
	if ((len = strlen(label)) > sizeof(tsb.sb_fname)) {
		if (!warned++)
			dbprintf("warning: truncating label from %lld to %lld "
				"characters\n", 
                                    (long long)len, (long long)sizeof(tsb.sb_fname));
		len = sizeof(tsb.sb_fname);
	}
	if ( len == 2 &&
	     (strcmp(label, "\"\"") == 0 ||
	      strcmp(label, "''")   == 0 ||
	      strcmp(label, "--")   == 0) )
		label[0] = label[1] = '\0';
	memset(&tsb.sb_fname, 0, sizeof(tsb.sb_fname));
	memcpy(&tsb.sb_fname, label, len);
	memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname));
	libxfs_xlate_sb(iocur_top->data, &tsb, -1, ARCH_CONVERT, XFS_SB_FNAME);
	write_cur();
	return &lbl[0];
}
コード例 #5
0
ファイル: sb.c プロジェクト: chandanr/xfsprogs-dev
static char *
do_label(xfs_agnumber_t agno, char *label)
{
	size_t		len;
	xfs_sb_t	tsb;
	static char	lbl[sizeof(tsb.sb_fname) + 1];

	if (!get_sb(agno, &tsb))
		return NULL;

	memset(&lbl[0], 0, sizeof(lbl));

	if (!label) {	/* get label */
		pop_cur();
		memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname));
		return &lbl[0];
	}
	/* set label */
	if ((len = strlen(label)) > sizeof(tsb.sb_fname)) {
		if (agno == 0)
			dbprintf(_("%s: truncating label length from %d to %d\n"),
				progname, (int)len, (int)sizeof(tsb.sb_fname));
		len = sizeof(tsb.sb_fname);
	}
	if ( len == 2 &&
	     (strcmp(label, "\"\"") == 0 ||
	      strcmp(label, "''")   == 0 ||
	      strcmp(label, "--")   == 0) )
		label[0] = label[1] = '\0';
	memset(&tsb.sb_fname, 0, sizeof(tsb.sb_fname));
	memcpy(&tsb.sb_fname, label, len);
	memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname));
	libxfs_sb_to_disk(iocur_top->data, &tsb);
	write_cur();
	return &lbl[0];
}
コード例 #6
0
ファイル: sb.c プロジェクト: chandanr/xfsprogs-dev
static int
uuid_f(
	int		argc,
	char		**argv)
{
	char	        bp[40];
	xfs_agnumber_t	agno;
	uuid_t		uu;
	uuid_t		*uup = NULL;

	if (argc != 1 && argc != 2) {
		dbprintf(_("invalid parameters\n"));
		return 0;
	}

	if (argc == 2) {	/* WRITE UUID */

		if ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode) {
			dbprintf(_("%s: not in expert mode, writing disabled\n"),
				progname);
			return 0;
		}

		if (!strcasecmp(argv[1], "generate")) {
			platform_uuid_generate(&uu);
		} else if (!strcasecmp(argv[1], "nil")) {
			platform_uuid_clear(&uu);
		} else if (!strcasecmp(argv[1], "rewrite")) {
			uup = do_uuid(0, NULL);
			if (!uup) {
				dbprintf(_("failed to read UUID from AG 0\n"));
				return 0;
			}
			memcpy(&uu, uup, sizeof(uuid_t));
			platform_uuid_unparse(&uu, bp);
			dbprintf(_("old UUID = %s\n"), bp);
		} else if (!strcasecmp(argv[1], "restore")) {
			xfs_sb_t	tsb;

			if (!get_sb(0, &tsb))
				return 0;

			/* Not set; nothing to do.  Success! */
			if (!xfs_sb_version_hasmetauuid(&tsb))
				return 0;
		
			memcpy(&uu, mp->m_sb.sb_meta_uuid, sizeof(uuid_t));
		} else {
			if (platform_uuid_parse(argv[1], &uu)) {
				dbprintf(_("invalid UUID\n"));
				return 0;
			}
		}

		/* clear the log (setting uuid) if it's not dirty */
		if (!sb_logzero(&uu))
			return 0;

		dbprintf(_("writing all SBs\n"));
		for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
			if (!do_uuid(agno, &uu)) {
				dbprintf(_("failed to set UUID in AG %d\n"), agno);
				break;
			}

		platform_uuid_unparse(&uu, bp);
		dbprintf(_("new UUID = %s\n"), bp);
		return 0;

	} else {	/* READ+CHECK UUID */

		for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
			uup = do_uuid(agno, NULL);
			if (!uup) {
				dbprintf(_("failed to read UUID from AG %d\n"),
					agno);
				return 0;
			}
			if (agno) {
				if (memcmp(&uu, uup, sizeof(uuid_t))) {
					dbprintf(_("warning: UUID in AG %d "
						 "differs to the primary SB\n"),
						agno);
					break;
				}
			} else {
				memcpy(&uu, uup, sizeof(uuid_t));
			}
		}
		if (mp->m_sb.sb_logstart) {
			if (x.logdev && x.logdev != x.ddev)
				dbprintf(_("warning - external log specified "
					 "for FS with an internal log\n"));
		} else if (!x.logdev || (x.logdev == x.ddev)) {
			dbprintf(_("warning - no external log specified "
				 "for FS with an external log\n"));
		}

		platform_uuid_unparse(&uu, bp);
		dbprintf(_("UUID = %s\n"), bp);
	}

	return 0;
}
コード例 #7
0
ファイル: sb.c プロジェクト: Claruarius/stblinux-2.6.37
/*
 * the way to verify that a primary sb is consistent with the
 * filesystem is find the secondaries given the info in the
 * primary and compare the geometries in the secondaries against
 * the geometry indicated by the primary.
 *
 * returns 1 if bad, 0 if ok
 */
int
verify_set_primary_sb(xfs_sb_t		*rsb,
			int		sb_index,
			int		*sb_modified)
{
	xfs_off_t	off;
	fs_geometry_t	geo;
	xfs_sb_t	*sb;
	fs_geo_list_t	*list;
	fs_geo_list_t	*current;
	char		*checked;
	xfs_agnumber_t	agno;
	int		num_sbs;
	int		skip;
	int		size;
	int		num_ok;
	int		retval;
	int		round;

	/*
	 * select the number of secondaries to try for
	 */
	num_sbs = MIN(NUM_SBS, rsb->sb_agcount);
	skip = howmany(num_sbs, rsb->sb_agcount);

	/*
	 * We haven't been able to validate the sector size yet properly
	 * (e.g. in the case of repairing an image in a file), so we need to
	 * take into account sector mismatches and so use the maximum possible
	 * sector size rather than the sector size in @rsb.
	 */
	size = NUM_AGH_SECTS * (1 << (XFS_MAX_SECTORSIZE_LOG));
	retval = 0;
	list = NULL;
	num_ok = 0;
	*sb_modified = 0;

	sb = (xfs_sb_t *) alloc_ag_buf(size);
	checked = calloc(rsb->sb_agcount, sizeof(char));
	if (!checked) {
		do_error(_("calloc failed in verify_set_primary_sb\n"));
		exit(1);
	}

	/*
	 * put the primary sb geometry info onto the geometry list
	 */
	checked[sb_index] = 1;
	get_sb_geometry(&geo, rsb);
	list = add_geo(list, &geo, sb_index);

	/*
	 * grab N secondaries.  check them off as we get them
	 * so we only process each one once
	 */
	for (round = 0; round < skip; round++)  {
		for (agno = round; agno < rsb->sb_agcount; agno += skip)  {
			if (checked[agno])
				continue;

			off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog;

			checked[agno] = 1;

			if (get_sb(sb, off, size, agno) == XR_EOF)  {
				retval = 1;
				goto out;
			}

			if (verify_sb(sb, 0) == XR_OK)  {
				/*
				 * save away geometry info.
				 * don't bother checking the sb
				 * against the agi/agf as the odds
				 * of the sb being corrupted in a way
				 * that it is internally consistent
				 * but not consistent with the rest
				 * of the filesystem is really really low.
				 */
				get_sb_geometry(&geo, sb);
				list = add_geo(list, &geo, agno);
				num_ok++;
			}
		}
	}

	/*
	 * see if we have enough superblocks to bother with
	 */
	if (num_ok < num_sbs / 2)
		return(XR_INSUFF_SEC_SB);

	current = get_best_geo(list);

	/*
	 * check that enough sbs agree that we're willing to
	 * go with this geometry.  if not, print out the
	 * geometry and a message about the force option.
	 */
	switch (num_sbs)  {
	case 2:
		/*
		 * If we only have two allocation groups, and the superblock
		 * in the second allocation group differs from the primary
		 * superblock we can't verify the geometry information.
		 * Warn the user about this situation and get out unless
		 * explicitly overridden.
		 */
		if (current->refs != 2)  {
			if (!force_geo)  {
				do_warn(
	_("Only two AGs detected and they do not match - "
	  "cannot validate filesystem geometry.\n"
	  "Use the -o force_geometry option to proceed.\n"));
				exit(1);
			}
		}
		goto out_free_list;
	case 1:
		/*
		 * If we only have a single allocation group there is no
		 * secondary superblock that we can use to verify the geometry
		 * information.  Warn the user about this situation and get
		 * out unless explicitly overridden.
		 */
		if (!force_geo)  {
			do_warn(
	_("Only one AG detected - "
	  "cannot validate filesystem geometry.\n"
	  "Use the -o force_geometry option to proceed.\n"));
			exit(1);
		}
		goto out_free_list;
	default:
		/*
		 * at least half of the probed superblocks have
		 * to agree.  if they don't, this fs is probably
		 * too far gone anyway considering the fact that
		 * XFS normally doesn't alter the secondary superblocks.
		 */
		if (current->refs < num_sbs / 2)  {
			do_warn(
		_("Not enough matching superblocks - cannot proceed.\n"));
			exit(1);
		}
	}

	/*
	 * set the geometry into primary superblock if necessary.
	 */

	if (current->index != sb_index)  {
		*sb_modified = 1;
		off = (xfs_off_t)current->index * current->geo.sb_agblocks
			* current->geo.sb_blocksize;
		if (get_sb(sb, off, current->geo.sb_sectsize,
				current->index) != XR_OK)
			do_error(_("could not read superblock\n"));

		copy_sb(sb, rsb);

		/*
		 * turn off inprogress bit since this is the primary.
		 * also save away values that we need to ensure are
		 * consistent in the other secondaries.
		 */
		rsb->sb_inprogress = 0;
		sb_inoalignmt = sb->sb_inoalignmt;
		sb_unit = sb->sb_unit;
		sb_width = sb->sb_width;
	}

out_free_list:
	free_geo(list);
out:
	free(sb);
	free(checked);
	return(retval);
}
コード例 #8
0
ファイル: phase1.c プロジェクト: brkt/fuse-xfs
/* ARGSUSED */
void
phase1(xfs_mount_t *mp)
{
	xfs_sb_t		*sb;
	char			*ag_bp;
	int			rval;

	do_log(_("Phase 1 - find and verify superblock...\n"));

	primary_sb_modified = 0;
	need_root_inode = 0;
	need_root_dotdot = 0;
	need_rbmino = 0;
	need_rsumino = 0;
	lost_quotas = 0;

	/*
	 * get AG 0 into ag header buf
	 */
	ag_bp = alloc_ag_buf(MAX_SECTSIZE);
	sb = (xfs_sb_t *) ag_bp;

	if (get_sb(sb, 0LL, MAX_SECTSIZE, 0) == XR_EOF)
		do_error(_("error reading primary superblock\n"));

	/*
	 * is this really an sb, verify internal consistency
	 */
	if ((rval = verify_sb(sb, 1)) != XR_OK)  {
		do_warn(_("bad primary superblock - %s !!!\n"),
			err_string(rval));
		if (!find_secondary_sb(sb))
			no_sb();
		primary_sb_modified = 1;
	} else if ((rval = verify_set_primary_sb(sb, 0,
					&primary_sb_modified)) != XR_OK)  {
		do_warn(_("couldn't verify primary superblock - %s !!!\n"),
			err_string(rval));
		if (!find_secondary_sb(sb))
			no_sb();
		primary_sb_modified = 1;
	}

	/*
	 * Check bad_features2 and make sure features2 the same as
	 * bad_features (ORing the two together). Leave bad_features2
	 * set so older kernels can still use it and not mount unsupported
	 * filesystems when it reads bad_features2.
	 */
	if (sb->sb_bad_features2 != 0 &&
			sb->sb_bad_features2 != sb->sb_features2) {
		sb->sb_features2 |= sb->sb_bad_features2;
		sb->sb_bad_features2 = sb->sb_features2;
		primary_sb_modified = 1;
		do_warn(_("superblock has a features2 mismatch, correcting\n"));
	}

	/*
	 * apply any version changes or conversions after the primary
	 * superblock has been verified or repaired
	 *
	 * Send output to stdout as do_log and everything else in repair
	 * is sent to stderr and there is no "quiet" option. xfs_admin
	 * will filter stderr but not stdout. This situation must be improved.
	 */
	if (convert_lazy_count) {
		if (lazy_count && !xfs_sb_version_haslazysbcount(sb)) {
			sb->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
			sb->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
			sb->sb_bad_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
			primary_sb_modified = 1;
			printf(_("Enabling lazy-counters\n"));
		} else
		if (!lazy_count && xfs_sb_version_haslazysbcount(sb)) {
			sb->sb_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT;
			sb->sb_bad_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT;
			printf(_("Disabling lazy-counters\n"));
			primary_sb_modified = 1;
		} else {
			printf(_("Lazy-counters are already %s\n"),
				lazy_count ? _("enabled") : _("disabled"));
			exit(0); /* no conversion required, exit */
		}
	}

	if (primary_sb_modified)  {
		if (!no_modify)  {
			do_warn(_("writing modified primary superblock\n"));
			write_primary_sb(sb, sb->sb_sectsize);
		} else  {
			do_warn(_("would write modified primary superblock\n"));
		}
	}

	/*
	 * misc. global var initialization
	 */
	sb_ifree = sb_icount = sb_fdblocks = sb_frextents = 0;

	free(sb);
}