// File: /workspace/github_cpp_makefile_star2_O2/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
subq $0x18, %rsp
movq %rdi, -0x30(%rbp)
movq 0x8(%rdi), %rax
movl 0x19c(%rax), %ecx
testl %ecx, %ecx
jg 0x529e
pushq $-0x1
popq %r15
xorl %r13d, %r13d
cmpl (%rax), %r13d
jge 0x529a
movq -0x30(%rbp), %rax
movq (%rax), %rdi
leal 0x2(%r13), %esi
callq 0x3a46
movq %rax, -0x38(%rbp)
movq 0x20(%rax), %r14
xorl %ebx, %ebx
cmpq $0x200, %rbx            # imm = 0x200
je 0x5272
leal 0x1(%r15), %r12d
cmpl $0x0, (%r14,%rbx)
jne 0x5266
leaq 0x15bd0(%rip), %rdi     # 0x1ae00
movl %r12d, %esi
callq 0x5eb0
cmpl $-0x1, %eax
jne 0x5266
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movslq 0x19c(%rax), %rcx
leal 0x1(%rcx), %edx
movl %edx, 0x19c(%rax)
movl %r12d, 0x1a0(%rax,%rcx,4)
cmpl $0x63, 0x19c(%rax)
jg 0x526f
addq $0x40, %rbx
movl %r12d, %r15d
jmp 0x5215
incl %r15d
movq -0x30(%rbp), %rbx
movq (%rbx), %rdi
movq -0x38(%rbp), %rsi
callq 0x3a16
movq 0x8(%rbx), %rax
movl 0x19c(%rax), %ecx
incl %r13d
cmpl $0x64, %ecx
jl 0x51f2
jmp 0x529e
testl %ecx, %ecx
jle 0x530d
decl %ecx
movl %ecx, 0x19c(%rax)
movl 0x1a0(%rax,%rcx,4), %esi
leaq 0x15b4c(%rip), %rdi     # 0x1ae00
callq 0x5dfa
testq %rax, %rax
je 0x52dd
movq %rax, %r14
movq %rax, %rdi
callq 0x5b24
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movl $0x1, 0x338(%rax)
jmp 0x52fb
movq 0x6cdc(%rip), %rdi      # 0xbfc0
leaq 0x2d75(%rip), %rsi      # 0x8060
callq 0x31e0
movq %rax, %rdi
callq 0x3100
xorl %r14d, %r14d
movq %r14, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x178c4(%rip), %rax     # 0x1cbd8
movl $0x1c, 0x10c8(%rax)
jmp 0x52f8