// File: /workspace/github_cpp_makefile_star2_O1/ljl0222[P]SecondFileSystem/FileSystem.cpp
// Function: FileSystem::IAlloc()
Inode* FileSystem::IAlloc()
{
	Buf* pBuf;
	Inode* pNode;
	User& u = globalUser;
	int ino;	/* ���䵽�Ŀ�������Inode���� */

	/*
	 * SuperBlockֱ�ӹ����Ŀ���Inode�������ѿգ�
	 * ���뵽��������������Inode���ȶ�inode�б�������
	 * ��Ϊ�����³����л����ж��̲������ܻᵼ�½����л���
	 * ���������п��ܷ��ʸ������������ᵼ�²�һ���ԡ�
	 */
	if (m_SuperBlock->s_ninode <= 0)
	{
		/* ����Inode���Ŵ�0��ʼ���ⲻͬ��Unix V6������Inode��1��ʼ���� */
		ino = -1;

		/* ���ζ�������Inode���еĴ��̿飬�������п�������Inode����������Inode������ */
		for (int i = 0; i < m_SuperBlock->s_isize; i++)
		{
			pBuf = this->m_BufferManager->Bread(FileSystem::INODE_ZONE_START_SECTOR + i);

			/* ��ȡ��������ַ */
			int* p = (int*)pBuf->b_addr;

			/* �����û�������ÿ������Inode��i_mode != 0����ʾ�Ѿ���ռ�� */
			for (int j = 0; j < FileSystem::INODE_NUMBER_PER_SECTOR; j++)
			{
				ino++;

				int mode = *(p + j * sizeof(DiskInode) / sizeof(int));

				/* ������Inode�ѱ�ռ�ã����ܼ�������Inode������ */
				if (mode != 0)
				{
					continue;
				}

				/*
				 * ��������inode��i_mode==0����ʱ������ȷ��
				 * ��inode�ǿ��еģ���Ϊ�п������ڴ�inodeû��д��
				 * ������,����Ҫ���������ڴ�inode���Ƿ�����Ӧ����
				 */
				if (globalINodeTable.IsLoaded(ino) == -1)
				{
					/* ������Inodeû�ж�Ӧ���ڴ濽����������������Inode������ */
					m_SuperBlock->s_inode[m_SuperBlock->s_ninode++] = ino;

					/* ���������������Ѿ�װ�����򲻼������� */
					if (m_SuperBlock->s_ninode >= 100)
					{
						break;
					}
				}
			}

			/* �����Ѷ��굱ǰ���̿飬�ͷ���Ӧ�Ļ��� */
			this->m_BufferManager->Brelse(pBuf);

			/* ���������������Ѿ�װ�����򲻼������� */
			if (m_SuperBlock->s_ninode >= 100)
			{
				break;
			}
		}

		/* �����ڴ�����û���������κο�������Inode������NULL */
		if (m_SuperBlock->s_ninode <= 0)
		{
			u.u_error = User::myENOSPC;
			return NULL;
		}
	}
	
	ino = m_SuperBlock->s_inode[--m_SuperBlock->s_ninode];
	pNode = globalINodeTable.IGet(ino);
	if (NULL == pNode) {
		cout << "û�п����ڴ���Inode" << endl;
		return NULL;
	}

	pNode->Clean();
	m_SuperBlock->s_fmod = 1;
	return pNode;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x8(%rdi), %rax
cmpl $0x0, 0x19c(%rax)
jg 0x52ba
movq 0x8(%rbx), %rax
cmpl $0x0, (%rax)
jle 0x52a9
xorl %r13d, %r13d
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movq (%rbx), %rdi
leal 0x2(%r13), %esi
callq 0x3af0
movq %rax, -0x30(%rbp)
movq 0x20(%rax), %r12
incl %r15d
movl %r15d, %eax
xorl %r14d, %r14d
movl %eax, %r15d
movl $0x7, %eax
cmpl $0x0, (%r12,%r14)
jne 0x5266
leaq 0x16bd3(%rip), %rdi     # 0x1be00
movl %r15d, %esi
callq 0x5ff2
cmpl $-0x1, %eax
jne 0x5264
movq 0x8(%rbx), %rcx
movslq 0x19c(%rcx), %rax
leal 0x1(%rax), %edx
movl %edx, 0x19c(%rcx)
movl %r15d, 0x1a0(%rcx,%rax,4)
movl $0x5, %eax
cmpl $0x63, 0x19c(%rcx)
jg 0x5266
xorl %eax, %eax
cmpl $0x7, %eax
je 0x526f
testl %eax, %eax
jne 0x5280
addq $0x40, %r14
leal 0x1(%r15), %eax
cmpq $0x200, %r14            # imm = 0x200
jne 0x5217
movq (%rbx), %rdi
movq -0x30(%rbp), %rsi
callq 0x3a9c
movq 0x8(%rbx), %rax
cmpl $0x64, 0x19c(%rax)
jge 0x52a9
incl %r13d
movq 0x8(%rbx), %rax
cmpl (%rax), %r13d
jl 0x51fa
movq 0x8(%rbx), %rax
cmpl $0x0, 0x19c(%rax)
jle 0x5346
movq 0x8(%rbx), %rax
movslq 0x19c(%rax), %rcx
leaq -0x1(%rcx), %rdx
movl %edx, 0x19c(%rax)
movl 0x19c(%rax,%rcx,4), %esi
leaq 0x16b23(%rip), %rdi     # 0x1be00
callq 0x5ee2
testq %rax, %rax
je 0x5302
movq %rax, %r14
movq %rax, %rdi
callq 0x5be4
movq 0x8(%rbx), %rax
movl $0x1, 0x338(%rax)
jmp 0x535a
movq 0x7cbf(%rip), %rbx      # 0xcfc8
leaq 0x3d50(%rip), %rsi      # 0x9060
movl $0x13, %edx
movq %rbx, %rdi
callq 0x3260
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x31f0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3170
jmp 0x5357
leaq 0x1888b(%rip), %rax     # 0x1dbd8
movl $0x1c, 0x10c8(%rax)
xorl %r14d, %r14d
movq %r14, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq