// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 */

#include "libxfs_priv.h"
#include "libxcmd.h"
#include <blkid/blkid.h>
#include "xfs_multidisk.h"
#include "libfrog/platform.h"

#define TERABYTES(count, blog)	((uint64_t)(count) << (40 - (blog)))
#define GIGABYTES(count, blog)	((uint64_t)(count) << (30 - (blog)))
#define MEGABYTES(count, blog)	((uint64_t)(count) << (20 - (blog)))

void
calc_default_ag_geometry(
	int		blocklog,
	uint64_t	dblocks,
	int		multidisk,
	uint64_t	*agsize,
	uint64_t	*agcount)
{
	uint64_t	blocks = 0;
	int		shift = 0;

	/*
	 * First handle the high extreme - the point at which we will
	 * always use the maximum AG size.
	 *
	 * This applies regardless of storage configuration.
	 */
	if (dblocks >= TERABYTES(32, blocklog)) {
		blocks = XFS_AG_MAX_BLOCKS(blocklog);
		goto done;
	}

	/*
	 * For a single underlying storage device over 4TB in size
	 * use the maximum AG size.  Between 128MB and 4TB, just use
	 * 4 AGs and scale up smoothly between min/max AG sizes.
	 */
	if (!multidisk) {
		if (dblocks >= TERABYTES(4, blocklog)) {
			blocks = XFS_AG_MAX_BLOCKS(blocklog);
			goto done;
		} else if (dblocks >= MEGABYTES(128, blocklog)) {
			shift = XFS_NOMULTIDISK_AGLOG;
			goto calc_blocks;
		}
	}

	/*
	 * For the multidisk configs we choose an AG count based on the number
	 * of data blocks available, trying to keep the number of AGs higher
	 * than the single disk configurations. This makes the assumption that
	 * larger filesystems have more parallelism available to them.
	 */
	shift = XFS_MULTIDISK_AGLOG;
	if (dblocks <= GIGABYTES(512, blocklog))
		shift--;
	if (dblocks <= GIGABYTES(8, blocklog))
		shift--;
	if (dblocks < MEGABYTES(128, blocklog))
		shift--;
	if (dblocks < MEGABYTES(64, blocklog))
		shift--;
	if (dblocks < MEGABYTES(32, blocklog))
		shift--;

	/*
	 * If dblocks is not evenly divisible by the number of
	 * desired AGs, round "blocks" up so we don't lose the
	 * last bit of the filesystem. The same principle applies
	 * to the AG count, so we don't lose the last AG!
	 */
calc_blocks:
	ASSERT(shift >= 0 && shift <= XFS_MULTIDISK_AGLOG);
	blocks = dblocks >> shift;
	if (dblocks & xfs_mask32lo(shift)) {
		if (blocks < XFS_AG_MAX_BLOCKS(blocklog))
		    blocks++;
	}
done:
	*agsize = blocks;
	*agcount = dblocks / blocks + (dblocks % blocks != 0);
}

/*
 * Check for existing filesystem or partition table on device.
 * Returns:
 *	 1 for existing fs or partition
 *	 0 for nothing found
 *	-1 for internal error
 */
int
check_overwrite(
	const char	*device)
{
	const char	*type;
	blkid_probe	pr = NULL;
	int		ret;
	int		fd;
	long long	size;
	int		bsz;

	if (!device || !*device)
		return 0;

	ret = -1; /* will reset on success of all setup calls */

	fd = open(device, O_RDONLY);
	if (fd < 0)
		goto out;
	platform_findsizes((char *)device, fd, &size, &bsz);
	close(fd);

	/* nothing to overwrite on a 0-length device */
	if (size == 0) {
		ret = 0;
		goto out;
	}

	pr = blkid_new_probe_from_filename(device);
	if (!pr)
		goto out;

	ret = blkid_probe_enable_partitions(pr, 1);
	if (ret < 0)
		goto out;

	ret = blkid_do_fullprobe(pr);
	if (ret < 0)
		goto out;

	/*
	 * Blkid returns 1 for nothing found and 0 when it finds a signature,
	 * but we want the exact opposite, so reverse the return value here.
	 *
	 * In addition print some useful diagnostics about what actually is
	 * on the device.
	 */
	if (ret) {
		ret = 0;
		goto out;
	}

	if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
		fprintf(stderr,
			_("%s: %s appears to contain an existing "
			"filesystem (%s).\n"), progname, device, type);
	} else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
		fprintf(stderr,
			_("%s: %s appears to contain a partition "
			"table (%s).\n"), progname, device, type);
	} else {
		fprintf(stderr,
			_("%s: %s appears to contain something weird "
			"according to blkid\n"), progname, device);
	}
	ret = 1;
