223 lines
6.3 KiB
NASM
223 lines
6.3 KiB
NASM
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;; ;;
|
||
|
;; Contains common resource allocation + freeing code. ;;
|
||
|
;; ;;
|
||
|
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||
|
;; Distributed under the terms of the new BSD license. ;;
|
||
|
;; ;;
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
;---------------------------------------------------------------------
|
||
|
; Frees a resource (block/inode).
|
||
|
; Input: eax = resource ID.
|
||
|
; edi = function pointer of ext2_bg_*_bitmap form, to
|
||
|
; get bitmap of resource.
|
||
|
; ecx = 0, block; 1, inode.
|
||
|
; ebp = pointer to EXTFS.
|
||
|
; Output: Block marked as free in block group.
|
||
|
; eax = error code.
|
||
|
;---------------------------------------------------------------------
|
||
|
ext2_resource_free:
|
||
|
push ebx edx esi
|
||
|
|
||
|
; Get block group.
|
||
|
sub eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
|
||
|
xor edx, edx
|
||
|
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
|
||
|
push eax edx
|
||
|
|
||
|
call edi
|
||
|
test eax, eax
|
||
|
jz .fail
|
||
|
mov esi, eax
|
||
|
|
||
|
; Read the bitmap.
|
||
|
mov eax, ebx
|
||
|
mov edx, eax
|
||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||
|
call ext2_block_read
|
||
|
test eax, eax
|
||
|
jnz .fail
|
||
|
|
||
|
pop eax
|
||
|
; Mark bit free.
|
||
|
call bitmap_clear_bit
|
||
|
test eax, eax
|
||
|
jz @F
|
||
|
|
||
|
; No need to save anything.
|
||
|
xor eax, eax
|
||
|
|
||
|
add esp, 4
|
||
|
jmp .return
|
||
|
|
||
|
@@:
|
||
|
mov eax, edx
|
||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||
|
call ext2_block_write
|
||
|
test eax, eax
|
||
|
jnz .fail
|
||
|
|
||
|
; Read the descriptor.
|
||
|
mov eax, [esp]
|
||
|
call ext2_bg_read_desc
|
||
|
test eax, eax
|
||
|
jz .fail_bg_desc_read
|
||
|
|
||
|
lea eax, [eax + EXT2_BLOCK_GROUP_DESC.free_blocks_count]
|
||
|
shl ecx, 1
|
||
|
add eax, ecx
|
||
|
inc word[eax]
|
||
|
|
||
|
lea eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
|
||
|
shl ecx, 1
|
||
|
add eax, ecx
|
||
|
inc dword[eax]
|
||
|
|
||
|
pop eax
|
||
|
call ext2_bg_write_desc
|
||
|
|
||
|
.return:
|
||
|
pop esi edx ebx
|
||
|
ret
|
||
|
|
||
|
.fail:
|
||
|
add esp, 4
|
||
|
.fail_bg_desc_read:
|
||
|
add esp, 4
|
||
|
xor eax, eax
|
||
|
not eax
|
||
|
jmp .return
|
||
|
|
||
|
;---------------------------------------------------------------------
|
||
|
; Allocates a resource.
|
||
|
; Input: eax = inode ID for "preference".
|
||
|
; ebp = pointer to EXTFS.
|
||
|
; [esp + 4], func pointer to ext2_bg_*_bitmap
|
||
|
; [esp + 8], pointer to free_*_count in SB.
|
||
|
; [esp + 12], *_per_group
|
||
|
; [esp + 16], offset to free_*_count in bg descriptor.
|
||
|
; [esp + 20], *_count
|
||
|
; Output: Resource marked as set in block group.
|
||
|
; eax = error code.
|
||
|
; ebx = resource ID.
|
||
|
;---------------------------------------------------------------------
|
||
|
ext2_resource_alloc:
|
||
|
; Block allocation is a pretty serious area, since bad allocation
|
||
|
; can lead to defragmentation. Thus, the best way to allocate that
|
||
|
; comes to mind is to allocate around an inode as much as possible.
|
||
|
; On the other hand, this isn't about a single inode/file/directory,
|
||
|
; and focusing just around the preferred inode would lead to
|
||
|
; congestion. Thus, after much though, the chosen allocation algorithm
|
||
|
; is to search forward, then backward.
|
||
|
push ecx edx esi edi
|
||
|
|
||
|
cmp dword[esp + 16 + 8], 0
|
||
|
jnz @F
|
||
|
|
||
|
; No free blocks.
|
||
|
xor eax, eax
|
||
|
not eax
|
||
|
pop edi esi edx ecx
|
||
|
ret 20
|
||
|
|
||
|
@@:
|
||
|
; Calculate which block group the preferred inode belongs to.
|
||
|
dec eax
|
||
|
xor edx, edx
|
||
|
|
||
|
; EAX = block group.
|
||
|
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
|
||
|
push eax
|
||
|
push eax
|
||
|
|
||
|
mov edi, .forward
|
||
|
|
||
|
.test_block_group:
|
||
|
call dword[esp + 16 + 8 + 4]
|
||
|
test eax, eax
|
||
|
jz .fail
|
||
|
mov esi, eax
|
||
|
|
||
|
mov eax, ebx
|
||
|
mov edx, eax
|
||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||
|
call ext2_block_read
|
||
|
test eax, eax
|
||
|
jnz .fail
|
||
|
|
||
|
mov ecx, [esp + 16 + 8 + 12]
|
||
|
call ext2_find_free_bit
|
||
|
cmp eax, 0xFFFFFFFF
|
||
|
jne @F
|
||
|
|
||
|
mov eax, edi
|
||
|
jmp eax
|
||
|
|
||
|
@@:
|
||
|
mov ecx, eax
|
||
|
|
||
|
mov eax, edx
|
||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||
|
call ext2_block_write
|
||
|
test eax, eax
|
||
|
jnz .fail
|
||
|
|
||
|
; ecx: the index of the matched entry.
|
||
|
; [esp]: block group where we found.
|
||
|
; [esp + 4]: starting block group.
|
||
|
; esi: block group descriptor.
|
||
|
mov eax, [esp] ; Index of block group in which we found.
|
||
|
mul dword[esp + 16 + 8 + 12]
|
||
|
add eax, ecx
|
||
|
mov ebx, eax
|
||
|
|
||
|
mov eax, [esp + 16 + 8 + 8]
|
||
|
dec dword[eax]
|
||
|
|
||
|
mov eax, esi
|
||
|
add eax, [esp + 16 + 8 + 16]
|
||
|
dec word[eax]
|
||
|
|
||
|
pop eax
|
||
|
call ext2_bg_write_desc
|
||
|
|
||
|
add esp, 4
|
||
|
jmp .return
|
||
|
|
||
|
; Continue forward.
|
||
|
.forward:
|
||
|
inc dword[esp]
|
||
|
mov eax, [esp]
|
||
|
mul dword[esp + 16 + 8 + 12]
|
||
|
cmp eax, [esp + 16 + 8 + 20]
|
||
|
jbe @F
|
||
|
|
||
|
; We need to go backward.
|
||
|
mov eax, [esp + 4]
|
||
|
mov [esp], eax
|
||
|
mov edi, .backward
|
||
|
jmp .backward
|
||
|
|
||
|
@@:
|
||
|
mov eax, [esp]
|
||
|
jmp .test_block_group
|
||
|
|
||
|
; Continue backward.
|
||
|
.backward:
|
||
|
cmp dword[esp], 0
|
||
|
je .fail
|
||
|
|
||
|
dec dword[esp]
|
||
|
mov eax, [esp]
|
||
|
jmp .test_block_group
|
||
|
|
||
|
.return:
|
||
|
pop edi esi edx ecx
|
||
|
ret 20
|
||
|
|
||
|
.fail:
|
||
|
add esp, 8
|
||
|
xor eax, eax
|
||
|
not eax
|
||
|
jmp .return
|