PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
cache.c
1/*
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.
9#
10# PFS metadata cache manipulation routines
11*/
12
13#include <errno.h>
14#include <stdio.h>
15#ifdef _IOP
16#include <sysclib.h>
17#else
18#include <string.h>
19#endif
20#include <hdd-ioctl.h>
21
22#include "libpfs.h"
23
24extern u32 pfsBlockSize;
25
26pfs_cache_t *pfsCacheBuf;
27u32 pfsCacheNumBuffers;
28
29void pfsCacheFree(pfs_cache_t *clink)
30{
31 if(clink==NULL) {
32 PFS_PRINTF(PFS_DRV_NAME": Warning: NULL buffer returned\n");
33 return;
34 }
35
36 if(clink->nused==0){
37 PFS_PRINTF(PFS_DRV_NAME": Error: Unused cache returned\n");
38 return;
39 }
40
41 clink->nused--;
42 if(clink->pfsMount!=NULL) {
43 if(clink->nused!=0)
44 return;
45 pfsCacheLink(pfsCacheBuf->prev, clink);
46 return;
47 }
48 if(clink->nused!=0) {
49 PFS_PRINTF(PFS_DRV_NAME": Warning: Invalidated buffer is in use\n");
50 return;
51 }
52 pfsCacheLink(pfsCacheBuf, clink);
53}
54
55void pfsCacheLink(pfs_cache_t *clink, pfs_cache_t *cnew)
56{
57 cnew->prev=clink;
58 cnew->next=clink->next;
59 clink->next->prev=cnew;
60 clink->next=cnew;
61}
62
63pfs_cache_t *pfsCacheUnLink(pfs_cache_t *clink)
64{
65 clink->prev->next=clink->next;
66 clink->next->prev=clink->prev;
67 return clink;
68}
69
70pfs_cache_t *pfsCacheUsedAdd(pfs_cache_t *clink)
71{
72 clink->nused++;
73 return clink;
74}
75
76int pfsCacheTransfer(pfs_cache_t* clink, int mode)
77{
78 pfs_mount_t *pfsMount=clink->pfsMount;
79 int err;
80
81 if(pfsMount->lastError == 0) { // no error
82 if((err=pfsMount->blockDev->transfer(pfsMount->fd, clink->u.data, clink->sub,
83 clink->block << pfsBlockSize, 1 << pfsBlockSize, mode))==0) {
84 if(mode==PFS_IO_MODE_READ) {
85 if(clink->flags & PFS_CACHE_FLAG_SEGD && ((pfs_inode_t *)clink->u.inode)->magic!=PFS_SEGD_MAGIC)
86 err=-EIO;
87 if(clink->flags & PFS_CACHE_FLAG_SEGI && ((pfs_inode_t *)clink->u.inode)->magic!=PFS_SEGI_MAGIC)
88 err=-EIO;
89 if(clink->flags & (PFS_CACHE_FLAG_SEGD|PFS_CACHE_FLAG_SEGI)) {
90 if(((pfs_inode_t *)clink->u.inode)->checksum!=(u32)(pfsInodeCheckSum(clink->u.inode)))
91 err=-EIO;
92 }
93 }
94 }
95 if(err!=0) {
96 PFS_PRINTF(PFS_DRV_NAME": Error: Disk error partition %ld, block %ld, err %d\n",
97 clink->sub, clink->block, err);
98#ifndef PFS_NO_WRITE_ERROR_STAT
99 pfsMount->blockDev->setPartitionError(pfsMount->fd);
100 pfsFsckStat(pfsMount, clink->u.superblock, PFS_FSCK_STAT_WRITE_ERROR, PFS_MODE_SET_FLAG);
101 pfsMount->lastError=err;
102#endif
103 }
104 }
105 clink->flags&=~PFS_CACHE_FLAG_DIRTY; // clear dirty :)
106 return pfsMount->lastError;
107}
108
109void pfsCacheFlushAllDirty(pfs_mount_t *pfsMount)
110{
111 u32 i;
112 int found=0;
113
114 for(i=1;i<pfsCacheNumBuffers+1;i++){
115 if(pfsCacheBuf[i].pfsMount == pfsMount &&
116 pfsCacheBuf[i].flags & PFS_CACHE_FLAG_DIRTY)
117 found=1;
118 }
119 if(found) {
120 pfsJournalWrite(pfsMount, pfsCacheBuf+1, pfsCacheNumBuffers);
121 for(i=1;i<pfsCacheNumBuffers+1;i++){
122 if(pfsCacheBuf[i].pfsMount == pfsMount &&
123 pfsCacheBuf[i].flags & PFS_CACHE_FLAG_DIRTY)
124 pfsCacheTransfer(&pfsCacheBuf[i], 1);
125 }
126 }
127
128 pfsJournalReset(pfsMount);
129}
130
131pfs_cache_t *pfsCacheAlloc(pfs_mount_t *pfsMount, u16 sub, u32 block,
132 int flags, int *result)
133{
134 pfs_cache_t *allocated;
135
136 if (pfsCacheBuf->prev==pfsCacheBuf && pfsCacheBuf->prev->next==pfsCacheBuf->prev) {
137 PFS_PRINTF(PFS_DRV_NAME": Error: Free buffer list is empty\n");
138 *result=-ENOMEM;
139 return NULL;
140 }
141 allocated=pfsCacheBuf->next;
142 if (pfsCacheBuf->next==NULL)
143 PFS_PRINTF(PFS_DRV_NAME": Panic: Null pointer allocated\n");
144 if (allocated->pfsMount && (allocated->flags & PFS_CACHE_FLAG_DIRTY))
145 pfsCacheFlushAllDirty(allocated->pfsMount);
146 allocated->flags = flags & PFS_CACHE_FLAG_MASKTYPE;
147 allocated->pfsMount = pfsMount;
148 allocated->sub = sub;
149 allocated->block = block;
150 allocated->nused = 1;
151 return pfsCacheUnLink(allocated);
152}
153
154pfs_cache_t *pfsCacheGetData(pfs_mount_t *pfsMount, u16 sub, u32 block,
155 int flags, int *result)
156{
157 u32 i;
158 pfs_cache_t *clink;
159
160 *result=0;
161
162 for (i=1; i < pfsCacheNumBuffers + 1; i++)
163 if ( pfsCacheBuf[i].pfsMount &&
164 (pfsCacheBuf[i].pfsMount==pfsMount) &&
165 (pfsCacheBuf[i].block == block))
166 if (pfsCacheBuf[i].sub==sub){
167 pfsCacheBuf[i].flags &= PFS_CACHE_FLAG_MASKSTATUS;
168 pfsCacheBuf[i].flags |= flags & PFS_CACHE_FLAG_MASKTYPE;
169 if (pfsCacheBuf[i].nused == 0)
170 pfsCacheUnLink(&pfsCacheBuf[i]);
171 pfsCacheBuf[i].nused++;
172 return &pfsCacheBuf[i];
173 }
174
175 clink=pfsCacheAlloc(pfsMount, sub, block, flags, result);
176
177 if (clink){
178 if (flags & PFS_CACHE_FLAG_NOLOAD)
179 return clink;
180
181 if ((*result=pfsCacheTransfer(clink, PFS_IO_MODE_READ))>=0)
182 return clink;
183
184 clink->pfsMount=NULL;
185 pfsCacheFree(clink);
186 }
187 return NULL;
188}
189
190pfs_cache_t *pfsCacheAllocClean(int *result)
191{
192 *result = 0;
193 return pfsCacheAlloc(NULL, 0, 0, 0, result);
194}
195
196// checks if the pfsCacheBuf list has some room
197int pfsCacheIsFull(void)
198{
199 if (pfsCacheBuf->prev != pfsCacheBuf) return 0;
200 return pfsCacheBuf->prev->next == pfsCacheBuf->prev;
201}
202
203int pfsCacheInit(u32 numBuf, u32 bufSize)
204{
205 char *cacheData;
206 u32 i;
207
208 if(numBuf > 127) {
209 PFS_PRINTF(PFS_DRV_NAME": Error: Number of buffers larger than 127.\n");
210 return -EINVAL;
211 }
212
213 cacheData = pfsAllocMem(numBuf * bufSize);
214
215 if(!cacheData || !(pfsCacheBuf = pfsAllocMem((numBuf + 1) * sizeof(pfs_cache_t))))
216 return -ENOMEM;
217
218 pfsCacheNumBuffers = numBuf;
219 memset(pfsCacheBuf, 0, (numBuf + 1) * sizeof(pfs_cache_t));
220
221 pfsCacheBuf->next = pfsCacheBuf;
222 pfsCacheBuf->prev = pfsCacheBuf;
223
224 for(i = 1; i < numBuf + 1; i++)
225 {
226 pfsCacheBuf[i].u.data = cacheData;
227 pfsCacheLink(pfsCacheBuf->prev, &pfsCacheBuf[i]);
228 cacheData += bufSize;
229 }
230
231 return 0;
232}
233
234int pfsCacheDeinit(void)
235{
236#if 0
237 unsigned int i;
238
239 for(i = 1; i < pfsCacheNumBuffers + 1; i++){
240 // !!! This code performs multiple frees
241 apaFreeMem(pfsCacheBuf[i].u.data);
242 }
243#else
244 // Unofficial: Free once at the head of the list
245 if (pfsCacheNumBuffers > 1)
246 {
247 pfsFreeMem(pfsCacheBuf[1].u.data);
248 }
249#endif
250 pfsFreeMem(pfsCacheBuf);
251 return 0;
252}
253
254void pfsCacheClose(pfs_mount_t *pfsMount)
255{
256 unsigned int i;
257
258#ifdef PFS_SUPPORT_BHDD
259 if (strcmp(pfsMount->blockDev->devName, "bhdd") != 0)
260#endif
261 {
262 pfsCacheFlushAllDirty(pfsMount);
263 }
264 for(i=1; i < pfsCacheNumBuffers+1;i++){
265 if(pfsCacheBuf[i].pfsMount==pfsMount)
266 pfsCacheBuf[i].pfsMount=NULL;
267 }
268}
269
270void pfsCacheMarkClean(const pfs_mount_t *pfsMount, u32 subpart, u32 blockStart, u32 blockEnd)
271{
272 u32 i;
273
274 for(i=1; i< pfsCacheNumBuffers+1;i++){
275 if(pfsCacheBuf[i].pfsMount==pfsMount && pfsCacheBuf[i].sub==subpart) {
276 if(pfsCacheBuf[i].block >= blockStart && pfsCacheBuf[i].block < blockEnd)
277 pfsCacheBuf[i].flags&=~PFS_CACHE_FLAG_DIRTY;
278 }
279 }
280}
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define EIO
Definition errno.h:29