out:
	if (pr)
		blkid_free_probe(pr);
	if (ret == -1)
		fprintf(stderr,
			_("%s: probe of %s failed, cannot detect "
			  "existing filesystem.\n"), progname, device);
	return ret;
}

static void
blkid_get_topology(
	const char		*device,
	struct device_topology	*dt,
	int			force_overwrite)
{
	blkid_topology tp;
	blkid_probe pr;

	pr = blkid_new_probe_from_filename(device);
	if (!pr)
		return;

	tp = blkid_probe_get_topology(pr);
	if (!tp)
		goto out_free_probe;

	dt->logical_sector_size = blkid_topology_get_logical_sector_size(tp);
	dt->physical_sector_size = blkid_topology_get_physical_sector_size(tp);
	dt->sunit = blkid_topology_get_minimum_io_size(tp);
	dt->swidth = blkid_topology_get_optimal_io_size(tp);

	/*
	 * If the reported values are the same as the physical sector size
	 * do not bother to report anything.  It will only cause warnings
	 * if people specify larger stripe units or widths manually.
	 */
	if (dt->sunit == dt->physical_sector_size ||
	    dt->swidth == dt->physical_sector_size) {
		dt->sunit = 0;
		dt->swidth = 0;
	}

	/*
	 * Blkid reports the information in terms of bytes, but we want it in
	 * terms of 512 bytes blocks (only to convert it to bytes later..)
	 */
	dt->sunit >>= 9;
	dt->swidth >>= 9;

	if (blkid_topology_get_alignment_offset(tp) != 0) {
		fprintf(stderr,
			_("warning: device is not properly aligned %s\n"),
			device);

		if (!force_overwrite) {
			fprintf(stderr,
				_("Use -f to force usage of a misaligned device\n"));

			exit(EXIT_FAILURE);
		}
		/* Do not use physical sector size if the device is misaligned */
		dt->physical_sector_size = dt->logical_sector_size;
	}

	blkid_free_probe(pr);
	return;

out_free_probe:
	blkid_free_probe(pr);
	fprintf(stderr,
		_("warning: unable to probe device topology for device %s\n"),
		device);
}

static void
get_device_topology(
	struct libxfs_dev	*dev,
	struct device_topology	*dt,
	int			force_overwrite)
{
	struct stat		st;

	/*
	 * Nothing to do if this particular subvolume doesn't exist.
	 */
	if (!dev->name)
		return;

	/*
	 * If our target is a regular file, use platform_findsizes
	 * to try to obtain the underlying filesystem's requirements
	 * for direct IO; we'll set our sector size to that if possible.
	 */
	if (dev->isfile || (!stat(dev->name, &st) && S_ISREG(st.st_mode))) {
		int flags = O_RDONLY;
		long long dummy;
		int fd;

		/* with xi->disfile we may not have the file yet! */
		if (dev->isfile)
			flags |= O_CREAT;

		fd = open(dev->name, flags, 0666);
		if (fd >= 0) {
			platform_findsizes(dev->name, fd, &dummy,
					&dt->logical_sector_size);
			close(fd);
		} else {
			dt->logical_sector_size = BBSIZE;
		}
	} else {
		blkid_get_topology(dev->name, dt, force_overwrite);
	}

	ASSERT(dt->logical_sector_size);

	/*
	 * Older kernels may not have physical/logical distinction.
	 */
	if (!dt->physical_sector_size)
		dt->physical_sector_size = dt->logical_sector_size;
}

void
get_topology(
	struct libxfs_init	*xi,
	struct fs_topology	*ft,
	int			force_overwrite)
{
	get_device_topology(&xi->data, &ft->data, force_overwrite);
	get_device_topology(&xi->rt, &ft->rt, force_overwrite);
	get_device_topology(&xi->log, &ft->log, force_overwrite);
}
