// File: /workspace/github_cpp_makefile_star2_O3/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
jle 0x5227
decl %ecx
movl %ecx, 0x19c(%rax)
movl 0x1a0(%rax,%rcx,4), %esi
leaq 0x16c09(%rip), %rdi     # 0x1be00
callq 0x5eae
testq %rax, %rax
je 0x5308
movq %rax, %r14
movq %rax, %rdi
callq 0x5bc2
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movl $0x1, 0x338(%rax)
jmp 0x534d
cmpl $0x0, (%rax)
jle 0x52f5
xorl %r13d, %r13d
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movq -0x30(%rbp), %rax
movq (%rax), %rdi
leal 0x2(%r13), %esi
callq 0x3aa4
movq %rax, -0x40(%rbp)
movq 0x20(%rax), %r14
movq %rbx, -0x38(%rbp)
leal 0x1(%rbx), %r15d
xorl %ebx, %ebx
cmpl $0x0, (%r14)
jne 0x5278
leal (%r15,%rbx), %r12d
leaq 0x16b95(%rip), %rdi     # 0x1be00
movl %r12d, %esi
callq 0x5fa6
cmpl $-0x1, %eax
je 0x5285
cmpl $0x6, %ebx
ja 0x52b3
incl %ebx
addq $0x40, %r14
jmp 0x525a
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 0x52b3
cmpl $0x7, %ebx
jb 0x527d
movq -0x30(%rbp), %r14
movq (%r14), %rdi
movq -0x40(%rbp), %rsi
callq 0x3a58
movq 0x8(%r14), %rax
movl 0x19c(%rax), %ecx
cmpl $0x64, %ecx
jge 0x51e1
movq -0x38(%rbp), %rdx
addl %ebx, %edx
incl %edx
movq %rdx, %rbx
incl %r13d
cmpl (%rax), %r13d
jl 0x5238
testl %ecx, %ecx
jg 0x51e1
leaq 0x188dc(%rip), %rax     # 0x1dbd8
movl $0x1c, 0x10c8(%rax)
jmp 0x534a
movq 0x7cb9(%rip), %rbx      # 0xcfc8
leaq 0x3d4a(%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
xorl %r14d, %r14d
movq %r14, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop