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