/*
 *  fs/partitions/aix.c
 *
 *  Copyright (C) 2012-2013 Philippe De Muyter <phdm@macqel.be>
 */

#include "check.h"
#include "aix.h"

struct lvm_rec {
	char lvm_id[4]; /* "_LVM" */
	char reserved4[16];
	__be32 lvmarea_len;
	__be32 vgda_len;
	__be32 vgda_psn[2];
	char reserved36[10];
	__be16 pp_size; /* log2(pp_size) */
	char reserved46[12];
	__be16 version;
	};

struct vgda {
	__be32 secs;
	__be32 usec;
	char reserved8[16];
	__be16 numlvs;
	__be16 maxlvs;
	__be16 pp_size;
	__be16 numpvs;
	__be16 total_vgdas;
	__be16 vgda_size;
	};

struct lvd {
	__be16 lv_ix;
	__be16 res2;
	__be16 res4;
	__be16 maxsize;
	__be16 lv_state;
	__be16 mirror;
	__be16 mirror_policy;
	__be16 num_lps;
	__be16 res10[8];
	};

struct lvname {
	char name[64];
	};

struct ppe {
	__be16 lv_ix;
	unsigned short res2;
	unsigned short res4;
	__be16 lp_ix;
	unsigned short res8[12];
	};

struct pvd {
	char reserved0[16];
	__be16 pp_count;
	char reserved18[2];
	__be32 psn_part1;
	char reserved24[8];
	struct ppe ppe[1016];
	};

#define LVM_MAXLVS 256

/**
 * last_lba(): return number of last logical block of device
 * @bdev: block device
 *
 * Description: Returns last LBA value on success, 0 on error.
 * This is stored (by sd and ide-geometry) in
 *  the part[0] entry for this disk, and is the number of
 *  physical sectors available on the disk.
 */
static u64 last_lba(struct block_device *bdev)
{
	if (!bdev || !bdev->bd_inode)
		return 0;
	return (bdev->bd_inode->i_size >> 9) - 1ULL;
}

/**
 * read_lba(): Read bytes from disk, starting at given LBA
 * @state
 * @lba
 * @buffer
 * @count
 *
 * Description:  Reads @count bytes from @state->bdev into @buffer.
 * Returns number of bytes read on success, 0 on error.
 */
static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer,
			size_t count)
{
	size_t totalreadcount = 0;

	if (!buffer || lba + count / 512 > last_lba(state->bdev))
		return 0;

	while (count) {
		int copied = 512;
		Sector sect;
		unsigned char *data = read_part_sector(state, lba++, &sect);
		if (!data)
			break;
		if (copied > count)
			copied = count;
		memcpy(buffer, data, copied);
		put_dev_sector(sect);
		buffer += copied;
		totalreadcount += copied;
		count -= copied;
	}
	return totalreadcount;
}

/**
 * alloc_pvd(): reads physical volume descriptor
 * @state
 * @lba
 *
 * Description: Returns pvd on success,  NULL on error.
 * Allocates space for pvd and fill it with disk blocks at @lba
 * Notes: remember to free pvd when you're done!
 */
static struct pvd *alloc_pvd(struct parsed_partitions *state, u32 lba)
{
	size_t count = sizeof(struct pvd);
	struct pvd *p;

	p = kmalloc(count, GFP_KERNEL);
	if (!p)
		return NULL;

	if (read_lba(state, lba, (u8 *) p, count) < count) {
		kfree(p);
		return NULL;
	}
	return p;
}

/**
 * alloc_lvn(): reads logical volume names
 * @state
 * @lba
 *
 * Description: Returns lvn on success,  NULL on error.
 * Allocates space for lvn and fill it with disk blocks at @lba
 * Notes: remember to free lvn when you're done!
 */
static struct lvname *alloc_lvn(struct parsed_partitions *state, u32 lba)
{
	size_t count = sizeof(struct lvname) * LVM_MAXLVS;
	struct lvname *p;

	p = kmalloc(count, GFP_KERNEL);
	if (!p)
		return NULL;

	if (read_lba(state, lba, (u8 *) p, count) < count) {
		kfree(p);
		return NULL;
	}
	return p;
}

