2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: block.c 911 2005-03-14 21:02:17Z oopo $
11 # PFS block/zone related routines
16 // Sets 'blockpos' to point to the next block segment for the inode (and moves onto the
17 // next block descriptor inode if necessary)
18 int blockSeekNextSegment(pfs_cache_t
*clink
, pfs_blockpos_t
*blockpos
)
20 pfs_cache_t
*nextSegment
;
23 if (blockpos
->byte_offset
)
25 printf("ps2fs: Panic: This is a bug!\n");
29 // If we're at the end of the block descriptor array for the current
30 // inode, then move onto the next inode
31 if (fixIndex(blockpos
->block_segment
+1)==0)
33 if ((nextSegment
=blockGetNextSegment(cacheUsedAdd(blockpos
->inode
), &result
)) == NULL
)
35 cacheAdd(blockpos
->inode
);
36 blockpos
->inode
=nextSegment
;
37 if (clink
->u
.inode
->number_data
-1 == ++blockpos
->block_segment
)
41 blockpos
->block_offset
=0;
42 blockpos
->block_segment
++;
46 u32
blockSyncPos(pfs_blockpos_t
*blockpos
, u64 size
)
50 i
= size
/ blockpos
->inode
->pfsMount
->zsize
;
51 blockpos
->byte_offset
+= size
% blockpos
->inode
->pfsMount
->zsize
;
53 if (blockpos
->byte_offset
>= blockpos
->inode
->pfsMount
->zsize
)
55 blockpos
->byte_offset
-= blockpos
->inode
->pfsMount
->zsize
;
61 int blockInitPos(pfs_cache_t
*clink
, pfs_blockpos_t
*blockpos
, u64 position
)
63 blockpos
->inode
=cacheUsedAdd(clink
);
64 blockpos
->byte_offset
=0;
66 if (clink
->u
.inode
->size
)
68 blockpos
->block_segment
=1;
69 blockpos
->block_offset
=0;
71 blockpos
->block_segment
=0;
72 blockpos
->block_offset
=1;
74 return inodeSync(blockpos
, position
, clink
->u
.inode
->number_data
);
77 // Attempt to expand the block segment 'blockpos' by 'count' blocks
78 int blockExpandSegment(pfs_cache_t
*clink
, pfs_blockpos_t
*blockpos
, u32 count
)
83 if(fixIndex(blockpos
->block_segment
)==0)
86 bi
= &blockpos
->inode
->u
.inode
->data
[fixIndex(blockpos
->block_segment
)];
88 if ((ret
= bitmapAllocateAdditionalZones(clink
->pfsMount
, bi
, count
)))
91 clink
->u
.inode
->number_blocks
+=ret
;
92 blockpos
->inode
->flags
|= CACHE_FLAG_DIRTY
;
93 clink
->flags
|= CACHE_FLAG_DIRTY
;
99 // Attempts to allocate 'blocks' new blocks for an inode
100 int blockAllocNewSegment(pfs_cache_t
*clink
, pfs_blockpos_t
*blockpos
, u32 blocks
)
102 pfs_blockinfo bi
, *bi2
;
104 pfs_mount_t
*pfsMount
=clink
->pfsMount
;
105 u32 i
, old_blocks
= blocks
;
107 dprintf2("ps2fs CALL: allocNewBlockSegment(, , %ld)\n", blocks
);
112 // create "indirect segment descriptor" if necessary
113 if (fixIndex(clink
->u
.inode
->number_data
) == 0)
117 bi2
= &blockpos
->inode
->u
.inode
->data
[fixIndex(blockpos
->block_segment
)];
118 bi
.subpart
=bi2
->subpart
;
120 bi
.number
=bi2
->number
+bi2
->count
;
121 result
=searchFreeZone(pfsMount
, &bi
, clink
->u
.inode
->number_blocks
);
124 dprintf("ps2fs: Error: Couldnt allocate zone! (1)\n");
128 clink2
=cacheGetData(pfsMount
, bi
.subpart
, bi
.number
<< pfsMount
->inode_scale
,
129 CACHE_FLAG_SEGI
| CACHE_FLAG_NOLOAD
, &result
);
130 memset(clink2
->u
.inode
, 0, sizeof(pfs_inode
));
131 clink2
->u
.inode
->magic
=PFS_SEGI_MAGIC
;
133 memcpy(&clink2
->u
.inode
->inode_block
, &clink
->u
.inode
->inode_block
, sizeof(pfs_blockinfo
));
134 memcpy(&clink2
->u
.inode
->last_segment
, &blockpos
->inode
->u
.inode
->data
[0], sizeof(pfs_blockinfo
));
135 memcpy(&clink2
->u
.inode
->data
[0], &bi
, sizeof(pfs_blockinfo
));
137 clink2
->flags
|= CACHE_FLAG_DIRTY
;
139 clink
->u
.inode
->number_blocks
+=bi
.count
;
140 clink
->u
.inode
->number_data
++;
142 memcpy(&clink
->u
.inode
->last_segment
, &bi
, sizeof(pfs_blockinfo
));
144 clink
->u
.inode
->number_segdesg
++;
146 clink
->flags
|= CACHE_FLAG_DIRTY
;
147 blockpos
->block_segment
++;
148 blockpos
->block_offset
=0;
150 memcpy(&blockpos
->inode
->u
.inode
->next_segment
, &bi
, sizeof(pfs_blockinfo
));
152 blockpos
->inode
->flags
|= CACHE_FLAG_DIRTY
;
153 cacheAdd(blockpos
->inode
);
154 blockpos
->inode
=clink2
;
157 bi2
= &blockpos
->inode
->u
.inode
->data
[fixIndex(blockpos
->block_segment
)];
158 bi
.subpart
= bi2
->subpart
;
160 bi
.number
= bi2
->number
+ bi2
->count
;
162 result
= searchFreeZone(pfsMount
, &bi
, clink
->u
.inode
->number_blocks
);
165 dprintf("ps2fs: Error: Couldnt allocate zone! (2)\n");
169 clink
->u
.inode
->number_blocks
+= bi
.count
;
170 clink
->u
.inode
->number_data
++;
171 clink
->flags
|= CACHE_FLAG_DIRTY
;
172 blockpos
->block_offset
=0;
173 blockpos
->block_segment
++;
175 i
= fixIndex(clink
->u
.inode
->number_data
-1);
176 memcpy(&blockpos
->inode
->u
.inode
->data
[i
], &bi
, sizeof(pfs_blockinfo
));
178 blockpos
->inode
->flags
|= CACHE_FLAG_DIRTY
;
181 blocks
-= blockExpandSegment(clink
, blockpos
, blocks
);
183 return old_blocks
- blocks
;
186 // Returns the block info for the block segment corresponding to the
187 // files current position.
188 pfs_blockinfo
* blockGetCurrent(pfs_blockpos_t
*blockpos
)
190 return &blockpos
->inode
->u
.inode
->data
[fixIndex(blockpos
->block_segment
)];
193 // Returns the next block descriptor inode
194 pfs_cache_t
*blockGetNextSegment(pfs_cache_t
*clink
, int *result
)
198 if (clink
->u
.inode
->next_segment
.number
)
199 return cacheGetData(clink
->pfsMount
,
200 clink
->u
.inode
->next_segment
.subpart
,
201 clink
->u
.inode
->next_segment
.number
<< clink
->pfsMount
->inode_scale
,
202 CACHE_FLAG_SEGI
, result
);
204 printf( "ps2fs: Error: There is no next segment descriptor\n");
209 pfs_cache_t
*blockGetLastSegmentDescriptorInode(pfs_cache_t
*clink
, int *result
)
211 return cacheGetData(clink
->pfsMount
, clink
->u
.inode
->last_segment
.subpart
,
212 clink
->u
.inode
->last_segment
.number
<<clink
->pfsMount
->inode_scale
,
213 (clink
->u
.inode
->last_segment
.subpart
==
214 clink
->u
.inode
->inode_block
.subpart
)&&
215 (clink
->u
.inode
->last_segment
.number
==
216 clink
->u
.inode
->inode_block
.number
) ? 16 : 32, result
);