1*5e96a66cSDavid du Colombier #include "stdinc.h" 2*5e96a66cSDavid du Colombier #include "dat.h" 3*5e96a66cSDavid du Colombier #include "fns.h" 4*5e96a66cSDavid du Colombier #include "error.h" 5*5e96a66cSDavid du Colombier 6*5e96a66cSDavid du Colombier /* 7*5e96a66cSDavid du Colombier * locking order is upwards. A thread can hold the lock for a File 8*5e96a66cSDavid du Colombier * and then acquire the lock of its parent 9*5e96a66cSDavid du Colombier */ 10*5e96a66cSDavid du Colombier 11*5e96a66cSDavid du Colombier struct File { 12*5e96a66cSDavid du Colombier Fs *fs; /* immutable */ 13*5e96a66cSDavid du Colombier 14*5e96a66cSDavid du Colombier /* meta data for file: protected by the lk in the parent */ 15*5e96a66cSDavid du Colombier int ref; /* holds this data structure up */ 16*5e96a66cSDavid du Colombier 17*5e96a66cSDavid du Colombier int partial; /* file was never really open */ 18*5e96a66cSDavid du Colombier int removed; /* file has been removed */ 19*5e96a66cSDavid du Colombier int dirty; /* dir is dirty with respect to meta data in block */ 20*5e96a66cSDavid du Colombier u32int boff; /* block offset within msource for this file's meta data */ 21*5e96a66cSDavid du Colombier 22*5e96a66cSDavid du Colombier DirEntry dir; /* meta data for this file */ 23*5e96a66cSDavid du Colombier 24*5e96a66cSDavid du Colombier File *up; /* parent file */ 25*5e96a66cSDavid du Colombier File *next; /* sibling */ 26*5e96a66cSDavid du Colombier 27*5e96a66cSDavid du Colombier /* data for file */ 28*5e96a66cSDavid du Colombier VtLock *lk; /* lock for the following */ 29*5e96a66cSDavid du Colombier Source *source; 30*5e96a66cSDavid du Colombier Source *msource; /* for directories: meta data for children */ 31*5e96a66cSDavid du Colombier File *down; /* children */ 32*5e96a66cSDavid du Colombier 33*5e96a66cSDavid du Colombier int mode; 34*5e96a66cSDavid du Colombier }; 35*5e96a66cSDavid du Colombier 36*5e96a66cSDavid du Colombier static int fileMetaFlush2(File*, char*); 37*5e96a66cSDavid du Colombier static u32int fileMetaAlloc(File*, DirEntry*, u32int); 38*5e96a66cSDavid du Colombier static int fileRLock(File*); 39*5e96a66cSDavid du Colombier static void fileRUnlock(File*); 40*5e96a66cSDavid du Colombier static int fileLock(File*); 41*5e96a66cSDavid du Colombier static void fileUnlock(File*); 42*5e96a66cSDavid du Colombier static void fileMetaLock(File*); 43*5e96a66cSDavid du Colombier static void fileMetaUnlock(File*); 44*5e96a66cSDavid du Colombier static void fileRAccess(File*); 45*5e96a66cSDavid du Colombier static void fileWAccess(File*, char*); 46*5e96a66cSDavid du Colombier 47*5e96a66cSDavid du Colombier static File * 48*5e96a66cSDavid du Colombier fileAlloc(Fs *fs) 49*5e96a66cSDavid du Colombier { 50*5e96a66cSDavid du Colombier File *f; 51*5e96a66cSDavid du Colombier 52*5e96a66cSDavid du Colombier f = vtMemAllocZ(sizeof(File)); 53*5e96a66cSDavid du Colombier f->lk = vtLockAlloc(); 54*5e96a66cSDavid du Colombier f->ref = 1; 55*5e96a66cSDavid du Colombier f->fs = fs; 56*5e96a66cSDavid du Colombier f->boff = NilBlock; 57*5e96a66cSDavid du Colombier f->mode = fs->mode; 58*5e96a66cSDavid du Colombier return f; 59*5e96a66cSDavid du Colombier } 60*5e96a66cSDavid du Colombier 61*5e96a66cSDavid du Colombier static void 62*5e96a66cSDavid du Colombier fileFree(File *f) 63*5e96a66cSDavid du Colombier { 64*5e96a66cSDavid du Colombier sourceClose(f->source); 65*5e96a66cSDavid du Colombier vtLockFree(f->lk); 66*5e96a66cSDavid du Colombier sourceClose(f->msource); 67*5e96a66cSDavid du Colombier deCleanup(&f->dir); 68*5e96a66cSDavid du Colombier 69*5e96a66cSDavid du Colombier memset(f, ~0, sizeof(File)); 70*5e96a66cSDavid du Colombier vtMemFree(f); 71*5e96a66cSDavid du Colombier } 72*5e96a66cSDavid du Colombier 73*5e96a66cSDavid du Colombier /* 74*5e96a66cSDavid du Colombier * the file is locked already 75*5e96a66cSDavid du Colombier * f->msource is unlocked 76*5e96a66cSDavid du Colombier */ 77*5e96a66cSDavid du Colombier static File * 78*5e96a66cSDavid du Colombier dirLookup(File *f, char *elem) 79*5e96a66cSDavid du Colombier { 80*5e96a66cSDavid du Colombier int i; 81*5e96a66cSDavid du Colombier MetaBlock mb; 82*5e96a66cSDavid du Colombier MetaEntry me; 83*5e96a66cSDavid du Colombier Block *b; 84*5e96a66cSDavid du Colombier Source *meta; 85*5e96a66cSDavid du Colombier File *ff; 86*5e96a66cSDavid du Colombier u32int bo, nb; 87*5e96a66cSDavid du Colombier 88*5e96a66cSDavid du Colombier meta = f->msource; 89*5e96a66cSDavid du Colombier b = nil; 90*5e96a66cSDavid du Colombier if(!sourceLock(meta, -1)) 91*5e96a66cSDavid du Colombier return nil; 92*5e96a66cSDavid du Colombier nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize; 93*5e96a66cSDavid du Colombier for(bo=0; bo<nb; bo++){ 94*5e96a66cSDavid du Colombier b = sourceBlock(meta, bo, OReadOnly); 95*5e96a66cSDavid du Colombier if(b == nil) 96*5e96a66cSDavid du Colombier goto Err; 97*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 98*5e96a66cSDavid du Colombier goto Err; 99*5e96a66cSDavid du Colombier if(mbSearch(&mb, elem, &i, &me)){ 100*5e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 101*5e96a66cSDavid du Colombier if(!deUnpack(&ff->dir, &me)){ 102*5e96a66cSDavid du Colombier fileFree(ff); 103*5e96a66cSDavid du Colombier goto Err; 104*5e96a66cSDavid du Colombier } 105*5e96a66cSDavid du Colombier sourceUnlock(meta); 106*5e96a66cSDavid du Colombier blockPut(b); 107*5e96a66cSDavid du Colombier ff->boff = bo; 108*5e96a66cSDavid du Colombier ff->mode = f->mode; 109*5e96a66cSDavid du Colombier return ff; 110*5e96a66cSDavid du Colombier } 111*5e96a66cSDavid du Colombier 112*5e96a66cSDavid du Colombier blockPut(b); 113*5e96a66cSDavid du Colombier b = nil; 114*5e96a66cSDavid du Colombier } 115*5e96a66cSDavid du Colombier vtSetError(ENoFile); 116*5e96a66cSDavid du Colombier /* fall through */ 117*5e96a66cSDavid du Colombier Err: 118*5e96a66cSDavid du Colombier sourceUnlock(meta); 119*5e96a66cSDavid du Colombier blockPut(b); 120*5e96a66cSDavid du Colombier return nil; 121*5e96a66cSDavid du Colombier } 122*5e96a66cSDavid du Colombier 123*5e96a66cSDavid du Colombier File * 124*5e96a66cSDavid du Colombier fileRoot(Source *r) 125*5e96a66cSDavid du Colombier { 126*5e96a66cSDavid du Colombier Block *b; 127*5e96a66cSDavid du Colombier Source *r0, *r1, *r2; 128*5e96a66cSDavid du Colombier MetaBlock mb; 129*5e96a66cSDavid du Colombier MetaEntry me; 130*5e96a66cSDavid du Colombier File *root, *mr; 131*5e96a66cSDavid du Colombier Fs *fs; 132*5e96a66cSDavid du Colombier 133*5e96a66cSDavid du Colombier b = nil; 134*5e96a66cSDavid du Colombier root = nil; 135*5e96a66cSDavid du Colombier mr = nil; 136*5e96a66cSDavid du Colombier r1 = nil; 137*5e96a66cSDavid du Colombier r2 = nil; 138*5e96a66cSDavid du Colombier 139*5e96a66cSDavid du Colombier fs = r->fs; 140*5e96a66cSDavid du Colombier if(!sourceLock(r, -1)) 141*5e96a66cSDavid du Colombier return nil; 142*5e96a66cSDavid du Colombier r0 = sourceOpen(r, 0, fs->mode); 143*5e96a66cSDavid du Colombier if(r0 == nil) 144*5e96a66cSDavid du Colombier goto Err; 145*5e96a66cSDavid du Colombier r1 = sourceOpen(r, 1, fs->mode); 146*5e96a66cSDavid du Colombier if(r1 == nil) 147*5e96a66cSDavid du Colombier goto Err; 148*5e96a66cSDavid du Colombier r2 = sourceOpen(r, 2, fs->mode); 149*5e96a66cSDavid du Colombier if(r2 == nil) 150*5e96a66cSDavid du Colombier goto Err; 151*5e96a66cSDavid du Colombier 152*5e96a66cSDavid du Colombier mr = fileAlloc(fs); 153*5e96a66cSDavid du Colombier mr->msource = r2; 154*5e96a66cSDavid du Colombier r2 = nil; 155*5e96a66cSDavid du Colombier 156*5e96a66cSDavid du Colombier root = fileAlloc(fs); 157*5e96a66cSDavid du Colombier root->boff = 0; 158*5e96a66cSDavid du Colombier root->up = mr; 159*5e96a66cSDavid du Colombier root->source = r0; 160*5e96a66cSDavid du Colombier r0 = nil; 161*5e96a66cSDavid du Colombier root->msource = r1; 162*5e96a66cSDavid du Colombier r1 = nil; 163*5e96a66cSDavid du Colombier 164*5e96a66cSDavid du Colombier mr->down = root; 165*5e96a66cSDavid du Colombier 166*5e96a66cSDavid du Colombier if(!sourceLock(mr->msource, -1)) 167*5e96a66cSDavid du Colombier goto Err; 168*5e96a66cSDavid du Colombier b = sourceBlock(mr->msource, 0, OReadOnly); 169*5e96a66cSDavid du Colombier sourceUnlock(mr->msource); 170*5e96a66cSDavid du Colombier if(b == nil) 171*5e96a66cSDavid du Colombier goto Err; 172*5e96a66cSDavid du Colombier 173*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, mr->msource->dsize)) 174*5e96a66cSDavid du Colombier goto Err; 175*5e96a66cSDavid du Colombier 176*5e96a66cSDavid du Colombier meUnpack(&me, &mb, 0); 177*5e96a66cSDavid du Colombier if(!deUnpack(&root->dir, &me)) 178*5e96a66cSDavid du Colombier goto Err; 179*5e96a66cSDavid du Colombier blockPut(b); 180*5e96a66cSDavid du Colombier sourceUnlock(r); 181*5e96a66cSDavid du Colombier fileRAccess(root); 182*5e96a66cSDavid du Colombier 183*5e96a66cSDavid du Colombier return root; 184*5e96a66cSDavid du Colombier Err: 185*5e96a66cSDavid du Colombier blockPut(b); 186*5e96a66cSDavid du Colombier if(r0) 187*5e96a66cSDavid du Colombier sourceClose(r0); 188*5e96a66cSDavid du Colombier if(r1) 189*5e96a66cSDavid du Colombier sourceClose(r1); 190*5e96a66cSDavid du Colombier if(r2) 191*5e96a66cSDavid du Colombier sourceClose(r2); 192*5e96a66cSDavid du Colombier if(mr) 193*5e96a66cSDavid du Colombier fileFree(mr); 194*5e96a66cSDavid du Colombier if(root) 195*5e96a66cSDavid du Colombier fileFree(root); 196*5e96a66cSDavid du Colombier sourceUnlock(r); 197*5e96a66cSDavid du Colombier 198*5e96a66cSDavid du Colombier return nil; 199*5e96a66cSDavid du Colombier } 200*5e96a66cSDavid du Colombier 201*5e96a66cSDavid du Colombier static Source * 202*5e96a66cSDavid du Colombier fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode) 203*5e96a66cSDavid du Colombier { 204*5e96a66cSDavid du Colombier Source *r; 205*5e96a66cSDavid du Colombier 206*5e96a66cSDavid du Colombier if(!sourceLock(f->source, mode)) 207*5e96a66cSDavid du Colombier return nil; 208*5e96a66cSDavid du Colombier r = sourceOpen(f->source, offset, mode); 209*5e96a66cSDavid du Colombier sourceUnlock(f->source); 210*5e96a66cSDavid du Colombier if(r == nil) 211*5e96a66cSDavid du Colombier return nil; 212*5e96a66cSDavid du Colombier if(r->gen != gen){ 213*5e96a66cSDavid du Colombier vtSetError(ERemoved); 214*5e96a66cSDavid du Colombier goto Err; 215*5e96a66cSDavid du Colombier } 216*5e96a66cSDavid du Colombier if(r->dir != dir && r->mode != -1){ 217*5e96a66cSDavid du Colombier fprint(2, "fileOpenSource: dir mismatch %d %d\n", r->dir, dir); 218*5e96a66cSDavid du Colombier vtSetError(EBadMeta); 219*5e96a66cSDavid du Colombier goto Err; 220*5e96a66cSDavid du Colombier } 221*5e96a66cSDavid du Colombier return r; 222*5e96a66cSDavid du Colombier Err: 223*5e96a66cSDavid du Colombier sourceClose(r); 224*5e96a66cSDavid du Colombier return nil; 225*5e96a66cSDavid du Colombier } 226*5e96a66cSDavid du Colombier 227*5e96a66cSDavid du Colombier File * 228*5e96a66cSDavid du Colombier _fileWalk(File *f, char *elem, int partial) 229*5e96a66cSDavid du Colombier { 230*5e96a66cSDavid du Colombier File *ff; 231*5e96a66cSDavid du Colombier 232*5e96a66cSDavid du Colombier fileRAccess(f); 233*5e96a66cSDavid du Colombier 234*5e96a66cSDavid du Colombier if(elem[0] == 0){ 235*5e96a66cSDavid du Colombier vtSetError(EBadPath); 236*5e96a66cSDavid du Colombier return nil; 237*5e96a66cSDavid du Colombier } 238*5e96a66cSDavid du Colombier 239*5e96a66cSDavid du Colombier if(!fileIsDir(f)){ 240*5e96a66cSDavid du Colombier vtSetError(ENotDir); 241*5e96a66cSDavid du Colombier return nil; 242*5e96a66cSDavid du Colombier } 243*5e96a66cSDavid du Colombier 244*5e96a66cSDavid du Colombier if(strcmp(elem, ".") == 0){ 245*5e96a66cSDavid du Colombier return fileIncRef(f); 246*5e96a66cSDavid du Colombier } 247*5e96a66cSDavid du Colombier 248*5e96a66cSDavid du Colombier if(strcmp(elem, "..") == 0){ 249*5e96a66cSDavid du Colombier if(fileIsRoot(f)) 250*5e96a66cSDavid du Colombier return fileIncRef(f); 251*5e96a66cSDavid du Colombier return fileIncRef(f->up); 252*5e96a66cSDavid du Colombier } 253*5e96a66cSDavid du Colombier 254*5e96a66cSDavid du Colombier if(!fileLock(f)) 255*5e96a66cSDavid du Colombier return nil; 256*5e96a66cSDavid du Colombier 257*5e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 258*5e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 259*5e96a66cSDavid du Colombier ff->ref++; 260*5e96a66cSDavid du Colombier goto Exit; 261*5e96a66cSDavid du Colombier } 262*5e96a66cSDavid du Colombier } 263*5e96a66cSDavid du Colombier 264*5e96a66cSDavid du Colombier ff = dirLookup(f, elem); 265*5e96a66cSDavid du Colombier if(ff == nil) 266*5e96a66cSDavid du Colombier goto Err; 267*5e96a66cSDavid du Colombier 268*5e96a66cSDavid du Colombier if(ff->dir.mode & ModeSnapshot) 269*5e96a66cSDavid du Colombier ff->mode = OReadOnly; 270*5e96a66cSDavid du Colombier 271*5e96a66cSDavid du Colombier if(partial){ 272*5e96a66cSDavid du Colombier /* 273*5e96a66cSDavid du Colombier * Do nothing. We're opening this file only so we can clri it. 274*5e96a66cSDavid du Colombier * Usually the sources can't be opened, hence we won't even bother. 275*5e96a66cSDavid du Colombier * Be VERY careful with the returned file. If you hand it to a routine 276*5e96a66cSDavid du Colombier * expecting ff->source and/or ff->msource to be non-nil, we're 277*5e96a66cSDavid du Colombier * likely to dereference nil. FileClri should be the only routine 278*5e96a66cSDavid du Colombier * setting partial. 279*5e96a66cSDavid du Colombier */ 280*5e96a66cSDavid du Colombier ff->partial = 1; 281*5e96a66cSDavid du Colombier }else if(ff->dir.mode & ModeDir){ 282*5e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode); 283*5e96a66cSDavid du Colombier ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode); 284*5e96a66cSDavid du Colombier if(ff->source == nil || ff->msource == nil) 285*5e96a66cSDavid du Colombier goto Err; 286*5e96a66cSDavid du Colombier }else{ 287*5e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode); 288*5e96a66cSDavid du Colombier if(ff->source == nil) 289*5e96a66cSDavid du Colombier goto Err; 290*5e96a66cSDavid du Colombier } 291*5e96a66cSDavid du Colombier 292*5e96a66cSDavid du Colombier /* link in and up parent ref count */ 293*5e96a66cSDavid du Colombier ff->next = f->down; 294*5e96a66cSDavid du Colombier f->down = ff; 295*5e96a66cSDavid du Colombier ff->up = f; 296*5e96a66cSDavid du Colombier fileIncRef(f); 297*5e96a66cSDavid du Colombier Exit: 298*5e96a66cSDavid du Colombier fileUnlock(f); 299*5e96a66cSDavid du Colombier return ff; 300*5e96a66cSDavid du Colombier Err: 301*5e96a66cSDavid du Colombier fileUnlock(f); 302*5e96a66cSDavid du Colombier if(ff != nil) 303*5e96a66cSDavid du Colombier fileDecRef(ff); 304*5e96a66cSDavid du Colombier return nil; 305*5e96a66cSDavid du Colombier } 306*5e96a66cSDavid du Colombier 307*5e96a66cSDavid du Colombier File * 308*5e96a66cSDavid du Colombier fileWalk(File *f, char *elem) 309*5e96a66cSDavid du Colombier { 310*5e96a66cSDavid du Colombier return _fileWalk(f, elem, 0); 311*5e96a66cSDavid du Colombier } 312*5e96a66cSDavid du Colombier 313*5e96a66cSDavid du Colombier File * 314*5e96a66cSDavid du Colombier _fileOpen(Fs *fs, char *path, int partial) 315*5e96a66cSDavid du Colombier { 316*5e96a66cSDavid du Colombier File *f, *ff; 317*5e96a66cSDavid du Colombier char *p, elem[VtMaxStringSize]; 318*5e96a66cSDavid du Colombier int n; 319*5e96a66cSDavid du Colombier 320*5e96a66cSDavid du Colombier f = fs->file; 321*5e96a66cSDavid du Colombier fileIncRef(f); 322*5e96a66cSDavid du Colombier while(*path != 0){ 323*5e96a66cSDavid du Colombier for(p = path; *p && *p != '/'; p++) 324*5e96a66cSDavid du Colombier ; 325*5e96a66cSDavid du Colombier n = p - path; 326*5e96a66cSDavid du Colombier if(n > 0){ 327*5e96a66cSDavid du Colombier if(n > VtMaxStringSize){ 328*5e96a66cSDavid du Colombier vtSetError(EBadPath); 329*5e96a66cSDavid du Colombier goto Err; 330*5e96a66cSDavid du Colombier } 331*5e96a66cSDavid du Colombier memmove(elem, path, n); 332*5e96a66cSDavid du Colombier elem[n] = 0; 333*5e96a66cSDavid du Colombier ff = _fileWalk(f, elem, partial && *p=='\0'); 334*5e96a66cSDavid du Colombier if(ff == nil) 335*5e96a66cSDavid du Colombier goto Err; 336*5e96a66cSDavid du Colombier fileDecRef(f); 337*5e96a66cSDavid du Colombier f = ff; 338*5e96a66cSDavid du Colombier } 339*5e96a66cSDavid du Colombier if(*p == '/') 340*5e96a66cSDavid du Colombier p++; 341*5e96a66cSDavid du Colombier path = p; 342*5e96a66cSDavid du Colombier } 343*5e96a66cSDavid du Colombier return f; 344*5e96a66cSDavid du Colombier Err: 345*5e96a66cSDavid du Colombier fileDecRef(f); 346*5e96a66cSDavid du Colombier return nil; 347*5e96a66cSDavid du Colombier } 348*5e96a66cSDavid du Colombier 349*5e96a66cSDavid du Colombier File* 350*5e96a66cSDavid du Colombier fileOpen(Fs *fs, char *path) 351*5e96a66cSDavid du Colombier { 352*5e96a66cSDavid du Colombier return _fileOpen(fs, path, 0); 353*5e96a66cSDavid du Colombier } 354*5e96a66cSDavid du Colombier 355*5e96a66cSDavid du Colombier File * 356*5e96a66cSDavid du Colombier fileCreate(File *f, char *elem, ulong mode, char *uid) 357*5e96a66cSDavid du Colombier { 358*5e96a66cSDavid du Colombier File *ff; 359*5e96a66cSDavid du Colombier DirEntry *dir; 360*5e96a66cSDavid du Colombier Source *pr, *r, *mr; 361*5e96a66cSDavid du Colombier int isdir; 362*5e96a66cSDavid du Colombier 363*5e96a66cSDavid du Colombier if(!fileLock(f)) 364*5e96a66cSDavid du Colombier return nil; 365*5e96a66cSDavid du Colombier 366*5e96a66cSDavid du Colombier r = nil; 367*5e96a66cSDavid du Colombier mr = nil; 368*5e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 369*5e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 370*5e96a66cSDavid du Colombier ff = nil; 371*5e96a66cSDavid du Colombier vtSetError(EExists); 372*5e96a66cSDavid du Colombier goto Err1; 373*5e96a66cSDavid du Colombier } 374*5e96a66cSDavid du Colombier } 375*5e96a66cSDavid du Colombier 376*5e96a66cSDavid du Colombier ff = dirLookup(f, elem); 377*5e96a66cSDavid du Colombier if(ff != nil){ 378*5e96a66cSDavid du Colombier vtSetError(EExists); 379*5e96a66cSDavid du Colombier goto Err1; 380*5e96a66cSDavid du Colombier } 381*5e96a66cSDavid du Colombier 382*5e96a66cSDavid du Colombier pr = f->source; 383*5e96a66cSDavid du Colombier if(pr->mode != OReadWrite){ 384*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 385*5e96a66cSDavid du Colombier goto Err1; 386*5e96a66cSDavid du Colombier } 387*5e96a66cSDavid du Colombier 388*5e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 389*5e96a66cSDavid du Colombier goto Err1; 390*5e96a66cSDavid du Colombier 391*5e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 392*5e96a66cSDavid du Colombier isdir = mode & ModeDir; 393*5e96a66cSDavid du Colombier 394*5e96a66cSDavid du Colombier r = sourceCreate(pr, pr->dsize, isdir, 0); 395*5e96a66cSDavid du Colombier if(r == nil) 396*5e96a66cSDavid du Colombier goto Err; 397*5e96a66cSDavid du Colombier if(isdir){ 398*5e96a66cSDavid du Colombier mr = sourceCreate(pr, pr->dsize, 0, r->offset); 399*5e96a66cSDavid du Colombier if(mr == nil) 400*5e96a66cSDavid du Colombier goto Err; 401*5e96a66cSDavid du Colombier } 402*5e96a66cSDavid du Colombier 403*5e96a66cSDavid du Colombier dir = &ff->dir; 404*5e96a66cSDavid du Colombier dir->elem = vtStrDup(elem); 405*5e96a66cSDavid du Colombier dir->entry = r->offset; 406*5e96a66cSDavid du Colombier dir->gen = r->gen; 407*5e96a66cSDavid du Colombier if(isdir){ 408*5e96a66cSDavid du Colombier dir->mentry = mr->offset; 409*5e96a66cSDavid du Colombier dir->mgen = mr->gen; 410*5e96a66cSDavid du Colombier } 411*5e96a66cSDavid du Colombier dir->size = 0; 412*5e96a66cSDavid du Colombier if(!fsNextQid(f->fs, &dir->qid)) 413*5e96a66cSDavid du Colombier goto Err; 414*5e96a66cSDavid du Colombier dir->uid = vtStrDup(uid); 415*5e96a66cSDavid du Colombier dir->gid = vtStrDup(f->dir.gid); 416*5e96a66cSDavid du Colombier dir->mid = vtStrDup(uid); 417*5e96a66cSDavid du Colombier dir->mtime = time(0L); 418*5e96a66cSDavid du Colombier dir->mcount = 0; 419*5e96a66cSDavid du Colombier dir->ctime = dir->mtime; 420*5e96a66cSDavid du Colombier dir->atime = dir->mtime; 421*5e96a66cSDavid du Colombier dir->mode = mode; 422*5e96a66cSDavid du Colombier 423*5e96a66cSDavid du Colombier ff->boff = fileMetaAlloc(f, dir, 0); 424*5e96a66cSDavid du Colombier if(ff->boff == NilBlock) 425*5e96a66cSDavid du Colombier goto Err; 426*5e96a66cSDavid du Colombier 427*5e96a66cSDavid du Colombier sourceUnlock(f->source); 428*5e96a66cSDavid du Colombier sourceUnlock(f->msource); 429*5e96a66cSDavid du Colombier 430*5e96a66cSDavid du Colombier ff->source = r; 431*5e96a66cSDavid du Colombier ff->msource = mr; 432*5e96a66cSDavid du Colombier 433*5e96a66cSDavid du Colombier /* link in and up parent ref count */ 434*5e96a66cSDavid du Colombier ff->next = f->down; 435*5e96a66cSDavid du Colombier f->down = ff; 436*5e96a66cSDavid du Colombier ff->up = f; 437*5e96a66cSDavid du Colombier fileIncRef(f); 438*5e96a66cSDavid du Colombier 439*5e96a66cSDavid du Colombier fileWAccess(f, uid); 440*5e96a66cSDavid du Colombier 441*5e96a66cSDavid du Colombier fileUnlock(f); 442*5e96a66cSDavid du Colombier return ff; 443*5e96a66cSDavid du Colombier 444*5e96a66cSDavid du Colombier Err: 445*5e96a66cSDavid du Colombier sourceUnlock(f->source); 446*5e96a66cSDavid du Colombier sourceUnlock(f->msource); 447*5e96a66cSDavid du Colombier Err1: 448*5e96a66cSDavid du Colombier if(r) 449*5e96a66cSDavid du Colombier sourceRemove(r); 450*5e96a66cSDavid du Colombier if(mr) 451*5e96a66cSDavid du Colombier sourceRemove(mr); 452*5e96a66cSDavid du Colombier if(ff) 453*5e96a66cSDavid du Colombier fileDecRef(ff); 454*5e96a66cSDavid du Colombier fileUnlock(f); 455*5e96a66cSDavid du Colombier return 0; 456*5e96a66cSDavid du Colombier } 457*5e96a66cSDavid du Colombier 458*5e96a66cSDavid du Colombier int 459*5e96a66cSDavid du Colombier fileRead(File *f, void *buf, int cnt, vlong offset) 460*5e96a66cSDavid du Colombier { 461*5e96a66cSDavid du Colombier Source *s; 462*5e96a66cSDavid du Colombier uvlong size; 463*5e96a66cSDavid du Colombier u32int bn; 464*5e96a66cSDavid du Colombier int off, dsize, n, nn; 465*5e96a66cSDavid du Colombier Block *b; 466*5e96a66cSDavid du Colombier uchar *p; 467*5e96a66cSDavid du Colombier 468*5e96a66cSDavid du Colombier if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset); 469*5e96a66cSDavid du Colombier 470*5e96a66cSDavid du Colombier if(!fileRLock(f)) 471*5e96a66cSDavid du Colombier return -1; 472*5e96a66cSDavid du Colombier 473*5e96a66cSDavid du Colombier if(offset < 0){ 474*5e96a66cSDavid du Colombier vtSetError(EBadOffset); 475*5e96a66cSDavid du Colombier goto Err1; 476*5e96a66cSDavid du Colombier } 477*5e96a66cSDavid du Colombier 478*5e96a66cSDavid du Colombier fileRAccess(f); 479*5e96a66cSDavid du Colombier 480*5e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)) 481*5e96a66cSDavid du Colombier goto Err1; 482*5e96a66cSDavid du Colombier 483*5e96a66cSDavid du Colombier s = f->source; 484*5e96a66cSDavid du Colombier dsize = s->dsize; 485*5e96a66cSDavid du Colombier size = sourceGetSize(s); 486*5e96a66cSDavid du Colombier 487*5e96a66cSDavid du Colombier if(offset >= size) 488*5e96a66cSDavid du Colombier offset = size; 489*5e96a66cSDavid du Colombier 490*5e96a66cSDavid du Colombier if(cnt > size-offset) 491*5e96a66cSDavid du Colombier cnt = size-offset; 492*5e96a66cSDavid du Colombier bn = offset/dsize; 493*5e96a66cSDavid du Colombier off = offset%dsize; 494*5e96a66cSDavid du Colombier p = buf; 495*5e96a66cSDavid du Colombier while(cnt > 0){ 496*5e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 497*5e96a66cSDavid du Colombier if(b == nil) 498*5e96a66cSDavid du Colombier goto Err; 499*5e96a66cSDavid du Colombier n = cnt; 500*5e96a66cSDavid du Colombier if(n > dsize-off) 501*5e96a66cSDavid du Colombier n = dsize-off; 502*5e96a66cSDavid du Colombier nn = dsize-off; 503*5e96a66cSDavid du Colombier if(nn > n) 504*5e96a66cSDavid du Colombier nn = n; 505*5e96a66cSDavid du Colombier memmove(p, b->data+off, nn); 506*5e96a66cSDavid du Colombier memset(p+nn, 0, nn-n); 507*5e96a66cSDavid du Colombier off = 0; 508*5e96a66cSDavid du Colombier bn++; 509*5e96a66cSDavid du Colombier cnt -= n; 510*5e96a66cSDavid du Colombier p += n; 511*5e96a66cSDavid du Colombier blockPut(b); 512*5e96a66cSDavid du Colombier } 513*5e96a66cSDavid du Colombier sourceUnlock(s); 514*5e96a66cSDavid du Colombier fileRUnlock(f); 515*5e96a66cSDavid du Colombier return p-(uchar*)buf; 516*5e96a66cSDavid du Colombier 517*5e96a66cSDavid du Colombier Err: 518*5e96a66cSDavid du Colombier sourceUnlock(s); 519*5e96a66cSDavid du Colombier Err1: 520*5e96a66cSDavid du Colombier fileRUnlock(f); 521*5e96a66cSDavid du Colombier return -1; 522*5e96a66cSDavid du Colombier } 523*5e96a66cSDavid du Colombier 524*5e96a66cSDavid du Colombier int 525*5e96a66cSDavid du Colombier fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid) 526*5e96a66cSDavid du Colombier { 527*5e96a66cSDavid du Colombier Source *s; 528*5e96a66cSDavid du Colombier ulong bn; 529*5e96a66cSDavid du Colombier int off, dsize, n; 530*5e96a66cSDavid du Colombier Block *b; 531*5e96a66cSDavid du Colombier uchar *p; 532*5e96a66cSDavid du Colombier vlong eof; 533*5e96a66cSDavid du Colombier 534*5e96a66cSDavid du Colombier if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); 535*5e96a66cSDavid du Colombier 536*5e96a66cSDavid du Colombier if(!fileLock(f)) 537*5e96a66cSDavid du Colombier return -1; 538*5e96a66cSDavid du Colombier 539*5e96a66cSDavid du Colombier s = nil; 540*5e96a66cSDavid du Colombier if(f->dir.mode & ModeDir){ 541*5e96a66cSDavid du Colombier vtSetError(ENotFile); 542*5e96a66cSDavid du Colombier goto Err; 543*5e96a66cSDavid du Colombier } 544*5e96a66cSDavid du Colombier 545*5e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 546*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 547*5e96a66cSDavid du Colombier goto Err; 548*5e96a66cSDavid du Colombier } 549*5e96a66cSDavid du Colombier if(offset < 0){ 550*5e96a66cSDavid du Colombier vtSetError(EBadOffset); 551*5e96a66cSDavid du Colombier goto Err; 552*5e96a66cSDavid du Colombier } 553*5e96a66cSDavid du Colombier 554*5e96a66cSDavid du Colombier fileWAccess(f, uid); 555*5e96a66cSDavid du Colombier 556*5e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 557*5e96a66cSDavid du Colombier goto Err; 558*5e96a66cSDavid du Colombier s = f->source; 559*5e96a66cSDavid du Colombier dsize = s->dsize; 560*5e96a66cSDavid du Colombier 561*5e96a66cSDavid du Colombier eof = sourceGetSize(s); 562*5e96a66cSDavid du Colombier if(f->dir.mode & ModeAppend) 563*5e96a66cSDavid du Colombier offset = eof; 564*5e96a66cSDavid du Colombier bn = offset/dsize; 565*5e96a66cSDavid du Colombier off = offset%dsize; 566*5e96a66cSDavid du Colombier p = buf; 567*5e96a66cSDavid du Colombier while(cnt > 0){ 568*5e96a66cSDavid du Colombier n = cnt; 569*5e96a66cSDavid du Colombier if(n > dsize-off) 570*5e96a66cSDavid du Colombier n = dsize-off; 571*5e96a66cSDavid du Colombier b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite); 572*5e96a66cSDavid du Colombier if(b == nil){ 573*5e96a66cSDavid du Colombier if(offset > eof) 574*5e96a66cSDavid du Colombier sourceSetSize(s, offset); 575*5e96a66cSDavid du Colombier goto Err; 576*5e96a66cSDavid du Colombier } 577*5e96a66cSDavid du Colombier memmove(b->data+off, p, n); 578*5e96a66cSDavid du Colombier off = 0; 579*5e96a66cSDavid du Colombier cnt -= n; 580*5e96a66cSDavid du Colombier p += n; 581*5e96a66cSDavid du Colombier offset += n; 582*5e96a66cSDavid du Colombier bn++; 583*5e96a66cSDavid du Colombier blockDirty(b); 584*5e96a66cSDavid du Colombier blockPut(b); 585*5e96a66cSDavid du Colombier } 586*5e96a66cSDavid du Colombier if(offset > eof && !sourceSetSize(s, offset)) 587*5e96a66cSDavid du Colombier goto Err; 588*5e96a66cSDavid du Colombier sourceUnlock(s); 589*5e96a66cSDavid du Colombier fileUnlock(f); 590*5e96a66cSDavid du Colombier return p-(uchar*)buf; 591*5e96a66cSDavid du Colombier Err: 592*5e96a66cSDavid du Colombier if(s) 593*5e96a66cSDavid du Colombier sourceUnlock(s); 594*5e96a66cSDavid du Colombier fileUnlock(f); 595*5e96a66cSDavid du Colombier return -1; 596*5e96a66cSDavid du Colombier } 597*5e96a66cSDavid du Colombier 598*5e96a66cSDavid du Colombier int 599*5e96a66cSDavid du Colombier fileGetDir(File *f, DirEntry *dir) 600*5e96a66cSDavid du Colombier { 601*5e96a66cSDavid du Colombier if(!fileRLock(f)) 602*5e96a66cSDavid du Colombier return 0; 603*5e96a66cSDavid du Colombier 604*5e96a66cSDavid du Colombier fileMetaLock(f); 605*5e96a66cSDavid du Colombier deCopy(dir, &f->dir); 606*5e96a66cSDavid du Colombier fileMetaUnlock(f); 607*5e96a66cSDavid du Colombier 608*5e96a66cSDavid du Colombier if(!fileIsDir(f)){ 609*5e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 610*5e96a66cSDavid du Colombier fileRUnlock(f); 611*5e96a66cSDavid du Colombier return 0; 612*5e96a66cSDavid du Colombier } 613*5e96a66cSDavid du Colombier dir->size = sourceGetSize(f->source); 614*5e96a66cSDavid du Colombier sourceUnlock(f->source); 615*5e96a66cSDavid du Colombier } 616*5e96a66cSDavid du Colombier fileRUnlock(f); 617*5e96a66cSDavid du Colombier 618*5e96a66cSDavid du Colombier return 1; 619*5e96a66cSDavid du Colombier } 620*5e96a66cSDavid du Colombier 621*5e96a66cSDavid du Colombier int 622*5e96a66cSDavid du Colombier fileTruncate(File *f, char *uid) 623*5e96a66cSDavid du Colombier { 624*5e96a66cSDavid du Colombier if(fileIsDir(f)){ 625*5e96a66cSDavid du Colombier vtSetError(ENotFile); 626*5e96a66cSDavid du Colombier return 0; 627*5e96a66cSDavid du Colombier } 628*5e96a66cSDavid du Colombier 629*5e96a66cSDavid du Colombier if(!fileLock(f)) 630*5e96a66cSDavid du Colombier return 0; 631*5e96a66cSDavid du Colombier 632*5e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 633*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 634*5e96a66cSDavid du Colombier fileUnlock(f); 635*5e96a66cSDavid du Colombier return 0; 636*5e96a66cSDavid du Colombier } 637*5e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)){ 638*5e96a66cSDavid du Colombier fileUnlock(f); 639*5e96a66cSDavid du Colombier return 0; 640*5e96a66cSDavid du Colombier } 641*5e96a66cSDavid du Colombier if(!sourceTruncate(f->source)){ 642*5e96a66cSDavid du Colombier sourceUnlock(f->source); 643*5e96a66cSDavid du Colombier fileUnlock(f); 644*5e96a66cSDavid du Colombier return 0; 645*5e96a66cSDavid du Colombier } 646*5e96a66cSDavid du Colombier sourceUnlock(f->source); 647*5e96a66cSDavid du Colombier fileUnlock(f); 648*5e96a66cSDavid du Colombier 649*5e96a66cSDavid du Colombier fileWAccess(f->up, uid); 650*5e96a66cSDavid du Colombier 651*5e96a66cSDavid du Colombier return 1; 652*5e96a66cSDavid du Colombier } 653*5e96a66cSDavid du Colombier 654*5e96a66cSDavid du Colombier int 655*5e96a66cSDavid du Colombier fileSetDir(File *f, DirEntry *dir, char *uid) 656*5e96a66cSDavid du Colombier { 657*5e96a66cSDavid du Colombier File *ff; 658*5e96a66cSDavid du Colombier char *oelem; 659*5e96a66cSDavid du Colombier u32int mask; 660*5e96a66cSDavid du Colombier u64int size; 661*5e96a66cSDavid du Colombier 662*5e96a66cSDavid du Colombier /* can not set permissions for the root */ 663*5e96a66cSDavid du Colombier if(fileIsRoot(f)){ 664*5e96a66cSDavid du Colombier vtSetError(ERoot); 665*5e96a66cSDavid du Colombier return 0; 666*5e96a66cSDavid du Colombier } 667*5e96a66cSDavid du Colombier 668*5e96a66cSDavid du Colombier if(!fileLock(f)) 669*5e96a66cSDavid du Colombier return 0; 670*5e96a66cSDavid du Colombier 671*5e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 672*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 673*5e96a66cSDavid du Colombier fileUnlock(f); 674*5e96a66cSDavid du Colombier return 0; 675*5e96a66cSDavid du Colombier } 676*5e96a66cSDavid du Colombier 677*5e96a66cSDavid du Colombier fileMetaLock(f); 678*5e96a66cSDavid du Colombier 679*5e96a66cSDavid du Colombier /* check new name does not already exist */ 680*5e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 681*5e96a66cSDavid du Colombier for(ff = f->up->down; ff; ff=ff->next){ 682*5e96a66cSDavid du Colombier if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ 683*5e96a66cSDavid du Colombier vtSetError(EExists); 684*5e96a66cSDavid du Colombier goto Err; 685*5e96a66cSDavid du Colombier } 686*5e96a66cSDavid du Colombier } 687*5e96a66cSDavid du Colombier 688*5e96a66cSDavid du Colombier ff = dirLookup(f->up, dir->elem); 689*5e96a66cSDavid du Colombier if(ff != nil){ 690*5e96a66cSDavid du Colombier fileDecRef(ff); 691*5e96a66cSDavid du Colombier vtSetError(EExists); 692*5e96a66cSDavid du Colombier goto Err; 693*5e96a66cSDavid du Colombier } 694*5e96a66cSDavid du Colombier } 695*5e96a66cSDavid du Colombier 696*5e96a66cSDavid du Colombier if(!fileIsDir(f)){ 697*5e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 698*5e96a66cSDavid du Colombier goto Err; 699*5e96a66cSDavid du Colombier size = sourceGetSize(f->source); 700*5e96a66cSDavid du Colombier if(size != dir->size){ 701*5e96a66cSDavid du Colombier if(!sourceSetSize(f->source, dir->size)){ 702*5e96a66cSDavid du Colombier sourceUnlock(f->source); 703*5e96a66cSDavid du Colombier goto Err; 704*5e96a66cSDavid du Colombier } 705*5e96a66cSDavid du Colombier /* commited to changing it now */ 706*5e96a66cSDavid du Colombier } 707*5e96a66cSDavid du Colombier sourceUnlock(f->source); 708*5e96a66cSDavid du Colombier } 709*5e96a66cSDavid du Colombier 710*5e96a66cSDavid du Colombier /* commited to changing it now */ 711*5e96a66cSDavid du Colombier oelem = nil; 712*5e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 713*5e96a66cSDavid du Colombier oelem = f->dir.elem; 714*5e96a66cSDavid du Colombier f->dir.elem = vtStrDup(dir->elem); 715*5e96a66cSDavid du Colombier } 716*5e96a66cSDavid du Colombier 717*5e96a66cSDavid du Colombier if(strcmp(f->dir.uid, dir->uid) != 0){ 718*5e96a66cSDavid du Colombier vtMemFree(f->dir.uid); 719*5e96a66cSDavid du Colombier f->dir.uid = vtStrDup(dir->uid); 720*5e96a66cSDavid du Colombier } 721*5e96a66cSDavid du Colombier 722*5e96a66cSDavid du Colombier if(strcmp(f->dir.gid, dir->gid) != 0){ 723*5e96a66cSDavid du Colombier vtMemFree(f->dir.gid); 724*5e96a66cSDavid du Colombier f->dir.gid = vtStrDup(dir->gid); 725*5e96a66cSDavid du Colombier } 726*5e96a66cSDavid du Colombier 727*5e96a66cSDavid du Colombier f->dir.mtime = dir->mtime; 728*5e96a66cSDavid du Colombier f->dir.atime = dir->atime; 729*5e96a66cSDavid du Colombier 730*5e96a66cSDavid du Colombier //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); 731*5e96a66cSDavid du Colombier mask = ~(ModeDir|ModeSnapshot); 732*5e96a66cSDavid du Colombier f->dir.mode &= ~mask; 733*5e96a66cSDavid du Colombier f->dir.mode |= mask & dir->mode; 734*5e96a66cSDavid du Colombier f->dirty = 1; 735*5e96a66cSDavid du Colombier //fprint(2, "->%x\n", f->dir.mode); 736*5e96a66cSDavid du Colombier 737*5e96a66cSDavid du Colombier fileMetaFlush2(f, oelem); 738*5e96a66cSDavid du Colombier vtMemFree(oelem); 739*5e96a66cSDavid du Colombier 740*5e96a66cSDavid du Colombier fileMetaUnlock(f); 741*5e96a66cSDavid du Colombier fileUnlock(f); 742*5e96a66cSDavid du Colombier 743*5e96a66cSDavid du Colombier fileWAccess(f->up, uid); 744*5e96a66cSDavid du Colombier 745*5e96a66cSDavid du Colombier return 1; 746*5e96a66cSDavid du Colombier Err: 747*5e96a66cSDavid du Colombier fileMetaUnlock(f); 748*5e96a66cSDavid du Colombier fileUnlock(f); 749*5e96a66cSDavid du Colombier return 0; 750*5e96a66cSDavid du Colombier } 751*5e96a66cSDavid du Colombier 752*5e96a66cSDavid du Colombier int 753*5e96a66cSDavid du Colombier fileSetQidSpace(File *f, u64int offset, u64int max) 754*5e96a66cSDavid du Colombier { 755*5e96a66cSDavid du Colombier int ret; 756*5e96a66cSDavid du Colombier 757*5e96a66cSDavid du Colombier if(!fileLock(f)) 758*5e96a66cSDavid du Colombier return 0; 759*5e96a66cSDavid du Colombier fileMetaLock(f); 760*5e96a66cSDavid du Colombier f->dir.qidSpace = 1; 761*5e96a66cSDavid du Colombier f->dir.qidOffset = offset; 762*5e96a66cSDavid du Colombier f->dir.qidMax = max; 763*5e96a66cSDavid du Colombier ret = fileMetaFlush2(f, nil); 764*5e96a66cSDavid du Colombier fileMetaUnlock(f); 765*5e96a66cSDavid du Colombier fileUnlock(f); 766*5e96a66cSDavid du Colombier return ret; 767*5e96a66cSDavid du Colombier } 768*5e96a66cSDavid du Colombier 769*5e96a66cSDavid du Colombier 770*5e96a66cSDavid du Colombier uvlong 771*5e96a66cSDavid du Colombier fileGetId(File *f) 772*5e96a66cSDavid du Colombier { 773*5e96a66cSDavid du Colombier /* immutable */ 774*5e96a66cSDavid du Colombier return f->dir.qid; 775*5e96a66cSDavid du Colombier } 776*5e96a66cSDavid du Colombier 777*5e96a66cSDavid du Colombier ulong 778*5e96a66cSDavid du Colombier fileGetMcount(File *f) 779*5e96a66cSDavid du Colombier { 780*5e96a66cSDavid du Colombier ulong mcount; 781*5e96a66cSDavid du Colombier 782*5e96a66cSDavid du Colombier fileMetaLock(f); 783*5e96a66cSDavid du Colombier mcount = f->dir.mcount; 784*5e96a66cSDavid du Colombier fileMetaUnlock(f); 785*5e96a66cSDavid du Colombier return mcount; 786*5e96a66cSDavid du Colombier } 787*5e96a66cSDavid du Colombier 788*5e96a66cSDavid du Colombier ulong 789*5e96a66cSDavid du Colombier fileGetMode(File *f) 790*5e96a66cSDavid du Colombier { 791*5e96a66cSDavid du Colombier ulong mode; 792*5e96a66cSDavid du Colombier 793*5e96a66cSDavid du Colombier fileMetaLock(f); 794*5e96a66cSDavid du Colombier mode = f->dir.mode; 795*5e96a66cSDavid du Colombier fileMetaUnlock(f); 796*5e96a66cSDavid du Colombier return mode; 797*5e96a66cSDavid du Colombier } 798*5e96a66cSDavid du Colombier 799*5e96a66cSDavid du Colombier int 800*5e96a66cSDavid du Colombier fileIsDir(File *f) 801*5e96a66cSDavid du Colombier { 802*5e96a66cSDavid du Colombier /* immutable */ 803*5e96a66cSDavid du Colombier return (f->dir.mode & ModeDir) != 0; 804*5e96a66cSDavid du Colombier } 805*5e96a66cSDavid du Colombier 806*5e96a66cSDavid du Colombier int 807*5e96a66cSDavid du Colombier fileIsRoot(File *f) 808*5e96a66cSDavid du Colombier { 809*5e96a66cSDavid du Colombier return f == f->fs->file; 810*5e96a66cSDavid du Colombier } 811*5e96a66cSDavid du Colombier 812*5e96a66cSDavid du Colombier int 813*5e96a66cSDavid du Colombier fileIsRoFs(File *f) 814*5e96a66cSDavid du Colombier { 815*5e96a66cSDavid du Colombier return f->fs->mode == OReadOnly; 816*5e96a66cSDavid du Colombier } 817*5e96a66cSDavid du Colombier 818*5e96a66cSDavid du Colombier int 819*5e96a66cSDavid du Colombier fileGetSize(File *f, uvlong *size) 820*5e96a66cSDavid du Colombier { 821*5e96a66cSDavid du Colombier if(!fileRLock(f)) 822*5e96a66cSDavid du Colombier return 0; 823*5e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 824*5e96a66cSDavid du Colombier fileRUnlock(f); 825*5e96a66cSDavid du Colombier return 0; 826*5e96a66cSDavid du Colombier } 827*5e96a66cSDavid du Colombier *size = sourceGetSize(f->source); 828*5e96a66cSDavid du Colombier sourceUnlock(f->source); 829*5e96a66cSDavid du Colombier fileRUnlock(f); 830*5e96a66cSDavid du Colombier 831*5e96a66cSDavid du Colombier return 1; 832*5e96a66cSDavid du Colombier } 833*5e96a66cSDavid du Colombier 834*5e96a66cSDavid du Colombier void 835*5e96a66cSDavid du Colombier fileMetaFlush(File *f, int rec) 836*5e96a66cSDavid du Colombier { 837*5e96a66cSDavid du Colombier File **kids, *p; 838*5e96a66cSDavid du Colombier int nkids; 839*5e96a66cSDavid du Colombier int i; 840*5e96a66cSDavid du Colombier 841*5e96a66cSDavid du Colombier fileMetaLock(f); 842*5e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 843*5e96a66cSDavid du Colombier fileMetaUnlock(f); 844*5e96a66cSDavid du Colombier 845*5e96a66cSDavid du Colombier if(!rec || !fileIsDir(f)) 846*5e96a66cSDavid du Colombier return; 847*5e96a66cSDavid du Colombier 848*5e96a66cSDavid du Colombier if(!fileLock(f)) 849*5e96a66cSDavid du Colombier return; 850*5e96a66cSDavid du Colombier nkids = 0; 851*5e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 852*5e96a66cSDavid du Colombier nkids++; 853*5e96a66cSDavid du Colombier kids = vtMemAlloc(nkids*sizeof(File*)); 854*5e96a66cSDavid du Colombier i = 0; 855*5e96a66cSDavid du Colombier for(p=f->down; p; p=p->next){ 856*5e96a66cSDavid du Colombier kids[i++] = p; 857*5e96a66cSDavid du Colombier p->ref++; 858*5e96a66cSDavid du Colombier } 859*5e96a66cSDavid du Colombier fileUnlock(f); 860*5e96a66cSDavid du Colombier 861*5e96a66cSDavid du Colombier for(i=0; i<nkids; i++){ 862*5e96a66cSDavid du Colombier fileMetaFlush(kids[i], 1); 863*5e96a66cSDavid du Colombier fileDecRef(kids[i]); 864*5e96a66cSDavid du Colombier } 865*5e96a66cSDavid du Colombier vtMemFree(kids); 866*5e96a66cSDavid du Colombier } 867*5e96a66cSDavid du Colombier 868*5e96a66cSDavid du Colombier /* assumes metaLock is held */ 869*5e96a66cSDavid du Colombier static int 870*5e96a66cSDavid du Colombier fileMetaFlush2(File *f, char *oelem) 871*5e96a66cSDavid du Colombier { 872*5e96a66cSDavid du Colombier File *fp; 873*5e96a66cSDavid du Colombier Block *b, *bb; 874*5e96a66cSDavid du Colombier MetaBlock mb; 875*5e96a66cSDavid du Colombier MetaEntry me, me2; 876*5e96a66cSDavid du Colombier int i, n; 877*5e96a66cSDavid du Colombier u32int boff; 878*5e96a66cSDavid du Colombier 879*5e96a66cSDavid du Colombier if(!f->dirty) 880*5e96a66cSDavid du Colombier return 1; 881*5e96a66cSDavid du Colombier 882*5e96a66cSDavid du Colombier if(oelem == nil) 883*5e96a66cSDavid du Colombier oelem = f->dir.elem; 884*5e96a66cSDavid du Colombier 885*5e96a66cSDavid du Colombier //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem); 886*5e96a66cSDavid du Colombier 887*5e96a66cSDavid du Colombier fp = f->up; 888*5e96a66cSDavid du Colombier 889*5e96a66cSDavid du Colombier if(!sourceLock(fp->msource, -1)) 890*5e96a66cSDavid du Colombier return 0; 891*5e96a66cSDavid du Colombier b = sourceBlock(fp->msource, f->boff, OReadWrite); 892*5e96a66cSDavid du Colombier if(b == nil) 893*5e96a66cSDavid du Colombier goto Err1; 894*5e96a66cSDavid du Colombier 895*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, fp->msource->dsize)) 896*5e96a66cSDavid du Colombier goto Err; 897*5e96a66cSDavid du Colombier if(!mbSearch(&mb, oelem, &i, &me)) 898*5e96a66cSDavid du Colombier goto Err; 899*5e96a66cSDavid du Colombier 900*5e96a66cSDavid du Colombier n = deSize(&f->dir); 901*5e96a66cSDavid du Colombier if(0)fprint(2, "old size %d new size %d\n", me.size, n); 902*5e96a66cSDavid du Colombier 903*5e96a66cSDavid du Colombier if(mbResize(&mb, &me, n)){ 904*5e96a66cSDavid du Colombier /* fits in the block */ 905*5e96a66cSDavid du Colombier mbDelete(&mb, i); 906*5e96a66cSDavid du Colombier if(strcmp(f->dir.elem, oelem) != 0) 907*5e96a66cSDavid du Colombier mbSearch(&mb, f->dir.elem, &i, &me2); 908*5e96a66cSDavid du Colombier dePack(&f->dir, &me); 909*5e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 910*5e96a66cSDavid du Colombier mbPack(&mb); 911*5e96a66cSDavid du Colombier blockDirty(b); 912*5e96a66cSDavid du Colombier blockPut(b); 913*5e96a66cSDavid du Colombier sourceUnlock(fp->msource); 914*5e96a66cSDavid du Colombier f->dirty = 0; 915*5e96a66cSDavid du Colombier 916*5e96a66cSDavid du Colombier return 1; 917*5e96a66cSDavid du Colombier } 918*5e96a66cSDavid du Colombier 919*5e96a66cSDavid du Colombier /* 920*5e96a66cSDavid du Colombier * moving entry to another block 921*5e96a66cSDavid du Colombier * it is feasible for the fs to crash leaving two copies 922*5e96a66cSDavid du Colombier * of the directory entry. This is just too much work to 923*5e96a66cSDavid du Colombier * fix. Given that entries are only allocated in a block that 924*5e96a66cSDavid du Colombier * is less than PercentageFull, most modifications of meta data 925*5e96a66cSDavid du Colombier * will fit within the block. i.e. this code should almost 926*5e96a66cSDavid du Colombier * never be executed. 927*5e96a66cSDavid du Colombier */ 928*5e96a66cSDavid du Colombier boff = fileMetaAlloc(fp, &f->dir, f->boff+1); 929*5e96a66cSDavid du Colombier if(boff == NilBlock){ 930*5e96a66cSDavid du Colombier /* mbResize might have modified block */ 931*5e96a66cSDavid du Colombier mbPack(&mb); 932*5e96a66cSDavid du Colombier blockDirty(b); 933*5e96a66cSDavid du Colombier goto Err; 934*5e96a66cSDavid du Colombier } 935*5e96a66cSDavid du Colombier fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff); 936*5e96a66cSDavid du Colombier f->boff = boff; 937*5e96a66cSDavid du Colombier 938*5e96a66cSDavid du Colombier /* make sure deletion goes to disk after new entry */ 939*5e96a66cSDavid du Colombier bb = sourceBlock(fp->msource, f->boff, OReadWrite); 940*5e96a66cSDavid du Colombier mbDelete(&mb, i); 941*5e96a66cSDavid du Colombier mbPack(&mb); 942*5e96a66cSDavid du Colombier blockDependency(b, bb, -1, nil); 943*5e96a66cSDavid du Colombier blockPut(bb); 944*5e96a66cSDavid du Colombier blockDirty(b); 945*5e96a66cSDavid du Colombier blockPut(b); 946*5e96a66cSDavid du Colombier sourceUnlock(fp->msource); 947*5e96a66cSDavid du Colombier 948*5e96a66cSDavid du Colombier f->dirty = 0; 949*5e96a66cSDavid du Colombier 950*5e96a66cSDavid du Colombier return 1; 951*5e96a66cSDavid du Colombier 952*5e96a66cSDavid du Colombier Err: 953*5e96a66cSDavid du Colombier blockPut(b); 954*5e96a66cSDavid du Colombier Err1: 955*5e96a66cSDavid du Colombier sourceUnlock(fp->msource); 956*5e96a66cSDavid du Colombier return 0; 957*5e96a66cSDavid du Colombier } 958*5e96a66cSDavid du Colombier 959*5e96a66cSDavid du Colombier static int 960*5e96a66cSDavid du Colombier fileMetaRemove(File *f, char *uid) 961*5e96a66cSDavid du Colombier { 962*5e96a66cSDavid du Colombier Block *b; 963*5e96a66cSDavid du Colombier MetaBlock mb; 964*5e96a66cSDavid du Colombier MetaEntry me; 965*5e96a66cSDavid du Colombier int i; 966*5e96a66cSDavid du Colombier File *up; 967*5e96a66cSDavid du Colombier 968*5e96a66cSDavid du Colombier up = f->up; 969*5e96a66cSDavid du Colombier 970*5e96a66cSDavid du Colombier fileWAccess(up, uid); 971*5e96a66cSDavid du Colombier 972*5e96a66cSDavid du Colombier fileMetaLock(f); 973*5e96a66cSDavid du Colombier 974*5e96a66cSDavid du Colombier sourceLock(up->msource, OReadWrite); 975*5e96a66cSDavid du Colombier b = sourceBlock(up->msource, f->boff, OReadWrite); 976*5e96a66cSDavid du Colombier if(b == nil) 977*5e96a66cSDavid du Colombier goto Err; 978*5e96a66cSDavid du Colombier 979*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, up->msource->dsize)) 980*5e96a66cSDavid du Colombier { 981*5e96a66cSDavid du Colombier fprint(2, "U\n"); 982*5e96a66cSDavid du Colombier goto Err; 983*5e96a66cSDavid du Colombier } 984*5e96a66cSDavid du Colombier if(!mbSearch(&mb, f->dir.elem, &i, &me)) 985*5e96a66cSDavid du Colombier { 986*5e96a66cSDavid du Colombier fprint(2, "S\n"); 987*5e96a66cSDavid du Colombier goto Err; 988*5e96a66cSDavid du Colombier } 989*5e96a66cSDavid du Colombier mbDelete(&mb, i); 990*5e96a66cSDavid du Colombier mbPack(&mb); 991*5e96a66cSDavid du Colombier sourceUnlock(up->msource); 992*5e96a66cSDavid du Colombier 993*5e96a66cSDavid du Colombier blockDirty(b); 994*5e96a66cSDavid du Colombier blockPut(b); 995*5e96a66cSDavid du Colombier 996*5e96a66cSDavid du Colombier f->removed = 1; 997*5e96a66cSDavid du Colombier f->boff = NilBlock; 998*5e96a66cSDavid du Colombier f->dirty = 0; 999*5e96a66cSDavid du Colombier 1000*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1001*5e96a66cSDavid du Colombier return 1; 1002*5e96a66cSDavid du Colombier 1003*5e96a66cSDavid du Colombier Err: 1004*5e96a66cSDavid du Colombier sourceUnlock(up->msource); 1005*5e96a66cSDavid du Colombier blockPut(b); 1006*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1007*5e96a66cSDavid du Colombier return 0; 1008*5e96a66cSDavid du Colombier } 1009*5e96a66cSDavid du Colombier 1010*5e96a66cSDavid du Colombier /* assume file is locked, assume f->msource is locked */ 1011*5e96a66cSDavid du Colombier static int 1012*5e96a66cSDavid du Colombier fileCheckEmpty(File *f) 1013*5e96a66cSDavid du Colombier { 1014*5e96a66cSDavid du Colombier u32int i, n; 1015*5e96a66cSDavid du Colombier Block *b; 1016*5e96a66cSDavid du Colombier MetaBlock mb; 1017*5e96a66cSDavid du Colombier Source *r; 1018*5e96a66cSDavid du Colombier 1019*5e96a66cSDavid du Colombier r = f->msource; 1020*5e96a66cSDavid du Colombier n = (sourceGetSize(r)+r->dsize-1)/r->dsize; 1021*5e96a66cSDavid du Colombier for(i=0; i<n; i++){ 1022*5e96a66cSDavid du Colombier b = sourceBlock(r, i, OReadOnly); 1023*5e96a66cSDavid du Colombier if(b == nil) 1024*5e96a66cSDavid du Colombier goto Err; 1025*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, r->dsize)) 1026*5e96a66cSDavid du Colombier goto Err; 1027*5e96a66cSDavid du Colombier if(mb.nindex > 0){ 1028*5e96a66cSDavid du Colombier vtSetError(ENotEmpty); 1029*5e96a66cSDavid du Colombier goto Err; 1030*5e96a66cSDavid du Colombier } 1031*5e96a66cSDavid du Colombier blockPut(b); 1032*5e96a66cSDavid du Colombier } 1033*5e96a66cSDavid du Colombier return 1; 1034*5e96a66cSDavid du Colombier Err: 1035*5e96a66cSDavid du Colombier blockPut(b); 1036*5e96a66cSDavid du Colombier return 0; 1037*5e96a66cSDavid du Colombier } 1038*5e96a66cSDavid du Colombier 1039*5e96a66cSDavid du Colombier int 1040*5e96a66cSDavid du Colombier fileRemove(File *f, char *uid) 1041*5e96a66cSDavid du Colombier { 1042*5e96a66cSDavid du Colombier File *ff; 1043*5e96a66cSDavid du Colombier 1044*5e96a66cSDavid du Colombier /* can not remove the root */ 1045*5e96a66cSDavid du Colombier if(fileIsRoot(f)){ 1046*5e96a66cSDavid du Colombier vtSetError(ERoot); 1047*5e96a66cSDavid du Colombier return 0; 1048*5e96a66cSDavid du Colombier } 1049*5e96a66cSDavid du Colombier 1050*5e96a66cSDavid du Colombier if(!fileLock(f)) 1051*5e96a66cSDavid du Colombier return 0; 1052*5e96a66cSDavid du Colombier 1053*5e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 1054*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 1055*5e96a66cSDavid du Colombier goto Err1; 1056*5e96a66cSDavid du Colombier } 1057*5e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 1058*5e96a66cSDavid du Colombier goto Err1; 1059*5e96a66cSDavid du Colombier if(fileIsDir(f) && !fileCheckEmpty(f)) 1060*5e96a66cSDavid du Colombier goto Err; 1061*5e96a66cSDavid du Colombier 1062*5e96a66cSDavid du Colombier for(ff=f->down; ff; ff=ff->next) 1063*5e96a66cSDavid du Colombier assert(ff->removed); 1064*5e96a66cSDavid du Colombier 1065*5e96a66cSDavid du Colombier sourceRemove(f->source); 1066*5e96a66cSDavid du Colombier f->source = nil; 1067*5e96a66cSDavid du Colombier if(f->msource){ 1068*5e96a66cSDavid du Colombier sourceRemove(f->msource); 1069*5e96a66cSDavid du Colombier f->msource = nil; 1070*5e96a66cSDavid du Colombier } 1071*5e96a66cSDavid du Colombier 1072*5e96a66cSDavid du Colombier fileUnlock(f); 1073*5e96a66cSDavid du Colombier 1074*5e96a66cSDavid du Colombier if(!fileMetaRemove(f, uid)) 1075*5e96a66cSDavid du Colombier return 0; 1076*5e96a66cSDavid du Colombier 1077*5e96a66cSDavid du Colombier return 1; 1078*5e96a66cSDavid du Colombier 1079*5e96a66cSDavid du Colombier Err: 1080*5e96a66cSDavid du Colombier sourceUnlock(f->source); 1081*5e96a66cSDavid du Colombier if(f->msource) 1082*5e96a66cSDavid du Colombier sourceUnlock(f->msource); 1083*5e96a66cSDavid du Colombier Err1: 1084*5e96a66cSDavid du Colombier fileUnlock(f); 1085*5e96a66cSDavid du Colombier return 0; 1086*5e96a66cSDavid du Colombier } 1087*5e96a66cSDavid du Colombier 1088*5e96a66cSDavid du Colombier int 1089*5e96a66cSDavid du Colombier fileClri(Fs *fs, char *path, char *uid) 1090*5e96a66cSDavid du Colombier { 1091*5e96a66cSDavid du Colombier int r; 1092*5e96a66cSDavid du Colombier File *f; 1093*5e96a66cSDavid du Colombier 1094*5e96a66cSDavid du Colombier f = _fileOpen(fs, path, 1); 1095*5e96a66cSDavid du Colombier if(f == nil) 1096*5e96a66cSDavid du Colombier return 0; 1097*5e96a66cSDavid du Colombier if(f->up->source->mode != OReadWrite){ 1098*5e96a66cSDavid du Colombier vtSetError(EReadOnly); 1099*5e96a66cSDavid du Colombier fileDecRef(f); 1100*5e96a66cSDavid du Colombier return 0; 1101*5e96a66cSDavid du Colombier } 1102*5e96a66cSDavid du Colombier r = fileMetaRemove(f, uid); 1103*5e96a66cSDavid du Colombier fileDecRef(f); 1104*5e96a66cSDavid du Colombier return r; 1105*5e96a66cSDavid du Colombier } 1106*5e96a66cSDavid du Colombier 1107*5e96a66cSDavid du Colombier File * 1108*5e96a66cSDavid du Colombier fileIncRef(File *vf) 1109*5e96a66cSDavid du Colombier { 1110*5e96a66cSDavid du Colombier fileMetaLock(vf); 1111*5e96a66cSDavid du Colombier assert(vf->ref > 0); 1112*5e96a66cSDavid du Colombier vf->ref++; 1113*5e96a66cSDavid du Colombier fileMetaUnlock(vf); 1114*5e96a66cSDavid du Colombier return vf; 1115*5e96a66cSDavid du Colombier } 1116*5e96a66cSDavid du Colombier 1117*5e96a66cSDavid du Colombier int 1118*5e96a66cSDavid du Colombier fileDecRef(File *f) 1119*5e96a66cSDavid du Colombier { 1120*5e96a66cSDavid du Colombier File *p, *q, **qq; 1121*5e96a66cSDavid du Colombier 1122*5e96a66cSDavid du Colombier if(f->up == nil){ 1123*5e96a66cSDavid du Colombier /* never linked in */ 1124*5e96a66cSDavid du Colombier assert(f->ref == 1); 1125*5e96a66cSDavid du Colombier fileFree(f); 1126*5e96a66cSDavid du Colombier return 1; 1127*5e96a66cSDavid du Colombier } 1128*5e96a66cSDavid du Colombier 1129*5e96a66cSDavid du Colombier fileMetaLock(f); 1130*5e96a66cSDavid du Colombier f->ref--; 1131*5e96a66cSDavid du Colombier if(f->ref > 0){ 1132*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1133*5e96a66cSDavid du Colombier return 0; 1134*5e96a66cSDavid du Colombier } 1135*5e96a66cSDavid du Colombier assert(f->ref == 0); 1136*5e96a66cSDavid du Colombier assert(f->down == nil); 1137*5e96a66cSDavid du Colombier 1138*5e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 1139*5e96a66cSDavid du Colombier 1140*5e96a66cSDavid du Colombier p = f->up; 1141*5e96a66cSDavid du Colombier qq = &p->down; 1142*5e96a66cSDavid du Colombier for(q = *qq; q; q = *qq){ 1143*5e96a66cSDavid du Colombier if(q == f) 1144*5e96a66cSDavid du Colombier break; 1145*5e96a66cSDavid du Colombier qq = &q->next; 1146*5e96a66cSDavid du Colombier } 1147*5e96a66cSDavid du Colombier assert(q != nil); 1148*5e96a66cSDavid du Colombier *qq = f->next; 1149*5e96a66cSDavid du Colombier 1150*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1151*5e96a66cSDavid du Colombier fileFree(f); 1152*5e96a66cSDavid du Colombier 1153*5e96a66cSDavid du Colombier fileDecRef(p); 1154*5e96a66cSDavid du Colombier return 1; 1155*5e96a66cSDavid du Colombier } 1156*5e96a66cSDavid du Colombier 1157*5e96a66cSDavid du Colombier File * 1158*5e96a66cSDavid du Colombier fileGetParent(File *f) 1159*5e96a66cSDavid du Colombier { 1160*5e96a66cSDavid du Colombier if(fileIsRoot(f)) 1161*5e96a66cSDavid du Colombier return fileIncRef(f); 1162*5e96a66cSDavid du Colombier return fileIncRef(f->up); 1163*5e96a66cSDavid du Colombier } 1164*5e96a66cSDavid du Colombier 1165*5e96a66cSDavid du Colombier DirEntryEnum * 1166*5e96a66cSDavid du Colombier deeOpen(File *f) 1167*5e96a66cSDavid du Colombier { 1168*5e96a66cSDavid du Colombier DirEntryEnum *dee; 1169*5e96a66cSDavid du Colombier File *p; 1170*5e96a66cSDavid du Colombier 1171*5e96a66cSDavid du Colombier if(!fileIsDir(f)){ 1172*5e96a66cSDavid du Colombier vtSetError(ENotDir); 1173*5e96a66cSDavid du Colombier fileDecRef(f); 1174*5e96a66cSDavid du Colombier return nil; 1175*5e96a66cSDavid du Colombier } 1176*5e96a66cSDavid du Colombier 1177*5e96a66cSDavid du Colombier /* flush out meta data */ 1178*5e96a66cSDavid du Colombier if(!fileLock(f)) 1179*5e96a66cSDavid du Colombier return nil; 1180*5e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 1181*5e96a66cSDavid du Colombier fileMetaFlush2(p, nil); 1182*5e96a66cSDavid du Colombier fileUnlock(f); 1183*5e96a66cSDavid du Colombier 1184*5e96a66cSDavid du Colombier dee = vtMemAllocZ(sizeof(DirEntryEnum)); 1185*5e96a66cSDavid du Colombier dee->file = fileIncRef(f); 1186*5e96a66cSDavid du Colombier 1187*5e96a66cSDavid du Colombier return dee; 1188*5e96a66cSDavid du Colombier } 1189*5e96a66cSDavid du Colombier 1190*5e96a66cSDavid du Colombier static int 1191*5e96a66cSDavid du Colombier dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size) 1192*5e96a66cSDavid du Colombier { 1193*5e96a66cSDavid du Colombier Block *b; 1194*5e96a66cSDavid du Colombier ulong bn; 1195*5e96a66cSDavid du Colombier Entry e; 1196*5e96a66cSDavid du Colombier int epb; 1197*5e96a66cSDavid du Colombier 1198*5e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 1199*5e96a66cSDavid du Colombier bn = elem/epb; 1200*5e96a66cSDavid du Colombier elem -= bn*epb; 1201*5e96a66cSDavid du Colombier 1202*5e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 1203*5e96a66cSDavid du Colombier if(b == nil) 1204*5e96a66cSDavid du Colombier goto Err; 1205*5e96a66cSDavid du Colombier if(!entryUnpack(&e, b->data, elem)) 1206*5e96a66cSDavid du Colombier goto Err; 1207*5e96a66cSDavid du Colombier 1208*5e96a66cSDavid du Colombier /* hanging entries are returned as zero size */ 1209*5e96a66cSDavid du Colombier if(!(e.flags & VtEntryActive) || e.gen != gen) 1210*5e96a66cSDavid du Colombier *size = 0; 1211*5e96a66cSDavid du Colombier else 1212*5e96a66cSDavid du Colombier *size = e.size; 1213*5e96a66cSDavid du Colombier blockPut(b); 1214*5e96a66cSDavid du Colombier return 1; 1215*5e96a66cSDavid du Colombier 1216*5e96a66cSDavid du Colombier Err: 1217*5e96a66cSDavid du Colombier blockPut(b); 1218*5e96a66cSDavid du Colombier return 0; 1219*5e96a66cSDavid du Colombier } 1220*5e96a66cSDavid du Colombier 1221*5e96a66cSDavid du Colombier static int 1222*5e96a66cSDavid du Colombier deeFill(DirEntryEnum *dee) 1223*5e96a66cSDavid du Colombier { 1224*5e96a66cSDavid du Colombier int i, n; 1225*5e96a66cSDavid du Colombier Source *meta, *source; 1226*5e96a66cSDavid du Colombier MetaBlock mb; 1227*5e96a66cSDavid du Colombier MetaEntry me; 1228*5e96a66cSDavid du Colombier File *f; 1229*5e96a66cSDavid du Colombier Block *b; 1230*5e96a66cSDavid du Colombier DirEntry *de; 1231*5e96a66cSDavid du Colombier 1232*5e96a66cSDavid du Colombier /* clean up first */ 1233*5e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 1234*5e96a66cSDavid du Colombier deCleanup(dee->buf+i); 1235*5e96a66cSDavid du Colombier vtMemFree(dee->buf); 1236*5e96a66cSDavid du Colombier dee->buf = nil; 1237*5e96a66cSDavid du Colombier dee->i = 0; 1238*5e96a66cSDavid du Colombier dee->n = 0; 1239*5e96a66cSDavid du Colombier 1240*5e96a66cSDavid du Colombier f = dee->file; 1241*5e96a66cSDavid du Colombier 1242*5e96a66cSDavid du Colombier source = f->source; 1243*5e96a66cSDavid du Colombier meta = f->msource; 1244*5e96a66cSDavid du Colombier 1245*5e96a66cSDavid du Colombier b = sourceBlock(meta, dee->boff, OReadOnly); 1246*5e96a66cSDavid du Colombier if(b == nil) 1247*5e96a66cSDavid du Colombier goto Err; 1248*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 1249*5e96a66cSDavid du Colombier goto Err; 1250*5e96a66cSDavid du Colombier 1251*5e96a66cSDavid du Colombier n = mb.nindex; 1252*5e96a66cSDavid du Colombier dee->buf = vtMemAlloc(n * sizeof(DirEntry)); 1253*5e96a66cSDavid du Colombier 1254*5e96a66cSDavid du Colombier for(i=0; i<n; i++){ 1255*5e96a66cSDavid du Colombier de = dee->buf + i; 1256*5e96a66cSDavid du Colombier meUnpack(&me, &mb, i); 1257*5e96a66cSDavid du Colombier if(!deUnpack(de, &me)) 1258*5e96a66cSDavid du Colombier goto Err; 1259*5e96a66cSDavid du Colombier dee->n++; 1260*5e96a66cSDavid du Colombier if(!(de->mode & ModeDir)) 1261*5e96a66cSDavid du Colombier if(!dirEntrySize(source, de->entry, de->gen, &de->size)) 1262*5e96a66cSDavid du Colombier goto Err; 1263*5e96a66cSDavid du Colombier } 1264*5e96a66cSDavid du Colombier dee->boff++; 1265*5e96a66cSDavid du Colombier blockPut(b); 1266*5e96a66cSDavid du Colombier return 1; 1267*5e96a66cSDavid du Colombier Err: 1268*5e96a66cSDavid du Colombier blockPut(b); 1269*5e96a66cSDavid du Colombier return 0; 1270*5e96a66cSDavid du Colombier } 1271*5e96a66cSDavid du Colombier 1272*5e96a66cSDavid du Colombier int 1273*5e96a66cSDavid du Colombier deeRead(DirEntryEnum *dee, DirEntry *de) 1274*5e96a66cSDavid du Colombier { 1275*5e96a66cSDavid du Colombier int ret, didread; 1276*5e96a66cSDavid du Colombier File *f; 1277*5e96a66cSDavid du Colombier u32int nb; 1278*5e96a66cSDavid du Colombier 1279*5e96a66cSDavid du Colombier f = dee->file; 1280*5e96a66cSDavid du Colombier if(!fileRLock(f)) 1281*5e96a66cSDavid du Colombier return -1; 1282*5e96a66cSDavid du Colombier 1283*5e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadOnly)){ 1284*5e96a66cSDavid du Colombier fileRUnlock(f); 1285*5e96a66cSDavid du Colombier return -1; 1286*5e96a66cSDavid du Colombier } 1287*5e96a66cSDavid du Colombier 1288*5e96a66cSDavid du Colombier nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize; 1289*5e96a66cSDavid du Colombier 1290*5e96a66cSDavid du Colombier didread = 0; 1291*5e96a66cSDavid du Colombier while(dee->i >= dee->n){ 1292*5e96a66cSDavid du Colombier if(dee->boff >= nb){ 1293*5e96a66cSDavid du Colombier ret = 0; 1294*5e96a66cSDavid du Colombier goto Return; 1295*5e96a66cSDavid du Colombier } 1296*5e96a66cSDavid du Colombier didread = 1; 1297*5e96a66cSDavid du Colombier if(!deeFill(dee)){ 1298*5e96a66cSDavid du Colombier ret = -1; 1299*5e96a66cSDavid du Colombier goto Return; 1300*5e96a66cSDavid du Colombier } 1301*5e96a66cSDavid du Colombier } 1302*5e96a66cSDavid du Colombier 1303*5e96a66cSDavid du Colombier memmove(de, dee->buf + dee->i, sizeof(DirEntry)); 1304*5e96a66cSDavid du Colombier dee->i++; 1305*5e96a66cSDavid du Colombier ret = 1; 1306*5e96a66cSDavid du Colombier 1307*5e96a66cSDavid du Colombier Return: 1308*5e96a66cSDavid du Colombier sourceUnlock(f->source); 1309*5e96a66cSDavid du Colombier sourceUnlock(f->msource); 1310*5e96a66cSDavid du Colombier fileRUnlock(f); 1311*5e96a66cSDavid du Colombier 1312*5e96a66cSDavid du Colombier if(didread) 1313*5e96a66cSDavid du Colombier fileRAccess(f); 1314*5e96a66cSDavid du Colombier return ret; 1315*5e96a66cSDavid du Colombier } 1316*5e96a66cSDavid du Colombier 1317*5e96a66cSDavid du Colombier void 1318*5e96a66cSDavid du Colombier deeClose(DirEntryEnum *dee) 1319*5e96a66cSDavid du Colombier { 1320*5e96a66cSDavid du Colombier int i; 1321*5e96a66cSDavid du Colombier if(dee == nil) 1322*5e96a66cSDavid du Colombier return; 1323*5e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 1324*5e96a66cSDavid du Colombier deCleanup(dee->buf+i); 1325*5e96a66cSDavid du Colombier vtMemFree(dee->buf); 1326*5e96a66cSDavid du Colombier fileDecRef(dee->file); 1327*5e96a66cSDavid du Colombier vtMemFree(dee); 1328*5e96a66cSDavid du Colombier } 1329*5e96a66cSDavid du Colombier 1330*5e96a66cSDavid du Colombier /* 1331*5e96a66cSDavid du Colombier * caller must lock f->source and f->msource 1332*5e96a66cSDavid du Colombier * caller must NOT lock the source and msource 1333*5e96a66cSDavid du Colombier * referenced by dir. 1334*5e96a66cSDavid du Colombier */ 1335*5e96a66cSDavid du Colombier static u32int 1336*5e96a66cSDavid du Colombier fileMetaAlloc(File *f, DirEntry *dir, u32int start) 1337*5e96a66cSDavid du Colombier { 1338*5e96a66cSDavid du Colombier u32int nb, bo; 1339*5e96a66cSDavid du Colombier Block *b, *bb; 1340*5e96a66cSDavid du Colombier MetaBlock mb; 1341*5e96a66cSDavid du Colombier int nn; 1342*5e96a66cSDavid du Colombier uchar *p; 1343*5e96a66cSDavid du Colombier int i, n, epb; 1344*5e96a66cSDavid du Colombier MetaEntry me; 1345*5e96a66cSDavid du Colombier Source *s, *ms; 1346*5e96a66cSDavid du Colombier 1347*5e96a66cSDavid du Colombier s = f->source; 1348*5e96a66cSDavid du Colombier ms = f->msource; 1349*5e96a66cSDavid du Colombier 1350*5e96a66cSDavid du Colombier n = deSize(dir); 1351*5e96a66cSDavid du Colombier nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize; 1352*5e96a66cSDavid du Colombier b = nil; 1353*5e96a66cSDavid du Colombier if(start > nb) 1354*5e96a66cSDavid du Colombier start = nb; 1355*5e96a66cSDavid du Colombier for(bo=start; bo<nb; bo++){ 1356*5e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 1357*5e96a66cSDavid du Colombier if(b == nil) 1358*5e96a66cSDavid du Colombier goto Err; 1359*5e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, ms->dsize)) 1360*5e96a66cSDavid du Colombier goto Err; 1361*5e96a66cSDavid du Colombier nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free; 1362*5e96a66cSDavid du Colombier if(n <= nn && mb.nindex < mb.maxindex) 1363*5e96a66cSDavid du Colombier break; 1364*5e96a66cSDavid du Colombier blockPut(b); 1365*5e96a66cSDavid du Colombier b = nil; 1366*5e96a66cSDavid du Colombier } 1367*5e96a66cSDavid du Colombier 1368*5e96a66cSDavid du Colombier /* add block to meta file */ 1369*5e96a66cSDavid du Colombier if(b == nil){ 1370*5e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 1371*5e96a66cSDavid du Colombier if(b == nil) 1372*5e96a66cSDavid du Colombier goto Err; 1373*5e96a66cSDavid du Colombier sourceSetSize(ms, (nb+1)*ms->dsize); 1374*5e96a66cSDavid du Colombier mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry); 1375*5e96a66cSDavid du Colombier } 1376*5e96a66cSDavid du Colombier 1377*5e96a66cSDavid du Colombier p = mbAlloc(&mb, n); 1378*5e96a66cSDavid du Colombier if(p == nil){ 1379*5e96a66cSDavid du Colombier /* mbAlloc might have changed block */ 1380*5e96a66cSDavid du Colombier mbPack(&mb); 1381*5e96a66cSDavid du Colombier blockDirty(b); 1382*5e96a66cSDavid du Colombier vtSetError(EBadMeta); 1383*5e96a66cSDavid du Colombier goto Err; 1384*5e96a66cSDavid du Colombier } 1385*5e96a66cSDavid du Colombier 1386*5e96a66cSDavid du Colombier mbSearch(&mb, dir->elem, &i, &me); 1387*5e96a66cSDavid du Colombier assert(me.p == nil); 1388*5e96a66cSDavid du Colombier me.p = p; 1389*5e96a66cSDavid du Colombier me.size = n; 1390*5e96a66cSDavid du Colombier dePack(dir, &me); 1391*5e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 1392*5e96a66cSDavid du Colombier mbPack(&mb); 1393*5e96a66cSDavid du Colombier 1394*5e96a66cSDavid du Colombier /* meta block depends on super block for qid ... */ 1395*5e96a66cSDavid du Colombier bb = cacheLocal(b->c, PartSuper, 0, OReadOnly); 1396*5e96a66cSDavid du Colombier blockDependency(b, bb, -1, nil); 1397*5e96a66cSDavid du Colombier blockPut(bb); 1398*5e96a66cSDavid du Colombier 1399*5e96a66cSDavid du Colombier /* ... and one or two dir entries */ 1400*5e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 1401*5e96a66cSDavid du Colombier bb = sourceBlock(s, dir->entry/epb, OReadOnly); 1402*5e96a66cSDavid du Colombier blockDependency(b, bb, -1, nil); 1403*5e96a66cSDavid du Colombier blockPut(bb); 1404*5e96a66cSDavid du Colombier if(dir->mode & ModeDir){ 1405*5e96a66cSDavid du Colombier bb = sourceBlock(s, dir->mentry/epb, OReadOnly); 1406*5e96a66cSDavid du Colombier blockDependency(b, bb, -1, nil); 1407*5e96a66cSDavid du Colombier blockPut(bb); 1408*5e96a66cSDavid du Colombier } 1409*5e96a66cSDavid du Colombier 1410*5e96a66cSDavid du Colombier blockDirty(b); 1411*5e96a66cSDavid du Colombier blockPut(b); 1412*5e96a66cSDavid du Colombier return bo; 1413*5e96a66cSDavid du Colombier Err: 1414*5e96a66cSDavid du Colombier blockPut(b); 1415*5e96a66cSDavid du Colombier return NilBlock; 1416*5e96a66cSDavid du Colombier } 1417*5e96a66cSDavid du Colombier 1418*5e96a66cSDavid du Colombier static int 1419*5e96a66cSDavid du Colombier chkSource(File *f) 1420*5e96a66cSDavid du Colombier { 1421*5e96a66cSDavid du Colombier if(f->partial) 1422*5e96a66cSDavid du Colombier return 1; 1423*5e96a66cSDavid du Colombier 1424*5e96a66cSDavid du Colombier if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){ 1425*5e96a66cSDavid du Colombier vtSetError(ERemoved); 1426*5e96a66cSDavid du Colombier return 0; 1427*5e96a66cSDavid du Colombier } 1428*5e96a66cSDavid du Colombier return 1; 1429*5e96a66cSDavid du Colombier } 1430*5e96a66cSDavid du Colombier 1431*5e96a66cSDavid du Colombier static int 1432*5e96a66cSDavid du Colombier fileRLock(File *f) 1433*5e96a66cSDavid du Colombier { 1434*5e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 1435*5e96a66cSDavid du Colombier vtRLock(f->lk); 1436*5e96a66cSDavid du Colombier if(!chkSource(f)){ 1437*5e96a66cSDavid du Colombier fileRUnlock(f); 1438*5e96a66cSDavid du Colombier return 0; 1439*5e96a66cSDavid du Colombier } 1440*5e96a66cSDavid du Colombier return 1; 1441*5e96a66cSDavid du Colombier } 1442*5e96a66cSDavid du Colombier 1443*5e96a66cSDavid du Colombier static void 1444*5e96a66cSDavid du Colombier fileRUnlock(File *f) 1445*5e96a66cSDavid du Colombier { 1446*5e96a66cSDavid du Colombier vtRUnlock(f->lk); 1447*5e96a66cSDavid du Colombier } 1448*5e96a66cSDavid du Colombier 1449*5e96a66cSDavid du Colombier static int 1450*5e96a66cSDavid du Colombier fileLock(File *f) 1451*5e96a66cSDavid du Colombier { 1452*5e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 1453*5e96a66cSDavid du Colombier vtLock(f->lk); 1454*5e96a66cSDavid du Colombier if(!chkSource(f)){ 1455*5e96a66cSDavid du Colombier fileUnlock(f); 1456*5e96a66cSDavid du Colombier return 0; 1457*5e96a66cSDavid du Colombier } 1458*5e96a66cSDavid du Colombier return 1; 1459*5e96a66cSDavid du Colombier } 1460*5e96a66cSDavid du Colombier 1461*5e96a66cSDavid du Colombier static void 1462*5e96a66cSDavid du Colombier fileUnlock(File *f) 1463*5e96a66cSDavid du Colombier { 1464*5e96a66cSDavid du Colombier vtUnlock(f->lk); 1465*5e96a66cSDavid du Colombier } 1466*5e96a66cSDavid du Colombier 1467*5e96a66cSDavid du Colombier /* 1468*5e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 1469*5e96a66cSDavid du Colombier * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2). 1470*5e96a66cSDavid du Colombier * We have to respect that ordering. 1471*5e96a66cSDavid du Colombier */ 1472*5e96a66cSDavid du Colombier static void 1473*5e96a66cSDavid du Colombier fileMetaLock(File *f) 1474*5e96a66cSDavid du Colombier { 1475*5e96a66cSDavid du Colombier if(f->up == nil) 1476*5e96a66cSDavid du Colombier fprint(2, "f->elem = %s\n", f->dir.elem); 1477*5e96a66cSDavid du Colombier assert(f->up != nil); 1478*5e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 1479*5e96a66cSDavid du Colombier vtLock(f->up->lk); 1480*5e96a66cSDavid du Colombier } 1481*5e96a66cSDavid du Colombier 1482*5e96a66cSDavid du Colombier static void 1483*5e96a66cSDavid du Colombier fileMetaUnlock(File *f) 1484*5e96a66cSDavid du Colombier { 1485*5e96a66cSDavid du Colombier vtUnlock(f->up->lk); 1486*5e96a66cSDavid du Colombier } 1487*5e96a66cSDavid du Colombier 1488*5e96a66cSDavid du Colombier /* 1489*5e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 1490*5e96a66cSDavid du Colombier * see fileMetaLock. 1491*5e96a66cSDavid du Colombier */ 1492*5e96a66cSDavid du Colombier static void 1493*5e96a66cSDavid du Colombier fileRAccess(File* f) 1494*5e96a66cSDavid du Colombier { 1495*5e96a66cSDavid du Colombier if(f->mode == OReadOnly) 1496*5e96a66cSDavid du Colombier return; 1497*5e96a66cSDavid du Colombier 1498*5e96a66cSDavid du Colombier fileMetaLock(f); 1499*5e96a66cSDavid du Colombier f->dir.atime = time(0L); 1500*5e96a66cSDavid du Colombier f->dirty = 1; 1501*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1502*5e96a66cSDavid du Colombier } 1503*5e96a66cSDavid du Colombier 1504*5e96a66cSDavid du Colombier /* 1505*5e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 1506*5e96a66cSDavid du Colombier * see fileMetaLock. 1507*5e96a66cSDavid du Colombier */ 1508*5e96a66cSDavid du Colombier static void 1509*5e96a66cSDavid du Colombier fileWAccess(File* f, char *mid) 1510*5e96a66cSDavid du Colombier { 1511*5e96a66cSDavid du Colombier if(f->mode == OReadOnly) 1512*5e96a66cSDavid du Colombier return; 1513*5e96a66cSDavid du Colombier 1514*5e96a66cSDavid du Colombier fileMetaLock(f); 1515*5e96a66cSDavid du Colombier f->dir.atime = f->dir.mtime = time(0L); 1516*5e96a66cSDavid du Colombier if(strcmp(f->dir.mid, mid) != 0){ 1517*5e96a66cSDavid du Colombier vtMemFree(f->dir.mid); 1518*5e96a66cSDavid du Colombier f->dir.mid = vtStrDup(mid); 1519*5e96a66cSDavid du Colombier } 1520*5e96a66cSDavid du Colombier f->dir.mcount++; 1521*5e96a66cSDavid du Colombier f->dirty = 1; 1522*5e96a66cSDavid du Colombier fileMetaUnlock(f); 1523*5e96a66cSDavid du Colombier } 1524*5e96a66cSDavid du Colombier 1525*5e96a66cSDavid du Colombier static void 1526*5e96a66cSDavid du Colombier markCopied(Block *b) 1527*5e96a66cSDavid du Colombier { 1528*5e96a66cSDavid du Colombier Block *lb; 1529*5e96a66cSDavid du Colombier Label l; 1530*5e96a66cSDavid du Colombier 1531*5e96a66cSDavid du Colombier if(globalToLocal(b->score) == NilBlock) 1532*5e96a66cSDavid du Colombier return; 1533*5e96a66cSDavid du Colombier 1534*5e96a66cSDavid du Colombier if(!(b->l.state & BsCopied)){ 1535*5e96a66cSDavid du Colombier /* 1536*5e96a66cSDavid du Colombier * We need to record that there are now pointers in 1537*5e96a66cSDavid du Colombier * b that are not unique to b. We do this by marking 1538*5e96a66cSDavid du Colombier * b as copied. Since we don't return the label block, 1539*5e96a66cSDavid du Colombier * the caller can't get the dependencies right. So we have 1540*5e96a66cSDavid du Colombier * to flush the block ourselves. This is a rare occurrence. 1541*5e96a66cSDavid du Colombier */ 1542*5e96a66cSDavid du Colombier l = b->l; 1543*5e96a66cSDavid du Colombier l.state |= BsCopied; 1544*5e96a66cSDavid du Colombier lb = _blockSetLabel(b, &l); 1545*5e96a66cSDavid du Colombier WriteAgain: 1546*5e96a66cSDavid du Colombier while(!blockWrite(lb)){ 1547*5e96a66cSDavid du Colombier fprint(2, "getEntry: could not write label block\n"); 1548*5e96a66cSDavid du Colombier sleep(10*1000); 1549*5e96a66cSDavid du Colombier } 1550*5e96a66cSDavid du Colombier while(lb->iostate != BioClean && lb->iostate != BioDirty){ 1551*5e96a66cSDavid du Colombier assert(lb->iostate == BioWriting); 1552*5e96a66cSDavid du Colombier vtSleep(lb->ioready); 1553*5e96a66cSDavid du Colombier } 1554*5e96a66cSDavid du Colombier if(lb->iostate == BioDirty) 1555*5e96a66cSDavid du Colombier goto WriteAgain; 1556*5e96a66cSDavid du Colombier blockPut(lb); 1557*5e96a66cSDavid du Colombier } 1558*5e96a66cSDavid du Colombier } 1559*5e96a66cSDavid du Colombier 1560*5e96a66cSDavid du Colombier static int 1561*5e96a66cSDavid du Colombier getEntry(Source *r, Entry *e, int mark) 1562*5e96a66cSDavid du Colombier { 1563*5e96a66cSDavid du Colombier Block *b; 1564*5e96a66cSDavid du Colombier 1565*5e96a66cSDavid du Colombier if(r == nil){ 1566*5e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 1567*5e96a66cSDavid du Colombier return 1; 1568*5e96a66cSDavid du Colombier } 1569*5e96a66cSDavid du Colombier 1570*5e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly); 1571*5e96a66cSDavid du Colombier if(b == nil) 1572*5e96a66cSDavid du Colombier return 0; 1573*5e96a66cSDavid du Colombier if(!entryUnpack(e, b->data, r->offset % r->epb)){ 1574*5e96a66cSDavid du Colombier blockPut(b); 1575*5e96a66cSDavid du Colombier return 0; 1576*5e96a66cSDavid du Colombier } 1577*5e96a66cSDavid du Colombier 1578*5e96a66cSDavid du Colombier if(mark) 1579*5e96a66cSDavid du Colombier markCopied(b); 1580*5e96a66cSDavid du Colombier blockPut(b); 1581*5e96a66cSDavid du Colombier return 1; 1582*5e96a66cSDavid du Colombier } 1583*5e96a66cSDavid du Colombier 1584*5e96a66cSDavid du Colombier static int 1585*5e96a66cSDavid du Colombier setEntry(Source *r, Entry *e) 1586*5e96a66cSDavid du Colombier { 1587*5e96a66cSDavid du Colombier Block *b; 1588*5e96a66cSDavid du Colombier Entry oe; 1589*5e96a66cSDavid du Colombier 1590*5e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite); 1591*5e96a66cSDavid du Colombier if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score); 1592*5e96a66cSDavid du Colombier if(b == nil) 1593*5e96a66cSDavid du Colombier return 0; 1594*5e96a66cSDavid du Colombier if(!entryUnpack(&oe, b->data, r->offset % r->epb)){ 1595*5e96a66cSDavid du Colombier blockPut(b); 1596*5e96a66cSDavid du Colombier return 0; 1597*5e96a66cSDavid du Colombier } 1598*5e96a66cSDavid du Colombier e->gen = oe.gen; 1599*5e96a66cSDavid du Colombier entryPack(e, b->data, r->offset % r->epb); 1600*5e96a66cSDavid du Colombier 1601*5e96a66cSDavid du Colombier /* BUG b should depend on the entry pointer */ 1602*5e96a66cSDavid du Colombier 1603*5e96a66cSDavid du Colombier markCopied(b); 1604*5e96a66cSDavid du Colombier blockDirty(b); 1605*5e96a66cSDavid du Colombier blockPut(b); 1606*5e96a66cSDavid du Colombier return 1; 1607*5e96a66cSDavid du Colombier } 1608*5e96a66cSDavid du Colombier 1609*5e96a66cSDavid du Colombier /* assumes hold elk */ 1610*5e96a66cSDavid du Colombier int 1611*5e96a66cSDavid du Colombier fileSnapshot(File *dst, File *src, u32int epoch, int doarchive) 1612*5e96a66cSDavid du Colombier { 1613*5e96a66cSDavid du Colombier Entry e, ee; 1614*5e96a66cSDavid du Colombier 1615*5e96a66cSDavid du Colombier /* add link to snapshot */ 1616*5e96a66cSDavid du Colombier if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1)) 1617*5e96a66cSDavid du Colombier return 0; 1618*5e96a66cSDavid du Colombier 1619*5e96a66cSDavid du Colombier e.snap = epoch; 1620*5e96a66cSDavid du Colombier e.archive = doarchive; 1621*5e96a66cSDavid du Colombier ee.snap = epoch; 1622*5e96a66cSDavid du Colombier ee.archive = doarchive; 1623*5e96a66cSDavid du Colombier 1624*5e96a66cSDavid du Colombier if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee)) 1625*5e96a66cSDavid du Colombier return 0; 1626*5e96a66cSDavid du Colombier return 1; 1627*5e96a66cSDavid du Colombier } 1628*5e96a66cSDavid du Colombier 1629*5e96a66cSDavid du Colombier int 1630*5e96a66cSDavid du Colombier fileGetSources(File *f, Entry *e, Entry *ee, int mark) 1631*5e96a66cSDavid du Colombier { 1632*5e96a66cSDavid du Colombier if(!getEntry(f->source, e, mark) 1633*5e96a66cSDavid du Colombier || !getEntry(f->msource, ee, mark)) 1634*5e96a66cSDavid du Colombier return 0; 1635*5e96a66cSDavid du Colombier return 1; 1636*5e96a66cSDavid du Colombier } 1637*5e96a66cSDavid du Colombier 1638*5e96a66cSDavid du Colombier int 1639*5e96a66cSDavid du Colombier fileWalkSources(File *f) 1640*5e96a66cSDavid du Colombier { 1641*5e96a66cSDavid du Colombier if(f->mode == OReadOnly) 1642*5e96a66cSDavid du Colombier return 1; 1643*5e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadWrite)) 1644*5e96a66cSDavid du Colombier return 0; 1645*5e96a66cSDavid du Colombier sourceUnlock(f->source); 1646*5e96a66cSDavid du Colombier sourceUnlock(f->msource); 1647*5e96a66cSDavid du Colombier return 1; 1648*5e96a66cSDavid du Colombier } 1649