// File: ljl0222[P]SecondFileSystem/INode.cpp
// Function: Inode::Bmap(int)
int Inode::Bmap(int lbn)
{
	Buf* pFirstBuf;
	Buf* pSecondBuf;
	int phyBlkno;	/* ת�����������̿��� */
	int* iTable;	/* ���ڷ��������̿���һ�μ��ӡ����μ��������� */
	int index;
	User& u = globalUser;
	BufferManager& bufMgr = globalBufferManager;
	FileSystem& fileSys = globalFileSystem;

	/*
	 * Unix V6++���ļ������ṹ��(С�͡����ͺ;����ļ�)
	 * (1) i_addr[0] - i_addr[5]Ϊֱ�����������ļ����ȷ�Χ��0 - 6���̿飻
	 *
	 * (2) i_addr[6] - i_addr[7]����һ�μ������������ڴ��̿��ţ�ÿ���̿�
	 * �ϴ���128���ļ������̿��ţ������ļ����ȷ�Χ��7 - (128 * 2 + 6)���̿飻
	 *
	 * (3) i_addr[8] - i_addr[9]���Ŷ��μ������������ڴ��̿��ţ�ÿ�����μ���
	 * ��������¼128��һ�μ������������ڴ��̿��ţ������ļ����ȷ�Χ��
	 * (128 * 2 + 6 ) < size <= (128 * 128 * 2 + 128 * 2 + 6)
	 */

	if (lbn >= Inode::HUGE_FILE_BLOCK)
	{
		u.u_error = User::myEFBIG;
		return 0;
	}

	if (lbn < 6)		/* ������С���ļ����ӻ���������i_addr[0-5]�л��������̿��ż��� */
	{
		phyBlkno = this->i_addr[lbn];

		/*
		 * �������߼����Ż�û����Ӧ�������̿�����֮��Ӧ��������һ�������顣
		 * ��ͨ�������ڶ��ļ���д�룬��д��λ�ó����ļ���С�����Ե�ǰ
		 * �ļ���������д�룬����Ҫ���������Ĵ��̿飬��Ϊ֮�����߼�����
		 * �������̿���֮����ӳ�䡣
		 */
		if (phyBlkno == 0 && (pFirstBuf = fileSys.Alloc()) != NULL)
		{
			/*
			 * ��Ϊ�����ܿ������ϻ�Ҫ�õ��˴��·��������ݿ飬���Բ���������������
			 * �����ϣ����ǽ���������Ϊ�ӳ�д��ʽ���������Լ���ϵͳ��I/O������
			 */
			bufMgr.Bdwrite(pFirstBuf);
			phyBlkno = pFirstBuf->b_blkno;
			/* ���߼�����lbnӳ�䵽�����̿���phyBlkno */
			this->i_addr[lbn] = phyBlkno;
			this->i_flag |= Inode::IUPD;
		}

		return phyBlkno;
	}
	else	/* lbn >= 6 ���͡������ļ� */
	{
		/* �����߼�����lbn��Ӧi_addr[]�е����� */

		if (lbn < Inode::LARGE_FILE_BLOCK)	/* �����ļ�: ���Ƚ���7 - (128 * 2 + 6)���̿�֮�� */
		{
			index = (lbn - Inode::SMALL_FILE_BLOCK) / Inode::ADDRESS_PER_INDEX_BLOCK + 6;
		}
		else	/* �����ļ�: ���Ƚ���263 - (128 * 128 * 2 + 128 * 2 + 6)���̿�֮�� */
		{
			index = (lbn - Inode::LARGE_FILE_BLOCK) / (Inode::ADDRESS_PER_INDEX_BLOCK * Inode::ADDRESS_PER_INDEX_BLOCK) + 8;
		}

		phyBlkno = this->i_addr[index];
		/* ������Ϊ�㣬����ʾ��������Ӧ�ļ����������� */
		if (0 == phyBlkno)
		{
			this->i_flag |= Inode::IUPD;
			/* ����һ�����̿����ż��������� */
			if ((pFirstBuf = fileSys.Alloc()) == NULL)
			{
				return 0;	/* ����ʧ�� */
			}
			/* i_addr[index]�м�¼�����������������̿��� */
			this->i_addr[index] = pFirstBuf->b_blkno;
		}
		else
		{
			/* �����洢�������������ַ��� */
			pFirstBuf = bufMgr.Bread(phyBlkno);
		}

		/* ��ȡ��������ַ */
		iTable = (int*)pFirstBuf->b_addr;

		if (index >= 8)	/* ASSERT: 8 <= index <= 9 */
		{
			/*
			 * ���ھ����ļ���������pFirstBuf���Ƕ��μ�����������
			 * ���������߼����ţ����ɶ��μ����������ҵ�һ�μ���������
			 */
			index = ((lbn - Inode::LARGE_FILE_BLOCK) / Inode::ADDRESS_PER_INDEX_BLOCK) % Inode::ADDRESS_PER_INDEX_BLOCK;

			/* iTableָ�򻺴��еĶ��μ���������������Ϊ�㣬������һ�μ��������� */
			phyBlkno = iTable[index];
			if (0 == phyBlkno)
			{
				if ((pSecondBuf = fileSys.Alloc()) == NULL)
				{
					/* ����һ�μ������������̿�ʧ�ܣ��ͷŻ����еĶ��μ�����������Ȼ�󷵻� */
					bufMgr.Brelse(pFirstBuf);
					return 0;
				}
				/* ���·�����һ�μ������������̿��ţ��������μ�����������Ӧ�� */
				iTable[index] = pSecondBuf->b_blkno;
				/* �����ĺ��Ķ��μ����������ӳ�д��ʽ���������� */
				bufMgr.Bdwrite(pFirstBuf);
			}
			else
			{
				/* �ͷŶ��μ���������ռ�õĻ��棬������һ�μ��������� */
				bufMgr.Brelse(pFirstBuf);
				pSecondBuf = bufMgr.Bread(phyBlkno);
			}

			pFirstBuf = pSecondBuf;
			/* ��iTableָ��һ�μ��������� */
			iTable = (int*)pSecondBuf->b_addr;
		}

		/* �����߼�����lbn����λ��һ�μ����������еı�������index */

		if (lbn < Inode::LARGE_FILE_BLOCK)
		{
			index = (lbn - Inode::SMALL_FILE_BLOCK) % Inode::ADDRESS_PER_INDEX_BLOCK;
		}
		else
		{
			index = (lbn - Inode::LARGE_FILE_BLOCK) % Inode::ADDRESS_PER_INDEX_BLOCK;
		}

		if ((phyBlkno = iTable[index]) == 0 && (pSecondBuf = fileSys.Alloc()) != NULL)
		{
			/* �����䵽���ļ������̿��ŵǼ���һ�μ����������� */
			phyBlkno = pSecondBuf->b_blkno;
			iTable[index] = phyBlkno;
			/* �������̿顢���ĺ���һ�μ������������ӳ�д��ʽ���������� */
			bufMgr.Bdwrite(pSecondBuf);
			bufMgr.Bdwrite(pFirstBuf);
		}
		else
		{
			/* �ͷ�һ�μ���������ռ�û��� */
			bufMgr.Brelse(pFirstBuf);
		}

		return phyBlkno;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
leaq 0x1cc8a(%rip), %rax     # 0x24cc8
movq %rax, -0x48(%rbp)
leaq 0xc307(%rip), %rax      # 0x14350
movq %rax, -0x50(%rbp)
leaq 0x1ae84(%rip), %rax     # 0x22ed8
movq %rax, -0x58(%rbp)
cmpl $0x8106, -0x14(%rbp)    # imm = 0x8106
jl 0x807e
leaq 0x1cc60(%rip), %rax     # 0x24cc8
movl $0x1b, 0x10c8(%rax)
movl $0x0, -0x4(%rbp)
jmp 0x8305
cmpl $0x6, -0x14(%rbp)
jge 0x80ea
movq -0x60(%rbp), %rax
movslq -0x14(%rbp), %rcx
movl 0x20(%rax,%rcx,4), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x80df
leaq 0x1ae38(%rip), %rdi     # 0x22ed8
callq 0x7ae0
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
je 0x80df
movq -0x20(%rbp), %rsi
leaq 0xc296(%rip), %rdi      # 0x14350
callq 0x4080
movq -0x60(%rbp), %rax
movq -0x20(%rbp), %rcx
movl 0x28(%rcx), %ecx
movl %ecx, -0x2c(%rbp)
movl -0x2c(%rbp), %edx
movslq -0x14(%rbp), %rcx
movl %edx, 0x20(%rax,%rcx,4)
movl (%rax), %ecx
orl $0x2, %ecx
movl %ecx, (%rax)
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x8305
cmpl $0x106, -0x14(%rbp)     # imm = 0x106
jge 0x8109
movl -0x14(%rbp), %eax
subl $0x6, %eax
movl $0x80, %ecx
cltd
idivl %ecx
addl $0x6, %eax
movl %eax, -0x3c(%rbp)
jmp 0x811f
movl -0x14(%rbp), %eax
subl $0x106, %eax            # imm = 0x106
movl $0x4000, %ecx           # imm = 0x4000
cltd
idivl %ecx
addl $0x8, %eax
movl %eax, -0x3c(%rbp)
movq -0x60(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl 0x20(%rax,%rcx,4), %eax
movl %eax, -0x2c(%rbp)
xorl %eax, %eax
cmpl -0x2c(%rbp), %eax
jne 0x8177
movq -0x60(%rbp), %rax
movl (%rax), %ecx
orl $0x2, %ecx
movl %ecx, (%rax)
leaq 0x1ad91(%rip), %rdi     # 0x22ed8
callq 0x7ae0
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x8162
movl $0x0, -0x4(%rbp)
jmp 0x8305
movq -0x60(%rbp), %rax
movq -0x20(%rbp), %rcx
movl 0x28(%rcx), %edx
movslq -0x3c(%rbp), %rcx
movl %edx, 0x20(%rax,%rcx,4)
jmp 0x818a
movl -0x2c(%rbp), %esi
leaq 0xc1cf(%rip), %rdi      # 0x14350
callq 0x3f10
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x38(%rbp)
cmpl $0x8, -0x3c(%rbp)
jl 0x825d
movl -0x14(%rbp), %eax
subl $0x106, %eax            # imm = 0x106
movl $0x80, %ecx
cltd
idivl %ecx
movl $0x80, %ecx
cltd
idivl %ecx
movl %edx, -0x3c(%rbp)
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x2c(%rbp)
xorl %eax, %eax
cmpl -0x2c(%rbp), %eax
jne 0x8226
leaq 0x1ad01(%rip), %rdi     # 0x22ed8
callq 0x7ae0
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
jne 0x8202
movq -0x20(%rbp), %rsi
leaq 0xc15f(%rip), %rdi      # 0x14350
callq 0x3e80
movl $0x0, -0x4(%rbp)
jmp 0x8305
movq -0x28(%rbp), %rax
movl 0x28(%rax), %edx
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x20(%rbp), %rsi
leaq 0xc131(%rip), %rdi      # 0x14350
callq 0x4080
jmp 0x8249
movq -0x20(%rbp), %rsi
leaq 0xc11f(%rip), %rdi      # 0x14350
callq 0x3e80
movl -0x2c(%rbp), %esi
leaq 0xc110(%rip), %rdi      # 0x14350
callq 0x3f10
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x38(%rbp)
cmpl $0x106, -0x14(%rbp)     # imm = 0x106
jge 0x8279
movl -0x14(%rbp), %eax
subl $0x6, %eax
movl $0x80, %ecx
cltd
idivl %ecx
movl %edx, -0x3c(%rbp)
jmp 0x828c
movl -0x14(%rbp), %eax
subl $0x106, %eax            # imm = 0x106
movl $0x80, %ecx
cltd
idivl %ecx
movl %edx, -0x3c(%rbp)
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, %eax
jne 0x82ef
leaq 0x1ac32(%rip), %rdi     # 0x22ed8
callq 0x7ae0
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x82ef
movq -0x28(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %edx
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x28(%rbp), %rsi
leaq 0xc078(%rip), %rdi      # 0x14350
callq 0x4080
movq -0x20(%rbp), %rsi
leaq 0xc068(%rip), %rdi      # 0x14350
callq 0x4080
jmp 0x82ff
movq -0x20(%rbp), %rsi
leaq 0xc056(%rip), %rdi      # 0x14350
callq 0x3e80
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nop