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  | }