1 | /* onode.c
2 | -------
3 |
4 | Code for manipulating FCFS O-Nodes and their forks.
5 | Maybe the Fork stuff should be in a seperate file,
6 | you're welcome to patch :)
7 |
8 | $Id: onode.c,v 1.15 2003/10/20 07:18:11 stewart Exp $
9 |
10 | (C)2003 Stewart Smith
11 | Distributed under the GNU Public License
12 |
13 | Debugged with Beer(TM)
14 | */
15 |
16 | #include <stdio.h>
17 | #include <stdlib.h>
18 | #include <string.h>
19 | #include <assert.h>
20 | #include <time.h>
21 |
22 | #include "testkit/types.h"
23 | #include "super_block.h"
24 | #include "disk.h"
25 | #include "onode.h"
26 | #include "onode_index.h"
27 | #include "space_bitmap.h"
28 | #include "onode_versioned.h"
29 |
30 | struct fcfs_onode1 *onode1_new(struct fcfs_disk *disk)
31 | {
32 | struct fcfs_onode1 *node;
33 |
34 | node = (struct fcfs_onode1*)malloc(sizeof(struct fcfs_onode1));
35 | if(!node)
36 | {
37 | fprintf(stderr,"cannot allocate onode1, exiting\n");
38 | abort();
39 | }
40 |
41 | node->magic1 = FCFS_ONODE_MAGIC1;
42 | node->onode_num = 0;
43 | node->onode_revision = 0;
44 | set_bit(FCFS_OFLAG_ForkLeaf,&(node->flags));
45 | node->use_count = 0;
46 | node->onode_size = sizeof(struct fcfs_onode1);
47 | node->forks.leaf.nr = 0;
48 |
49 | return node;
50 | }
51 |
52 | struct fcfs_onode1 *onode1_free(struct fcfs_onode1 *onode)
53 | {
54 | free(onode);
55 | return NULL;
56 | }
57 |
58 | /*
59 | FIXME: the allow_internal is nasty hack, should be removed and made elegant
60 | */
61 | int onode1_fork_new(struct fcfs_disk *disk, struct fcfs_block_run *onode_br, u64 fork_type, u64 content_length, void* content,int allow_internal)
62 | {
63 | struct fcfs_disk_block *block;
64 | struct fcfs_onode1 *onode;
65 |
66 | block = disk_getblock(disk,BR_SECTOR_T(disk,onode_br));
67 | onode = (struct fcfs_onode1*)block->data;
68 |
69 | onode->forks.leaf.nr++; /* should be atomic */
70 | onode->forks.leaf.fork[onode->forks.leaf.nr-1].fork_type = fork_type;
71 | onode->forks.leaf.fork[onode->forks.leaf.nr-1].content_length = content_length;
72 | if(content_length <= FCFS_FORK_SMALL_DATA_SIZE && content_length > 0 && allow_internal)
73 | { /* Let's make it a small_data node */
74 | onode->forks.leaf.fork[onode->forks.leaf.nr-1].fork_flags = FCFS_FORK_InForkData;
75 | if(content!=NULL)
76 | memcpy(onode->forks.leaf.fork[onode->forks.leaf.nr-1].data.small_data, content,content_length);
77 | else
78 | memset(onode->forks.leaf.fork[onode->forks.leaf.nr-1].data.small_data, 0,FCFS_FORK_SMALL_DATA_SIZE);
79 | }
80 | else /* We're going to need more space! */
81 | {
82 | onode->forks.leaf.fork[onode->forks.leaf.nr-1].fork_flags = 0;
83 | onode->forks.leaf.fork[onode->forks.leaf.nr-1].data.space.leaf.nr = 0;
84 |
85 | if(content_length > FCFS_FORK_SMALL_DATA_SIZE && content!=NULL)
86 | fprintf(stderr,"**FIXME** Need larger objects\n");
87 | else
88 | {
89 | #ifdef DEBUG_ONODE
90 | fprintf(stderr,"PREALLOCATING ONODE FORK SPACE\n\n");
91 | #endif
92 | onode1_fork_grow(disk,onode_br,onode->forks.leaf.nr-1,content_length/disk->bsize + ((content_length%disk->bsize)?1:0));}
93 | }
94 |
95 | disk_writeblock(block);
96 | disk_freeblock(block);
97 |
98 | return onode->forks.leaf.nr-1;
99 | }
100 |
101 | struct fcfs_disk_block *onode1_fork_getblock(struct fcfs_disk *disk, struct fcfs_onode1 *onode,int forknr,u64 blocknr)
102 | {
103 | int i;
104 | u64 cur_blocknr;
105 | struct fcfs_disk_block *block;
106 |
107 | block = NULL;
108 |
109 | if(forknr > onode->forks.leaf.nr)
110 | {
111 | fprintf(stderr,"Invalid Fork Number for onode\n");
112 | abort();
113 | }
114 |
115 | // fprintf(stderr,"\n\n\t\t\tGETTING blocknr %llu from leaf.nr %d\n\n",blocknr,onode->forks.leaf.fork[forknr].data.space.leaf.nr);
116 |
117 | cur_blocknr = 0;
118 | for(i=0;i<onode->forks.leaf.fork[forknr].data.space.leaf.nr;i++)
119 | {
120 | if(cur_blocknr+onode->forks.leaf.fork[forknr].data.space.leaf.br[i].len
121 | >= blocknr)
122 | { /* blocknr in current br */
123 | block = disk_getblock(disk,
124 | BR_SECTOR_T(disk,
125 | &(onode->forks.leaf.fork[forknr].data.space.leaf.br[i]))
126 | +(blocknr-cur_blocknr));
127 | // fprintf(stderr,"GOT BLOCK #%llu\n",block->blocknr);
128 |
129 | break;
130 | }
131 | else
132 | {
133 | cur_blocknr+=onode->forks.leaf.fork[forknr].data.space.leaf.br[i].len;
134 | }
135 | }
136 |
137 | return block;
138 | }
139 |
140 | u64 onode1_fork_length(struct fcfs_onode1 *onode,int forknr)
141 | {
142 | return (onode->forks.leaf.fork[forknr].content_length);
143 | }
144 |
145 | int onode1_fork_write_versioned(struct fcfs_disk *disk,struct fcfs_onode1 *onode, struct fcfs_block_run *onode_br,int forknr,u64 pos,u64 content_length,void* content)
146 | {
147 | void* olddata;
148 | struct fcfs_onode_fork_rev rev;
149 |
150 | rev.magic1 = FCFS_ONODE_FORK_REV_MAGIC1;
151 | rev.time = time(NULL);
152 | rev.revision = onode->onode_revision; /* FIXME */
153 | rev.consistent_revision = onode->onode_revision; /* FIXME */
154 | rev.operation = FCFS_ONODE_FORK_REV_REPLACE;
155 | rev.rev_offset = onode1_fork_length(onode,forknr+1);
156 | rev.rev_length = content_length;
157 | rev.offset = pos;
158 | memset(rev.space,0,16);
159 |
160 | olddata = malloc(content_length);
161 | if(!olddata)
162 | {fprintf(stderr,"No memory for updating content\n");abort();}
163 | onode1_fork_read(disk,onode,forknr,pos,content_length,olddata);
164 | onode1_fork_write(disk,onode_br,forknr+1,onode1_fork_length(onode,forknr+1),content_length,olddata);
165 | onode1_fork_write(disk,onode_br,forknr+2,onode1_fork_length(onode,forknr+2),sizeof(struct fcfs_onode_fork_rev),&rev);
166 | onode1_fork_write(disk,onode_br,forknr,pos,content_length,content);
167 | return 1;
168 | }
169 |
170 | int onode1_fork_write(struct fcfs_disk *disk, struct fcfs_block_run *onode_br,int forknr, u64 pos, u64 content_length, void* content)
171 | {
172 | struct fcfs_disk_block *onode_block;
173 | struct fcfs_disk_block *block;
174 | struct fcfs_onode1 *onode;
175 | u64 write_length;
176 | u64 done_length;
177 |
178 | onode_block = disk_getblock(disk,BR_SECTOR_T(disk,onode_br));
179 | onode = (struct fcfs_onode1*)onode_block->data;
180 |
181 | if(forknr > onode->forks.leaf.nr)
182 | {
183 | fprintf(stderr,"Invalid Fork Number for onode\n");
184 | abort();
185 | }
186 | if(content_length==0)
187 | {
188 | fprintf(stderr,"Must have some content to write\n");
189 | abort();
190 | }
191 |
192 | if((pos+content_length) > onode->forks.leaf.fork[forknr].content_length)
193 | { /* Grow Onode Fork */
194 | if(content_length > (disk->bsize - onode->forks.leaf.fork[forknr].content_length%disk->bsize) || onode->forks.leaf.fork[forknr].content_length%disk->bsize==0)
195 | {
196 | #ifdef DEBUG_ONODE_WRITE
197 | fprintf(stderr,"GROWING in WRITE\n");
198 | #endif
199 | onode1_fork_grow(disk,onode_br,forknr,
200 | (pos+content_length
201 | - onode->forks.leaf.fork[forknr].content_length)
202 | / disk->bsize
203 | );
204 | }
205 | else
206 | fprintf(stderr,"ENOUGH SPACE IN EXISTING BLOCK\n");
207 | }
208 |
209 | done_length = pos%disk->bsize;
210 | do
211 | {
212 | // fprintf(stderr,"DEBUG---- content %llu done %llu\n",content_length,done_length);
213 |
214 | if(content_length<= disk->bsize)
215 | if((disk->bsize - done_length%disk->bsize) < content_length)
216 | {//fprintf(stderr,"\n\n\t\t1\n\n");
217 | write_length = disk->bsize - done_length%disk->bsize;}
218 | else
219 | {//fprintf(stderr,"\n\n\t\t2\n\n");
220 | write_length = content_length;}
221 | else
222 | {//fprintf(stderr,"\n\n\t\t3\n\n");
223 | write_length = disk->bsize - (done_length%disk->bsize);}
224 |
225 | #ifdef DEBUG_ONODE_WRITE
226 | fprintf(stderr,"&&&&&&&&&&&WRITE LENGTH = %llu, %llu, %llu\n",write_length,pos,done_length);
227 | #endif
228 |
229 | // fprintf(stderr,"^^^^^^^^^^^GETTING BLOCK = %llu\n",done_length/disk->bsize);
230 | block = onode1_fork_getblock(disk,onode,forknr,(pos + (done_length - pos%disk->bsize)) / disk->bsize);
231 |
232 | memcpy(block->data+(done_length%disk->bsize),content+(done_length - pos%disk->bsize),write_length);
233 |
234 | onode->forks.leaf.fork[forknr].content_length+=write_length;
235 | content_length-=write_length;
236 | done_length+=write_length;
237 |
238 | disk_writeblock(block);
239 | disk_freeblock(block);
240 | // fprintf(stderr,"!!!!!!!!!!!!!!LOOPING WITH %llu, %llu\n",content_length,done_length);
241 | } while(content_length > 0);
242 |
243 | // fprintf(stderr,"\n\nDONE WRITE()\n\n");
244 |
245 | disk_writeblock(onode_block);
246 | disk_freeblock(onode_block);
247 | }
248 |
249 | u64 onode1_fork_read(struct fcfs_disk *disk, struct fcfs_onode1 *onode,int forknr, u64 pos, u64 content_length, void* content)
250 | {
251 | struct fcfs_disk_block *block;
252 | u64 read_length;
253 | u64 done_length;
254 |
255 | if(forknr > onode->forks.leaf.nr)
256 | {
257 | fprintf(stderr,"Invalid Fork Number for onode\n");
258 | abort();
259 | }
260 | if(content_length==0)
261 | {
262 | fprintf(stderr,"Must have some content to read\n");
263 | abort();
264 | }
265 |
266 | if(pos > onode->forks.leaf.fork[forknr].content_length)
267 | {
268 | fprintf(stderr,"ERROR IN READ(): pos > content_length\n");
269 | return 0;
270 | }
271 |
272 | if((pos+content_length) > onode->forks.leaf.fork[forknr].content_length)
273 | {
274 | fprintf(stderr,"ERROR IN READ(): pos+content_length > content_length\n");
275 | content_length = onode->forks.leaf.fork[forknr].content_length - pos;
276 | }
277 |
278 | done_length = pos%disk->bsize;
279 | do
280 | {
281 | #ifdef DEBUG_ONODE_READ
282 | fprintf(stderr,"DEBUG---- content %llu done %llu\n",content_length,done_length);
283 | #endif
284 |
285 | if(content_length<= disk->bsize)
286 | if((disk->bsize - done_length%disk->bsize) < content_length)
287 | {read_length = disk->bsize - done_length%disk->bsize;}
288 | else
289 | {read_length = content_length;}
290 | else
291 | {read_length = disk->bsize - (done_length%disk->bsize);}
292 |
293 | #ifdef DEBUG_ONODE_READ
294 | fprintf(stderr,"&&&&&&&&&&&READ LENGTH = %llu\n",read_length);
295 |
296 | fprintf(stderr,"^^^^^^^^^^^GETTING BLOCK = %llu\n",done_length/disk->bsize);
297 | #endif
298 | block = onode1_fork_getblock(disk,onode,forknr,(pos + (done_length - pos%disk->bsize)) / disk->bsize);
299 |
300 | memcpy(content+(done_length - pos%disk->bsize),block->data+(done_length%disk->bsize),read_length);
301 |
302 | content_length-=read_length;
303 | done_length+=read_length;
304 |
305 | disk_freeblock(block);
306 | #ifdef DEBUG_ONODE_READ
307 | fprintf(stderr,"!!!!!!!!!!!!!!LOOPING WITH %llu, %llu\n",content_length,done_length);
308 | #endif
309 | } while(content_length > 0);
310 | #ifdef DEBUG_ONODE_READ
311 | fprintf(stderr,"\n\nDONE READ()\n\n");
312 | #endif
313 | return (done_length - pos%disk->bsize);
314 | }
315 |
316 |
317 | int onode1_fork_grow(struct fcfs_disk *disk, struct fcfs_block_run *onode_br, int forknr, u64 blocksnr)
318 | {
319 | struct fcfs_block_run *newbr;
320 | struct fcfs_onode1 *onode;
321 | struct fcfs_disk_block *block;
322 | struct fcfs_disk_block *blockz;
323 | int leafnr;
324 | int i;
325 |
326 | block = disk_getblock(disk,BR_SECTOR_T(disk,onode_br));
327 | onode = (struct fcfs_onode1*)block->data;
328 | if(test_bit(FCFS_FORK_InForkData,&(onode->forks.leaf.fork[forknr].fork_flags)))
329 | {
330 | /* We're changing a InFork Fork - and we shouldn't be! */
331 | fprintf(stderr,"ERROR: Trying to grow InForkData fork!\n");
332 | abort();
333 | }
334 | else
335 | {
336 | /* We're changing a normal fork */
337 | if(onode->forks.leaf.fork[forknr].data.space.leaf.nr >= FSFS_ONODE1_SPACE_LEAF_MAXNR)
338 | {
339 | fprintf(stderr,"FIXME-ERROR: Growing fork beyond leaf size\n");
340 | abort();
341 | }
342 | else
343 | {
344 | #ifdef ONODE_GROW_DEBUG
345 | fprintf(stderr,"ONODE GROW\n");
346 | #endif
347 | leafnr = onode->forks.leaf.fork[forknr].data.space.leaf.nr;
348 | // printf("onode_fork_grow\n");
349 | if(leafnr)
350 | newbr = ag_allocate_block(disk,
351 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].allocation_group,
352 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].start,
353 | //+onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].len-1,
354 | //onode_br->start,
355 | blocksnr);
356 | else
357 | newbr = ag_allocate_block(disk,
358 | onode_br->allocation_group,
359 | 300,
360 | blocksnr);
361 |
362 |
363 | #ifdef ONODE_GROW_DEBUG
364 | fprintf(stderr,"\n\t\t\t\t\tFORKNR INFO %u %u %u %u\n\n",
365 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].allocation_group,
366 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].start,
367 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].len,newbr->start);
368 | #endif
369 |
370 | if(leafnr>0 &&
371 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].allocation_group == newbr->allocation_group
372 | && onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].start
373 | + onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].len
374 | == newbr->start
375 | )
376 | { /* Extend current block_run */
377 | #ifdef ONODE_GROW_DEBUG
378 | fprintf(stderr,"Extended Existing Block Run! by %u\n",newbr->len);
379 | #endif
380 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].len+=
381 | newbr->len;
382 | }
383 | else
384 | {
385 | onode->forks.leaf.fork[forknr].data.space.leaf.nr++;
386 | leafnr = onode->forks.leaf.fork[forknr].data.space.leaf.nr;
387 |
388 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].allocation_group = newbr->allocation_group;
389 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].start = newbr->start;
390 | onode->forks.leaf.fork[forknr].data.space.leaf.br[leafnr-1].len = newbr->len;
391 | #ifdef ONODE_GROW_DEBUG
392 | fprintf(stderr,"ONODE GROWN WITH BR: %u %u %u #%u\n",
393 | newbr->allocation_group,
394 | newbr->start,
395 | newbr->len,
396 | onode->forks.leaf.fork[forknr].data.space.leaf.nr
397 | );
398 | #endif
399 | }
400 | for(i=BR_SECTOR_T(disk,newbr);i<BR_SECTOR_T(disk,newbr)+newbr->len;i++)
401 | {
402 | blockz = disk_newblock(disk,i);
403 | //disk_writeblock(blockz); // we don't write, as we're about
404 | // to anyway (after return)
405 | disk_freeblock(blockz);
406 | }
407 | free(newbr);
408 | }
409 | }
410 | disk_writeblock(block);
411 | disk_freeblock(block);
412 | return 1;
413 | }