int aix_partition(struct parsed_partitions *state)
{
	int ret = 0;
	Sector sect;
	unsigned char *d;
	u32 pp_bytes_size;
	u32 pp_blocks_size = 0;
	u32 vgda_sector = 0;
	u32 vgda_len = 0;
	int numlvs = 0;
	struct pvd *pvd;
	struct lv_info {
		unsigned short pps_per_lv;
		unsigned short pps_found;
		unsigned char lv_is_contiguous;
	} *lvip;
	struct lvname *n = NULL;

	d = read_part_sector(state, 7, &sect);
	if (d) {
		struct lvm_rec *p = (struct lvm_rec *)d;
		u16 lvm_version = be16_to_cpu(p->version);
		char tmp[64];

		if (lvm_version == 1) {
			int pp_size_log2 = be16_to_cpu(p->pp_size);

			pp_bytes_size = 1 << pp_size_log2;
			pp_blocks_size = pp_bytes_size / 512;
			snprintf(tmp, sizeof(tmp),
				" AIX LVM header version %u found\n",
				lvm_version);
			vgda_len = be32_to_cpu(p->vgda_len);
			vgda_sector = be32_to_cpu(p->vgda_psn[0]);
		} else {
			snprintf(tmp, sizeof(tmp),
				" unsupported AIX LVM version %d found\n",
				lvm_version);
		}
		strlcat(state->pp_buf, tmp, PAGE_SIZE);
		put_dev_sector(sect);
	}
	if (vgda_sector && (d = read_part_sector(state, vgda_sector, &sect))) {
		struct vgda *p = (struct vgda *)d;

		numlvs = be16_to_cpu(p->numlvs);
		put_dev_sector(sect);
	}
	lvip = kzalloc(sizeof(struct lv_info) * state->limit, GFP_KERNEL);
	if (!lvip)
		return 0;
	if (numlvs && (d = read_part_sector(state, vgda_sector + 1, &sect))) {
		struct lvd *p = (struct lvd *)d;
		int i;

		n = alloc_lvn(state, vgda_sector + vgda_len - 33);
		if (n) {
			int foundlvs = 0;

			for (i = 0; foundlvs < numlvs && i < state->limit; i += 1) {
				lvip[i].pps_per_lv = be16_to_cpu(p[i].num_lps);
				if (lvip[i].pps_per_lv)
					foundlvs += 1;
			}
		}
		put_dev_sector(sect);
	}
	pvd = alloc_pvd(state, vgda_sector + 17);
	if (pvd) {
		int numpps = be16_to_cpu(pvd->pp_count);
		int psn_part1 = be32_to_cpu(pvd->psn_part1);
		int i;
		int cur_lv_ix = -1;
		int next_lp_ix = 1;
		int lp_ix;

		for (i = 0; i < numpps; i += 1) {
			struct ppe *p = pvd->ppe + i;
			unsigned int lv_ix;

			lp_ix = be16_to_cpu(p->lp_ix);
			if (!lp_ix) {
				next_lp_ix = 1;
				continue;
			}
			lv_ix = be16_to_cpu(p->lv_ix) - 1;
			if (lv_ix >= state->limit) {
				cur_lv_ix = -1;
				continue;
			}
			lvip[lv_ix].pps_found += 1;
			if (lp_ix == 1) {
				cur_lv_ix = lv_ix;
				next_lp_ix = 1;
			} else if (lv_ix != cur_lv_ix || lp_ix != next_lp_ix) {
				next_lp_ix = 1;
				continue;
			}
			if (lp_ix == lvip[lv_ix].pps_per_lv) {
				char tmp[70];

				put_partition(state, lv_ix + 1,
				  (i + 1 - lp_ix) * pp_blocks_size + psn_part1,
				  lvip[lv_ix].pps_per_lv * pp_blocks_size);
				snprintf(tmp, sizeof(tmp), " <%s>\n",
					 n[lv_ix].name);
				strlcat(state->pp_buf, tmp, PAGE_SIZE);
				lvip[lv_ix].lv_is_contiguous = 1;
				ret = 1;
				next_lp_ix = 1;
			} else
				next_lp_ix += 1;
		}
		for (i = 0; i < state->limit; i += 1)
			if (lvip[i].pps_found && !lvip[i].lv_is_contiguous)
				pr_warn("partition %s (%u pp's found) is "
					"not contiguous\n",
					n[i].name, lvip[i].pps_found);
		kfree(pvd);
	}
	kfree(n);
	kfree(lvip);
	return ret;
}
