15e96a66cSDavid du Colombier #include "stdinc.h" 23b86f2f8SDavid du Colombier #include "9.h" /* for consPrint */ 35e96a66cSDavid du Colombier #include "dat.h" 45e96a66cSDavid du Colombier #include "fns.h" 55e96a66cSDavid du Colombier #include "error.h" 65e96a66cSDavid du Colombier 75e96a66cSDavid du Colombier /* 85e96a66cSDavid du Colombier * locking order is upwards. A thread can hold the lock for a File 95e96a66cSDavid du Colombier * and then acquire the lock of its parent 105e96a66cSDavid du Colombier */ 115e96a66cSDavid du Colombier 125e96a66cSDavid du Colombier struct File { 135e96a66cSDavid du Colombier Fs *fs; /* immutable */ 145e96a66cSDavid du Colombier 155e96a66cSDavid du Colombier /* meta data for file: protected by the lk in the parent */ 165e96a66cSDavid du Colombier int ref; /* holds this data structure up */ 175e96a66cSDavid du Colombier 185e96a66cSDavid du Colombier int partial; /* file was never really open */ 195e96a66cSDavid du Colombier int removed; /* file has been removed */ 205e96a66cSDavid du Colombier int dirty; /* dir is dirty with respect to meta data in block */ 215e96a66cSDavid du Colombier u32int boff; /* block offset within msource for this file's meta data */ 225e96a66cSDavid du Colombier 233b86f2f8SDavid du Colombier DirEntry dir; /* meta data for this file, including component name */ 245e96a66cSDavid du Colombier 253b86f2f8SDavid du Colombier File *up; /* parent file (directory) */ 265e96a66cSDavid du Colombier File *next; /* sibling */ 275e96a66cSDavid du Colombier 285e96a66cSDavid du Colombier /* data for file */ 295e96a66cSDavid du Colombier VtLock *lk; /* lock for the following */ 305e96a66cSDavid du Colombier Source *source; 315e96a66cSDavid du Colombier Source *msource; /* for directories: meta data for children */ 325e96a66cSDavid du Colombier File *down; /* children */ 335e96a66cSDavid du Colombier 345e96a66cSDavid du Colombier int mode; 3557195852SDavid du Colombier int issnapshot; 365e96a66cSDavid du Colombier }; 375e96a66cSDavid du Colombier 385e96a66cSDavid du Colombier static int fileMetaFlush2(File*, char*); 395e96a66cSDavid du Colombier static u32int fileMetaAlloc(File*, DirEntry*, u32int); 405e96a66cSDavid du Colombier static int fileRLock(File*); 415e96a66cSDavid du Colombier static void fileRUnlock(File*); 425e96a66cSDavid du Colombier static int fileLock(File*); 435e96a66cSDavid du Colombier static void fileUnlock(File*); 445e96a66cSDavid du Colombier static void fileMetaLock(File*); 455e96a66cSDavid du Colombier static void fileMetaUnlock(File*); 465e96a66cSDavid du Colombier static void fileRAccess(File*); 475e96a66cSDavid du Colombier static void fileWAccess(File*, char*); 485e96a66cSDavid du Colombier 495e96a66cSDavid du Colombier static File * 505e96a66cSDavid du Colombier fileAlloc(Fs *fs) 515e96a66cSDavid du Colombier { 525e96a66cSDavid du Colombier File *f; 535e96a66cSDavid du Colombier 545e96a66cSDavid du Colombier f = vtMemAllocZ(sizeof(File)); 555e96a66cSDavid du Colombier f->lk = vtLockAlloc(); 565e96a66cSDavid du Colombier f->ref = 1; 575e96a66cSDavid du Colombier f->fs = fs; 585e96a66cSDavid du Colombier f->boff = NilBlock; 595e96a66cSDavid du Colombier f->mode = fs->mode; 605e96a66cSDavid du Colombier return f; 615e96a66cSDavid du Colombier } 625e96a66cSDavid du Colombier 635e96a66cSDavid du Colombier static void 645e96a66cSDavid du Colombier fileFree(File *f) 655e96a66cSDavid du Colombier { 665e96a66cSDavid du Colombier sourceClose(f->source); 675e96a66cSDavid du Colombier vtLockFree(f->lk); 685e96a66cSDavid du Colombier sourceClose(f->msource); 695e96a66cSDavid du Colombier deCleanup(&f->dir); 705e96a66cSDavid du Colombier 715e96a66cSDavid du Colombier memset(f, ~0, sizeof(File)); 725e96a66cSDavid du Colombier vtMemFree(f); 735e96a66cSDavid du Colombier } 745e96a66cSDavid du Colombier 755e96a66cSDavid du Colombier /* 765e96a66cSDavid du Colombier * the file is locked already 775e96a66cSDavid du Colombier * f->msource is unlocked 785e96a66cSDavid du Colombier */ 795e96a66cSDavid du Colombier static File * 805e96a66cSDavid du Colombier dirLookup(File *f, char *elem) 815e96a66cSDavid du Colombier { 825e96a66cSDavid du Colombier int i; 835e96a66cSDavid du Colombier MetaBlock mb; 845e96a66cSDavid du Colombier MetaEntry me; 855e96a66cSDavid du Colombier Block *b; 865e96a66cSDavid du Colombier Source *meta; 875e96a66cSDavid du Colombier File *ff; 885e96a66cSDavid du Colombier u32int bo, nb; 895e96a66cSDavid du Colombier 905e96a66cSDavid du Colombier meta = f->msource; 915e96a66cSDavid du Colombier b = nil; 925e96a66cSDavid du Colombier if(!sourceLock(meta, -1)) 935e96a66cSDavid du Colombier return nil; 945e96a66cSDavid du Colombier nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize; 955e96a66cSDavid du Colombier for(bo=0; bo<nb; bo++){ 965e96a66cSDavid du Colombier b = sourceBlock(meta, bo, OReadOnly); 975e96a66cSDavid du Colombier if(b == nil) 985e96a66cSDavid du Colombier goto Err; 995e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 1005e96a66cSDavid du Colombier goto Err; 1015e96a66cSDavid du Colombier if(mbSearch(&mb, elem, &i, &me)){ 1025e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 1035e96a66cSDavid du Colombier if(!deUnpack(&ff->dir, &me)){ 1045e96a66cSDavid du Colombier fileFree(ff); 1055e96a66cSDavid du Colombier goto Err; 1065e96a66cSDavid du Colombier } 1075e96a66cSDavid du Colombier sourceUnlock(meta); 1085e96a66cSDavid du Colombier blockPut(b); 1095e96a66cSDavid du Colombier ff->boff = bo; 1105e96a66cSDavid du Colombier ff->mode = f->mode; 11157195852SDavid du Colombier ff->issnapshot = f->issnapshot; 1125e96a66cSDavid du Colombier return ff; 1135e96a66cSDavid du Colombier } 1145e96a66cSDavid du Colombier 1155e96a66cSDavid du Colombier blockPut(b); 1165e96a66cSDavid du Colombier b = nil; 1175e96a66cSDavid du Colombier } 1185e96a66cSDavid du Colombier vtSetError(ENoFile); 1195e96a66cSDavid du Colombier /* fall through */ 1205e96a66cSDavid du Colombier Err: 1215e96a66cSDavid du Colombier sourceUnlock(meta); 1225e96a66cSDavid du Colombier blockPut(b); 1235e96a66cSDavid du Colombier return nil; 1245e96a66cSDavid du Colombier } 1255e96a66cSDavid du Colombier 1265e96a66cSDavid du Colombier File * 1275e96a66cSDavid du Colombier fileRoot(Source *r) 1285e96a66cSDavid du Colombier { 1295e96a66cSDavid du Colombier Block *b; 1305e96a66cSDavid du Colombier Source *r0, *r1, *r2; 1315e96a66cSDavid du Colombier MetaBlock mb; 1325e96a66cSDavid du Colombier MetaEntry me; 1335e96a66cSDavid du Colombier File *root, *mr; 1345e96a66cSDavid du Colombier Fs *fs; 1355e96a66cSDavid du Colombier 1365e96a66cSDavid du Colombier b = nil; 1375e96a66cSDavid du Colombier root = nil; 1385e96a66cSDavid du Colombier mr = nil; 1395e96a66cSDavid du Colombier r1 = nil; 1405e96a66cSDavid du Colombier r2 = nil; 1415e96a66cSDavid du Colombier 1425e96a66cSDavid du Colombier fs = r->fs; 1435e96a66cSDavid du Colombier if(!sourceLock(r, -1)) 1445e96a66cSDavid du Colombier return nil; 14557195852SDavid du Colombier r0 = sourceOpen(r, 0, fs->mode, 0); 1465e96a66cSDavid du Colombier if(r0 == nil) 1475e96a66cSDavid du Colombier goto Err; 14857195852SDavid du Colombier r1 = sourceOpen(r, 1, fs->mode, 0); 1495e96a66cSDavid du Colombier if(r1 == nil) 1505e96a66cSDavid du Colombier goto Err; 15157195852SDavid du Colombier r2 = sourceOpen(r, 2, fs->mode, 0); 1525e96a66cSDavid du Colombier if(r2 == nil) 1535e96a66cSDavid du Colombier goto Err; 1545e96a66cSDavid du Colombier 1555e96a66cSDavid du Colombier mr = fileAlloc(fs); 1565e96a66cSDavid du Colombier mr->msource = r2; 1575e96a66cSDavid du Colombier r2 = nil; 1585e96a66cSDavid du Colombier 1595e96a66cSDavid du Colombier root = fileAlloc(fs); 1605e96a66cSDavid du Colombier root->boff = 0; 1615e96a66cSDavid du Colombier root->up = mr; 1625e96a66cSDavid du Colombier root->source = r0; 1633b86f2f8SDavid du Colombier r0->file = root; /* point back to source */ 1645e96a66cSDavid du Colombier r0 = nil; 1655e96a66cSDavid du Colombier root->msource = r1; 1665e96a66cSDavid du Colombier r1 = nil; 1675e96a66cSDavid du Colombier 1685e96a66cSDavid du Colombier mr->down = root; 1695e96a66cSDavid du Colombier 1705e96a66cSDavid du Colombier if(!sourceLock(mr->msource, -1)) 1715e96a66cSDavid du Colombier goto Err; 1725e96a66cSDavid du Colombier b = sourceBlock(mr->msource, 0, OReadOnly); 1735e96a66cSDavid du Colombier sourceUnlock(mr->msource); 1745e96a66cSDavid du Colombier if(b == nil) 1755e96a66cSDavid du Colombier goto Err; 1765e96a66cSDavid du Colombier 1775e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, mr->msource->dsize)) 1785e96a66cSDavid du Colombier goto Err; 1795e96a66cSDavid du Colombier 1805e96a66cSDavid du Colombier meUnpack(&me, &mb, 0); 1815e96a66cSDavid du Colombier if(!deUnpack(&root->dir, &me)) 1825e96a66cSDavid du Colombier goto Err; 1835e96a66cSDavid du Colombier blockPut(b); 1845e96a66cSDavid du Colombier sourceUnlock(r); 1855e96a66cSDavid du Colombier fileRAccess(root); 1865e96a66cSDavid du Colombier 1875e96a66cSDavid du Colombier return root; 1885e96a66cSDavid du Colombier Err: 1895e96a66cSDavid du Colombier blockPut(b); 1905e96a66cSDavid du Colombier if(r0) 1915e96a66cSDavid du Colombier sourceClose(r0); 1925e96a66cSDavid du Colombier if(r1) 1935e96a66cSDavid du Colombier sourceClose(r1); 1945e96a66cSDavid du Colombier if(r2) 1955e96a66cSDavid du Colombier sourceClose(r2); 1965e96a66cSDavid du Colombier if(mr) 1975e96a66cSDavid du Colombier fileFree(mr); 1985e96a66cSDavid du Colombier if(root) 1995e96a66cSDavid du Colombier fileFree(root); 2005e96a66cSDavid du Colombier sourceUnlock(r); 2015e96a66cSDavid du Colombier 2025e96a66cSDavid du Colombier return nil; 2035e96a66cSDavid du Colombier } 2045e96a66cSDavid du Colombier 2055e96a66cSDavid du Colombier static Source * 2063b86f2f8SDavid du Colombier fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode, 2073b86f2f8SDavid du Colombier int issnapshot) 2085e96a66cSDavid du Colombier { 2093b86f2f8SDavid du Colombier char *rname, *fname; 2105e96a66cSDavid du Colombier Source *r; 2115e96a66cSDavid du Colombier 2125e96a66cSDavid du Colombier if(!sourceLock(f->source, mode)) 2135e96a66cSDavid du Colombier return nil; 21457195852SDavid du Colombier r = sourceOpen(f->source, offset, mode, issnapshot); 2155e96a66cSDavid du Colombier sourceUnlock(f->source); 2165e96a66cSDavid du Colombier if(r == nil) 2175e96a66cSDavid du Colombier return nil; 2185e96a66cSDavid du Colombier if(r->gen != gen){ 2195e96a66cSDavid du Colombier vtSetError(ERemoved); 2205e96a66cSDavid du Colombier goto Err; 2215e96a66cSDavid du Colombier } 2225e96a66cSDavid du Colombier if(r->dir != dir && r->mode != -1){ 2233b86f2f8SDavid du Colombier /* this hasn't been as useful as we hoped it would be. */ 2243b86f2f8SDavid du Colombier rname = sourceName(r); 2253b86f2f8SDavid du Colombier fname = fileName(f); 2263b86f2f8SDavid du Colombier consPrint("%s: source %s for file %s: fileOpenSource: " 2273b86f2f8SDavid du Colombier "dir mismatch %d %d\n", 2283b86f2f8SDavid du Colombier f->source->fs->name, rname, fname, r->dir, dir); 2293b86f2f8SDavid du Colombier free(rname); 2303b86f2f8SDavid du Colombier free(fname); 2313b86f2f8SDavid du Colombier 2325e96a66cSDavid du Colombier vtSetError(EBadMeta); 2335e96a66cSDavid du Colombier goto Err; 2345e96a66cSDavid du Colombier } 2355e96a66cSDavid du Colombier return r; 2365e96a66cSDavid du Colombier Err: 2375e96a66cSDavid du Colombier sourceClose(r); 2385e96a66cSDavid du Colombier return nil; 2395e96a66cSDavid du Colombier } 2405e96a66cSDavid du Colombier 2415e96a66cSDavid du Colombier File * 2425e96a66cSDavid du Colombier _fileWalk(File *f, char *elem, int partial) 2435e96a66cSDavid du Colombier { 2445e96a66cSDavid du Colombier File *ff; 2455e96a66cSDavid du Colombier 2465e96a66cSDavid du Colombier fileRAccess(f); 2475e96a66cSDavid du Colombier 2485e96a66cSDavid du Colombier if(elem[0] == 0){ 2495e96a66cSDavid du Colombier vtSetError(EBadPath); 2505e96a66cSDavid du Colombier return nil; 2515e96a66cSDavid du Colombier } 2525e96a66cSDavid du Colombier 2535e96a66cSDavid du Colombier if(!fileIsDir(f)){ 2545e96a66cSDavid du Colombier vtSetError(ENotDir); 2555e96a66cSDavid du Colombier return nil; 2565e96a66cSDavid du Colombier } 2575e96a66cSDavid du Colombier 2585e96a66cSDavid du Colombier if(strcmp(elem, ".") == 0){ 2595e96a66cSDavid du Colombier return fileIncRef(f); 2605e96a66cSDavid du Colombier } 2615e96a66cSDavid du Colombier 2625e96a66cSDavid du Colombier if(strcmp(elem, "..") == 0){ 2635e96a66cSDavid du Colombier if(fileIsRoot(f)) 2645e96a66cSDavid du Colombier return fileIncRef(f); 2655e96a66cSDavid du Colombier return fileIncRef(f->up); 2665e96a66cSDavid du Colombier } 2675e96a66cSDavid du Colombier 2685e96a66cSDavid du Colombier if(!fileLock(f)) 2695e96a66cSDavid du Colombier return nil; 2705e96a66cSDavid du Colombier 2715e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 2725e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 2735e96a66cSDavid du Colombier ff->ref++; 2745e96a66cSDavid du Colombier goto Exit; 2755e96a66cSDavid du Colombier } 2765e96a66cSDavid du Colombier } 2775e96a66cSDavid du Colombier 2785e96a66cSDavid du Colombier ff = dirLookup(f, elem); 2795e96a66cSDavid du Colombier if(ff == nil) 2805e96a66cSDavid du Colombier goto Err; 2815e96a66cSDavid du Colombier 28257195852SDavid du Colombier if(ff->dir.mode & ModeSnapshot){ 2835e96a66cSDavid du Colombier ff->mode = OReadOnly; 28457195852SDavid du Colombier ff->issnapshot = 1; 28557195852SDavid du Colombier } 2865e96a66cSDavid du Colombier 2875e96a66cSDavid du Colombier if(partial){ 2885e96a66cSDavid du Colombier /* 2895e96a66cSDavid du Colombier * Do nothing. We're opening this file only so we can clri it. 2905e96a66cSDavid du Colombier * Usually the sources can't be opened, hence we won't even bother. 2915e96a66cSDavid du Colombier * Be VERY careful with the returned file. If you hand it to a routine 2925e96a66cSDavid du Colombier * expecting ff->source and/or ff->msource to be non-nil, we're 2935e96a66cSDavid du Colombier * likely to dereference nil. FileClri should be the only routine 2945e96a66cSDavid du Colombier * setting partial. 2955e96a66cSDavid du Colombier */ 2965e96a66cSDavid du Colombier ff->partial = 1; 2975e96a66cSDavid du Colombier }else if(ff->dir.mode & ModeDir){ 2983b86f2f8SDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 2993b86f2f8SDavid du Colombier 1, ff->mode, ff->issnapshot); 3003b86f2f8SDavid du Colombier ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen, 3013b86f2f8SDavid du Colombier 0, ff->mode, ff->issnapshot); 3025e96a66cSDavid du Colombier if(ff->source == nil || ff->msource == nil) 3035e96a66cSDavid du Colombier goto Err; 3045e96a66cSDavid du Colombier }else{ 3053b86f2f8SDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 3063b86f2f8SDavid du Colombier 0, ff->mode, ff->issnapshot); 3075e96a66cSDavid du Colombier if(ff->source == nil) 3085e96a66cSDavid du Colombier goto Err; 3095e96a66cSDavid du Colombier } 3105e96a66cSDavid du Colombier 3115e96a66cSDavid du Colombier /* link in and up parent ref count */ 3123b86f2f8SDavid du Colombier if (ff->source) 3133b86f2f8SDavid du Colombier ff->source->file = ff; /* point back */ 3145e96a66cSDavid du Colombier ff->next = f->down; 3155e96a66cSDavid du Colombier f->down = ff; 3165e96a66cSDavid du Colombier ff->up = f; 3175e96a66cSDavid du Colombier fileIncRef(f); 3185e96a66cSDavid du Colombier Exit: 3195e96a66cSDavid du Colombier fileUnlock(f); 3205e96a66cSDavid du Colombier return ff; 3215e96a66cSDavid du Colombier Err: 3225e96a66cSDavid du Colombier fileUnlock(f); 3235e96a66cSDavid du Colombier if(ff != nil) 3245e96a66cSDavid du Colombier fileDecRef(ff); 3255e96a66cSDavid du Colombier return nil; 3265e96a66cSDavid du Colombier } 3275e96a66cSDavid du Colombier 3285e96a66cSDavid du Colombier File * 3295e96a66cSDavid du Colombier fileWalk(File *f, char *elem) 3305e96a66cSDavid du Colombier { 3315e96a66cSDavid du Colombier return _fileWalk(f, elem, 0); 3325e96a66cSDavid du Colombier } 3335e96a66cSDavid du Colombier 3345e96a66cSDavid du Colombier File * 3355e96a66cSDavid du Colombier _fileOpen(Fs *fs, char *path, int partial) 3365e96a66cSDavid du Colombier { 3375e96a66cSDavid du Colombier File *f, *ff; 338f8e525acSDavid du Colombier char *p, elem[VtMaxStringSize], *opath; 3395e96a66cSDavid du Colombier int n; 3405e96a66cSDavid du Colombier 3415e96a66cSDavid du Colombier f = fs->file; 3425e96a66cSDavid du Colombier fileIncRef(f); 343f8e525acSDavid du Colombier opath = path; 3445e96a66cSDavid du Colombier while(*path != 0){ 3455e96a66cSDavid du Colombier for(p = path; *p && *p != '/'; p++) 3465e96a66cSDavid du Colombier ; 3475e96a66cSDavid du Colombier n = p - path; 3485e96a66cSDavid du Colombier if(n > 0){ 3495e96a66cSDavid du Colombier if(n > VtMaxStringSize){ 350f8e525acSDavid du Colombier vtSetError("%s: element too long", EBadPath); 3515e96a66cSDavid du Colombier goto Err; 3525e96a66cSDavid du Colombier } 3535e96a66cSDavid du Colombier memmove(elem, path, n); 3545e96a66cSDavid du Colombier elem[n] = 0; 3555e96a66cSDavid du Colombier ff = _fileWalk(f, elem, partial && *p=='\0'); 356f8e525acSDavid du Colombier if(ff == nil){ 3573b86f2f8SDavid du Colombier vtSetError("%.*s: %R", utfnlen(opath, p-opath), 3583b86f2f8SDavid du Colombier opath); 3595e96a66cSDavid du Colombier goto Err; 360f8e525acSDavid du Colombier } 3615e96a66cSDavid du Colombier fileDecRef(f); 3625e96a66cSDavid du Colombier f = ff; 3635e96a66cSDavid du Colombier } 3645e96a66cSDavid du Colombier if(*p == '/') 3655e96a66cSDavid du Colombier p++; 3665e96a66cSDavid du Colombier path = p; 3675e96a66cSDavid du Colombier } 3685e96a66cSDavid du Colombier return f; 3695e96a66cSDavid du Colombier Err: 3705e96a66cSDavid du Colombier fileDecRef(f); 3715e96a66cSDavid du Colombier return nil; 3725e96a66cSDavid du Colombier } 3735e96a66cSDavid du Colombier 3745e96a66cSDavid du Colombier File* 3755e96a66cSDavid du Colombier fileOpen(Fs *fs, char *path) 3765e96a66cSDavid du Colombier { 3775e96a66cSDavid du Colombier return _fileOpen(fs, path, 0); 3785e96a66cSDavid du Colombier } 3795e96a66cSDavid du Colombier 380fe853e23SDavid du Colombier static void 381fe853e23SDavid du Colombier fileSetTmp(File *f, int istmp) 382fe853e23SDavid du Colombier { 383fe853e23SDavid du Colombier int i; 384fe853e23SDavid du Colombier Entry e; 385fe853e23SDavid du Colombier Source *r; 386fe853e23SDavid du Colombier 387fe853e23SDavid du Colombier for(i=0; i<2; i++){ 388fe853e23SDavid du Colombier if(i==0) 389fe853e23SDavid du Colombier r = f->source; 390fe853e23SDavid du Colombier else 391fe853e23SDavid du Colombier r = f->msource; 392fe853e23SDavid du Colombier if(r == nil) 393fe853e23SDavid du Colombier continue; 394f352e144SDavid du Colombier if(!sourceGetEntry(r, &e)){ 395fe853e23SDavid du Colombier fprint(2, "sourceGetEntry failed (cannot happen): %r\n"); 396fe853e23SDavid du Colombier continue; 397fe853e23SDavid du Colombier } 398fe853e23SDavid du Colombier if(istmp) 399fe853e23SDavid du Colombier e.flags |= VtEntryNoArchive; 400fe853e23SDavid du Colombier else 401fe853e23SDavid du Colombier e.flags &= ~VtEntryNoArchive; 402f352e144SDavid du Colombier if(!sourceSetEntry(r, &e)){ 403fe853e23SDavid du Colombier fprint(2, "sourceSetEntry failed (cannot happen): %r\n"); 404fe853e23SDavid du Colombier continue; 405fe853e23SDavid du Colombier } 406fe853e23SDavid du Colombier } 407fe853e23SDavid du Colombier } 408fe853e23SDavid du Colombier 4095e96a66cSDavid du Colombier File * 4105e96a66cSDavid du Colombier fileCreate(File *f, char *elem, ulong mode, char *uid) 4115e96a66cSDavid du Colombier { 4125e96a66cSDavid du Colombier File *ff; 4135e96a66cSDavid du Colombier DirEntry *dir; 4145e96a66cSDavid du Colombier Source *pr, *r, *mr; 4155e96a66cSDavid du Colombier int isdir; 4165e96a66cSDavid du Colombier 4175e96a66cSDavid du Colombier if(!fileLock(f)) 4185e96a66cSDavid du Colombier return nil; 4195e96a66cSDavid du Colombier 4205e96a66cSDavid du Colombier r = nil; 4215e96a66cSDavid du Colombier mr = nil; 4225e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 4235e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 4245e96a66cSDavid du Colombier ff = nil; 4255e96a66cSDavid du Colombier vtSetError(EExists); 4265e96a66cSDavid du Colombier goto Err1; 4275e96a66cSDavid du Colombier } 4285e96a66cSDavid du Colombier } 4295e96a66cSDavid du Colombier 4305e96a66cSDavid du Colombier ff = dirLookup(f, elem); 4315e96a66cSDavid du Colombier if(ff != nil){ 4325e96a66cSDavid du Colombier vtSetError(EExists); 4335e96a66cSDavid du Colombier goto Err1; 4345e96a66cSDavid du Colombier } 4355e96a66cSDavid du Colombier 4365e96a66cSDavid du Colombier pr = f->source; 4375e96a66cSDavid du Colombier if(pr->mode != OReadWrite){ 4385e96a66cSDavid du Colombier vtSetError(EReadOnly); 4395e96a66cSDavid du Colombier goto Err1; 4405e96a66cSDavid du Colombier } 4415e96a66cSDavid du Colombier 4425e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 4435e96a66cSDavid du Colombier goto Err1; 4445e96a66cSDavid du Colombier 4455e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 4465e96a66cSDavid du Colombier isdir = mode & ModeDir; 4475e96a66cSDavid du Colombier 4485e96a66cSDavid du Colombier r = sourceCreate(pr, pr->dsize, isdir, 0); 4495e96a66cSDavid du Colombier if(r == nil) 4505e96a66cSDavid du Colombier goto Err; 4515e96a66cSDavid du Colombier if(isdir){ 4525e96a66cSDavid du Colombier mr = sourceCreate(pr, pr->dsize, 0, r->offset); 4535e96a66cSDavid du Colombier if(mr == nil) 4545e96a66cSDavid du Colombier goto Err; 4555e96a66cSDavid du Colombier } 4565e96a66cSDavid du Colombier 4575e96a66cSDavid du Colombier dir = &ff->dir; 4585e96a66cSDavid du Colombier dir->elem = vtStrDup(elem); 4595e96a66cSDavid du Colombier dir->entry = r->offset; 4605e96a66cSDavid du Colombier dir->gen = r->gen; 4615e96a66cSDavid du Colombier if(isdir){ 4625e96a66cSDavid du Colombier dir->mentry = mr->offset; 4635e96a66cSDavid du Colombier dir->mgen = mr->gen; 4645e96a66cSDavid du Colombier } 4655e96a66cSDavid du Colombier dir->size = 0; 4665e96a66cSDavid du Colombier if(!fsNextQid(f->fs, &dir->qid)) 4675e96a66cSDavid du Colombier goto Err; 4685e96a66cSDavid du Colombier dir->uid = vtStrDup(uid); 4695e96a66cSDavid du Colombier dir->gid = vtStrDup(f->dir.gid); 4705e96a66cSDavid du Colombier dir->mid = vtStrDup(uid); 4715e96a66cSDavid du Colombier dir->mtime = time(0L); 4725e96a66cSDavid du Colombier dir->mcount = 0; 4735e96a66cSDavid du Colombier dir->ctime = dir->mtime; 4745e96a66cSDavid du Colombier dir->atime = dir->mtime; 4755e96a66cSDavid du Colombier dir->mode = mode; 4765e96a66cSDavid du Colombier 4775e96a66cSDavid du Colombier ff->boff = fileMetaAlloc(f, dir, 0); 4785e96a66cSDavid du Colombier if(ff->boff == NilBlock) 4795e96a66cSDavid du Colombier goto Err; 4805e96a66cSDavid du Colombier 4815e96a66cSDavid du Colombier sourceUnlock(f->source); 4825e96a66cSDavid du Colombier sourceUnlock(f->msource); 4835e96a66cSDavid du Colombier 4845e96a66cSDavid du Colombier ff->source = r; 4853b86f2f8SDavid du Colombier r->file = ff; /* point back */ 4865e96a66cSDavid du Colombier ff->msource = mr; 4875e96a66cSDavid du Colombier 488fe853e23SDavid du Colombier if(mode&ModeTemporary){ 489fe853e23SDavid du Colombier if(!sourceLock2(r, mr, -1)) 490fe853e23SDavid du Colombier goto Err1; 491fe853e23SDavid du Colombier fileSetTmp(ff, 1); 492fe853e23SDavid du Colombier sourceUnlock(r); 493fe853e23SDavid du Colombier if(mr) 494fe853e23SDavid du Colombier sourceUnlock(mr); 495fe853e23SDavid du Colombier } 496fe853e23SDavid du Colombier 497fe853e23SDavid du Colombier /* committed */ 498fe853e23SDavid du Colombier 4995e96a66cSDavid du Colombier /* link in and up parent ref count */ 5005e96a66cSDavid du Colombier ff->next = f->down; 5015e96a66cSDavid du Colombier f->down = ff; 5025e96a66cSDavid du Colombier ff->up = f; 5035e96a66cSDavid du Colombier fileIncRef(f); 5045e96a66cSDavid du Colombier 5055e96a66cSDavid du Colombier fileWAccess(f, uid); 5065e96a66cSDavid du Colombier 5075e96a66cSDavid du Colombier fileUnlock(f); 5085e96a66cSDavid du Colombier return ff; 5095e96a66cSDavid du Colombier 5105e96a66cSDavid du Colombier Err: 5115e96a66cSDavid du Colombier sourceUnlock(f->source); 5125e96a66cSDavid du Colombier sourceUnlock(f->msource); 5135e96a66cSDavid du Colombier Err1: 514dc5a79c1SDavid du Colombier if(r){ 515dc5a79c1SDavid du Colombier sourceLock(r, -1); 5165e96a66cSDavid du Colombier sourceRemove(r); 517dc5a79c1SDavid du Colombier } 518dc5a79c1SDavid du Colombier if(mr){ 519dc5a79c1SDavid du Colombier sourceLock(mr, -1); 5205e96a66cSDavid du Colombier sourceRemove(mr); 521dc5a79c1SDavid du Colombier } 5225e96a66cSDavid du Colombier if(ff) 5235e96a66cSDavid du Colombier fileDecRef(ff); 5245e96a66cSDavid du Colombier fileUnlock(f); 5255e96a66cSDavid du Colombier return 0; 5265e96a66cSDavid du Colombier } 5275e96a66cSDavid du Colombier 5285e96a66cSDavid du Colombier int 5295e96a66cSDavid du Colombier fileRead(File *f, void *buf, int cnt, vlong offset) 5305e96a66cSDavid du Colombier { 5315e96a66cSDavid du Colombier Source *s; 5325e96a66cSDavid du Colombier uvlong size; 5335e96a66cSDavid du Colombier u32int bn; 5345e96a66cSDavid du Colombier int off, dsize, n, nn; 5355e96a66cSDavid du Colombier Block *b; 5365e96a66cSDavid du Colombier uchar *p; 5375e96a66cSDavid du Colombier 5385e96a66cSDavid du Colombier if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset); 5395e96a66cSDavid du Colombier 5405e96a66cSDavid du Colombier if(!fileRLock(f)) 5415e96a66cSDavid du Colombier return -1; 5425e96a66cSDavid du Colombier 5435e96a66cSDavid du Colombier if(offset < 0){ 5445e96a66cSDavid du Colombier vtSetError(EBadOffset); 5455e96a66cSDavid du Colombier goto Err1; 5465e96a66cSDavid du Colombier } 5475e96a66cSDavid du Colombier 5485e96a66cSDavid du Colombier fileRAccess(f); 5495e96a66cSDavid du Colombier 5505e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)) 5515e96a66cSDavid du Colombier goto Err1; 5525e96a66cSDavid du Colombier 5535e96a66cSDavid du Colombier s = f->source; 5545e96a66cSDavid du Colombier dsize = s->dsize; 5555e96a66cSDavid du Colombier size = sourceGetSize(s); 5565e96a66cSDavid du Colombier 5575e96a66cSDavid du Colombier if(offset >= size) 5585e96a66cSDavid du Colombier offset = size; 5595e96a66cSDavid du Colombier 5605e96a66cSDavid du Colombier if(cnt > size-offset) 5615e96a66cSDavid du Colombier cnt = size-offset; 5625e96a66cSDavid du Colombier bn = offset/dsize; 5635e96a66cSDavid du Colombier off = offset%dsize; 5645e96a66cSDavid du Colombier p = buf; 5655e96a66cSDavid du Colombier while(cnt > 0){ 5665e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 5675e96a66cSDavid du Colombier if(b == nil) 5685e96a66cSDavid du Colombier goto Err; 5695e96a66cSDavid du Colombier n = cnt; 5705e96a66cSDavid du Colombier if(n > dsize-off) 5715e96a66cSDavid du Colombier n = dsize-off; 5725e96a66cSDavid du Colombier nn = dsize-off; 5735e96a66cSDavid du Colombier if(nn > n) 5745e96a66cSDavid du Colombier nn = n; 5755e96a66cSDavid du Colombier memmove(p, b->data+off, nn); 5765e96a66cSDavid du Colombier memset(p+nn, 0, nn-n); 5775e96a66cSDavid du Colombier off = 0; 5785e96a66cSDavid du Colombier bn++; 5795e96a66cSDavid du Colombier cnt -= n; 5805e96a66cSDavid du Colombier p += n; 5815e96a66cSDavid du Colombier blockPut(b); 5825e96a66cSDavid du Colombier } 5835e96a66cSDavid du Colombier sourceUnlock(s); 5845e96a66cSDavid du Colombier fileRUnlock(f); 5855e96a66cSDavid du Colombier return p-(uchar*)buf; 5865e96a66cSDavid du Colombier 5875e96a66cSDavid du Colombier Err: 5885e96a66cSDavid du Colombier sourceUnlock(s); 5895e96a66cSDavid du Colombier Err1: 5905e96a66cSDavid du Colombier fileRUnlock(f); 5915e96a66cSDavid du Colombier return -1; 5925e96a66cSDavid du Colombier } 5935e96a66cSDavid du Colombier 594fe853e23SDavid du Colombier /* 595fe853e23SDavid du Colombier * Changes the file block bn to be the given block score. 596fe853e23SDavid du Colombier * Very sneaky. Only used by flfmt. 597fe853e23SDavid du Colombier */ 598fe853e23SDavid du Colombier int 599fe853e23SDavid du Colombier fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag) 600fe853e23SDavid du Colombier { 601fe853e23SDavid du Colombier Block *b; 602fe853e23SDavid du Colombier Entry e; 603fe853e23SDavid du Colombier Source *s; 604fe853e23SDavid du Colombier 605fe853e23SDavid du Colombier if(!fileLock(f)) 606fe853e23SDavid du Colombier return 0; 607fe853e23SDavid du Colombier 608fe853e23SDavid du Colombier s = nil; 609fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){ 610fe853e23SDavid du Colombier vtSetError(ENotFile); 611fe853e23SDavid du Colombier goto Err; 612fe853e23SDavid du Colombier } 613fe853e23SDavid du Colombier 614fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){ 615fe853e23SDavid du Colombier vtSetError(EReadOnly); 616fe853e23SDavid du Colombier goto Err; 617fe853e23SDavid du Colombier } 618fe853e23SDavid du Colombier 619fe853e23SDavid du Colombier if(!sourceLock(f->source, -1)) 620fe853e23SDavid du Colombier goto Err; 621fe853e23SDavid du Colombier 622fe853e23SDavid du Colombier s = f->source; 623fe853e23SDavid du Colombier b = _sourceBlock(s, bn, OReadWrite, 1, tag); 624fe853e23SDavid du Colombier if(b == nil) 625fe853e23SDavid du Colombier goto Err; 626fe853e23SDavid du Colombier 627fe853e23SDavid du Colombier if(!sourceGetEntry(s, &e)) 628fe853e23SDavid du Colombier goto Err; 629fe853e23SDavid du Colombier if(b->l.type == BtDir){ 630fe853e23SDavid du Colombier memmove(e.score, score, VtScoreSize); 631fe853e23SDavid du Colombier assert(e.tag == tag || e.tag == 0); 632fe853e23SDavid du Colombier e.tag = tag; 633fe853e23SDavid du Colombier e.flags |= VtEntryLocal; 634fe853e23SDavid du Colombier entryPack(&e, b->data, f->source->offset % f->source->epb); 635fe853e23SDavid du Colombier }else 636fe853e23SDavid du Colombier memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize); 637fe853e23SDavid du Colombier blockDirty(b); 638fe853e23SDavid du Colombier blockPut(b); 639fe853e23SDavid du Colombier sourceUnlock(s); 640fe853e23SDavid du Colombier fileUnlock(f); 641fe853e23SDavid du Colombier return 1; 642fe853e23SDavid du Colombier 643fe853e23SDavid du Colombier Err: 644fe853e23SDavid du Colombier if(s) 645fe853e23SDavid du Colombier sourceUnlock(s); 646fe853e23SDavid du Colombier fileUnlock(f); 647fe853e23SDavid du Colombier return 0; 648fe853e23SDavid du Colombier } 649fe853e23SDavid du Colombier 650fe853e23SDavid du Colombier int 651fe853e23SDavid du Colombier fileSetSize(File *f, uvlong size) 652fe853e23SDavid du Colombier { 653fe853e23SDavid du Colombier int r; 654fe853e23SDavid du Colombier 655fe853e23SDavid du Colombier if(!fileLock(f)) 656fe853e23SDavid du Colombier return 0; 657fe853e23SDavid du Colombier r = 0; 658fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){ 659fe853e23SDavid du Colombier vtSetError(ENotFile); 660fe853e23SDavid du Colombier goto Err; 661fe853e23SDavid du Colombier } 662fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){ 663fe853e23SDavid du Colombier vtSetError(EReadOnly); 664fe853e23SDavid du Colombier goto Err; 665fe853e23SDavid du Colombier } 666fe853e23SDavid du Colombier if(!sourceLock(f->source, -1)) 667fe853e23SDavid du Colombier goto Err; 668fe853e23SDavid du Colombier r = sourceSetSize(f->source, size); 669fe853e23SDavid du Colombier sourceUnlock(f->source); 670fe853e23SDavid du Colombier Err: 671fe853e23SDavid du Colombier fileUnlock(f); 672fe853e23SDavid du Colombier return r; 673fe853e23SDavid du Colombier } 674fe853e23SDavid du Colombier 6755e96a66cSDavid du Colombier int 6765e96a66cSDavid du Colombier fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid) 6775e96a66cSDavid du Colombier { 6785e96a66cSDavid du Colombier Source *s; 6795e96a66cSDavid du Colombier ulong bn; 6805e96a66cSDavid du Colombier int off, dsize, n; 6815e96a66cSDavid du Colombier Block *b; 6825e96a66cSDavid du Colombier uchar *p; 6835e96a66cSDavid du Colombier vlong eof; 6845e96a66cSDavid du Colombier 6855e96a66cSDavid du Colombier if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); 6865e96a66cSDavid du Colombier 6875e96a66cSDavid du Colombier if(!fileLock(f)) 6885e96a66cSDavid du Colombier return -1; 6895e96a66cSDavid du Colombier 6905e96a66cSDavid du Colombier s = nil; 6915e96a66cSDavid du Colombier if(f->dir.mode & ModeDir){ 6925e96a66cSDavid du Colombier vtSetError(ENotFile); 6935e96a66cSDavid du Colombier goto Err; 6945e96a66cSDavid du Colombier } 6955e96a66cSDavid du Colombier 6965e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 6975e96a66cSDavid du Colombier vtSetError(EReadOnly); 6985e96a66cSDavid du Colombier goto Err; 6995e96a66cSDavid du Colombier } 7005e96a66cSDavid du Colombier if(offset < 0){ 7015e96a66cSDavid du Colombier vtSetError(EBadOffset); 7025e96a66cSDavid du Colombier goto Err; 7035e96a66cSDavid du Colombier } 7045e96a66cSDavid du Colombier 7055e96a66cSDavid du Colombier fileWAccess(f, uid); 7065e96a66cSDavid du Colombier 7075e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 7085e96a66cSDavid du Colombier goto Err; 7095e96a66cSDavid du Colombier s = f->source; 7105e96a66cSDavid du Colombier dsize = s->dsize; 7115e96a66cSDavid du Colombier 7125e96a66cSDavid du Colombier eof = sourceGetSize(s); 7135e96a66cSDavid du Colombier if(f->dir.mode & ModeAppend) 7145e96a66cSDavid du Colombier offset = eof; 7155e96a66cSDavid du Colombier bn = offset/dsize; 7165e96a66cSDavid du Colombier off = offset%dsize; 7175e96a66cSDavid du Colombier p = buf; 7185e96a66cSDavid du Colombier while(cnt > 0){ 7195e96a66cSDavid du Colombier n = cnt; 7205e96a66cSDavid du Colombier if(n > dsize-off) 7215e96a66cSDavid du Colombier n = dsize-off; 7225e96a66cSDavid du Colombier b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite); 7235e96a66cSDavid du Colombier if(b == nil){ 7245e96a66cSDavid du Colombier if(offset > eof) 7255e96a66cSDavid du Colombier sourceSetSize(s, offset); 7265e96a66cSDavid du Colombier goto Err; 7275e96a66cSDavid du Colombier } 7285e96a66cSDavid du Colombier memmove(b->data+off, p, n); 7295e96a66cSDavid du Colombier off = 0; 7305e96a66cSDavid du Colombier cnt -= n; 7315e96a66cSDavid du Colombier p += n; 7325e96a66cSDavid du Colombier offset += n; 7335e96a66cSDavid du Colombier bn++; 7345e96a66cSDavid du Colombier blockDirty(b); 7355e96a66cSDavid du Colombier blockPut(b); 7365e96a66cSDavid du Colombier } 7375e96a66cSDavid du Colombier if(offset > eof && !sourceSetSize(s, offset)) 7385e96a66cSDavid du Colombier goto Err; 7395e96a66cSDavid du Colombier sourceUnlock(s); 7405e96a66cSDavid du Colombier fileUnlock(f); 7415e96a66cSDavid du Colombier return p-(uchar*)buf; 7425e96a66cSDavid du Colombier Err: 7435e96a66cSDavid du Colombier if(s) 7445e96a66cSDavid du Colombier sourceUnlock(s); 7455e96a66cSDavid du Colombier fileUnlock(f); 7465e96a66cSDavid du Colombier return -1; 7475e96a66cSDavid du Colombier } 7485e96a66cSDavid du Colombier 7495e96a66cSDavid du Colombier int 7505e96a66cSDavid du Colombier fileGetDir(File *f, DirEntry *dir) 7515e96a66cSDavid du Colombier { 7525e96a66cSDavid du Colombier if(!fileRLock(f)) 7535e96a66cSDavid du Colombier return 0; 7545e96a66cSDavid du Colombier 7555e96a66cSDavid du Colombier fileMetaLock(f); 7565e96a66cSDavid du Colombier deCopy(dir, &f->dir); 7575e96a66cSDavid du Colombier fileMetaUnlock(f); 7585e96a66cSDavid du Colombier 7595e96a66cSDavid du Colombier if(!fileIsDir(f)){ 7605e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 7615e96a66cSDavid du Colombier fileRUnlock(f); 7625e96a66cSDavid du Colombier return 0; 7635e96a66cSDavid du Colombier } 7645e96a66cSDavid du Colombier dir->size = sourceGetSize(f->source); 7655e96a66cSDavid du Colombier sourceUnlock(f->source); 7665e96a66cSDavid du Colombier } 7675e96a66cSDavid du Colombier fileRUnlock(f); 7685e96a66cSDavid du Colombier 7695e96a66cSDavid du Colombier return 1; 7705e96a66cSDavid du Colombier } 7715e96a66cSDavid du Colombier 7725e96a66cSDavid du Colombier int 7735e96a66cSDavid du Colombier fileTruncate(File *f, char *uid) 7745e96a66cSDavid du Colombier { 7755e96a66cSDavid du Colombier if(fileIsDir(f)){ 7765e96a66cSDavid du Colombier vtSetError(ENotFile); 7775e96a66cSDavid du Colombier return 0; 7785e96a66cSDavid du Colombier } 7795e96a66cSDavid du Colombier 7805e96a66cSDavid du Colombier if(!fileLock(f)) 7815e96a66cSDavid du Colombier return 0; 7825e96a66cSDavid du Colombier 7835e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 7845e96a66cSDavid du Colombier vtSetError(EReadOnly); 7855e96a66cSDavid du Colombier fileUnlock(f); 7865e96a66cSDavid du Colombier return 0; 7875e96a66cSDavid du Colombier } 7885e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)){ 7895e96a66cSDavid du Colombier fileUnlock(f); 7905e96a66cSDavid du Colombier return 0; 7915e96a66cSDavid du Colombier } 7925e96a66cSDavid du Colombier if(!sourceTruncate(f->source)){ 7935e96a66cSDavid du Colombier sourceUnlock(f->source); 7945e96a66cSDavid du Colombier fileUnlock(f); 7955e96a66cSDavid du Colombier return 0; 7965e96a66cSDavid du Colombier } 7975e96a66cSDavid du Colombier sourceUnlock(f->source); 7985e96a66cSDavid du Colombier fileUnlock(f); 7995e96a66cSDavid du Colombier 800a960ed1cSDavid du Colombier fileWAccess(f, uid); 8015e96a66cSDavid du Colombier 8025e96a66cSDavid du Colombier return 1; 8035e96a66cSDavid du Colombier } 8045e96a66cSDavid du Colombier 8055e96a66cSDavid du Colombier int 8065e96a66cSDavid du Colombier fileSetDir(File *f, DirEntry *dir, char *uid) 8075e96a66cSDavid du Colombier { 8085e96a66cSDavid du Colombier File *ff; 8095e96a66cSDavid du Colombier char *oelem; 8105e96a66cSDavid du Colombier u32int mask; 8115e96a66cSDavid du Colombier u64int size; 8125e96a66cSDavid du Colombier 8135e96a66cSDavid du Colombier /* can not set permissions for the root */ 8145e96a66cSDavid du Colombier if(fileIsRoot(f)){ 8155e96a66cSDavid du Colombier vtSetError(ERoot); 8165e96a66cSDavid du Colombier return 0; 8175e96a66cSDavid du Colombier } 8185e96a66cSDavid du Colombier 8195e96a66cSDavid du Colombier if(!fileLock(f)) 8205e96a66cSDavid du Colombier return 0; 8215e96a66cSDavid du Colombier 8225e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 8235e96a66cSDavid du Colombier vtSetError(EReadOnly); 8245e96a66cSDavid du Colombier fileUnlock(f); 8255e96a66cSDavid du Colombier return 0; 8265e96a66cSDavid du Colombier } 8275e96a66cSDavid du Colombier 8285e96a66cSDavid du Colombier fileMetaLock(f); 8295e96a66cSDavid du Colombier 8305e96a66cSDavid du Colombier /* check new name does not already exist */ 8315e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 8325e96a66cSDavid du Colombier for(ff = f->up->down; ff; ff=ff->next){ 8335e96a66cSDavid du Colombier if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ 8345e96a66cSDavid du Colombier vtSetError(EExists); 8355e96a66cSDavid du Colombier goto Err; 8365e96a66cSDavid du Colombier } 8375e96a66cSDavid du Colombier } 8385e96a66cSDavid du Colombier 8395e96a66cSDavid du Colombier ff = dirLookup(f->up, dir->elem); 8405e96a66cSDavid du Colombier if(ff != nil){ 8415e96a66cSDavid du Colombier fileDecRef(ff); 8425e96a66cSDavid du Colombier vtSetError(EExists); 8435e96a66cSDavid du Colombier goto Err; 8445e96a66cSDavid du Colombier } 8455e96a66cSDavid du Colombier } 8465e96a66cSDavid du Colombier 847fe853e23SDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 8485e96a66cSDavid du Colombier goto Err; 849fe853e23SDavid du Colombier if(!fileIsDir(f)){ 8505e96a66cSDavid du Colombier size = sourceGetSize(f->source); 8515e96a66cSDavid du Colombier if(size != dir->size){ 8525e96a66cSDavid du Colombier if(!sourceSetSize(f->source, dir->size)){ 8535e96a66cSDavid du Colombier sourceUnlock(f->source); 854fe853e23SDavid du Colombier if(f->msource) 855fe853e23SDavid du Colombier sourceUnlock(f->msource); 8565e96a66cSDavid du Colombier goto Err; 8575e96a66cSDavid du Colombier } 8585e96a66cSDavid du Colombier /* commited to changing it now */ 8595e96a66cSDavid du Colombier } 8605e96a66cSDavid du Colombier } 8615e96a66cSDavid du Colombier /* commited to changing it now */ 862fe853e23SDavid du Colombier if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary)) 863fe853e23SDavid du Colombier fileSetTmp(f, dir->mode&ModeTemporary); 864fe853e23SDavid du Colombier sourceUnlock(f->source); 865fe853e23SDavid du Colombier if(f->msource) 866fe853e23SDavid du Colombier sourceUnlock(f->msource); 867fe853e23SDavid du Colombier 8685e96a66cSDavid du Colombier oelem = nil; 8695e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 8705e96a66cSDavid du Colombier oelem = f->dir.elem; 8715e96a66cSDavid du Colombier f->dir.elem = vtStrDup(dir->elem); 8725e96a66cSDavid du Colombier } 8735e96a66cSDavid du Colombier 8745e96a66cSDavid du Colombier if(strcmp(f->dir.uid, dir->uid) != 0){ 8755e96a66cSDavid du Colombier vtMemFree(f->dir.uid); 8765e96a66cSDavid du Colombier f->dir.uid = vtStrDup(dir->uid); 8775e96a66cSDavid du Colombier } 8785e96a66cSDavid du Colombier 8795e96a66cSDavid du Colombier if(strcmp(f->dir.gid, dir->gid) != 0){ 8805e96a66cSDavid du Colombier vtMemFree(f->dir.gid); 8815e96a66cSDavid du Colombier f->dir.gid = vtStrDup(dir->gid); 8825e96a66cSDavid du Colombier } 8835e96a66cSDavid du Colombier 8845e96a66cSDavid du Colombier f->dir.mtime = dir->mtime; 8855e96a66cSDavid du Colombier f->dir.atime = dir->atime; 8865e96a66cSDavid du Colombier 8875e96a66cSDavid du Colombier //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); 8885e96a66cSDavid du Colombier mask = ~(ModeDir|ModeSnapshot); 8895e96a66cSDavid du Colombier f->dir.mode &= ~mask; 8905e96a66cSDavid du Colombier f->dir.mode |= mask & dir->mode; 8915e96a66cSDavid du Colombier f->dirty = 1; 8925e96a66cSDavid du Colombier //fprint(2, "->%x\n", f->dir.mode); 8935e96a66cSDavid du Colombier 8945e96a66cSDavid du Colombier fileMetaFlush2(f, oelem); 8955e96a66cSDavid du Colombier vtMemFree(oelem); 8965e96a66cSDavid du Colombier 8975e96a66cSDavid du Colombier fileMetaUnlock(f); 8985e96a66cSDavid du Colombier fileUnlock(f); 8995e96a66cSDavid du Colombier 9005e96a66cSDavid du Colombier fileWAccess(f->up, uid); 9015e96a66cSDavid du Colombier 9025e96a66cSDavid du Colombier return 1; 9035e96a66cSDavid du Colombier Err: 9045e96a66cSDavid du Colombier fileMetaUnlock(f); 9055e96a66cSDavid du Colombier fileUnlock(f); 9065e96a66cSDavid du Colombier return 0; 9075e96a66cSDavid du Colombier } 9085e96a66cSDavid du Colombier 9095e96a66cSDavid du Colombier int 9105e96a66cSDavid du Colombier fileSetQidSpace(File *f, u64int offset, u64int max) 9115e96a66cSDavid du Colombier { 9125e96a66cSDavid du Colombier int ret; 9135e96a66cSDavid du Colombier 9145e96a66cSDavid du Colombier if(!fileLock(f)) 9155e96a66cSDavid du Colombier return 0; 9165e96a66cSDavid du Colombier fileMetaLock(f); 9175e96a66cSDavid du Colombier f->dir.qidSpace = 1; 9185e96a66cSDavid du Colombier f->dir.qidOffset = offset; 9195e96a66cSDavid du Colombier f->dir.qidMax = max; 9200b9a5132SDavid du Colombier ret = fileMetaFlush2(f, nil)>=0; 9215e96a66cSDavid du Colombier fileMetaUnlock(f); 9225e96a66cSDavid du Colombier fileUnlock(f); 9235e96a66cSDavid du Colombier return ret; 9245e96a66cSDavid du Colombier } 9255e96a66cSDavid du Colombier 9265e96a66cSDavid du Colombier 9275e96a66cSDavid du Colombier uvlong 9285e96a66cSDavid du Colombier fileGetId(File *f) 9295e96a66cSDavid du Colombier { 9305e96a66cSDavid du Colombier /* immutable */ 9315e96a66cSDavid du Colombier return f->dir.qid; 9325e96a66cSDavid du Colombier } 9335e96a66cSDavid du Colombier 9345e96a66cSDavid du Colombier ulong 9355e96a66cSDavid du Colombier fileGetMcount(File *f) 9365e96a66cSDavid du Colombier { 9375e96a66cSDavid du Colombier ulong mcount; 9385e96a66cSDavid du Colombier 9395e96a66cSDavid du Colombier fileMetaLock(f); 9405e96a66cSDavid du Colombier mcount = f->dir.mcount; 9415e96a66cSDavid du Colombier fileMetaUnlock(f); 9425e96a66cSDavid du Colombier return mcount; 9435e96a66cSDavid du Colombier } 9445e96a66cSDavid du Colombier 9455e96a66cSDavid du Colombier ulong 9465e96a66cSDavid du Colombier fileGetMode(File *f) 9475e96a66cSDavid du Colombier { 9485e96a66cSDavid du Colombier ulong mode; 9495e96a66cSDavid du Colombier 9505e96a66cSDavid du Colombier fileMetaLock(f); 9515e96a66cSDavid du Colombier mode = f->dir.mode; 9525e96a66cSDavid du Colombier fileMetaUnlock(f); 9535e96a66cSDavid du Colombier return mode; 9545e96a66cSDavid du Colombier } 9555e96a66cSDavid du Colombier 9565e96a66cSDavid du Colombier int 9575e96a66cSDavid du Colombier fileIsDir(File *f) 9585e96a66cSDavid du Colombier { 9595e96a66cSDavid du Colombier /* immutable */ 9605e96a66cSDavid du Colombier return (f->dir.mode & ModeDir) != 0; 9615e96a66cSDavid du Colombier } 9625e96a66cSDavid du Colombier 9635e96a66cSDavid du Colombier int 9645e96a66cSDavid du Colombier fileIsRoot(File *f) 9655e96a66cSDavid du Colombier { 9665e96a66cSDavid du Colombier return f == f->fs->file; 9675e96a66cSDavid du Colombier } 9685e96a66cSDavid du Colombier 9695e96a66cSDavid du Colombier int 9705e96a66cSDavid du Colombier fileIsRoFs(File *f) 9715e96a66cSDavid du Colombier { 9725e96a66cSDavid du Colombier return f->fs->mode == OReadOnly; 9735e96a66cSDavid du Colombier } 9745e96a66cSDavid du Colombier 9755e96a66cSDavid du Colombier int 9765e96a66cSDavid du Colombier fileGetSize(File *f, uvlong *size) 9775e96a66cSDavid du Colombier { 9785e96a66cSDavid du Colombier if(!fileRLock(f)) 9795e96a66cSDavid du Colombier return 0; 9805e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 9815e96a66cSDavid du Colombier fileRUnlock(f); 9825e96a66cSDavid du Colombier return 0; 9835e96a66cSDavid du Colombier } 9845e96a66cSDavid du Colombier *size = sourceGetSize(f->source); 9855e96a66cSDavid du Colombier sourceUnlock(f->source); 9865e96a66cSDavid du Colombier fileRUnlock(f); 9875e96a66cSDavid du Colombier 9885e96a66cSDavid du Colombier return 1; 9895e96a66cSDavid du Colombier } 9905e96a66cSDavid du Colombier 9910b9a5132SDavid du Colombier int 9925e96a66cSDavid du Colombier fileMetaFlush(File *f, int rec) 9935e96a66cSDavid du Colombier { 9945e96a66cSDavid du Colombier File **kids, *p; 9955e96a66cSDavid du Colombier int nkids; 9960b9a5132SDavid du Colombier int i, rv; 9975e96a66cSDavid du Colombier 9985e96a66cSDavid du Colombier fileMetaLock(f); 9990b9a5132SDavid du Colombier rv = fileMetaFlush2(f, nil); 10005e96a66cSDavid du Colombier fileMetaUnlock(f); 10015e96a66cSDavid du Colombier 10025e96a66cSDavid du Colombier if(!rec || !fileIsDir(f)) 10030b9a5132SDavid du Colombier return rv; 10045e96a66cSDavid du Colombier 10055e96a66cSDavid du Colombier if(!fileLock(f)) 10060b9a5132SDavid du Colombier return rv; 10075e96a66cSDavid du Colombier nkids = 0; 10085e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 10095e96a66cSDavid du Colombier nkids++; 10105e96a66cSDavid du Colombier kids = vtMemAlloc(nkids*sizeof(File*)); 10115e96a66cSDavid du Colombier i = 0; 10125e96a66cSDavid du Colombier for(p=f->down; p; p=p->next){ 10135e96a66cSDavid du Colombier kids[i++] = p; 10145e96a66cSDavid du Colombier p->ref++; 10155e96a66cSDavid du Colombier } 10165e96a66cSDavid du Colombier fileUnlock(f); 10175e96a66cSDavid du Colombier 10185e96a66cSDavid du Colombier for(i=0; i<nkids; i++){ 10190b9a5132SDavid du Colombier rv |= fileMetaFlush(kids[i], 1); 10205e96a66cSDavid du Colombier fileDecRef(kids[i]); 10215e96a66cSDavid du Colombier } 10225e96a66cSDavid du Colombier vtMemFree(kids); 10230b9a5132SDavid du Colombier return rv; 10245e96a66cSDavid du Colombier } 10255e96a66cSDavid du Colombier 10265e96a66cSDavid du Colombier /* assumes metaLock is held */ 10275e96a66cSDavid du Colombier static int 10285e96a66cSDavid du Colombier fileMetaFlush2(File *f, char *oelem) 10295e96a66cSDavid du Colombier { 10305e96a66cSDavid du Colombier File *fp; 10315e96a66cSDavid du Colombier Block *b, *bb; 10325e96a66cSDavid du Colombier MetaBlock mb; 10335e96a66cSDavid du Colombier MetaEntry me, me2; 10345e96a66cSDavid du Colombier int i, n; 10355e96a66cSDavid du Colombier u32int boff; 10365e96a66cSDavid du Colombier 10375e96a66cSDavid du Colombier if(!f->dirty) 10380b9a5132SDavid du Colombier return 0; 10395e96a66cSDavid du Colombier 10405e96a66cSDavid du Colombier if(oelem == nil) 10415e96a66cSDavid du Colombier oelem = f->dir.elem; 10425e96a66cSDavid du Colombier 10435e96a66cSDavid du Colombier //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem); 10445e96a66cSDavid du Colombier 10455e96a66cSDavid du Colombier fp = f->up; 10465e96a66cSDavid du Colombier 10475e96a66cSDavid du Colombier if(!sourceLock(fp->msource, -1)) 10480b9a5132SDavid du Colombier return -1; 10496042bf6dSDavid du Colombier /* can happen if source is clri'ed out from under us */ 10506042bf6dSDavid du Colombier if(f->boff == NilBlock) 10516042bf6dSDavid du Colombier goto Err1; 10525e96a66cSDavid du Colombier b = sourceBlock(fp->msource, f->boff, OReadWrite); 10535e96a66cSDavid du Colombier if(b == nil) 10545e96a66cSDavid du Colombier goto Err1; 10555e96a66cSDavid du Colombier 10565e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, fp->msource->dsize)) 10575e96a66cSDavid du Colombier goto Err; 10585e96a66cSDavid du Colombier if(!mbSearch(&mb, oelem, &i, &me)) 10595e96a66cSDavid du Colombier goto Err; 10605e96a66cSDavid du Colombier 10615e96a66cSDavid du Colombier n = deSize(&f->dir); 10625e96a66cSDavid du Colombier if(0)fprint(2, "old size %d new size %d\n", me.size, n); 10635e96a66cSDavid du Colombier 10645e96a66cSDavid du Colombier if(mbResize(&mb, &me, n)){ 10655e96a66cSDavid du Colombier /* fits in the block */ 10665e96a66cSDavid du Colombier mbDelete(&mb, i); 10675e96a66cSDavid du Colombier if(strcmp(f->dir.elem, oelem) != 0) 10685e96a66cSDavid du Colombier mbSearch(&mb, f->dir.elem, &i, &me2); 10695e96a66cSDavid du Colombier dePack(&f->dir, &me); 10705e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 10715e96a66cSDavid du Colombier mbPack(&mb); 10725e96a66cSDavid du Colombier blockDirty(b); 10735e96a66cSDavid du Colombier blockPut(b); 10745e96a66cSDavid du Colombier sourceUnlock(fp->msource); 10755e96a66cSDavid du Colombier f->dirty = 0; 10765e96a66cSDavid du Colombier 10775e96a66cSDavid du Colombier return 1; 10785e96a66cSDavid du Colombier } 10795e96a66cSDavid du Colombier 10805e96a66cSDavid du Colombier /* 10815e96a66cSDavid du Colombier * moving entry to another block 10825e96a66cSDavid du Colombier * it is feasible for the fs to crash leaving two copies 10835e96a66cSDavid du Colombier * of the directory entry. This is just too much work to 10845e96a66cSDavid du Colombier * fix. Given that entries are only allocated in a block that 10855e96a66cSDavid du Colombier * is less than PercentageFull, most modifications of meta data 10865e96a66cSDavid du Colombier * will fit within the block. i.e. this code should almost 10875e96a66cSDavid du Colombier * never be executed. 10885e96a66cSDavid du Colombier */ 10895e96a66cSDavid du Colombier boff = fileMetaAlloc(fp, &f->dir, f->boff+1); 10905e96a66cSDavid du Colombier if(boff == NilBlock){ 10915e96a66cSDavid du Colombier /* mbResize might have modified block */ 10925e96a66cSDavid du Colombier mbPack(&mb); 10935e96a66cSDavid du Colombier blockDirty(b); 10945e96a66cSDavid du Colombier goto Err; 10955e96a66cSDavid du Colombier } 10965e96a66cSDavid du Colombier fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff); 10975e96a66cSDavid du Colombier f->boff = boff; 10985e96a66cSDavid du Colombier 10995e96a66cSDavid du Colombier /* make sure deletion goes to disk after new entry */ 11005e96a66cSDavid du Colombier bb = sourceBlock(fp->msource, f->boff, OReadWrite); 11015e96a66cSDavid du Colombier mbDelete(&mb, i); 11025e96a66cSDavid du Colombier mbPack(&mb); 110361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 11045e96a66cSDavid du Colombier blockPut(bb); 11055e96a66cSDavid du Colombier blockDirty(b); 11065e96a66cSDavid du Colombier blockPut(b); 11075e96a66cSDavid du Colombier sourceUnlock(fp->msource); 11085e96a66cSDavid du Colombier 11095e96a66cSDavid du Colombier f->dirty = 0; 11105e96a66cSDavid du Colombier 11115e96a66cSDavid du Colombier return 1; 11125e96a66cSDavid du Colombier 11135e96a66cSDavid du Colombier Err: 11145e96a66cSDavid du Colombier blockPut(b); 11155e96a66cSDavid du Colombier Err1: 11165e96a66cSDavid du Colombier sourceUnlock(fp->msource); 11170b9a5132SDavid du Colombier return -1; 11185e96a66cSDavid du Colombier } 11195e96a66cSDavid du Colombier 11205e96a66cSDavid du Colombier static int 11215e96a66cSDavid du Colombier fileMetaRemove(File *f, char *uid) 11225e96a66cSDavid du Colombier { 11235e96a66cSDavid du Colombier Block *b; 11245e96a66cSDavid du Colombier MetaBlock mb; 11255e96a66cSDavid du Colombier MetaEntry me; 11265e96a66cSDavid du Colombier int i; 11275e96a66cSDavid du Colombier File *up; 11285e96a66cSDavid du Colombier 11295e96a66cSDavid du Colombier up = f->up; 11305e96a66cSDavid du Colombier 11315e96a66cSDavid du Colombier fileWAccess(up, uid); 11325e96a66cSDavid du Colombier 11335e96a66cSDavid du Colombier fileMetaLock(f); 11345e96a66cSDavid du Colombier 11355e96a66cSDavid du Colombier sourceLock(up->msource, OReadWrite); 11365e96a66cSDavid du Colombier b = sourceBlock(up->msource, f->boff, OReadWrite); 11375e96a66cSDavid du Colombier if(b == nil) 11385e96a66cSDavid du Colombier goto Err; 11395e96a66cSDavid du Colombier 11405e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, up->msource->dsize)) 11415e96a66cSDavid du Colombier { 11425e96a66cSDavid du Colombier fprint(2, "U\n"); 11435e96a66cSDavid du Colombier goto Err; 11445e96a66cSDavid du Colombier } 11455e96a66cSDavid du Colombier if(!mbSearch(&mb, f->dir.elem, &i, &me)) 11465e96a66cSDavid du Colombier { 11475e96a66cSDavid du Colombier fprint(2, "S\n"); 11485e96a66cSDavid du Colombier goto Err; 11495e96a66cSDavid du Colombier } 11505e96a66cSDavid du Colombier mbDelete(&mb, i); 11515e96a66cSDavid du Colombier mbPack(&mb); 11525e96a66cSDavid du Colombier sourceUnlock(up->msource); 11535e96a66cSDavid du Colombier 11545e96a66cSDavid du Colombier blockDirty(b); 11555e96a66cSDavid du Colombier blockPut(b); 11565e96a66cSDavid du Colombier 11575e96a66cSDavid du Colombier f->removed = 1; 11585e96a66cSDavid du Colombier f->boff = NilBlock; 11595e96a66cSDavid du Colombier f->dirty = 0; 11605e96a66cSDavid du Colombier 11615e96a66cSDavid du Colombier fileMetaUnlock(f); 11625e96a66cSDavid du Colombier return 1; 11635e96a66cSDavid du Colombier 11645e96a66cSDavid du Colombier Err: 11655e96a66cSDavid du Colombier sourceUnlock(up->msource); 11665e96a66cSDavid du Colombier blockPut(b); 11675e96a66cSDavid du Colombier fileMetaUnlock(f); 11685e96a66cSDavid du Colombier return 0; 11695e96a66cSDavid du Colombier } 11705e96a66cSDavid du Colombier 11715e96a66cSDavid du Colombier /* assume file is locked, assume f->msource is locked */ 11725e96a66cSDavid du Colombier static int 11735e96a66cSDavid du Colombier fileCheckEmpty(File *f) 11745e96a66cSDavid du Colombier { 11755e96a66cSDavid du Colombier u32int i, n; 11765e96a66cSDavid du Colombier Block *b; 11775e96a66cSDavid du Colombier MetaBlock mb; 11785e96a66cSDavid du Colombier Source *r; 11795e96a66cSDavid du Colombier 11805e96a66cSDavid du Colombier r = f->msource; 11815e96a66cSDavid du Colombier n = (sourceGetSize(r)+r->dsize-1)/r->dsize; 11825e96a66cSDavid du Colombier for(i=0; i<n; i++){ 11835e96a66cSDavid du Colombier b = sourceBlock(r, i, OReadOnly); 11845e96a66cSDavid du Colombier if(b == nil) 11855e96a66cSDavid du Colombier goto Err; 11865e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, r->dsize)) 11875e96a66cSDavid du Colombier goto Err; 11885e96a66cSDavid du Colombier if(mb.nindex > 0){ 11895e96a66cSDavid du Colombier vtSetError(ENotEmpty); 11905e96a66cSDavid du Colombier goto Err; 11915e96a66cSDavid du Colombier } 11925e96a66cSDavid du Colombier blockPut(b); 11935e96a66cSDavid du Colombier } 11945e96a66cSDavid du Colombier return 1; 11955e96a66cSDavid du Colombier Err: 11965e96a66cSDavid du Colombier blockPut(b); 11975e96a66cSDavid du Colombier return 0; 11985e96a66cSDavid du Colombier } 11995e96a66cSDavid du Colombier 12005e96a66cSDavid du Colombier int 12015e96a66cSDavid du Colombier fileRemove(File *f, char *uid) 12025e96a66cSDavid du Colombier { 12035e96a66cSDavid du Colombier File *ff; 12045e96a66cSDavid du Colombier 12055e96a66cSDavid du Colombier /* can not remove the root */ 12065e96a66cSDavid du Colombier if(fileIsRoot(f)){ 12075e96a66cSDavid du Colombier vtSetError(ERoot); 12085e96a66cSDavid du Colombier return 0; 12095e96a66cSDavid du Colombier } 12105e96a66cSDavid du Colombier 12115e96a66cSDavid du Colombier if(!fileLock(f)) 12125e96a66cSDavid du Colombier return 0; 12135e96a66cSDavid du Colombier 12145e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 12155e96a66cSDavid du Colombier vtSetError(EReadOnly); 12165e96a66cSDavid du Colombier goto Err1; 12175e96a66cSDavid du Colombier } 12185e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 12195e96a66cSDavid du Colombier goto Err1; 12205e96a66cSDavid du Colombier if(fileIsDir(f) && !fileCheckEmpty(f)) 12215e96a66cSDavid du Colombier goto Err; 12225e96a66cSDavid du Colombier 12235e96a66cSDavid du Colombier for(ff=f->down; ff; ff=ff->next) 12245e96a66cSDavid du Colombier assert(ff->removed); 12255e96a66cSDavid du Colombier 12265e96a66cSDavid du Colombier sourceRemove(f->source); 12273b86f2f8SDavid du Colombier f->source->file = nil; /* erase back pointer */ 12285e96a66cSDavid du Colombier f->source = nil; 12295e96a66cSDavid du Colombier if(f->msource){ 12305e96a66cSDavid du Colombier sourceRemove(f->msource); 12315e96a66cSDavid du Colombier f->msource = nil; 12325e96a66cSDavid du Colombier } 12335e96a66cSDavid du Colombier 12345e96a66cSDavid du Colombier fileUnlock(f); 12355e96a66cSDavid du Colombier 12365e96a66cSDavid du Colombier if(!fileMetaRemove(f, uid)) 12375e96a66cSDavid du Colombier return 0; 12385e96a66cSDavid du Colombier 12395e96a66cSDavid du Colombier return 1; 12405e96a66cSDavid du Colombier 12415e96a66cSDavid du Colombier Err: 12425e96a66cSDavid du Colombier sourceUnlock(f->source); 12435e96a66cSDavid du Colombier if(f->msource) 12445e96a66cSDavid du Colombier sourceUnlock(f->msource); 12455e96a66cSDavid du Colombier Err1: 12465e96a66cSDavid du Colombier fileUnlock(f); 12475e96a66cSDavid du Colombier return 0; 12485e96a66cSDavid du Colombier } 12495e96a66cSDavid du Colombier 1250dc5a79c1SDavid du Colombier static int 1251dc5a79c1SDavid du Colombier clri(File *f, char *uid) 12525e96a66cSDavid du Colombier { 12535e96a66cSDavid du Colombier int r; 12545e96a66cSDavid du Colombier 12555e96a66cSDavid du Colombier if(f == nil) 12565e96a66cSDavid du Colombier return 0; 12575e96a66cSDavid du Colombier if(f->up->source->mode != OReadWrite){ 12585e96a66cSDavid du Colombier vtSetError(EReadOnly); 12595e96a66cSDavid du Colombier fileDecRef(f); 12605e96a66cSDavid du Colombier return 0; 12615e96a66cSDavid du Colombier } 12625e96a66cSDavid du Colombier r = fileMetaRemove(f, uid); 12635e96a66cSDavid du Colombier fileDecRef(f); 12645e96a66cSDavid du Colombier return r; 12655e96a66cSDavid du Colombier } 12665e96a66cSDavid du Colombier 1267dc5a79c1SDavid du Colombier int 1268dc5a79c1SDavid du Colombier fileClriPath(Fs *fs, char *path, char *uid) 1269dc5a79c1SDavid du Colombier { 1270dc5a79c1SDavid du Colombier return clri(_fileOpen(fs, path, 1), uid); 1271dc5a79c1SDavid du Colombier } 1272dc5a79c1SDavid du Colombier 1273dc5a79c1SDavid du Colombier int 1274dc5a79c1SDavid du Colombier fileClri(File *dir, char *elem, char *uid) 1275dc5a79c1SDavid du Colombier { 1276dc5a79c1SDavid du Colombier return clri(_fileWalk(dir, elem, 1), uid); 1277dc5a79c1SDavid du Colombier } 1278dc5a79c1SDavid du Colombier 12795e96a66cSDavid du Colombier File * 12805e96a66cSDavid du Colombier fileIncRef(File *vf) 12815e96a66cSDavid du Colombier { 12825e96a66cSDavid du Colombier fileMetaLock(vf); 12835e96a66cSDavid du Colombier assert(vf->ref > 0); 12845e96a66cSDavid du Colombier vf->ref++; 12855e96a66cSDavid du Colombier fileMetaUnlock(vf); 12865e96a66cSDavid du Colombier return vf; 12875e96a66cSDavid du Colombier } 12885e96a66cSDavid du Colombier 12895e96a66cSDavid du Colombier int 12905e96a66cSDavid du Colombier fileDecRef(File *f) 12915e96a66cSDavid du Colombier { 12925e96a66cSDavid du Colombier File *p, *q, **qq; 12935e96a66cSDavid du Colombier 12945e96a66cSDavid du Colombier if(f->up == nil){ 12955e96a66cSDavid du Colombier /* never linked in */ 12965e96a66cSDavid du Colombier assert(f->ref == 1); 12975e96a66cSDavid du Colombier fileFree(f); 12985e96a66cSDavid du Colombier return 1; 12995e96a66cSDavid du Colombier } 13005e96a66cSDavid du Colombier 13015e96a66cSDavid du Colombier fileMetaLock(f); 13025e96a66cSDavid du Colombier f->ref--; 13035e96a66cSDavid du Colombier if(f->ref > 0){ 13045e96a66cSDavid du Colombier fileMetaUnlock(f); 13055e96a66cSDavid du Colombier return 0; 13065e96a66cSDavid du Colombier } 13075e96a66cSDavid du Colombier assert(f->ref == 0); 13085e96a66cSDavid du Colombier assert(f->down == nil); 13095e96a66cSDavid du Colombier 13105e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 13115e96a66cSDavid du Colombier 13125e96a66cSDavid du Colombier p = f->up; 13135e96a66cSDavid du Colombier qq = &p->down; 13145e96a66cSDavid du Colombier for(q = *qq; q; q = *qq){ 13155e96a66cSDavid du Colombier if(q == f) 13165e96a66cSDavid du Colombier break; 13175e96a66cSDavid du Colombier qq = &q->next; 13185e96a66cSDavid du Colombier } 13195e96a66cSDavid du Colombier assert(q != nil); 13205e96a66cSDavid du Colombier *qq = f->next; 13215e96a66cSDavid du Colombier 13225e96a66cSDavid du Colombier fileMetaUnlock(f); 13235e96a66cSDavid du Colombier fileFree(f); 13245e96a66cSDavid du Colombier 13255e96a66cSDavid du Colombier fileDecRef(p); 13265e96a66cSDavid du Colombier return 1; 13275e96a66cSDavid du Colombier } 13285e96a66cSDavid du Colombier 13295e96a66cSDavid du Colombier File * 13305e96a66cSDavid du Colombier fileGetParent(File *f) 13315e96a66cSDavid du Colombier { 13325e96a66cSDavid du Colombier if(fileIsRoot(f)) 13335e96a66cSDavid du Colombier return fileIncRef(f); 13345e96a66cSDavid du Colombier return fileIncRef(f->up); 13355e96a66cSDavid du Colombier } 13365e96a66cSDavid du Colombier 13375e96a66cSDavid du Colombier DirEntryEnum * 13385e96a66cSDavid du Colombier deeOpen(File *f) 13395e96a66cSDavid du Colombier { 13405e96a66cSDavid du Colombier DirEntryEnum *dee; 13415e96a66cSDavid du Colombier File *p; 13425e96a66cSDavid du Colombier 13435e96a66cSDavid du Colombier if(!fileIsDir(f)){ 13445e96a66cSDavid du Colombier vtSetError(ENotDir); 13455e96a66cSDavid du Colombier fileDecRef(f); 13465e96a66cSDavid du Colombier return nil; 13475e96a66cSDavid du Colombier } 13485e96a66cSDavid du Colombier 13495e96a66cSDavid du Colombier /* flush out meta data */ 13505e96a66cSDavid du Colombier if(!fileLock(f)) 13515e96a66cSDavid du Colombier return nil; 13525e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 13535e96a66cSDavid du Colombier fileMetaFlush2(p, nil); 13545e96a66cSDavid du Colombier fileUnlock(f); 13555e96a66cSDavid du Colombier 13565e96a66cSDavid du Colombier dee = vtMemAllocZ(sizeof(DirEntryEnum)); 13575e96a66cSDavid du Colombier dee->file = fileIncRef(f); 13585e96a66cSDavid du Colombier 13595e96a66cSDavid du Colombier return dee; 13605e96a66cSDavid du Colombier } 13615e96a66cSDavid du Colombier 13625e96a66cSDavid du Colombier static int 13635e96a66cSDavid du Colombier dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size) 13645e96a66cSDavid du Colombier { 13655e96a66cSDavid du Colombier Block *b; 13665e96a66cSDavid du Colombier ulong bn; 13675e96a66cSDavid du Colombier Entry e; 13685e96a66cSDavid du Colombier int epb; 13695e96a66cSDavid du Colombier 13705e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 13715e96a66cSDavid du Colombier bn = elem/epb; 13725e96a66cSDavid du Colombier elem -= bn*epb; 13735e96a66cSDavid du Colombier 13745e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 13755e96a66cSDavid du Colombier if(b == nil) 13765e96a66cSDavid du Colombier goto Err; 13775e96a66cSDavid du Colombier if(!entryUnpack(&e, b->data, elem)) 13785e96a66cSDavid du Colombier goto Err; 13795e96a66cSDavid du Colombier 13805e96a66cSDavid du Colombier /* hanging entries are returned as zero size */ 13815e96a66cSDavid du Colombier if(!(e.flags & VtEntryActive) || e.gen != gen) 13825e96a66cSDavid du Colombier *size = 0; 13835e96a66cSDavid du Colombier else 13845e96a66cSDavid du Colombier *size = e.size; 13855e96a66cSDavid du Colombier blockPut(b); 13865e96a66cSDavid du Colombier return 1; 13875e96a66cSDavid du Colombier 13885e96a66cSDavid du Colombier Err: 13895e96a66cSDavid du Colombier blockPut(b); 13905e96a66cSDavid du Colombier return 0; 13915e96a66cSDavid du Colombier } 13925e96a66cSDavid du Colombier 13935e96a66cSDavid du Colombier static int 13945e96a66cSDavid du Colombier deeFill(DirEntryEnum *dee) 13955e96a66cSDavid du Colombier { 13965e96a66cSDavid du Colombier int i, n; 13975e96a66cSDavid du Colombier Source *meta, *source; 13985e96a66cSDavid du Colombier MetaBlock mb; 13995e96a66cSDavid du Colombier MetaEntry me; 14005e96a66cSDavid du Colombier File *f; 14015e96a66cSDavid du Colombier Block *b; 14025e96a66cSDavid du Colombier DirEntry *de; 14035e96a66cSDavid du Colombier 14045e96a66cSDavid du Colombier /* clean up first */ 14055e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 14065e96a66cSDavid du Colombier deCleanup(dee->buf+i); 14075e96a66cSDavid du Colombier vtMemFree(dee->buf); 14085e96a66cSDavid du Colombier dee->buf = nil; 14095e96a66cSDavid du Colombier dee->i = 0; 14105e96a66cSDavid du Colombier dee->n = 0; 14115e96a66cSDavid du Colombier 14125e96a66cSDavid du Colombier f = dee->file; 14135e96a66cSDavid du Colombier 14145e96a66cSDavid du Colombier source = f->source; 14155e96a66cSDavid du Colombier meta = f->msource; 14165e96a66cSDavid du Colombier 14175e96a66cSDavid du Colombier b = sourceBlock(meta, dee->boff, OReadOnly); 14185e96a66cSDavid du Colombier if(b == nil) 14195e96a66cSDavid du Colombier goto Err; 14205e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 14215e96a66cSDavid du Colombier goto Err; 14225e96a66cSDavid du Colombier 14235e96a66cSDavid du Colombier n = mb.nindex; 14245e96a66cSDavid du Colombier dee->buf = vtMemAlloc(n * sizeof(DirEntry)); 14255e96a66cSDavid du Colombier 14265e96a66cSDavid du Colombier for(i=0; i<n; i++){ 14275e96a66cSDavid du Colombier de = dee->buf + i; 14285e96a66cSDavid du Colombier meUnpack(&me, &mb, i); 14295e96a66cSDavid du Colombier if(!deUnpack(de, &me)) 14305e96a66cSDavid du Colombier goto Err; 14315e96a66cSDavid du Colombier dee->n++; 14325e96a66cSDavid du Colombier if(!(de->mode & ModeDir)) 14335e96a66cSDavid du Colombier if(!dirEntrySize(source, de->entry, de->gen, &de->size)) 14345e96a66cSDavid du Colombier goto Err; 14355e96a66cSDavid du Colombier } 14365e96a66cSDavid du Colombier dee->boff++; 14375e96a66cSDavid du Colombier blockPut(b); 14385e96a66cSDavid du Colombier return 1; 14395e96a66cSDavid du Colombier Err: 14405e96a66cSDavid du Colombier blockPut(b); 14415e96a66cSDavid du Colombier return 0; 14425e96a66cSDavid du Colombier } 14435e96a66cSDavid du Colombier 14445e96a66cSDavid du Colombier int 14455e96a66cSDavid du Colombier deeRead(DirEntryEnum *dee, DirEntry *de) 14465e96a66cSDavid du Colombier { 14475e96a66cSDavid du Colombier int ret, didread; 14485e96a66cSDavid du Colombier File *f; 14495e96a66cSDavid du Colombier u32int nb; 14505e96a66cSDavid du Colombier 1451418f3c22SDavid du Colombier if(dee == nil){ 1452418f3c22SDavid du Colombier vtSetError("cannot happen in deeRead"); 1453418f3c22SDavid du Colombier return -1; 1454418f3c22SDavid du Colombier } 1455418f3c22SDavid du Colombier 14565e96a66cSDavid du Colombier f = dee->file; 14575e96a66cSDavid du Colombier if(!fileRLock(f)) 14585e96a66cSDavid du Colombier return -1; 14595e96a66cSDavid du Colombier 14605e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadOnly)){ 14615e96a66cSDavid du Colombier fileRUnlock(f); 14625e96a66cSDavid du Colombier return -1; 14635e96a66cSDavid du Colombier } 14645e96a66cSDavid du Colombier 14655e96a66cSDavid du Colombier nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize; 14665e96a66cSDavid du Colombier 14675e96a66cSDavid du Colombier didread = 0; 14685e96a66cSDavid du Colombier while(dee->i >= dee->n){ 14695e96a66cSDavid du Colombier if(dee->boff >= nb){ 14705e96a66cSDavid du Colombier ret = 0; 14715e96a66cSDavid du Colombier goto Return; 14725e96a66cSDavid du Colombier } 14735e96a66cSDavid du Colombier didread = 1; 14745e96a66cSDavid du Colombier if(!deeFill(dee)){ 14755e96a66cSDavid du Colombier ret = -1; 14765e96a66cSDavid du Colombier goto Return; 14775e96a66cSDavid du Colombier } 14785e96a66cSDavid du Colombier } 14795e96a66cSDavid du Colombier 14805e96a66cSDavid du Colombier memmove(de, dee->buf + dee->i, sizeof(DirEntry)); 14815e96a66cSDavid du Colombier dee->i++; 14825e96a66cSDavid du Colombier ret = 1; 14835e96a66cSDavid du Colombier 14845e96a66cSDavid du Colombier Return: 14855e96a66cSDavid du Colombier sourceUnlock(f->source); 14865e96a66cSDavid du Colombier sourceUnlock(f->msource); 14875e96a66cSDavid du Colombier fileRUnlock(f); 14885e96a66cSDavid du Colombier 14895e96a66cSDavid du Colombier if(didread) 14905e96a66cSDavid du Colombier fileRAccess(f); 14915e96a66cSDavid du Colombier return ret; 14925e96a66cSDavid du Colombier } 14935e96a66cSDavid du Colombier 14945e96a66cSDavid du Colombier void 14955e96a66cSDavid du Colombier deeClose(DirEntryEnum *dee) 14965e96a66cSDavid du Colombier { 14975e96a66cSDavid du Colombier int i; 14985e96a66cSDavid du Colombier if(dee == nil) 14995e96a66cSDavid du Colombier return; 15005e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 15015e96a66cSDavid du Colombier deCleanup(dee->buf+i); 15025e96a66cSDavid du Colombier vtMemFree(dee->buf); 15035e96a66cSDavid du Colombier fileDecRef(dee->file); 15045e96a66cSDavid du Colombier vtMemFree(dee); 15055e96a66cSDavid du Colombier } 15065e96a66cSDavid du Colombier 15075e96a66cSDavid du Colombier /* 15085e96a66cSDavid du Colombier * caller must lock f->source and f->msource 15095e96a66cSDavid du Colombier * caller must NOT lock the source and msource 15105e96a66cSDavid du Colombier * referenced by dir. 15115e96a66cSDavid du Colombier */ 15125e96a66cSDavid du Colombier static u32int 15135e96a66cSDavid du Colombier fileMetaAlloc(File *f, DirEntry *dir, u32int start) 15145e96a66cSDavid du Colombier { 15155e96a66cSDavid du Colombier u32int nb, bo; 15165e96a66cSDavid du Colombier Block *b, *bb; 15175e96a66cSDavid du Colombier MetaBlock mb; 15185e96a66cSDavid du Colombier int nn; 15195e96a66cSDavid du Colombier uchar *p; 15205e96a66cSDavid du Colombier int i, n, epb; 15215e96a66cSDavid du Colombier MetaEntry me; 15225e96a66cSDavid du Colombier Source *s, *ms; 15235e96a66cSDavid du Colombier 15245e96a66cSDavid du Colombier s = f->source; 15255e96a66cSDavid du Colombier ms = f->msource; 15265e96a66cSDavid du Colombier 15275e96a66cSDavid du Colombier n = deSize(dir); 15285e96a66cSDavid du Colombier nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize; 15295e96a66cSDavid du Colombier b = nil; 15305e96a66cSDavid du Colombier if(start > nb) 15315e96a66cSDavid du Colombier start = nb; 15325e96a66cSDavid du Colombier for(bo=start; bo<nb; bo++){ 15335e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 15345e96a66cSDavid du Colombier if(b == nil) 15355e96a66cSDavid du Colombier goto Err; 15365e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, ms->dsize)) 15375e96a66cSDavid du Colombier goto Err; 15385e96a66cSDavid du Colombier nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free; 15395e96a66cSDavid du Colombier if(n <= nn && mb.nindex < mb.maxindex) 15405e96a66cSDavid du Colombier break; 15415e96a66cSDavid du Colombier blockPut(b); 15425e96a66cSDavid du Colombier b = nil; 15435e96a66cSDavid du Colombier } 15445e96a66cSDavid du Colombier 15455e96a66cSDavid du Colombier /* add block to meta file */ 15465e96a66cSDavid du Colombier if(b == nil){ 15475e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 15485e96a66cSDavid du Colombier if(b == nil) 15495e96a66cSDavid du Colombier goto Err; 15505e96a66cSDavid du Colombier sourceSetSize(ms, (nb+1)*ms->dsize); 15515e96a66cSDavid du Colombier mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry); 15525e96a66cSDavid du Colombier } 15535e96a66cSDavid du Colombier 15545e96a66cSDavid du Colombier p = mbAlloc(&mb, n); 15555e96a66cSDavid du Colombier if(p == nil){ 15565e96a66cSDavid du Colombier /* mbAlloc might have changed block */ 15575e96a66cSDavid du Colombier mbPack(&mb); 15585e96a66cSDavid du Colombier blockDirty(b); 15595e96a66cSDavid du Colombier vtSetError(EBadMeta); 15605e96a66cSDavid du Colombier goto Err; 15615e96a66cSDavid du Colombier } 15625e96a66cSDavid du Colombier 15635e96a66cSDavid du Colombier mbSearch(&mb, dir->elem, &i, &me); 15645e96a66cSDavid du Colombier assert(me.p == nil); 15655e96a66cSDavid du Colombier me.p = p; 15665e96a66cSDavid du Colombier me.size = n; 15675e96a66cSDavid du Colombier dePack(dir, &me); 15685e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 15695e96a66cSDavid du Colombier mbPack(&mb); 15705e96a66cSDavid du Colombier 15715e96a66cSDavid du Colombier /* meta block depends on super block for qid ... */ 15725e96a66cSDavid du Colombier bb = cacheLocal(b->c, PartSuper, 0, OReadOnly); 157361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15745e96a66cSDavid du Colombier blockPut(bb); 15755e96a66cSDavid du Colombier 15765e96a66cSDavid du Colombier /* ... and one or two dir entries */ 15775e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 15785e96a66cSDavid du Colombier bb = sourceBlock(s, dir->entry/epb, OReadOnly); 157961201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15805e96a66cSDavid du Colombier blockPut(bb); 15815e96a66cSDavid du Colombier if(dir->mode & ModeDir){ 15825e96a66cSDavid du Colombier bb = sourceBlock(s, dir->mentry/epb, OReadOnly); 158361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15845e96a66cSDavid du Colombier blockPut(bb); 15855e96a66cSDavid du Colombier } 15865e96a66cSDavid du Colombier 15875e96a66cSDavid du Colombier blockDirty(b); 15885e96a66cSDavid du Colombier blockPut(b); 15895e96a66cSDavid du Colombier return bo; 15905e96a66cSDavid du Colombier Err: 15915e96a66cSDavid du Colombier blockPut(b); 15925e96a66cSDavid du Colombier return NilBlock; 15935e96a66cSDavid du Colombier } 15945e96a66cSDavid du Colombier 15955e96a66cSDavid du Colombier static int 15965e96a66cSDavid du Colombier chkSource(File *f) 15975e96a66cSDavid du Colombier { 15985e96a66cSDavid du Colombier if(f->partial) 15995e96a66cSDavid du Colombier return 1; 16005e96a66cSDavid du Colombier 16015e96a66cSDavid du Colombier if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){ 16025e96a66cSDavid du Colombier vtSetError(ERemoved); 16035e96a66cSDavid du Colombier return 0; 16045e96a66cSDavid du Colombier } 16055e96a66cSDavid du Colombier return 1; 16065e96a66cSDavid du Colombier } 16075e96a66cSDavid du Colombier 16085e96a66cSDavid du Colombier static int 16095e96a66cSDavid du Colombier fileRLock(File *f) 16105e96a66cSDavid du Colombier { 16115e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 16125e96a66cSDavid du Colombier vtRLock(f->lk); 16135e96a66cSDavid du Colombier if(!chkSource(f)){ 16145e96a66cSDavid du Colombier fileRUnlock(f); 16155e96a66cSDavid du Colombier return 0; 16165e96a66cSDavid du Colombier } 16175e96a66cSDavid du Colombier return 1; 16185e96a66cSDavid du Colombier } 16195e96a66cSDavid du Colombier 16205e96a66cSDavid du Colombier static void 16215e96a66cSDavid du Colombier fileRUnlock(File *f) 16225e96a66cSDavid du Colombier { 16235e96a66cSDavid du Colombier vtRUnlock(f->lk); 16245e96a66cSDavid du Colombier } 16255e96a66cSDavid du Colombier 16265e96a66cSDavid du Colombier static int 16275e96a66cSDavid du Colombier fileLock(File *f) 16285e96a66cSDavid du Colombier { 16295e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 16305e96a66cSDavid du Colombier vtLock(f->lk); 16315e96a66cSDavid du Colombier if(!chkSource(f)){ 16325e96a66cSDavid du Colombier fileUnlock(f); 16335e96a66cSDavid du Colombier return 0; 16345e96a66cSDavid du Colombier } 16355e96a66cSDavid du Colombier return 1; 16365e96a66cSDavid du Colombier } 16375e96a66cSDavid du Colombier 16385e96a66cSDavid du Colombier static void 16395e96a66cSDavid du Colombier fileUnlock(File *f) 16405e96a66cSDavid du Colombier { 16415e96a66cSDavid du Colombier vtUnlock(f->lk); 16425e96a66cSDavid du Colombier } 16435e96a66cSDavid du Colombier 16445e96a66cSDavid du Colombier /* 16455e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16465e96a66cSDavid du Colombier * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2). 16475e96a66cSDavid du Colombier * We have to respect that ordering. 16485e96a66cSDavid du Colombier */ 16495e96a66cSDavid du Colombier static void 16505e96a66cSDavid du Colombier fileMetaLock(File *f) 16515e96a66cSDavid du Colombier { 16525e96a66cSDavid du Colombier if(f->up == nil) 16535e96a66cSDavid du Colombier fprint(2, "f->elem = %s\n", f->dir.elem); 16545e96a66cSDavid du Colombier assert(f->up != nil); 16555e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 16565e96a66cSDavid du Colombier vtLock(f->up->lk); 16575e96a66cSDavid du Colombier } 16585e96a66cSDavid du Colombier 16595e96a66cSDavid du Colombier static void 16605e96a66cSDavid du Colombier fileMetaUnlock(File *f) 16615e96a66cSDavid du Colombier { 16625e96a66cSDavid du Colombier vtUnlock(f->up->lk); 16635e96a66cSDavid du Colombier } 16645e96a66cSDavid du Colombier 16655e96a66cSDavid du Colombier /* 16665e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16675e96a66cSDavid du Colombier * see fileMetaLock. 16685e96a66cSDavid du Colombier */ 16695e96a66cSDavid du Colombier static void 16705e96a66cSDavid du Colombier fileRAccess(File* f) 16715e96a66cSDavid du Colombier { 1672f4051287SDavid du Colombier if(f->mode == OReadOnly || f->fs->noatimeupd) 16735e96a66cSDavid du Colombier return; 16745e96a66cSDavid du Colombier 16755e96a66cSDavid du Colombier fileMetaLock(f); 16765e96a66cSDavid du Colombier f->dir.atime = time(0L); 16775e96a66cSDavid du Colombier f->dirty = 1; 16785e96a66cSDavid du Colombier fileMetaUnlock(f); 16795e96a66cSDavid du Colombier } 16805e96a66cSDavid du Colombier 16815e96a66cSDavid du Colombier /* 16825e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16835e96a66cSDavid du Colombier * see fileMetaLock. 16845e96a66cSDavid du Colombier */ 16855e96a66cSDavid du Colombier static void 16865e96a66cSDavid du Colombier fileWAccess(File* f, char *mid) 16875e96a66cSDavid du Colombier { 16885e96a66cSDavid du Colombier if(f->mode == OReadOnly) 16895e96a66cSDavid du Colombier return; 16905e96a66cSDavid du Colombier 16915e96a66cSDavid du Colombier fileMetaLock(f); 16925e96a66cSDavid du Colombier f->dir.atime = f->dir.mtime = time(0L); 16935e96a66cSDavid du Colombier if(strcmp(f->dir.mid, mid) != 0){ 16945e96a66cSDavid du Colombier vtMemFree(f->dir.mid); 16955e96a66cSDavid du Colombier f->dir.mid = vtStrDup(mid); 16965e96a66cSDavid du Colombier } 16975e96a66cSDavid du Colombier f->dir.mcount++; 16985e96a66cSDavid du Colombier f->dirty = 1; 16995e96a66cSDavid du Colombier fileMetaUnlock(f); 1700d58da526SDavid du Colombier 1701d58da526SDavid du Colombier /*RSC: let's try this */ 1702d58da526SDavid du Colombier /*presotto - lets not 1703d58da526SDavid du Colombier if(f->up) 1704d58da526SDavid du Colombier fileWAccess(f->up, mid); 1705d58da526SDavid du Colombier */ 17065e96a66cSDavid du Colombier } 17075e96a66cSDavid du Colombier 17085e96a66cSDavid du Colombier static int 1709e569ccb5SDavid du Colombier getEntry(Source *r, Entry *e, int checkepoch) 17105e96a66cSDavid du Colombier { 1711e569ccb5SDavid du Colombier u32int epoch; 17125e96a66cSDavid du Colombier Block *b; 17135e96a66cSDavid du Colombier 17145e96a66cSDavid du Colombier if(r == nil){ 17155e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 17165e96a66cSDavid du Colombier return 1; 17175e96a66cSDavid du Colombier } 17185e96a66cSDavid du Colombier 17195e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly); 17205e96a66cSDavid du Colombier if(b == nil) 17215e96a66cSDavid du Colombier return 0; 17225e96a66cSDavid du Colombier if(!entryUnpack(e, b->data, r->offset % r->epb)){ 17235e96a66cSDavid du Colombier blockPut(b); 17245e96a66cSDavid du Colombier return 0; 17255e96a66cSDavid du Colombier } 1726e569ccb5SDavid du Colombier epoch = b->l.epoch; 17275e96a66cSDavid du Colombier blockPut(b); 1728e569ccb5SDavid du Colombier 1729e569ccb5SDavid du Colombier if(checkepoch){ 1730e569ccb5SDavid du Colombier b = cacheGlobal(r->fs->cache, e->score, entryType(e), e->tag, OReadOnly); 1731e569ccb5SDavid du Colombier if(b){ 1732e569ccb5SDavid du Colombier if(b->l.epoch >= epoch) 1733e569ccb5SDavid du Colombier fprint(2, "warning: entry %p epoch not older %#.8ux/%d %V/%d in getEntry\n", 1734e569ccb5SDavid du Colombier r, b->addr, b->l.epoch, r->score, epoch); 1735e569ccb5SDavid du Colombier blockPut(b); 1736e569ccb5SDavid du Colombier } 1737e569ccb5SDavid du Colombier } 1738e569ccb5SDavid du Colombier 17395e96a66cSDavid du Colombier return 1; 17405e96a66cSDavid du Colombier } 17415e96a66cSDavid du Colombier 17425e96a66cSDavid du Colombier static int 17435e96a66cSDavid du Colombier setEntry(Source *r, Entry *e) 17445e96a66cSDavid du Colombier { 17455e96a66cSDavid du Colombier Block *b; 17465e96a66cSDavid du Colombier Entry oe; 17475e96a66cSDavid du Colombier 17485e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite); 17495e96a66cSDavid du Colombier if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score); 17505e96a66cSDavid du Colombier if(b == nil) 17515e96a66cSDavid du Colombier return 0; 17525e96a66cSDavid du Colombier if(!entryUnpack(&oe, b->data, r->offset % r->epb)){ 17535e96a66cSDavid du Colombier blockPut(b); 17545e96a66cSDavid du Colombier return 0; 17555e96a66cSDavid du Colombier } 17565e96a66cSDavid du Colombier e->gen = oe.gen; 17575e96a66cSDavid du Colombier entryPack(e, b->data, r->offset % r->epb); 17585e96a66cSDavid du Colombier 17595e96a66cSDavid du Colombier /* BUG b should depend on the entry pointer */ 17605e96a66cSDavid du Colombier 17615e96a66cSDavid du Colombier blockDirty(b); 17625e96a66cSDavid du Colombier blockPut(b); 17635e96a66cSDavid du Colombier return 1; 17645e96a66cSDavid du Colombier } 17655e96a66cSDavid du Colombier 17665e96a66cSDavid du Colombier /* assumes hold elk */ 17675e96a66cSDavid du Colombier int 17685e96a66cSDavid du Colombier fileSnapshot(File *dst, File *src, u32int epoch, int doarchive) 17695e96a66cSDavid du Colombier { 17705e96a66cSDavid du Colombier Entry e, ee; 17715e96a66cSDavid du Colombier 17725e96a66cSDavid du Colombier /* add link to snapshot */ 17735e96a66cSDavid du Colombier if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1)) 17745e96a66cSDavid du Colombier return 0; 17755e96a66cSDavid du Colombier 17765e96a66cSDavid du Colombier e.snap = epoch; 17775e96a66cSDavid du Colombier e.archive = doarchive; 17785e96a66cSDavid du Colombier ee.snap = epoch; 17795e96a66cSDavid du Colombier ee.archive = doarchive; 17805e96a66cSDavid du Colombier 17815e96a66cSDavid du Colombier if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee)) 17825e96a66cSDavid du Colombier return 0; 17835e96a66cSDavid du Colombier return 1; 17845e96a66cSDavid du Colombier } 17855e96a66cSDavid du Colombier 17865e96a66cSDavid du Colombier int 1787e569ccb5SDavid du Colombier fileGetSources(File *f, Entry *e, Entry *ee) 17885e96a66cSDavid du Colombier { 1789e569ccb5SDavid du Colombier if(!getEntry(f->source, e, 0) 1790e569ccb5SDavid du Colombier || !getEntry(f->msource, ee, 0)) 17915e96a66cSDavid du Colombier return 0; 17925e96a66cSDavid du Colombier return 1; 17935e96a66cSDavid du Colombier } 17945e96a66cSDavid du Colombier 1795e569ccb5SDavid du Colombier /* 1796e569ccb5SDavid du Colombier * Walk down to the block(s) containing the Entries 1797e569ccb5SDavid du Colombier * for f->source and f->msource, copying as we go. 1798e569ccb5SDavid du Colombier */ 17995e96a66cSDavid du Colombier int 18005e96a66cSDavid du Colombier fileWalkSources(File *f) 18015e96a66cSDavid du Colombier { 1802e569ccb5SDavid du Colombier if(f->mode == OReadOnly){ 1803e569ccb5SDavid du Colombier fprint(2, "readonly in fileWalkSources\n"); 18045e96a66cSDavid du Colombier return 1; 1805e569ccb5SDavid du Colombier } 1806e569ccb5SDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadWrite)){ 1807e569ccb5SDavid du Colombier fprint(2, "sourceLock2 failed in fileWalkSources\n"); 18085e96a66cSDavid du Colombier return 0; 1809e569ccb5SDavid du Colombier } 18105e96a66cSDavid du Colombier sourceUnlock(f->source); 18115e96a66cSDavid du Colombier sourceUnlock(f->msource); 18125e96a66cSDavid du Colombier return 1; 18135e96a66cSDavid du Colombier } 18143b86f2f8SDavid du Colombier 18153b86f2f8SDavid du Colombier /* 18163b86f2f8SDavid du Colombier * convert File* to full path name in malloced string. 18173b86f2f8SDavid du Colombier * this hasn't been as useful as we hoped it would be. 18183b86f2f8SDavid du Colombier */ 18193b86f2f8SDavid du Colombier char * 18203b86f2f8SDavid du Colombier fileName(File *f) 18213b86f2f8SDavid du Colombier { 18223b86f2f8SDavid du Colombier char *name, *pname; 18233b86f2f8SDavid du Colombier File *p; 18243b86f2f8SDavid du Colombier static char root[] = "/"; 18253b86f2f8SDavid du Colombier 18263b86f2f8SDavid du Colombier if (f == nil) 1827*1bdadbfaSDavid du Colombier return vtStrDup("/**GOK**"); 18283b86f2f8SDavid du Colombier 18293b86f2f8SDavid du Colombier p = fileGetParent(f); 18303b86f2f8SDavid du Colombier if (p == f) 1831*1bdadbfaSDavid du Colombier name = vtStrDup(root); 18323b86f2f8SDavid du Colombier else { 18333b86f2f8SDavid du Colombier pname = fileName(p); 18343b86f2f8SDavid du Colombier if (strcmp(pname, root) == 0) 18353b86f2f8SDavid du Colombier name = smprint("/%s", f->dir.elem); 18363b86f2f8SDavid du Colombier else 18373b86f2f8SDavid du Colombier name = smprint("%s/%s", pname, f->dir.elem); 18383b86f2f8SDavid du Colombier free(pname); 18393b86f2f8SDavid du Colombier } 18403b86f2f8SDavid du Colombier fileDecRef(p); 18413b86f2f8SDavid du Colombier return name; 18423b86f2f8SDavid du Colombier } 1843